150 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			150 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
namespace nur;
 | 
						|
 | 
						|
use nur\b\ui\IContent;
 | 
						|
use nur\b\ui\IPrintable;
 | 
						|
 | 
						|
/**
 | 
						|
 * Class c: gestion de contenu iterable, {@link IPrintable}, {@link IContent}
 | 
						|
 *
 | 
						|
 * @see co
 | 
						|
 */
 | 
						|
class c {
 | 
						|
  /**
 | 
						|
   * quoter $vs si c'est un scalaire non nul.
 | 
						|
   * retourner null si $vs vaut null ou false.
 | 
						|
   * sinon retourner le tableau tel quel
 | 
						|
   */
 | 
						|
  static final function qnz($vs): ?iterable {
 | 
						|
    if ($vs === null || $vs === false) return null;
 | 
						|
    elseif ($vs instanceof IPrintable) return [$vs];
 | 
						|
    elseif ($vs instanceof IContent) return [$vs];
 | 
						|
    elseif (is_iterable($vs)) return $vs;
 | 
						|
    else return [htmlspecialchars(strval($vs))];
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * quoter $vs si c'est un scalaire. sinon retourner le tableau tel quel
 | 
						|
   *
 | 
						|
   * NB: cette méthode est accessible via la fonction globale {@link q()}
 | 
						|
   */
 | 
						|
  static final function q($vs): iterable {
 | 
						|
    if ($vs === null || $vs === false) return [];
 | 
						|
    elseif ($vs instanceof IPrintable) return [$vs];
 | 
						|
    elseif ($vs instanceof IContent) return [$vs];
 | 
						|
    elseif (is_iterable($vs)) return $vs;
 | 
						|
    else return [htmlspecialchars(strval($vs))];
 | 
						|
  }
 | 
						|
 | 
						|
  /** retourner un tableau pour $vs sans le quoter si c'est un scalaire */
 | 
						|
  static final function nq($vs): iterable {
 | 
						|
    if ($vs === null || $vs === false) return [];
 | 
						|
    elseif ($vs instanceof IPrintable) return [$vs];
 | 
						|
    elseif ($vs instanceof IContent) return [$vs];
 | 
						|
    elseif (is_iterable($vs)) return $vs;
 | 
						|
    else return [strval($vs)];
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * s'assurer que la valeur est une chaine si elle n'est pas nulle et que ce
 | 
						|
   * n'est pas déjà une instance de {@link IPrintable} ou {@link IContent}
 | 
						|
   */
 | 
						|
  private static function _strval($value) {
 | 
						|
    if ($value === null) { #NOP
 | 
						|
    } elseif ($value instanceof IPrintable) { #NOP
 | 
						|
    } elseif ($value instanceof IContent) { #NOP
 | 
						|
    } else $value = strval($value);
 | 
						|
    return $value;
 | 
						|
  }
 | 
						|
 | 
						|
  /** fusionner deux valeurs */
 | 
						|
  private static function _merge($pvalue, $value) {
 | 
						|
    if (!$pvalue) {
 | 
						|
      # prendre $value
 | 
						|
      if (!is_iterable($value)) $value = self::_strval($value);
 | 
						|
      return $value;
 | 
						|
    } elseif (!$value) {
 | 
						|
      # garder $pvalue
 | 
						|
      return $pvalue;
 | 
						|
    } else {
 | 
						|
      if (!is_iterable($value)) $value = self::_strval($value);
 | 
						|
      return array_merge(A::with($pvalue), A::with($value));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Applatir le tableau $values
 | 
						|
   *
 | 
						|
   * - [a, [b]] devient [a, b]
 | 
						|
   * - [a => x, [a => y]] devient [a => [x, y]]
 | 
						|
   *
 | 
						|
   * si $recursive==true, alors
 | 
						|
   * - [a => [x, [y]]] devient [a => [x, y]]
 | 
						|
   */
 | 
						|
  static final function flatten(?iterable $values, bool $recursive=true): array {
 | 
						|
    $flattened = [];
 | 
						|
    if ($values !== null) {
 | 
						|
      $index = 0;
 | 
						|
      foreach ($values as $key => $value) {
 | 
						|
        if ($key === $index) {
 | 
						|
          # valeurs séquentielles
 | 
						|
          # elles ne sont jamais quotées
 | 
						|
          $index++;
 | 
						|
          if (is_iterable($value)) {
 | 
						|
            $value = self::flatten($value);
 | 
						|
            $index2 = 0;
 | 
						|
            foreach ($value as $key2 => $value2) {
 | 
						|
              if ($key2 === $index2) {
 | 
						|
                # sequentiel
 | 
						|
                $index2++;
 | 
						|
                $flattened[] = $value2;
 | 
						|
              } else {
 | 
						|
                if (array_key_exists($key2, $flattened)) {
 | 
						|
                  $pvalue2 = $flattened[$key2];
 | 
						|
                  $value2 = self::_merge($pvalue2, $value2);
 | 
						|
                }
 | 
						|
                $flattened[$key2] = $value2;
 | 
						|
              }
 | 
						|
            }
 | 
						|
          } else {
 | 
						|
            $flattened[] = self::_strval($value);
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          # valeurs associatives
 | 
						|
          # la valeur est quotée si elle n'est pas dans un tableau
 | 
						|
          if (array_key_exists($key, $flattened)) {
 | 
						|
            $value = self::_merge($flattened[$key], $value);
 | 
						|
          }
 | 
						|
          if ($recursive && is_array($value)) {
 | 
						|
            $value = self::flatten($value, true);
 | 
						|
          }
 | 
						|
          $flattened[$key] = $value;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return $flattened;
 | 
						|
  }
 | 
						|
 | 
						|
  /** méthode de convenance pour quoter puis applatir $vs */
 | 
						|
  static final function fq($vs): array {
 | 
						|
    return self::flatten(self::q($vs));
 | 
						|
  }
 | 
						|
 | 
						|
  /** retourner la chaine correspondant au tableau $vs applati */
 | 
						|
  static final function string(iterable $vs): string {
 | 
						|
    $pieces = [];
 | 
						|
    foreach (c::flatten($vs) as $v) {
 | 
						|
      if ($v instanceof IContent) {
 | 
						|
        $pieces[] = self::string($v->getContent());
 | 
						|
      } elseif ($v instanceof IPrintable) {
 | 
						|
        ob_start(null, 0, PHP_OUTPUT_HANDLER_STDFLAGS ^ PHP_OUTPUT_HANDLER_FLUSHABLE);
 | 
						|
        $v->print();
 | 
						|
        $pieces[] = ob_get_clean();
 | 
						|
      } else {
 | 
						|
        $pieces[] = $v;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return implode("", $pieces);
 | 
						|
  }
 | 
						|
}
 |