411 lines
14 KiB
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;
|
||
|
}
|
||
|
}
|