410 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			410 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| namespace nur\mapper\item;
 | |
| 
 | |
| use nur\A;
 | |
| use nur\b\IllegalAccessException;
 | |
| 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;
 | |
|   }
 | |
| }
 |