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;
 | 
						|
  }
 | 
						|
}
 |