344 lines
11 KiB
PHP
344 lines
11 KiB
PHP
<?php
|
|
namespace nulib;
|
|
|
|
use nulib\php\func;
|
|
use Traversable;
|
|
|
|
/**
|
|
* Class A: gestion de tableaux ou d'instances de {@link IArrayWrapper}
|
|
*
|
|
* cette classe reprend les méthodes de {@link cl} avec la différence que la
|
|
* modification est faite en place
|
|
*/
|
|
class A {
|
|
/**
|
|
* s'assurer que $array est un array non null. retourner true si $array n'a
|
|
* pas été modifié (s'il était déjà un array), false sinon.
|
|
*/
|
|
static final function ensure_array(&$array): bool {
|
|
if (is_array($array)) return true;
|
|
if ($array instanceof IArrayWrapper) $array = $array->wrappedArray();
|
|
if ($array === null || $array === false) $array = [];
|
|
elseif ($array instanceof Traversable) $array = cl::all($array);
|
|
else $array = [$array];
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* s'assurer que $array est un array s'il est non null. retourner true si
|
|
* $array n'a pas été modifié (s'il était déjà un array ou s'il valait null).
|
|
*/
|
|
static final function ensure_narray(&$array): bool {
|
|
if ($array instanceof IArrayWrapper) $array = $array->wrappedArray();
|
|
if ($array === null || is_array($array)) return true;
|
|
if ($array === false) $array = [];
|
|
elseif ($array instanceof Traversable) $array = cl::all($array);
|
|
else $array = [$array];
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* s'assurer que $array est un tableau de $size éléments, en complétant avec
|
|
* des occurrences de $default si nécessaire
|
|
*
|
|
* @return bool true si le tableau a été modifié, false sinon
|
|
*/
|
|
static final function ensure_size(?array &$array, int $size, $default=null): bool {
|
|
$modified = false;
|
|
if ($array === null) {
|
|
$array = [];
|
|
$modified = true;
|
|
}
|
|
if ($size < 0) return $modified;
|
|
$count = count($array);
|
|
if ($count == $size) return $modified;
|
|
if ($count < $size) {
|
|
# agrandir le tableau
|
|
while ($count++ < $size) {
|
|
$array[] = $default;
|
|
}
|
|
return true;
|
|
}
|
|
# rétrécir le tableau
|
|
$tmparray = [];
|
|
foreach ($array as $key => $value) {
|
|
if ($size-- == 0) break;
|
|
$tmparray[$key] = $value;
|
|
}
|
|
$array = $tmparray;
|
|
return true;
|
|
}
|
|
|
|
static function merge(&$dest, ...$merges): void {
|
|
self::ensure_narray($dest);
|
|
$dest = cl::merge($dest, ...$merges);
|
|
}
|
|
|
|
static function merge2(&$dest, ...$merges): void {
|
|
self::ensure_narray($dest);
|
|
$dest = cl::merge2($dest, ...$merges);
|
|
}
|
|
|
|
static final function select(&$dest, ?array $mappings, bool $inverse=false): void {
|
|
self::ensure_narray($dest);
|
|
$dest = cl::select($dest, $mappings, $inverse);
|
|
}
|
|
|
|
static final function selectm(&$dest, ?array $mappings, ?array $merge=null): void {
|
|
self::ensure_narray($dest);
|
|
$dest = cl::selectm($dest, $mappings, $merge);
|
|
}
|
|
|
|
static final function mselect(&$dest, ?array $merge, ?array $mappings): void {
|
|
self::ensure_narray($dest);
|
|
$dest = cl::mselect($dest, $merge, $mappings);
|
|
}
|
|
|
|
static final function pselect(&$dest, ?array $pkeys): void {
|
|
self::ensure_narray($dest);
|
|
$dest = cl::pselect($dest, $pkeys);
|
|
}
|
|
|
|
static final function pselectm(&$dest, ?array $pkeys, ?array $merge=null): void {
|
|
self::ensure_narray($dest);
|
|
$dest = cl::pselectm($dest, $pkeys, $merge);
|
|
}
|
|
|
|
static final function mpselect(&$dest, ?array $merge, ?array $pkeys): void {
|
|
self::ensure_narray($dest);
|
|
$dest = cl::mpselect($dest, $merge, $pkeys);
|
|
}
|
|
|
|
static final function set_nn(&$dest, $key, $value) {
|
|
self::ensure_narray($dest);
|
|
if ($value !== null) {
|
|
if ($key === null) $dest[] = $value;
|
|
else $dest[$key] = $value;
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
static final function append_nn(&$dest, $value) {
|
|
return self::set_nn($dest, null, $value);
|
|
}
|
|
|
|
static final function set_nz(&$dest, $key, $value) {
|
|
self::ensure_narray($dest);
|
|
if ($value !== null && $value !== false) {
|
|
if ($key === null) $dest[] = $value;
|
|
else $dest[$key] = $value;
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
static final function append_nz(&$dest, $value) {
|
|
self::ensure_narray($dest);
|
|
return self::set_nz($dest, null, $value);
|
|
}
|
|
|
|
static final function prepend_nn(&$dest, $value) {
|
|
self::ensure_narray($dest);
|
|
if ($value !== null) {
|
|
if ($dest === null) $dest = [];
|
|
array_unshift($dest, $value);
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
static final function prepend_nz(&$dest, $value) {
|
|
self::ensure_narray($dest);
|
|
if ($value !== null && $value !== false) {
|
|
if ($dest === null) $dest = [];
|
|
array_unshift($dest, $value);
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
static final function replace_nx(&$dest, $key, $value) {
|
|
self::ensure_narray($dest);
|
|
if ($dest !== null && !array_key_exists($key, $dest)) {
|
|
return $dest[$key] = $value;
|
|
} else {
|
|
return $dest[$key] ?? null;
|
|
}
|
|
}
|
|
|
|
static final function replace_n(&$dest, $key, $value) {
|
|
self::ensure_narray($dest);
|
|
$pvalue = $dest[$key] ?? null;
|
|
if ($pvalue === null) $dest[$key] = $value;
|
|
return $pvalue;
|
|
}
|
|
|
|
static final function replace_z(&$dest, $key, $value) {
|
|
self::ensure_narray($dest);
|
|
$pvalue = $dest[$key] ?? null;
|
|
if ($pvalue === null || $pvalue === false) $dest[$key] = $value;
|
|
return $pvalue;
|
|
}
|
|
|
|
static final function pop(&$dest, $key, $default=null) {
|
|
if ($dest === null) return $default;
|
|
self::ensure_narray($dest);
|
|
if ($key === null) return array_pop($dest);
|
|
$value = $dest[$key] ?? $default;
|
|
unset($dest[$key]);
|
|
return $value;
|
|
}
|
|
|
|
static final function popx(&$dest, ?array $keys): array {
|
|
$values = [];
|
|
if ($dest === null) return $values;
|
|
self::ensure_narray($dest);
|
|
if ($keys === null) return $values;
|
|
foreach ($keys as $key) {
|
|
$values[$key] = self::pop($dest, $key);
|
|
}
|
|
return $values;
|
|
}
|
|
|
|
static final function filter_if(&$dest, callable $cond): void {
|
|
self::ensure_narray($dest);
|
|
$dest = cl::filter_if($dest, $cond);
|
|
}
|
|
|
|
static final function filter_z($dest): void { self::filter_if($dest, [cv::class, "z"]);}
|
|
static final function filter_nz($dest): void { self::filter_if($dest, [cv::class, "nz"]);}
|
|
static final function filter_n($dest): void { self::filter_if($dest, [cv::class, "n"]);}
|
|
static final function filter_nn($dest): void { self::filter_if($dest, [cv::class, "nn"]);}
|
|
static final function filter_t($dest): void { self::filter_if($dest, [cv::class, "t"]);}
|
|
static final function filter_f($dest): void { self::filter_if($dest, [cv::class, "f"]);}
|
|
static final function filter_pt($dest): void { self::filter_if($dest, [cv::class, "pt"]);}
|
|
static final function filter_pf($dest): void { self::filter_if($dest, [cv::class, "pf"]);}
|
|
static final function filter_equals($dest, $value): void { self::filter_if($dest, cv::equals($value)); }
|
|
static final function filter_not_equals($dest, $value): void { self::filter_if($dest, cv::not_equals($value)); }
|
|
static final function filter_same($dest, $value): void { self::filter_if($dest, cv::same($value)); }
|
|
static final function filter_not_same($dest, $value): void { self::filter_if($dest, cv::not_same($value)); }
|
|
|
|
#############################################################################
|
|
|
|
static final function sort(?array &$array, int $flags=SORT_REGULAR, bool $assoc=false): void {
|
|
if ($array === null) return;
|
|
if ($assoc) asort($array, $flags);
|
|
else sort($array, $flags);
|
|
}
|
|
|
|
static final function ksort(?array &$array, int $flags=SORT_REGULAR): void {
|
|
if ($array === null) return;
|
|
ksort($array, $flags);
|
|
}
|
|
|
|
static final function usort(?array &$array, array $keys, bool $assoc=false): void {
|
|
if ($array === null) return;
|
|
if ($assoc) uasort($array, cl::compare($keys));
|
|
else usort($array, cl::compare($keys));
|
|
}
|
|
|
|
#############################################################################
|
|
|
|
/**
|
|
* s'assurer que $array est un tableau associatif, en remplaçant toutes les
|
|
* clés numériques par la clé correspondante dans $key
|
|
* <code>
|
|
* $array = ["first", "second"]
|
|
* A::ensure_assoc($array, ["a", "b"]);
|
|
* // returns ["a" => "first", "b" => "second"]
|
|
* </code>
|
|
*/
|
|
static final function ensure_assoc(?array &$array, array $keys, ?array $params=null): void {
|
|
$prefix = $params["key_prefix"] ?? null;
|
|
$suffix = $params["key_suffix"] ?? null;
|
|
$index = 0;
|
|
foreach ($keys as $key) {
|
|
if ($prefix !== null || $suffix !== null) {
|
|
$destKey = "$prefix$key$suffix";
|
|
} else {
|
|
# préserver les clés numériques
|
|
$destKey = $key;
|
|
}
|
|
if ($array !== null && array_key_exists($destKey, $array)) continue;
|
|
while (in_array($index, $keys, true)) {
|
|
$index++;
|
|
}
|
|
if ($array !== null && array_key_exists($index, $array)) {
|
|
$array[$destKey] = $array[$index];
|
|
unset($array[$index]);
|
|
$index++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* s'assurer que $array contient toutes les clés de $defaults, avec la valeur
|
|
* par défaut le cas échéant
|
|
*
|
|
* $missings est un tableau indiquant des valeurs qui si elles sont dans
|
|
* $array, signifie que la clé correspondante doit être considérée comme
|
|
* inexistante (et donc remplacée par la valeur de $defaults)
|
|
*/
|
|
static final function ensure_keys(?array &$array, array $defaults, ?array $missings=null, ?array $params=null): void {
|
|
$keys = array_keys($defaults);
|
|
$prefix = $params["key_prefix"] ?? null;
|
|
$suffix = $params["key_suffix"] ?? null;
|
|
foreach ($keys as $key) {
|
|
$destKey = "$prefix$key$suffix";
|
|
$haveMissing = $missings !== null && array_key_exists($key, $missings);
|
|
if ($array === null || !array_key_exists($destKey, $array)) {
|
|
$array[$destKey] = $defaults[$key];
|
|
} elseif ($haveMissing && $array[$destKey] === $missings[$key]) {
|
|
$array[$destKey] = $defaults[$key];
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* supprimer dans $array les clés dont les valeurs correspondent au tableau
|
|
* $missings
|
|
*/
|
|
static final function delete_missings(?array &$array, array $missings, ?array $params=null): void {
|
|
$prefix = $params["key_prefix"] ?? null;
|
|
$suffix = $params["key_suffix"] ?? null;
|
|
foreach ($missings as $key => $missing) {
|
|
$destKey = "$prefix$key$suffix";
|
|
if (array_key_exists($destKey, $array) && $array[$destKey] === $missing) {
|
|
unset($array[$destKey]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* s'assurer que les clés dans $array sont dans le même ordre que dans $keys
|
|
*
|
|
* les clés supplémentaires sont poussées à la fin du tableau
|
|
*/
|
|
static final function ensure_order(?array &$array, array $keys, ?array $params=null): void {
|
|
if ($array === null) return;
|
|
|
|
$prefix = $params["key_prefix"] ?? null;
|
|
$suffix = $params["key_suffix"] ?? null;
|
|
if ($prefix !== null || $suffix !== null) {
|
|
foreach ($keys as &$key) {
|
|
$key = "$prefix$key$suffix";
|
|
}; unset($key);
|
|
}
|
|
|
|
$destKeys = array_keys($array);
|
|
$keyCount = count($keys);
|
|
if (array_slice($destKeys, 0, $keyCount) === $keys) {
|
|
# si le tableau a déjà les bonnes clés dans le bon ordre, rien à faire
|
|
return;
|
|
}
|
|
|
|
$ordered = [];
|
|
foreach ($keys as $key) {
|
|
if (array_key_exists($key, $array)) {
|
|
$ordered[$key] = $array[$key];
|
|
unset($array[$key]);
|
|
}
|
|
}
|
|
$preserveKeys = $params["preserve_keys"] ?? false;
|
|
if ($preserveKeys) $array = cl::merge2($ordered, $array);
|
|
else $array = array_merge($ordered, $array);
|
|
}
|
|
}
|