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