nur-sery/nur_src/mapper/item/AbstractStringMapper.php

411 lines
14 KiB
PHP

<?php
namespace nur\mapper\item;
use nur\A;
use nur\b\IllegalAccessException;
use nur\b\params\parametrable_utils;
use nur\b\params\Tparametrable;
use nur\base;
use nur\mapper\base\Mapper;
use nur\mapper\base\mapper_utils;
use nur\mapper\base\mark_utils;
use nur\str;
/**
* Class AbstractStringMapper: un mapper qui fait des opérations sur des chaines
* (cette classe factorise les méthodes communes entre {@link StringMapper} et
* {@link TextMapper})
*/
abstract class AbstractStringMapper extends Mapper {
use Tparametrable;
# si l'élément est un tableau, ces actions sont faites sur chaque valeur
const ACTION_SET_VALUE = 1;
const ACTION_ADD_PREFIX = 2;
const ACTION_ADD_SUFFIX = 3;
const ACTION_DEL_PREFIX = 4;
const ACTION_DEL_SUFFIX = 5;
const ACTION_LEFT = 6;
const ACTION_RIGHT = 7;
const ACTION_SUBSTR = 8;
const ACTION_REPLACE = 9;
const ACTION_SPLIT = 10;
const ACTION_JOIN = 11;
const ACTION_TRUNC = 12;
const ACTION_TRIM = 13;
const ACTION_LTRIM = 14;
const ACTION_RTRIM = 15;
const ACTION_LOWER = 16;
const ACTION_LOWER1 = 17;
const ACTION_UPPER = 18;
const ACTION_UPPER1 = 19;
const ACTION_UPPERW = 20;
# si l'élément est un tableau, ces actions sont faites sur l'élément en entier
const ACTION_WHOLE_ITEM = 100;
const ACTION_SPLIT_ALL = 101;
const ACTION_JOIN_ALL = 102;
/** @var array */
protected $actions = [];
function addAction(?string $action): self {
if (preg_match('/^([A-Za-z0-9_]*)=(.*)$/', $action, $vs)) {
$key = A::get($vs, 1);
$action = A::get($vs, 2);
} else {
$key = null;
}
if (mapper_utils::check_prefix($action, $value, "set:", "=")) {
$this->actions[] = [self::ACTION_SET_VALUE, $key, $value];
} elseif (mapper_utils::check_prefix($action, $value, "addp:", "+#")) {
$this->actions[] = [self::ACTION_ADD_PREFIX, $key, $value];
} elseif (mapper_utils::check_prefix($action, $value, "adds:", "+%", "+")) {
$this->actions[] = [self::ACTION_ADD_SUFFIX, $key, $value];
} elseif (mapper_utils::check_prefix($action, $value, "delp:", "-#", "#")) {
$this->actions[] = [self::ACTION_DEL_PREFIX, $key, $value];
} elseif (mapper_utils::check_prefix($action, $value, "dels:", "-%", "%", "-")) {
$this->actions[] = [self::ACTION_DEL_SUFFIX, $key, $value];
} elseif (mapper_utils::check_prefix($action, $value, "left:", "l:")) {
$length = intval($value);
$this->actions[] = [self::ACTION_LEFT, $key, $length];
} elseif (mapper_utils::check_prefix($action, $value, "right:", "r:")) {
$length = intval($value);
$this->actions[] = [self::ACTION_RIGHT, $key, $length];
} elseif (mapper_utils::check_prefix($action, $value, "substr:", "mid:", "m:")) {
preg_match('/^([^:]*)(?::(.*))?$/', $value, $vs);
$offset = $vs[1];
$offset = $offset? intval($offset): 0;
$length = A::get($vs, 2);
if ($length !== null) $length = intval($length);
$this->actions[] = [self::ACTION_SUBSTR, $key, $offset, $length];
} elseif (mapper_utils::check_prefix($action, $value, "replace:", "repl:", "r//", "r/")) {
if (str::_starts_with("r//", $action)) {
$sep = "/";
$limit = -1;
} elseif (str::_starts_with("r/", $action)) {
$sep = "/";
$limit = 1;
} else {
$sep = ":";
$limit = -1;
}
[$from, $to] = str::split_pair($value, $sep);
if ($sep == "/") str::del_suffix($to, "/");
$this->actions[] = [self::ACTION_REPLACE, $key, false, $from, $to, $limit];
} elseif (mapper_utils::check_prefix($action, $value, "split:", "|", "split")) {
if ($action === "split") $value = ",";
$this->actions[] = [self::ACTION_SPLIT, $key, $value];
} elseif (mapper_utils::check_prefix($action, $value, "join:", "§", "join")) {
if ($action === "join") $value = ",";
$this->actions[] = [self::ACTION_JOIN, $key, $value];
} elseif (mapper_utils::check_prefix($action, $value, "trunc:")) {
preg_match('/^([^:]*)(?::([^:]*)(?::([^:]*))?)?$/', $value, $vs);
$length = $vs[1];
$length = $length? intval($length): 0;
$ellips = base::t2(A::get($vs, 2));
$suffix = A::get($vs, 3);
$this->actions[] = [self::ACTION_TRUNC, $key, $length, $ellips, $suffix];
} elseif (mapper_utils::check_prefix($action, $value, "trim", "t")) {
$this->actions[] = [self::ACTION_TRIM, $key];
} elseif (mapper_utils::check_prefix($action, $value, "ltrim", "lt")) {
$this->actions[] = [self::ACTION_LTRIM, $key];
} elseif (mapper_utils::check_prefix($action, $value, "rtrim", "rt")) {
$this->actions[] = [self::ACTION_RTRIM, $key];
} elseif (mapper_utils::check_prefix($action, $value, "lower", "l")) {
$this->actions[] = [self::ACTION_LOWER, $key];
} elseif (mapper_utils::check_prefix($action, $value, "lower1", "l1")) {
$this->actions[] = [self::ACTION_LOWER1, $key];
} elseif (mapper_utils::check_prefix($action, $value, "upper", "u")) {
$this->actions[] = [self::ACTION_UPPER, $key];
} elseif (mapper_utils::check_prefix($action, $value, "upper1", "u1")) {
$this->actions[] = [self::ACTION_UPPER1, $key];
} elseif (mapper_utils::check_prefix($action, $value, "upperw", "uw")) {
$this->actions[] = [self::ACTION_UPPERW, $key];
} elseif (mapper_utils::check_prefix($action, $value, "split_all:", "split_all")) {
if ($action === "split_all") $value = ",";
$this->actions[] = [self::ACTION_SPLIT_ALL, $key, $value];
} elseif (mapper_utils::check_prefix($action, $value, "join_all:", "join_all")) {
if ($action === "join_all") $value = ",";
$this->actions[] = [self::ACTION_JOIN_ALL, $key, $value];
} else {
# par défaut, spécifier la valeur
$this->actions[] = [self::ACTION_SET_VALUE, $key, $action];
}
return $this;
}
function addActionSetValue(?string $value, ?string $key=null): self {
$this->actions[] = [self::ACTION_SET_VALUE, $key, $value];
return $this;
}
function addActionAddPrefix(?string $value, ?string $key=null): self {
$this->actions[] = [self::ACTION_ADD_PREFIX, $key, $value];
return $this;
}
function addActionAddSuffix(?string $value, ?string $key=null): self {
$this->actions[] = [self::ACTION_ADD_SUFFIX, $key, $value];
return $this;
}
function addActionDelPrefix(?string $value, ?string $key=null): self {
$this->actions[] = [self::ACTION_DEL_PREFIX, $key, $value];
return $this;
}
function addActionDelSuffix(?string $value, ?string $key=null): self {
$this->actions[] = [self::ACTION_DEL_SUFFIX, $key, $value];
return $this;
}
function addActionLeft(int $length, ?string $key=null): self {
$this->actions[] = [self::ACTION_LEFT, $key, $length];
return $this;
}
function addActionRight(int $length, ?string $key=null): self {
$this->actions[] = [self::ACTION_RIGHT, $key, $length];
return $this;
}
function addActionSubstr(int $offset, ?int $length, ?string $key=null): self {
$this->actions[] = [self::ACTION_SUBSTR, $key, $offset, $length];
return $this;
}
function addActionReplace(string $from, ?string $to, int $limit=-1, ?string $key=null): self {
$this->actions[] = [self::ACTION_REPLACE, $key, false, $from, $to, $limit];
return $this;
}
function addActionSplit(?string $sep, ?string $key=null): self {
$this->actions[] = [self::ACTION_SPLIT, $key, $sep];
return $this;
}
function addActionJoin(?string $sep, ?string $key=null): self {
$this->actions[] = [self::ACTION_JOIN, $key, $sep];
return $this;
}
function addActionTrunc(int $length, bool $ellips=false, ?string $suffix=null, ?string $key=null): self {
$this->actions[] = [self::ACTION_TRUNC, $key, $length, $ellips, $suffix];
return $this;
}
function addActionTrim(?string $key=null): self {
$this->actions[] = [self::ACTION_TRIM, $key];
return $this;
}
function addActionLtrim(?string $key=null): self {
$this->actions[] = [self::ACTION_LTRIM, $key];
return $this;
}
function addActionRtrim(?string $key=null): self {
$this->actions[] = [self::ACTION_RTRIM, $key];
return $this;
}
function addActionLower(?string $key=null): self {
$this->actions[] = [self::ACTION_LOWER, $key];
return $this;
}
function addActionLower1(?string $key=null): self {
$this->actions[] = [self::ACTION_LOWER1, $key];
return $this;
}
function addActionUpper(?string $key=null): self {
$this->actions[] = [self::ACTION_UPPER, $key];
return $this;
}
function addActionUpper1(?string $key=null): self {
$this->actions[] = [self::ACTION_UPPER1, $key];
return $this;
}
function addActionUpperw(?string $key=null): self {
$this->actions[] = [self::ACTION_UPPERW, $key];
return $this;
}
const PARAMETRABLE_PARAMS_SCHEMA = [
"actions" => ["?array", null, "actions à effectuer sur les chaines du flux"],
"marked_only" => ["bool", null, "ne faire les actions que sur les éléments marqués"],
];
function pp_setActions(?array $actions): void {
if ($actions !== null) {
foreach ($actions as $action) {
$this->addAction($action);
}
}
}
/** @var bool */
protected $markedOnly;
#############################################################################
protected static function apply(&$item, ?string $forKey, callable $func, array $args): void {
if (is_array($item)) {
foreach ($item as $key => &$value) {
if ($forKey !== null & $key != $forKey) continue;
self::apply($value, null, $func, $args);
}
} else {
$item = $func($item, ...$args);
}
}
protected static function set_value($value) {
if (base::z($value)) return $value;
return strval($value);
}
protected static function add_prefix($value, ?string $prefix) {
return "$prefix$value";
}
protected static function add_suffix($value, ?string $suffix) {
return "$value$suffix";
}
protected static function split($value, string $sep): array {
if ($value === null) return [];
return explode($sep, strval($value));
}
protected function doActionItem(&$item, int $action, ?string $forKey, array $params): void {
switch ($action) {
case self::ACTION_SET_VALUE:
if (is_array($item)) {
foreach ($item as $key => &$value) {
if ($forKey !== null & $key != $forKey) continue;
$value = self::set_value(...$params);
}
} else {
$item = self::set_value(...$params);
}
break;
case self::ACTION_ADD_PREFIX:
self::apply($item, $forKey, [static::class, "add_prefix"], $params);
break;
case self::ACTION_ADD_SUFFIX:
self::apply($item, $forKey, [static::class, "add_suffix"], $params);
break;
case self::ACTION_DEL_PREFIX:
self::apply($item, $forKey, [static::class, "del_prefix"], $params);
break;
case self::ACTION_DEL_SUFFIX:
self::apply($item, $forKey, [static::class, "del_suffix"], $params);
break;
case self::ACTION_LEFT:
self::apply($item, $forKey, [static::class, "left"], $params);
break;
case self::ACTION_RIGHT:
self::apply($item, $forKey, [static::class, "right"], $params);
break;
case self::ACTION_SUBSTR:
self::apply($item, $forKey, [static::class, "substr"], $params);
break;
case self::ACTION_REPLACE:
$regexp = $params[0];
$params = array_slice($params, 1);
if ($regexp) {
#XXX à implémenter
#self::apply($item, $forKey, [static::class, "preg_replace"], $params);
} else {
self::apply($item, $forKey, [static::class, "str_replace"], $params);
}
break;
case self::ACTION_SPLIT:
self::apply($item, $forKey, [static::class, "split"], $params);
break;
case self::ACTION_JOIN:
self::apply($item, $forKey, [static::class, "join"], $params);
break;
case self::ACTION_TRUNC:
self::apply($item, $forKey, [static::class, "trunc"], $params);
break;
case self::ACTION_TRIM:
self::apply($item, $forKey, [static::class, "trim"], $params);
break;
case self::ACTION_LTRIM:
self::apply($item, $forKey, [static::class, "ltrim"], $params);
break;
case self::ACTION_RTRIM:
self::apply($item, $forKey, [static::class, "rtrim"], $params);
break;
case self::ACTION_LOWER:
self::apply($item, $forKey, [static::class, "lower"], $params);
break;
case self::ACTION_LOWER1:
self::apply($item, $forKey, [static::class, "lower1"], $params);
break;
case self::ACTION_UPPER:
self::apply($item, $forKey, [static::class, "upper"], $params);
break;
case self::ACTION_UPPER1:
self::apply($item, $forKey, [static::class, "upper1"], $params);
break;
case self::ACTION_UPPERW:
self::apply($item, $forKey, [static::class, "upperw"], $params);
break;
default:
throw IllegalAccessException::not_implemented("action $action");
}
}
protected static function split_all($item, string $sep): array {
if (base::z($item)) return $item;
if (is_array($item)) $item = self::join_all($item, "");
return explode($sep, strval($item));
}
protected static function join_all($item, string $sep): string {
if (base::z($item)) return $item;
return implode($sep, A::with($item));
}
protected function doActionWhole(&$item, int $action, ?string $forKey, array $params): void {
switch ($action) {
case self::ACTION_SPLIT_ALL:
$item = static::split_all($item, ...$params);
break;
case self::ACTION_JOIN_ALL:
$item = static::join_all($item, ...$params);
break;
default:
throw IllegalAccessException::not_implemented("action $action");
}
}
protected function setup(): void {
parent::setup();
if ($this->markedOnly === null) {
$this->markedOnly = mark_utils::is_use_marks($this);
}
}
function mapper($item) {
if (!$this->markedOnly || $this->isItemMarked($item)) {
foreach ($this->actions as $actionParams) {
[$action, $forKey] = array_slice($actionParams, 0, 2);
$params = array_slice($actionParams, 2);
if ($action < self::ACTION_WHOLE_ITEM) {
$this->doActionItem($item, $action, $forKey, $params);
} else {
$this->doActionWhole($item, $action, $forKey, $params);
}
}
}
return $item;
}
}