diff --git a/src/php/func.php b/src/php/func.php index 2502373..7a9a305 100644 --- a/src/php/func.php +++ b/src/php/func.php @@ -4,7 +4,6 @@ namespace nur\sery\php; use Closure; use nur\sery\cl; use nur\sery\ref\php\ref_func; -use nur\sery\str; use nur\sery\ValueException; use ReflectionClass; use ReflectionFunction; @@ -12,111 +11,55 @@ use ReflectionMethod; /** * Class func: outils pour appeler des fonctions et méthodes dynamiquement - * - * Les formats supportés sont: - * - fonctions globales - * - "func" si function_exists("func") - * - [false, "func", ...] - * - méthodes statiques - * - "::method" méthode à lier à une classe avant l'appel - * - "class::method" - * - ["method"] si !class_exists("method") - * - [null, "method", ...] méthode à lier à une classe avant l'appel - * - ["class", "method", ...] - * - méthodes - * - "->method" méthode à lier à un objet avant l'appel - * - ["method"] si !class_exists("method") - * - [null, "method", ...] méthode à lier à un objet avant l'appel - * - [$object, "method", ...] - * - classes - * - "class" si !function_exists("class") - * - "class::" - * - ["class"] si class_exists("class") - * - ["class", null, ...] - * - * les formes "func" et "class" sont distinguées en vérifiant l'existence de la - * fonction - * - * les formes ["class"] et ["method"] sont distinguées en vérifiant l'existence - * de la classe */ class func { - /** tester si $value est une chaine non vide */ - private static function is_ne($value): bool { - return is_string($value) && strlen($value) > 0; - } - /** - * tester si $func est d'une des formes suivantes: - * - "func" si function_exists("func") - * - [false, "func", ...] + * tester si $func est une chaine de la forme "XXX::method" où XXX est une + * chaine quelconque éventuellement vide, ou un tableau de la forme ["method"] + * ou [anything, "method", ...] + * + * Avec la forme tableau, "method" ne doit pas contenir le caractère '\', pour + * pouvoir utiliser conjointement {@link is_class()} */ - static final function is_global($func): bool { - if (self::is_ne($func)) { + static final function is_static($func, bool $allowClass=false): bool { + if (is_string($func)) { $pos = strpos($func, "::"); - return $pos === false && function_exists($func); - } elseif (is_array($func)) { - return ($func[0] ?? null) === false - && self::is_ne($func[1] ?? null); - } - return false; - } - - static final function fix_global_args(&$func, ?array &$args): bool { - if ($args === null) $args = []; - if (is_array($func)) { - if (count($func) > 2) { - $prefix_args = array_slice($func, 2); - $func = array_slice($func, 1, 1)[0]; - $args = array_merge($prefix_args, $args); - } else { - $func = $func[0]; - } - return true; - } - return false; - } - - /** - * tester si $func est d'une des formes suivantes: - * - "::method" - * - "class::method" - * - ["method"] si !class_exists("method") - * - [anything, "method", ...] - */ - static final function is_static($func): bool { - if (self::is_ne($func)) { - $pos = strpos($func, "::"); - return $pos !== false && $pos + 2 < strlen($func); + if ($pos === false) return false; + return $pos + 2 < strlen($func); } elseif (is_array($func) && array_key_exists(0, $func)) { $count = count($func); if ($count == 1) { - return self::is_ne($func[0]) && !class_exists($func[0]); - } elseif ($count > 1 && array_key_exists(1, $func)) { - return self::is_ne($func[1]); + if (!is_string($func[0]) || strlen($func[0]) == 0) return false; + if (strpos($func[0], "\\") !== false) return false; + return true; + } elseif ($count > 1) { + if (!array_key_exists(1, $func)) return false; + if (!is_string($func[1]) || strlen($func[1]) == 0) return false; + if (strpos($func[1], "\\") !== false) return false; + return true; } } return false; } /** - * en assumant que {@link self::is_static()} retourne true: - * - si $func est une chaine de la forme "::method" alors la remplacer par la + * si $func est une chaine de la forme "::method" alors la remplacer par la * chaine "$class::method" - * - si $func est un tableau de la forme ["method"] ou [null, "method"], alors + * + * si $func est un tableau de la forme ["method"] ou [null, "method"], alors * le remplacer par [$class, "method"] * + * on assume que {@link is_static()}($func) retourne true + * * @return bool true si la correction a été faite */ static final function fix_static(&$func, $class): bool { if (is_object($class)) $class = get_class($class); - if (is_string($func)) { - if (substr($func, 0, 2) == "::") { - $func = "$class$func"; - return true; - } - } else { + if (is_string($func) && substr($func, 0, 2) == "::") { + $func = "$class$func"; + return true; + } elseif (is_array($func) && array_key_exists(0, $func)) { $count = count($func); if ($count == 1) { $func = [$class, $func[0]]; @@ -130,43 +73,37 @@ class func { } /** tester si $method est une chaine de la forme "->method" */ - private static function isam(&$method, bool $requireArrow=false): bool { - if (is_string($method)) { - if (substr($method, 0, 2) == "->") { - $method = substr($method, 2); - } elseif ($requireArrow) { - return false; - } - return strlen($method) > 0; - } - return false; + private static function isam($method): bool { + return is_string($method) + && strlen($method) > 2 + && substr($method, 0, 2) == "->"; } /** - * tester si $func est d'une des formes suivantes: - * - "->method" - * - ["method"] si !class_exists("method") - * - [anything, "method", ...] + * tester si $func est une chaine de la forme "->method" ou un tableau de la + * forme ["->method", ...] ou [anything, "->method", ...] */ static final function is_method($func): bool { if (is_string($func)) { - return self::isam($func, true); + return self::isam($func); } elseif (is_array($func) && array_key_exists(0, $func)) { - $count = count($func); - if ($count == 1) { - return self::isam($func[0]) && !class_exists($func[0]); - } elseif ($count > 1 && array_key_exists(1, $func)) { - return self::isam($func[1]); + if (self::isam($func[0])) { + # ["->method", ...] + return true; + } + if (array_key_exists(1, $func) && self::isam($func[1])) { + # [anything, "->method", ...] + return true; } } return false; } /** - * en assumant que {@link self::is_method()} retourne true: - * - si $func est une chaine de la forme "->method" alors la remplacer par le + * si $func est une chaine de la forme "->method" alors la remplacer par le * tableau [$object, "method"] - * - si $func est un tableau de la forme ["method"] ou [anything, "method"], + * + * si $func est un tableau de la forme ["->method"] ou [anything, "->method"], * alors le remplacer par [$object, "method"] * * @return bool true si la correction a été faite @@ -176,18 +113,14 @@ class func { if (is_string($func)) { if (self::isam($func)) { - $func = [$object, $func]; + $func = [$object, substr($func, 2)]; return true; } - } else { - $count = count($func); - if ($count == 1) { - self::isam($func[0]); - $func = [$object, $func[0]]; - return true; - } else { + } elseif (is_array($func) && array_key_exists(0, $func)) { + if (self::isam($func[0])) $func = array_merge([null], $func); + if (count($func) > 1 && array_key_exists(1, $func) && self::isam($func[1])) { $func[0] = $object; - self::isam($func[1]); + $func[1] = substr($func[1], 2); return true; } } @@ -423,32 +356,29 @@ class func { } /** - * tester si $class est d'une des formes suivantes: - * - "class" si !function_exists("class") - * - "class::" - * - ["class"] si class_exists("class") - * - ["class", null, ...] + * tester si $func est une chaine de la forme "XXX" où XXX est une classe + * valide, ou un tableau de la forme ["XXX", ...] + * + * NB: il est possible d'avoir {@link is_static()} et {@link is_class()} + * vraies pour la même valeur. s'il faut supporter les deux cas, appeler + * {@link is_static()} d'abord, mais dans ce cas, on ne supporte que les + * classes qui sont dans un package */ static final function is_class($class): bool { - if (self::is_ne($class)) { - return str::ends_with("::", $class) - || !function_exists($class); - } elseif (is_array($class) && self::is_ne($class[0] ?? null)) { - $count = count($class); - if ($count == 1) { - return class_exists($class[0]); - } elseif ($count > 1 && array_key_exists(1, $class)) { - return $class[1] === null; - } + if (is_string($class)) { + return class_exists($class); + } elseif (is_array($class) && array_key_exists(0, $class)) { + return class_exists($class[0]); } return false; } /** - * si $class est un tableau de plus de 2 éléments, alors déplacer les éléments - * supplémentaires au début de $args. par exemple: + * en assumant que {@link is_class()} est vrai, si $class est un tableau de + * plus de 1 éléments, alors déplacer les éléments supplémentaires au début de + * $args. par exemple: * ~~~ - * $class = ["class", null, "arg1", "arg2"]; + * $class = ["class", "arg1", "arg2"]; * $args = ["arg3"]; * func::fix_class_args($class, $args) * # $class === "class" @@ -460,8 +390,8 @@ class func { static final function fix_class_args(&$class, ?array &$args): bool { if ($args === null) $args = []; if (is_array($class)) { - if (count($class) > 2) { - $prefix_args = array_slice($class, 2); + if (count($class) > 1) { + $prefix_args = array_slice($class, 1); $class = array_slice($class, 0, 1)[0]; $args = array_merge($prefix_args, $args); } else {