importation initiale
This commit is contained in:
commit
b20a040c70
|
@ -0,0 +1,10 @@
|
|||
# -*- coding: utf-8 mode: yaml -*- vim:sw=2:sts=2:et:ai:si:sta:fenc=utf-8
|
||||
composer_php_min: '7.3'
|
||||
composer_php_max: '8.0'
|
||||
composer_registry: pubdocker.univ-reunion.fr
|
||||
composer_image: image/phpbuilder:d10
|
||||
require:
|
||||
branch:
|
||||
master:
|
||||
develop:
|
||||
wip:
|
|
@ -0,0 +1 @@
|
|||
/sbin/composer.phar -delta
|
|
@ -0,0 +1,18 @@
|
|||
/.idea/**/workspace.xml
|
||||
/.idea/**/tasks.xml
|
||||
/.idea/**/usage.statistics.xml
|
||||
/.idea/**/dictionaries
|
||||
/.idea/**/shelf
|
||||
/.idea/**/contentModel.xml
|
||||
/.idea/**/dataSources/
|
||||
/.idea/**/dataSources.ids
|
||||
/.idea/**/dataSources.local.xml
|
||||
/.idea/**/sqlDataSources.xml
|
||||
/.idea/**/dynamic.xml
|
||||
/.idea/**/uiDesigner.xml
|
||||
/.idea/**/dbnavigator.xml
|
||||
/.phpunit.result.cache
|
||||
|
||||
.~lock*#
|
||||
.*.swp
|
||||
/vendor/
|
|
@ -0,0 +1 @@
|
|||
runphp
|
|
@ -0,0 +1,52 @@
|
|||
#!/bin/bash
|
||||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
MYDIR="$(dirname -- "$0")"; MYNAME="$(basename -- "$0")"
|
||||
function die() { echo 1>&2 "ERROR: $*"; exit 1; }
|
||||
|
||||
case "$MYNAME" in
|
||||
runphp) ;;
|
||||
composer)
|
||||
if [ -f "$MYDIR/composer.phar" ]; then
|
||||
set -- "$MYDIR/composer.phar" "$@"
|
||||
elif [ -f "$MYDIR/../sbin/composer.phar" ]; then
|
||||
set -- "$MYDIR/../sbin/composer.phar" "$@"
|
||||
elif [ -f "/usr/bin/composer" ]; then
|
||||
set -- "/usr/bin/composer" "$@"
|
||||
else
|
||||
set -- "" "$@"
|
||||
fi
|
||||
;;
|
||||
*) die "$MYNAME: nom de script invalide";;
|
||||
esac
|
||||
|
||||
function runphp_help() {
|
||||
echo "$MYNAME: lance un programme PHP en sélectionnant une version en particulier
|
||||
|
||||
USAGE
|
||||
$MYNAME [options] <SCRIPT.php> [args...]
|
||||
|
||||
OPTIONS
|
||||
-s, --min PHP_MIN
|
||||
-m, --max PHP_MAX
|
||||
-i, --image IMAGE"
|
||||
}
|
||||
|
||||
SOPTS=+smi
|
||||
LOPTS=help,php-min,min,php-max,max,image
|
||||
args="$(getopt -n runphp -o "$SOPTS" -l "$LOPTS" -- "$@")" || exit 1; eval "set -- $args"
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--) shift; break;;
|
||||
--help) runphp_help; exit 0;;
|
||||
*) die "$1: option non configurée";;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
script="$1"; shift
|
||||
[ -n "$script" ] || die "vous devez spécifier le script à lancer"
|
||||
[ -f "$script" ] || die "$script: script introuvable"
|
||||
|
||||
scriptdir="$(dirname -- "$script")"
|
||||
scritname="$(basename -- "$script")"
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "nucore/php",
|
||||
"type": "library",
|
||||
"description": "fonctions et classes essentielles",
|
||||
"repositories": [
|
||||
{
|
||||
"type": "composer",
|
||||
"url": "https://repos.univ-reunion.fr/composer"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"mur/tests": "7.3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"nucore\\": "php/src_base"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"nucore\\": "php/tests"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jephte Clain",
|
||||
"email": "Jephte.Clain@univ-reunion.fr"
|
||||
}
|
||||
]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
MYDIR="$(dirname -- "$0")"
|
||||
VENDOR="$MYDIR/../vendor"
|
||||
"$VENDOR/bin/phpunit" --bootstrap "$VENDOR/autoload.php" "$@" "$MYDIR/tests"
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
namespace nucore;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class AccessException: indiquer que la resource ou l'objet auquel on veut
|
||||
* accéder n'est pas accessible. il s'agit donc d'une erreur de l'utilisateur
|
||||
*/
|
||||
class AccessException extends Exception {
|
||||
static final function immutable_object(?string $dest=null, ?string $prefix=null): self {
|
||||
if ($prefix) $prefix = "$prefix: ";
|
||||
if ($dest === null) $dest = "this object";
|
||||
$message = "$dest is immutable";
|
||||
return new static($prefix.$message);
|
||||
}
|
||||
|
||||
static final function not_allowed(?string $action=null, ?string $prefix=null): self {
|
||||
if ($prefix) $prefix = "$prefix: ";
|
||||
if ($action === null) $action = "this operation";
|
||||
$message = "$action is not allowed";
|
||||
return new static($prefix.$message);
|
||||
}
|
||||
|
||||
static final function not_accessible(?string $dest=null, ?string $prefix=null): self {
|
||||
if ($prefix) $prefix = "$prefix: ";
|
||||
if ($dest === null) $dest = "this resource";
|
||||
$message = "$dest is not accessible";
|
||||
return new static($prefix.$message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
namespace nucore;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class StateException: indiquer que l'état dans lequel on se trouve est
|
||||
* inattendu: il s'agit donc d'un bug
|
||||
*/
|
||||
class StateException extends Exception {
|
||||
static final function not_implemented(?string $method=null, ?string $prefix=null): self {
|
||||
if ($method === null) $method = "this method";
|
||||
$message = "$method is not implemented";
|
||||
if ($prefix) $prefix = "$prefix: ";
|
||||
return new static($prefix.$message);
|
||||
}
|
||||
|
||||
static final function unexpected_state(?string $prefix=null): self {
|
||||
$message = "unexpected state";
|
||||
if ($prefix) $prefix = "$prefix: ";
|
||||
return new static($prefix.$message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
namespace nucore;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class ValueException: indiquer qu'une valeur est invalide
|
||||
*/
|
||||
class ValueException extends Exception {
|
||||
private static function value($value): string {
|
||||
if (is_object($value)) {
|
||||
return "<".get_class($value).">";
|
||||
} elseif (is_array($value)) {
|
||||
$values = $value;
|
||||
$parts = [];
|
||||
foreach ($values as $value) {
|
||||
$parts[] = self::value($value);
|
||||
}
|
||||
return "[".implode(", ", $parts)."]";
|
||||
} else {
|
||||
return var_export($value, true);
|
||||
}
|
||||
}
|
||||
|
||||
private static function message($value, ?string $message, ?string $kind, ?string $prefix, ?string $suffix): string {
|
||||
if ($kind === null) $kind = "value";
|
||||
if ($message === null) $message = "$kind$suffix";
|
||||
if ($value !== null) {
|
||||
$value = self::value($value);
|
||||
if ($prefix) $prefix = "$prefix: $value";
|
||||
else $prefix = $value;
|
||||
}
|
||||
if ($prefix) $prefix = "$prefix: ";
|
||||
return $prefix.$message;
|
||||
}
|
||||
|
||||
static final function null(?string $kind=null, ?string $prefix=null, ?string $message=null): self {
|
||||
return new static(self::message(null, $message, $kind, $prefix, " is null"));
|
||||
}
|
||||
|
||||
static final function invalid($value=null, ?string $kind=null, ?string $prefix=null, ?string $message=null): self {
|
||||
return new static(self::message($value, $message, $kind, $prefix, " is invalid"));
|
||||
}
|
||||
|
||||
static final function forbidden($value=null, ?string $kind=null, ?string $prefix=null, ?string $message=null): self {
|
||||
return new static(self::message($value, $message, $kind, $prefix, " is forbidden"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,467 @@
|
|||
<?php
|
||||
namespace nucore;
|
||||
|
||||
use ArrayAccess;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
* Class cl: gestion de tableau de valeurs scalaires
|
||||
*/
|
||||
class cl {
|
||||
/** retourner un array non null à partir de $array */
|
||||
static final function with($array): array {
|
||||
if (is_array($array)) return $array;
|
||||
elseif ($array === null || $array === false) return [];
|
||||
elseif ($array instanceof Traversable) return iterator_to_array($array);
|
||||
else return [$array];
|
||||
}
|
||||
|
||||
/** retourner un array à partir de $array, ou null */
|
||||
static final function withn($array): ?array {
|
||||
if (is_array($array)) return $array;
|
||||
elseif ($array === null || $array === false) return null;
|
||||
elseif ($array instanceof Traversable) return iterator_to_array($array);
|
||||
else return [$array];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
elseif ($array === null || $array === false) $array = [];
|
||||
elseif ($array instanceof Traversable) $array = iterator_to_array($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 === null || is_array($array)) return true;
|
||||
elseif ($array === false) $array = [];
|
||||
elseif ($array instanceof Traversable) $array = iterator_to_array($array);
|
||||
else $array = [$array];
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* tester si $array contient la clé $key
|
||||
*
|
||||
* @param array|ArrayAccess $array
|
||||
*/
|
||||
static final function has($array, $key): bool {
|
||||
if (is_array($array)) {
|
||||
return array_key_exists($key, $array);
|
||||
} elseif ($array instanceof ArrayAccess) {
|
||||
return $array->offsetExists($key);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* retourner $array[$key] ou $default si la clé n'existe pas
|
||||
*
|
||||
* @param array|ArrayAccess $array
|
||||
*/
|
||||
static final function get($array, $key, $default=null) {
|
||||
if (is_array($array)) {
|
||||
if (array_key_exists($key, $array)) return $array[$key];
|
||||
} elseif ($array instanceof ArrayAccess) {
|
||||
if ($array->offsetExists($key)) return $array->offsetGet($key);
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* si $array est un array ou une instance de ArrayAccess, créer ou modifier
|
||||
* l'élément dont la clé est $key
|
||||
*
|
||||
* @param array|ArrayAccess $array
|
||||
*/
|
||||
static final function set(&$array, $key, $value): void {
|
||||
if (is_array($array) || $array === null) {
|
||||
if ($key === null) $array[] = $value;
|
||||
else $array[$key] = $value;
|
||||
} elseif ($array instanceof ArrayAccess) {
|
||||
$array->offsetSet($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* si $array est un array ou une instance de ArrayAccess, supprimer l'élément
|
||||
* dont la clé est $key
|
||||
*
|
||||
* @param array|ArrayAccess $array
|
||||
*/
|
||||
static final function del(&$array, $key): void {
|
||||
if (is_array($array)) {
|
||||
unset($array[$key]);
|
||||
} elseif ($array instanceof ArrayAccess) {
|
||||
$array->offsetUnset($key);
|
||||
}
|
||||
}
|
||||
|
||||
/** retourner le nombre d'éléments de $array */
|
||||
static final function count(?array $array): int {
|
||||
return $array !== null? count($array): 0;
|
||||
}
|
||||
|
||||
/** retourner la liste des clés de $array */
|
||||
static final function keys(?array $array): array {
|
||||
return $array !== null? array_keys($array): [];
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
|
||||
/**
|
||||
* Fusionner tous les tableaux spécifiés. Les valeurs null sont ignorées.
|
||||
* Retourner null si aucun tableau n'est fourni ou s'ils étaient tous null.
|
||||
*/
|
||||
static final function merge(...$arrays): ?array {
|
||||
$merges = [];
|
||||
foreach ($arrays as $array) {
|
||||
self::ensure_narray($array);
|
||||
if ($array !== null) $merges[] = $array;
|
||||
}
|
||||
return $merges? array_merge(...$merges): null;
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
|
||||
/**
|
||||
* vérifier que le chemin $keys existe dans le tableau $array
|
||||
*
|
||||
* si $keys est vide ou null, retourner true
|
||||
*/
|
||||
static final function phas($array, $pkey): bool {
|
||||
if ($pkey !== null && !is_array($pkey)) {
|
||||
$pkey = explode(".", strval($pkey));
|
||||
}
|
||||
if ($pkey === null || $pkey === []) return true;
|
||||
$first = true;
|
||||
foreach($pkey as $key) {
|
||||
if ($key === "" && $first) {
|
||||
# une chaine vide en première position est ignorée
|
||||
continue;
|
||||
} elseif (is_array($array)) {
|
||||
if (!array_key_exists($key, $array)) return false;
|
||||
$array = $array[$key];
|
||||
} elseif ($array instanceof ArrayAccess) {
|
||||
if (!$array->offsetExists($key)) return false;
|
||||
$array = $array->offsetGet($key);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
$first = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static final function each_phas($array, ?array $pkeys): array {
|
||||
$result = [];
|
||||
if ($pkeys !== null) {
|
||||
foreach ($pkeys as $pkey) {
|
||||
$result[] = self::phas($array, $pkey);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* obtenir la valeur correspondant au chemin $keys dans $array
|
||||
*
|
||||
* si $keys est vide ou null, retourner $default
|
||||
*/
|
||||
static final function pget($array, $pkey, $default=null) {
|
||||
if ($pkey !== null && !is_array($pkey)) {
|
||||
$pkey = explode(".", strval($pkey));
|
||||
}
|
||||
if ($pkey === null || $pkey === []) return true;
|
||||
$value = $array;
|
||||
$first = true;
|
||||
foreach($pkey as $key) {
|
||||
if ($key === "" && $first) {
|
||||
# une chaine vide en première position est ignorée
|
||||
continue;
|
||||
} elseif (is_array($value)) {
|
||||
if (!array_key_exists($key, $value)) return $default;
|
||||
$value = $value[$key];
|
||||
} elseif ($value instanceof ArrayAccess) {
|
||||
if (!$value->offsetExists($key)) return $default;
|
||||
$value = $value->offsetGet($key);
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
$first = false;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
static final function each_pget($array, ?array $pkeys): array {
|
||||
$result = [];
|
||||
if ($pkeys !== null) {
|
||||
foreach ($pkeys as $key => $pkey) {
|
||||
$result[$key] = self::pget($array, $pkey);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* modifier la valeur au chemin de clé $keys dans le tableau $array
|
||||
*
|
||||
* utiliser la clé "" (chaine vide) en dernière position pour rajouter à la fin, e.g
|
||||
* - _pset($array, [""], $value) est équivalent à $array[] = $value
|
||||
* - _pset($array, ["a", "b", ""], $value) est équivalent à $array["a"]["b"][] = $value
|
||||
* la clé "" n'a pas de propriété particulière quand elle n'est pas en dernière position
|
||||
*
|
||||
* si $keys est vide ou null, $array est remplacé par $value
|
||||
*/
|
||||
static final function pset(&$array, $pkey, $value): void {
|
||||
if ($pkey !== null && !is_array($pkey)) {
|
||||
$pkey = explode(".", strval($pkey));
|
||||
}
|
||||
if ($pkey === null || $pkey === []) {
|
||||
$array = $value;
|
||||
return;
|
||||
}
|
||||
self::ensure_array($array);
|
||||
$current =& $array;
|
||||
$key = null;
|
||||
$last = count($pkey) - 1;
|
||||
$i = 0;
|
||||
foreach ($pkey as $key) {
|
||||
if ($i == $last) break;
|
||||
if ($current instanceof ArrayAccess) {
|
||||
if (!$current->offsetExists($key)) $current->offsetSet($key, []);
|
||||
$current =& $current->offsetGet($key);
|
||||
if ($current === null) {
|
||||
$current = [];
|
||||
} elseif (!is_array($current) && !($current instanceof ArrayAccess)) {
|
||||
$current = [$current];
|
||||
}
|
||||
} else {
|
||||
self::ensure_array($current[$key]);
|
||||
$current =& $current[$key];
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
if ($key === "") $current[] = $value;
|
||||
else $current[$key] = $value;
|
||||
}
|
||||
|
||||
static final function each_pset(&$array, ?array $values): void {
|
||||
if ($values !== null) {
|
||||
foreach ($values as $pkey => $value) {
|
||||
self::pset($array, $pkey, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* supprimer la valeur au chemin $keys fourni sous forme de tableau
|
||||
*/
|
||||
static final function pdel_a(&$array, ?array $pkey): void {
|
||||
}
|
||||
|
||||
/**
|
||||
* supprimer la valeur au chemin de clé $keys dans $array
|
||||
*
|
||||
* si $array vaut null ou false, sa valeur est inchangée.
|
||||
* si $keys est vide ou null, $array devient null
|
||||
*/
|
||||
static final function pdel(&$array, $pkey): void {
|
||||
if ($array === false || $array === null) return;
|
||||
if ($pkey !== null && !is_array($pkey)) {
|
||||
$pkey = explode(".", strval($pkey));
|
||||
}
|
||||
if ($pkey === null || $pkey === []) {
|
||||
$array = null;
|
||||
return;
|
||||
}
|
||||
self::ensure_array($array);
|
||||
$current =& $array;
|
||||
$key = null;
|
||||
$last = count($pkey) - 1;
|
||||
$i = 0;
|
||||
foreach ($pkey as $key) {
|
||||
if ($i == $last) break;
|
||||
if ($current instanceof ArrayAccess) {
|
||||
if (!$current->offsetExists($key)) break;
|
||||
} elseif (is_array($current)) {
|
||||
if (!array_key_exists($key, $current)) break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
$current =& $current[$key];
|
||||
$i++;
|
||||
}
|
||||
if ($i == $last) {
|
||||
if ($current instanceof ArrayAccess) {
|
||||
$current->offsetUnset($key);
|
||||
} elseif (is_array($current)) {
|
||||
unset($current[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static final function each_pdel(&$array, ?array $pkeys): void {
|
||||
if ($pkeys !== null) {
|
||||
foreach ($pkeys as $pkey) {
|
||||
self::pdel($array, $pkey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
|
||||
/**
|
||||
* retourner le tableau $array en "renommant" les clés selon le tableau
|
||||
* $mappings qui contient des associations de la forme [$from => $to]
|
||||
*/
|
||||
static function rekey(?array $array, ?array $mappings): ?array {
|
||||
if ($array === null || $mappings === null) return $array;
|
||||
$mapped = [];
|
||||
foreach ($array as $key => $value) {
|
||||
if (array_key_exists($key, $mappings)) $key = $mappings[$key];
|
||||
$mapped[$key] = $value;
|
||||
}
|
||||
return $mapped;
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
|
||||
/** tester si tous les éléments du tableau satisfont la condition */
|
||||
static final function all_if(?array $array, callable $cond): bool {
|
||||
if ($array !== null) {
|
||||
foreach ($array as $value) {
|
||||
if (!$cond($value)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static final function all_z(?array $array): bool { return self::all_if($array, [cv::class, "z"]);}
|
||||
static final function all_nz(?array $array): bool { return self::all_if($array, [cv::class, "nz"]);}
|
||||
static final function all_n(?array $array): bool { return self::all_if($array, [cv::class, "n"]);}
|
||||
static final function all_nn(?array $array): bool { return self::all_if($array, [cv::class, "nn"]);}
|
||||
static final function all_t(?array $array): bool { return self::all_if($array, [cv::class, "t"]);}
|
||||
static final function all_f(?array $array): bool { return self::all_if($array, [cv::class, "f"]);}
|
||||
static final function all_pt(?array $array): bool { return self::all_if($array, [cv::class, "pt"]);}
|
||||
static final function all_pf(?array $array): bool { return self::all_if($array, [cv::class, "pf"]);}
|
||||
static final function all_equals(?array $array, $value): bool { return self::all_if($array, cv::equals($value)); }
|
||||
static final function all_not_equals(?array $array, $value): bool { return self::all_if($array, cv::not_equals($value)); }
|
||||
static final function all_same(?array $array, $value): bool { return self::all_if($array, cv::same($value)); }
|
||||
static final function all_not_same(?array $array, $value): bool { return self::all_if($array, cv::not_same($value)); }
|
||||
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
/** tester si au moins un élément du tableau satisfait la condition */
|
||||
static final function any_if(?array $array, callable $cond): bool {
|
||||
if ($array !== null) {
|
||||
foreach ($array as $value) {
|
||||
if ($cond($value)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static final function any_z(?array $array): bool { return self::any_if($array, [cv::class, "z"]);}
|
||||
static final function any_nz(?array $array): bool { return self::any_if($array, [cv::class, "nz"]);}
|
||||
static final function any_n(?array $array): bool { return self::any_if($array, [cv::class, "n"]);}
|
||||
static final function any_nn(?array $array): bool { return self::any_if($array, [cv::class, "nn"]);}
|
||||
static final function any_t(?array $array): bool { return self::any_if($array, [cv::class, "t"]);}
|
||||
static final function any_f(?array $array): bool { return self::any_if($array, [cv::class, "f"]);}
|
||||
static final function any_pt(?array $array): bool { return self::any_if($array, [cv::class, "pt"]);}
|
||||
static final function any_pf(?array $array): bool { return self::any_if($array, [cv::class, "pf"]);}
|
||||
static final function any_equals(?array $array, $value): bool { return self::any_if($array, cv::equals($value)); }
|
||||
static final function any_not_equals(?array $array, $value): bool { return self::any_if($array, cv::not_equals($value)); }
|
||||
static final function any_same(?array $array, $value): bool { return self::any_if($array, cv::same($value)); }
|
||||
static final function any_not_same(?array $array, $value): bool { return self::any_if($array, cv::not_same($value)); }
|
||||
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
static final function filter_if(?array $array, callable $cond): ?array {
|
||||
if ($array === null) return null;
|
||||
$filtered = [];
|
||||
$index = 0;
|
||||
foreach ($array as $key => $value) {
|
||||
if (!$cond($value)) {
|
||||
if ($key === $index) {
|
||||
$index++;
|
||||
$filtered[] = $value;
|
||||
} else {
|
||||
$filtered[$key] = $value;
|
||||
}
|
||||
} elseif ($key === $index) {
|
||||
$index++;
|
||||
}
|
||||
}
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
static final function filter_z(?array $array): ?array { return self::filter_if($array, [cv::class, "z"]);}
|
||||
static final function filter_nz(?array $array): ?array { return self::filter_if($array, [cv::class, "nz"]);}
|
||||
static final function filter_n(?array $array): ?array { return self::filter_if($array, [cv::class, "n"]);}
|
||||
static final function filter_nn(?array $array): ?array { return self::filter_if($array, [cv::class, "nn"]);}
|
||||
static final function filter_t(?array $array): ?array { return self::filter_if($array, [cv::class, "t"]);}
|
||||
static final function filter_f(?array $array): ?array { return self::filter_if($array, [cv::class, "f"]);}
|
||||
static final function filter_pt(?array $array): ?array { return self::filter_if($array, [cv::class, "pt"]);}
|
||||
static final function filter_pf(?array $array): ?array { return self::filter_if($array, [cv::class, "pf"]);}
|
||||
static final function filter_equals(?array $array, $value): ?array { return self::filter_if($array, cv::equals($value)); }
|
||||
static final function filter_not_equals(?array $array, $value): ?array { return self::filter_if($array, cv::not_equals($value)); }
|
||||
static final function filter_same(?array $array, $value): ?array { return self::filter_if($array, cv::same($value)); }
|
||||
static final function filter_not_same(?array $array, $value): ?array { return self::filter_if($array, cv::not_same($value)); }
|
||||
|
||||
#############################################################################
|
||||
|
||||
static final function sorted(?array $array, int $flags=SORT_REGULAR, bool $assoc=false): ?array {
|
||||
if ($array === null) return null;
|
||||
if ($assoc) asort($array, $flags);
|
||||
else sort($array, $flags);
|
||||
return $array;
|
||||
}
|
||||
|
||||
static final function ksorted(?array $array, int $flags=SORT_REGULAR): ?array {
|
||||
if ($array === null) return null;
|
||||
ksort($array, $flags);
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* retourner une fonction permettant de trier un tableau sur les clés
|
||||
* spécifiées.
|
||||
*
|
||||
* - les clés ayant le préfixe '+' ou le suffixe '|asc' indiquent un tri
|
||||
* ascendant
|
||||
* - les clés ayant le préfixe '-' ou le suffixe '|desc' indiquent un tri
|
||||
* descendant
|
||||
* - sinon, par défaut, le tri est ascendant
|
||||
*/
|
||||
static final function compare(array $keys): callable {
|
||||
return function ($a, $b) use ($keys) {
|
||||
foreach ($keys as $key) {
|
||||
if (cstr::del_prefix($key, "+")) $w = 1;
|
||||
elseif (cstr::del_prefix($key, "-")) $w = -1;
|
||||
elseif (cstr::del_suffix($key, "|asc")) $w = 1;
|
||||
elseif (cstr::del_suffix($key, "|desc")) $w = -1;
|
||||
else $w = 1;
|
||||
if ($c = $w * cv::compare(cl::get($a, $key), cl::get($b, $key))) {
|
||||
return $c;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
static final function usorted(?array $array, array $keys, bool $assoc=false): ?array {
|
||||
if ($array === null) return null;
|
||||
if ($assoc) uasort($array, self::compare($keys));
|
||||
else usort($array, self::compare($keys));
|
||||
return $array;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,367 @@
|
|||
<?php
|
||||
namespace nucore;
|
||||
|
||||
/**
|
||||
* Class cstr: gestion des chaines de caractère "simples"
|
||||
*/
|
||||
class cstr {
|
||||
/**
|
||||
* Retourner $s converti en chaine non nulle, ou "" si $s est fausse (cela
|
||||
* n'inclue pas la chaine "0")
|
||||
*/
|
||||
static final function with($s): string {
|
||||
if (!is_string($s)) {
|
||||
if (!$s) return "";
|
||||
else $s = strval($s);
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourner $s converti en chaine non nulle, ou "" si $s est fausse selon les
|
||||
* règles de PHP
|
||||
*/
|
||||
static final function pwith($s): string {
|
||||
if (!is_string($s)) {
|
||||
if (!$s) return "";
|
||||
else $s = strval($s);
|
||||
}
|
||||
return $s?: "";
|
||||
}
|
||||
|
||||
/**
|
||||
* tronquer si nécessaire $s à la valeur $length.
|
||||
* la chaine $suffix est rajoutée le cas échéant de façon que la taille
|
||||
* totale n'excède pas $length caractères.
|
||||
*
|
||||
* si $ellips est true et que le troncage est nécessaire, remplacer les 3
|
||||
* derniers caractères par "..."
|
||||
*/
|
||||
static final function trunc(?string $s, int $length, bool $ellips=false, ?string $suffix=null): ?string {
|
||||
if ($s === null) return null;
|
||||
if ($suffix !== null) $length -= strlen($suffix);
|
||||
if (strlen($s) > $length) {
|
||||
if ($ellips && $length > 3) $s = substr($s, 0, $length - 3)."...";
|
||||
else $s = substr($s, 0, $length);
|
||||
}
|
||||
if ($suffix !== null) $s .= $suffix;
|
||||
return $s;
|
||||
}
|
||||
|
||||
/** trimmer $s */
|
||||
static final function trim(?string $s): ?string {
|
||||
if ($s === null) return null;
|
||||
else return trim($s);
|
||||
}
|
||||
|
||||
/** trimmer $s à gauche */
|
||||
static final function ltrim(?string $s): ?string {
|
||||
if ($s === null) return null;
|
||||
else return ltrim($s);
|
||||
}
|
||||
|
||||
/** trimmer $s à droite */
|
||||
static final function rtrim(?string $s): ?string {
|
||||
if ($s === null) return null;
|
||||
else return rtrim($s);
|
||||
}
|
||||
|
||||
static final function lower(?string $s): ?string {
|
||||
if ($s === null) return null;
|
||||
else return strtolower($s);
|
||||
}
|
||||
|
||||
static final function lower1(?string $s): ?string {
|
||||
if ($s === null) return null;
|
||||
else return lcfirst($s);
|
||||
}
|
||||
|
||||
static final function upper(?string $s): ?string {
|
||||
if ($s === null) return null;
|
||||
else return strtoupper($s);
|
||||
}
|
||||
|
||||
static final function upper1(?string $s): ?string {
|
||||
if ($s === null) return null;
|
||||
else return ucfirst($s);
|
||||
}
|
||||
|
||||
static final function upperw(?string $s, ?string $delimiters=null): ?string {
|
||||
if ($s === null) return null;
|
||||
if ($delimiters !== null) return ucwords($s, $delimiters);
|
||||
else return ucwords($s, " _-\t\r\n\f\v");
|
||||
}
|
||||
|
||||
protected static final function _starts_with(string $prefix, string $s, ?int $min_len=null): bool {
|
||||
if ($prefix === $s) return true;
|
||||
$len = strlen($prefix);
|
||||
if ($min_len !== null && ($len < $min_len || $len > strlen($s))) return false;
|
||||
return $len == 0 || $prefix === substr($s, 0, $len);
|
||||
}
|
||||
|
||||
/**
|
||||
* tester si $s commence par $prefix
|
||||
* par exemple:
|
||||
* - starts_with("", "whatever") est true
|
||||
* - starts_with("fi", "first") est true
|
||||
* - starts_with("no", "yes") est false
|
||||
*
|
||||
* si $min_len n'est pas null, c'est la longueur minimum requise de $prefix
|
||||
* pour qu'on teste la correspondance. dans le cas contraire, la valeur de
|
||||
* retour est toujours false, sauf s'il y a égalité. e.g
|
||||
* - starts_with("a", "abc", 2) est false
|
||||
* - starts_with("a", "a", 2) est true
|
||||
*/
|
||||
static final function starts_with(?string $prefix, ?string $s, ?int $min_len=null): bool {
|
||||
if ($s === null || $prefix === null) return false;
|
||||
else return self::_starts_with($prefix, $s, $min_len);
|
||||
}
|
||||
|
||||
/** Retourner $s sans le préfixe $prefix s'il existe */
|
||||
static final function without_prefix(?string $prefix, ?string $s): ?string {
|
||||
if ($s === null || $prefix === null) return $s;
|
||||
if (self::_starts_with($prefix, $s)) $s = substr($s, strlen($prefix));
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* modifier $s en place pour supprimer le préfixe $prefix s'il existe
|
||||
*
|
||||
* retourner true si le préfixe a été enlevé.
|
||||
*/
|
||||
static final function del_prefix(?string &$s, ?string $prefix): bool {
|
||||
if ($s === null || !self::_starts_with($prefix, $s)) return false;
|
||||
$s = self::without_prefix($prefix, $s);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourner $s avec le préfixe $prefix
|
||||
*
|
||||
* Si $unless_exists, ne pas ajouter le préfixe s'il existe déjà
|
||||
*/
|
||||
static final function with_prefix(?string $prefix, ?string $s, ?string $sep=null, bool $unless_exists=false): ?string {
|
||||
if ($s === null || $prefix === null) return $s;
|
||||
if (!self::_starts_with($prefix, $s) || !$unless_exists) $s = $prefix.$sep.$s;
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* modifier $s en place pour ajouter le préfixe $prefix
|
||||
*
|
||||
* retourner true si le préfixe a été ajouté.
|
||||
*/
|
||||
static final function add_prefix(?string &$s, ?string $prefix, bool $unless_exists=true): bool {
|
||||
if (($s === null || self::_starts_with($prefix, $s)) && $unless_exists) return false;
|
||||
$s = self::with_prefix($prefix, $s, null, $unless_exists);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected static final function _ends_with(string $suffix, string $s, ?int $min_len=null): bool {
|
||||
if ($suffix === $s) return true;
|
||||
$len = strlen($suffix);
|
||||
if ($min_len !== null && ($len < $min_len || $len > strlen($s))) return false;
|
||||
return $len == 0 || $suffix === substr($s, -$len);
|
||||
}
|
||||
|
||||
/**
|
||||
* tester si $string se termine par $suffix
|
||||
* par exemple:
|
||||
* - ends_with("", "whatever") est true
|
||||
* - ends_with("st", "first") est true
|
||||
* - ends_with("no", "yes") est false
|
||||
*
|
||||
* si $min_len n'est pas null, c'est la longueur minimum requise de $prefix
|
||||
* pour qu'on teste la correspondance. dans le cas contraire, la valeur de
|
||||
* retour est toujours false, sauf s'il y a égalité. e.g
|
||||
* - ends_with("c", "abc", 2) est false
|
||||
* - ends_with("c", "c", 2) est true
|
||||
*/
|
||||
static final function ends_with(?string $suffix, ?string $s, ?int $min_len=null): bool {
|
||||
if ($s === null || $suffix === null) return false;
|
||||
else return self::_ends_with($suffix, $s, $min_len);
|
||||
}
|
||||
|
||||
/** Retourner $s sans le suffixe $suffix s'il existe */
|
||||
static final function without_suffix(?string $suffix, ?string $s): ?string {
|
||||
if ($s === null || $suffix === null) return $s;
|
||||
if (self::_ends_with($suffix, $s)) $s = substr($s, 0, -strlen($suffix));
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* modifier $s en place pour supprimer le suffixe $suffix s'il existe
|
||||
*
|
||||
* retourner true si le suffixe a été enlevé.
|
||||
*/
|
||||
static final function del_suffix(?string &$s, ?string $suffix): bool {
|
||||
if ($s === null || !self::_ends_with($suffix, $s)) return false;
|
||||
$s = self::without_suffix($suffix, $s);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourner $s avec le suffixe $suffix
|
||||
*
|
||||
* Si $unless_exists, ne pas ajouter le suffixe s'il existe déjà
|
||||
*/
|
||||
static final function with_suffix(?string $suffix, ?string $s, ?string $sep=null, bool $unless_exists=false): ?string {
|
||||
if ($s === null || $suffix === null) return $s;
|
||||
if (!self::_ends_with($suffix, $s) || !$unless_exists) $s = $s.$sep.$suffix;
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* modifier $s en place pour ajouter le suffixe $suffix
|
||||
*
|
||||
* retourner true si le suffixe a été ajouté.
|
||||
*/
|
||||
static final function add_suffix(?string &$s, ?string $suffix, bool $unless_exists=true): bool {
|
||||
if (($s === null || self::_ends_with($suffix, $s)) && $unless_exists) return false;
|
||||
$s = self::with_suffix($suffix, $s, null, $unless_exists);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** splitter $s en deux chaines séparées par $sep */
|
||||
static final function split_pair(?string $s, string $sep=":"): array {
|
||||
if ($s === null) return [null, null];
|
||||
$parts = explode($sep, $s, 2);
|
||||
if ($parts === false) return [null, null];
|
||||
if (count($parts) < 2) $parts[] = null;
|
||||
return $parts;
|
||||
}
|
||||
|
||||
/** retourner $line sans son caractère de fin de ligne */
|
||||
static final function strip_nl(?string $line): ?string {
|
||||
if ($line === null) return null;
|
||||
if (substr($line, -2) == "\r\n") {
|
||||
$line = substr($line, 0, -2);
|
||||
} elseif (substr($line, -1) == "\n") {
|
||||
$line = substr($line, 0, -1);
|
||||
} elseif (substr($line, -1) == "\r") {
|
||||
$line = substr($line, 0, -1);
|
||||
}
|
||||
return $line;
|
||||
}
|
||||
|
||||
/**
|
||||
* normaliser le caractère de fin de ligne: tous les occurrences de [CR]LF et CR sont remplacées par LF
|
||||
*/
|
||||
static final function norm_nl(?string $s): ?string {
|
||||
if ($s === null) return null;
|
||||
$s = str_replace("\r\n", "\n", $s);
|
||||
$s = str_replace("\r", "\n", $s);
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* joindre les éléments de $parts comme avec implode(), mais en ignorant les
|
||||
* valeurs fausses (cela n'inclue pas la chaine "0")
|
||||
*
|
||||
* pour chaque valeur du tableau avec une clé associative, c'est la clé qui
|
||||
* est utilisée mais uniquement si la valeur est vraie
|
||||
*/
|
||||
static final function join(string $glue, ?array $values): ?string {
|
||||
if ($values === null) return null;
|
||||
$pieces = [];
|
||||
$index = 0;
|
||||
foreach ($values as $key => $value) {
|
||||
if (is_array($value)) $value = self::join($glue, $value);
|
||||
if ($key === $index) {
|
||||
$index++;
|
||||
if (cv::t($value)) $pieces[] = $value;
|
||||
} elseif (cv::t($value)) {
|
||||
$pieces[] = $key;
|
||||
}
|
||||
}
|
||||
return implode($glue, $pieces);
|
||||
}
|
||||
|
||||
/**
|
||||
* comme {@link join()} mais en ignorant les valeurs fausses selon les règles
|
||||
* de PHP
|
||||
*/
|
||||
static final function pjoin(string $glue, ?array $values): ?string {
|
||||
if ($values === null) return null;
|
||||
$pieces = [];
|
||||
$index = 0;
|
||||
foreach ($values as $key => $value) {
|
||||
if (is_array($value)) $value = self::join($glue, $value);
|
||||
if ($key === $index) {
|
||||
$index++;
|
||||
if ($value) $pieces[] = $value;
|
||||
} elseif ($value) {
|
||||
$pieces[] = $key;
|
||||
}
|
||||
}
|
||||
return implode($glue, $pieces);
|
||||
}
|
||||
|
||||
const CAMEL_PATTERN0 = '/([A-Z0-9]+)$/A';
|
||||
const CAMEL_PATTERN1 = '/([A-Z0-9]+)[A-Z]/A';
|
||||
const CAMEL_PATTERN2 = '/([^A-Z]+)/A';
|
||||
const CAMEL_PATTERN3 = '/([A-Z][^A-Z]*)/A';
|
||||
|
||||
/**
|
||||
* convertir une chaine de la forme "camelCase" en "under_score". le premier
|
||||
* ensemble de caractères en majuscule est considéré comme étant en minuscule
|
||||
*
|
||||
* par exemple:
|
||||
* - 'myCamelCase' devient 'my_camel_case'
|
||||
* - 'AValue' devient 'a_value'
|
||||
* - 'UPPERValue' devient 'upper_value'
|
||||
* - 'UPPER' devient 'upper'
|
||||
* - 'aXYZ' devient 'a_x_y_z'
|
||||
*
|
||||
* $delimiter est le séparateur en sortie ('_' par défaut)
|
||||
* $upper indique s'il faut transformer le résultat en majuscule
|
||||
*/
|
||||
static final function camel2us(?string $camel, bool $upper=false, string $delimiter="_"): ?string {
|
||||
if ($camel === null || $camel === "") return $camel;
|
||||
$parts = [];
|
||||
if (preg_match(self::CAMEL_PATTERN0, $camel, $vs, PREG_OFFSET_CAPTURE)) {
|
||||
# que des majuscules
|
||||
} elseif (preg_match(self::CAMEL_PATTERN1, $camel, $vs, PREG_OFFSET_CAPTURE)) {
|
||||
# préfixe en majuscule
|
||||
} elseif (preg_match(self::CAMEL_PATTERN2, $camel, $vs, PREG_OFFSET_CAPTURE)) {
|
||||
# préfixe en minuscule
|
||||
} else {
|
||||
throw ValueException::invalid($camel, "camel string");
|
||||
}
|
||||
$parts[] = strtolower($vs[1][0]);
|
||||
$index = intval($vs[1][1]) + strlen($vs[1][0]);
|
||||
while (preg_match(self::CAMEL_PATTERN3, $camel, $vs, PREG_OFFSET_CAPTURE, $index)) {
|
||||
$parts[] = strtolower($vs[1][0]);
|
||||
$index = intval($vs[1][1]) + strlen($vs[1][0]);
|
||||
}
|
||||
$us = implode($delimiter, $parts);
|
||||
if ($upper) $us = strtoupper($us);
|
||||
return $us;
|
||||
}
|
||||
|
||||
const US_PATTERN = '/([ _\-\t\r\n\f\v])/';
|
||||
|
||||
/**
|
||||
* convertir une chaine de la forme "under_score" en "camelCase"
|
||||
*
|
||||
* par exemple, 'my_camel_case' devient 'myCamelCalse'
|
||||
* et 'UPPER_VALUE' devient 'upperValue'
|
||||
*
|
||||
* si la chaine de départ ne contient pas de delimiter, e.g 'myValue', elle
|
||||
* est retournée inchangée
|
||||
*/
|
||||
static final function us2camel(?string $us, ?string $delimiters=null): ?string {
|
||||
if ($us === null || $us === "") return $us;
|
||||
if ($delimiters === null) $pattern = self::US_PATTERN;
|
||||
else $pattern = '/(['.preg_quote($delimiters).'])/';
|
||||
$parts = preg_split($pattern, $us);
|
||||
$count = count($parts);
|
||||
if ($count == 1) return $us;
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$part = strtolower($parts[$i]);
|
||||
if ($i > 0) $part = ucfirst($part);
|
||||
$parts[$i] = $part;
|
||||
}
|
||||
return implode("", $parts);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,216 @@
|
|||
<?php
|
||||
namespace nucore;
|
||||
|
||||
/**
|
||||
* Class cv: gestion de valeurs scalaires
|
||||
*/
|
||||
class cv {
|
||||
/** tester si $value vaut null ou false */
|
||||
static final function z($value): bool {
|
||||
return $value === false || $value === null;
|
||||
}
|
||||
|
||||
/** tester si $value ne vaut ni null ni false */
|
||||
static final function nz($value): bool {
|
||||
return $value !== false && $value !== null;
|
||||
}
|
||||
|
||||
/** tester si $value vaut null */
|
||||
static final function n($value): bool {
|
||||
return $value === null;
|
||||
}
|
||||
|
||||
/** tester si $value n'est pas null */
|
||||
static final function nn($value): bool {
|
||||
return $value !== null;
|
||||
}
|
||||
|
||||
/** tester si $value est vraie (y compris la chaine "0") */
|
||||
static final function t($value): bool {
|
||||
return $value || $value === "0";
|
||||
}
|
||||
|
||||
/** tester si $value est fausse (cela n'inclue pas la chaine "0") */
|
||||
static final function f($value): bool {
|
||||
return !$value && $value !== "0";
|
||||
}
|
||||
|
||||
/** tester si $value est vraie selon les règles de PHP. */
|
||||
static final function pt($value): bool {
|
||||
return boolval($value);
|
||||
}
|
||||
|
||||
/** tester si $value est fausse selon les règles de PHP. */
|
||||
static final function pf($value): bool {
|
||||
return !$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* contruire une fonction qui retourne vrai si on lui passe en argument une
|
||||
* valeur égale à $value
|
||||
*/
|
||||
static final function equals($value): callable {
|
||||
return function ($arg) use($value) { return $arg == $value; };
|
||||
}
|
||||
|
||||
/**
|
||||
* contruire une fonction qui retourne vrai si on lui passe en argument une
|
||||
* valeur qui n'est pas égale à $value
|
||||
*/
|
||||
static final function not_equals($value): callable {
|
||||
return function ($arg) use($value) { return $arg != $value; };
|
||||
}
|
||||
|
||||
/**
|
||||
* contruire une fonction qui retourne vrai si on lui passe en argument une
|
||||
* valeur strictement égale à $value
|
||||
*/
|
||||
static final function same($value): callable {
|
||||
return function ($arg) use($value) { return $arg === $value; };
|
||||
}
|
||||
|
||||
/**
|
||||
* contruire une fonction qui retourne vrai si on lui passe en argument une
|
||||
* valeur qui n'est pas strictement égale à $value
|
||||
*/
|
||||
static final function not_same($value): callable {
|
||||
return function ($arg) use($value) { return $arg !== $value; };
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
|
||||
/** mettre à jour $dest avec $value si $cond($value) est vrai */
|
||||
static final function set_if(&$dest, $value, callable $cond) {
|
||||
if ($cond($value)) $dest = $value;
|
||||
return $dest;
|
||||
}
|
||||
static final function set_z(&$dest, $value) { return self::set_if($dest, $value, [self::class, "z"]);}
|
||||
static final function set_nz(&$dest, $value) { return self::set_if($dest, $value, [self::class, "nz"]);}
|
||||
static final function set_n(&$dest, $value) { return self::set_if($dest, $value, [self::class, "n"]);}
|
||||
static final function set_nn(&$dest, $value) { return self::set_if($dest, $value, [self::class, "nn"]);}
|
||||
static final function set_t(&$dest, $value) { return self::set_if($dest, $value, [self::class, "t"]);}
|
||||
static final function set_f(&$dest, $value) { return self::set_if($dest, $value, [self::class, "f"]);}
|
||||
static final function set_pt(&$dest, $value) { return self::set_if($dest, $value, [self::class, "pt"]);}
|
||||
static final function set_pf(&$dest, $value) { return self::set_if($dest, $value, [self::class, "pf"]);}
|
||||
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
/** mettre à jour $dest avec $value si $cond($dest) est vrai */
|
||||
static final function update_if(&$dest, $value, callable $cond) {
|
||||
if ($cond($dest)) $dest = $value;
|
||||
return $dest;
|
||||
}
|
||||
static final function update_z(&$dest, $value) { return self::update_if($dest, $value, [self::class, "z"]);}
|
||||
static final function update_nz(&$dest, $value) { return self::update_if($dest, $value, [self::class, "nz"]);}
|
||||
static final function update_n(&$dest, $value) { return self::update_if($dest, $value, [self::class, "n"]);}
|
||||
static final function update_nn(&$dest, $value) { return self::update_if($dest, $value, [self::class, "nn"]);}
|
||||
static final function update_t(&$dest, $value) { return self::update_if($dest, $value, [self::class, "t"]);}
|
||||
static final function update_f(&$dest, $value) { return self::update_if($dest, $value, [self::class, "f"]);}
|
||||
static final function update_pt(&$dest, $value) { return self::update_if($dest, $value, [self::class, "pt"]);}
|
||||
static final function update_pf(&$dest, $value) { return self::update_if($dest, $value, [self::class, "pf"]);}
|
||||
|
||||
#############################################################################
|
||||
|
||||
/** retourner $value si elle est vraie (y compris la chaine "0"), false sinon */
|
||||
static final function vf($value) {
|
||||
return $value || $value === "0"? $value: false;
|
||||
}
|
||||
|
||||
/** retourner $value si elle est vraie (y compris la chaine "0"), null sinon */
|
||||
static final function vn($value) {
|
||||
return $value || $value === "0"? $value: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* retourner la première valeur vraie (y compris la chaine "0")
|
||||
*
|
||||
* si toutes les valeurs sont fausses, retourner la dernière valeur de la
|
||||
* liste, ou null si la liste est vide
|
||||
*/
|
||||
static final function firstv(...$values) {
|
||||
$value = null;
|
||||
foreach ($values as $value) {
|
||||
if ($value || $value === "0") return $value;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* retourner la première valeur vraie selon les règles de PHP.
|
||||
*
|
||||
* si toutes les valeurs sont fausses, retourner la dernière valeur de la
|
||||
* liste, ou null si la liste est vide
|
||||
*/
|
||||
static final function firstpv(...$values) {
|
||||
$value = null;
|
||||
foreach ($values as $value) {
|
||||
if ($value) return $value;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
|
||||
/** vérifier si $value est un booléen, sinon retourner null */
|
||||
static final function check_bool($value): ?bool {
|
||||
return is_bool($value)? $value: null;
|
||||
}
|
||||
|
||||
/** vérifier si $value est un integer, sinon retourner null */
|
||||
static final function check_int($value): ?int {
|
||||
return is_int($value)? $value: null;
|
||||
}
|
||||
|
||||
/** vérifier si $value est un string, sinon retourner null */
|
||||
static final function check_string($value): ?string {
|
||||
return is_string($value)? $value: null;
|
||||
}
|
||||
|
||||
/** vérifier si $value est un array, sinon retourner null */
|
||||
static final function check_array($value): ?array {
|
||||
return is_array($value)? $value: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* retourner [$index, $key] initialisés chacun en fonction du type de $value
|
||||
* (index est numérique, key est une chaine)
|
||||
*
|
||||
* lever une exception si $value n'est d'aucun de ces types
|
||||
*/
|
||||
static final function check_key($value, ?string $prefix=null, bool $throw_exception=true): array {
|
||||
$index = is_int($value)? $value : null;
|
||||
$key = is_string($value)? $value : null;
|
||||
if ($index === null && $key === null && $throw_exception) {
|
||||
throw ValueException::invalid($value, "key", $prefix);
|
||||
} else {
|
||||
return [$index, $key];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* retourner [$bool, $string, $array] initialisés chacun en fonction du type
|
||||
* de $value.
|
||||
*
|
||||
* @throws ValueException si $value n'est d'aucun de ces types
|
||||
*/
|
||||
static final function check_bsa($value, ?string $prefix=null, bool $throw_exception=true): array {
|
||||
$bool = is_bool($value)? $value : null;
|
||||
$string = is_string($value)? $value : null;
|
||||
$array = is_array($value)? $value : null;
|
||||
if ($bool === null && $string === null && $array === null && $throw_exception) {
|
||||
throw ValueException::invalid($value, "value", $prefix);
|
||||
} else {
|
||||
return [$bool, $string, $array];
|
||||
}
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
|
||||
/** retourner -1, 0 ou 1 en fonction de l'ordre relatif entre $a et $b */
|
||||
static final function compare($a, $b): int {
|
||||
if ($a === $b) return 0;
|
||||
if ($a < $b) return -1;
|
||||
if ($a > $b) return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
namespace nucore;
|
||||
|
||||
use mur\tests\TestCase;
|
||||
|
||||
class cstrTest extends TestCase {
|
||||
function testSplit_pair() {
|
||||
self::assertSame([null, null], cstr::split_pair(null));
|
||||
self::assertSame(["", null], cstr::split_pair(""));
|
||||
self::assertSame(["first", null], cstr::split_pair("first"));
|
||||
self::assertSame(["first", ""], cstr::split_pair("first:"));
|
||||
self::assertSame(["first", "second"], cstr::split_pair("first:second"));
|
||||
self::assertSame(["first", "second:third"], cstr::split_pair("first:second:third"));
|
||||
}
|
||||
|
||||
function testXxxSuffix() {
|
||||
$s = "blahSUF";
|
||||
self::assertTrue(cstr::del_suffix($s, "SUF"));
|
||||
self::assertSame("blah", $s);
|
||||
self::assertFalse(cstr::del_suffix($s, "SUF"));
|
||||
|
||||
self::assertTrue(cstr::add_suffix($s, "SUF"));
|
||||
self::assertSame("blahSUF", $s);
|
||||
self::assertFalse(cstr::add_suffix($s, "SUF"));
|
||||
}
|
||||
|
||||
function testXxxPrefix() {
|
||||
$s = "PREblah";
|
||||
self::assertTrue(cstr::del_prefix($s, "PRE"));
|
||||
self::assertSame("blah", $s);
|
||||
self::assertFalse(cstr::del_prefix($s, "PRE"));
|
||||
|
||||
self::assertTrue(cstr::add_prefix($s, "PRE"));
|
||||
self::assertSame("PREblah", $s);
|
||||
self::assertFalse(cstr::add_prefix($s, "PRE"));
|
||||
}
|
||||
|
||||
function testUs2camel() {
|
||||
# avec délimiteur
|
||||
self::assertSame("myCamel", cstr::us2camel("my_camel"));
|
||||
self::assertSame("myCamel", cstr::us2camel("MY_CAMEL"));
|
||||
self::assertSame("myCamel", cstr::us2camel("My_Camel"));
|
||||
self::assertSame("myCamel", cstr::us2camel("mY_cAMEL"));
|
||||
self::assertSame("myCamel", cstr::us2camel("my-camel"));
|
||||
self::assertSame("myCamel", cstr::us2camel("my camel"));
|
||||
self::assertSame("myCamel", cstr::us2camel("my\tcamel"));
|
||||
self::assertSame("myCamel", cstr::us2camel("my\rcamel"));
|
||||
self::assertSame("myCamel", cstr::us2camel("my\ncamel"));
|
||||
self::assertSame("myCamel", cstr::us2camel("my\fcamel"));
|
||||
self::assertSame("myCamel", cstr::us2camel("my\vcamel"));
|
||||
# sans délimiteur
|
||||
self::assertSame("myCamel", cstr::us2camel("myCamel"));
|
||||
self::assertSame("MyCamel", cstr::us2camel("MyCamel"));
|
||||
self::assertSame("MyCaMEL", cstr::us2camel("MyCaMEL"));
|
||||
}
|
||||
}
|
Binary file not shown.
Loading…
Reference in New Issue