From 88c0ebf1c2b4e1ec4be43f817386cd27ca9d1c4e Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Thu, 12 Sep 2024 08:43:19 +0400 Subject: [PATCH] modifs.mineures sans commentaires --- tests/wip/php/funcTest.php | 298 +++++++++------ tests/wip/php/impl/CC.php | 15 + tests/wip/php/impl/{MyClass.php => SC.php} | 6 +- wip/php/func.php | 403 ++++++++++++++------- 4 files changed, 480 insertions(+), 242 deletions(-) create mode 100644 tests/wip/php/impl/CC.php rename tests/wip/php/impl/{MyClass.php => SC.php} (72%) diff --git a/tests/wip/php/funcTest.php b/tests/wip/php/funcTest.php index b0c2dfe..e5da71e 100644 --- a/tests/wip/php/funcTest.php +++ b/tests/wip/php/funcTest.php @@ -10,10 +10,10 @@ namespace nur\sery\wip\php\impl { namespace nur\sery\wip\php { use nulib\tests\TestCase; - use nur\sery\wip\php\impl\MyClass; + use nur\sery\wip\php\impl\SC; class funcTest extends TestCase { - const SIMPLE_TESTS = [ + const FUNCTION_TESTS = [ # scalaires [null, false, null, @@ -63,19 +63,27 @@ namespace nur\sery\wip\php { false, null, false, null, ], - [MyClass::class."::tstatic", + ["xxx::tmissing", false, null, false, null, ], - [MyClass::class."->tmethod", + ["xxx->tmissing", false, null, false, null, ], - [MyClass::class."::tmissing", + [SC::class."::tstatic", false, null, false, null, ], - [MyClass::class."->tmissing", + [SC::class."->tmethod", + false, null, + false, null, + ], + [SC::class."::tmissing", + false, null, + false, null, + ], + [SC::class."->tmissing", false, null, false, null, ], @@ -128,19 +136,27 @@ namespace nur\sery\wip\php { false, null, false, null, ], - [[MyClass::class."::tstatic"], + [["xxx::tmissing"], false, null, false, null, ], - [[MyClass::class."->tmethod"], + [["xxx->tmissing"], false, null, false, null, ], - [[MyClass::class."::tmissing"], + [[SC::class."::tstatic"], false, null, false, null, ], - [[MyClass::class."->tmissing"], + [[SC::class."->tmethod"], + false, null, + false, null, + ], + [[SC::class."::tmissing"], + false, null, + false, null, + ], + [[SC::class."->tmissing"], false, null, false, null, ], @@ -229,53 +245,68 @@ namespace nur\sery\wip\php { false, null, false, null, ], - [[MyClass::class, "tstatic"], + [["xxx", "tmissing"], false, null, false, null, ], - [[MyClass::class, "::tstatic"], + [["xxx", "::tmissing"], false, null, false, null, ], - [[MyClass::class, "tmethod"], + [["xxx", "->tmissing"], false, null, false, null, ], - [[MyClass::class, "->tmethod"], + [[SC::class, "tstatic"], false, null, false, null, ], - [[MyClass::class, "tmissing"], + [[SC::class, "::tstatic"], false, null, false, null, ], - [[MyClass::class, "::tmissing"], + [[SC::class, "tmethod"], false, null, false, null, ], - [[MyClass::class, "->tmissing"], + [[SC::class, "->tmethod"], + false, null, + false, null, + ], + [[SC::class, "tmissing"], + false, null, + false, null, + ], + [[SC::class, "::tmissing"], + false, null, + false, null, + ], + [[SC::class, "->tmissing"], false, null, false, null, ], ]; - function testSimple() { - foreach (self::SIMPLE_TESTS as $args) { + function testFunction() { + foreach (self::FUNCTION_TESTS as $args) { [$func, $verifix1, $func1, $verifix2, $func2, ] = $args; + if ($func === ["", "tsimple"]) { + //echo "breakpoint"; + } $workf = $func; $msg = var_export($func, true)." (strict)"; - self::assertSame($verifix1, func::verifix_simple($workf, true), "$msg --> verifix"); + self::assertSame($verifix1, func::verifix_function($workf, true), "$msg --> verifix"); if ($verifix1) { self::assertSame($func1, $workf, "$msg --> func"); } $workf = $func; $msg = var_export($func, true)." (lenient)"; - self::assertSame($verifix2, func::verifix_simple($workf, false), "$msg --> verifix"); + self::assertSame($verifix2, func::verifix_function($workf, false), "$msg --> verifix"); if ($verifix2) { self::assertSame($func2, $workf, "$msg --> func"); } @@ -332,19 +363,27 @@ namespace nur\sery\wip\php { false, null, null, false, null, null, ], - [MyClass::class."::tstatic", - true, true, [MyClass::class, "tstatic"], - true, true, [MyClass::class, "tstatic"], + ["xxx::tmissing", + false, null, null, + true, true, ["xxx", "tmissing"], ], - [MyClass::class."->tmethod", + ["xxx->tmissing", false, null, null, false, null, null, ], - [MyClass::class."::tmissing", - false, null, null, - true, true, [MyClass::class, "tmissing"], + [SC::class."::tstatic", + true, true, [SC::class, "tstatic"], + true, true, [SC::class, "tstatic"], ], - [MyClass::class."->tmissing", + [SC::class."->tmethod", + false, null, null, + false, null, null, + ], + [SC::class."::tmissing", + false, null, null, + true, true, [SC::class, "tmissing"], + ], + [SC::class."->tmissing", false, null, null, false, null, null, ], @@ -397,19 +436,27 @@ namespace nur\sery\wip\php { false, null, null, false, null, null, ], - [[MyClass::class."::tstatic"], - true, true, [MyClass::class, "tstatic"], - true, true, [MyClass::class, "tstatic"], + [["xxx::tmissing"], + false, null, null, + true, true, ["xxx", "tmissing"], ], - [[MyClass::class."->tmethod"], + [["xxx->tmissing"], false, null, null, false, null, null, ], - [[MyClass::class."::tmissing"], - false, null, null, - true, true, [MyClass::class, "tmissing"], + [[SC::class."::tstatic"], + true, true, [SC::class, "tstatic"], + true, true, [SC::class, "tstatic"], ], - [[MyClass::class."->tmissing"], + [[SC::class."->tmethod"], + false, null, null, + false, null, null, + ], + [[SC::class."::tmissing"], + false, null, null, + true, true, [SC::class, "tmissing"], + ], + [[SC::class."->tmissing"], false, null, null, false, null, null, ], @@ -471,58 +518,70 @@ namespace nur\sery\wip\php { false, null, null, ], [["", "tsimple"], - true, false, [null, "tsimple"], - true, false, [null, "tsimple"], + false, null, null, + false, null, null, ], [["", 'nur\sery\wip\php\impl\ntsimple'], false, null, null, false, null, null, ], [["", "tmissing"], - true, false, [null, "tmissing"], - true, false, [null, "tmissing"], + false, null, null, + false, null, null, ], [["", "::tstatic"], - true, false, [null, "tstatic"], - true, false, [null, "tstatic"], + false, null, null, + false, null, null, ], [["", "->tmethod"], false, null, null, false, null, null, ], [["", "::tmissing"], - true, false, [null, "tmissing"], - true, false, [null, "tmissing"], + false, null, null, + false, null, null, ], [["", "->tmissing"], false, null, null, false, null, null, ], - [[MyClass::class, "tstatic"], - true, true, [MyClass::class, "tstatic"], - true, true, [MyClass::class, "tstatic"], + [["xxx", "tmissing"], + false, null, null, + true, true, ["xxx", "tmissing"], ], - [[MyClass::class, "::tstatic"], - true, true, [MyClass::class, "tstatic"], - true, true, [MyClass::class, "tstatic"], + [["xxx", "::tmissing"], + false, null, null, + true, true, ["xxx", "tmissing"], ], - [[MyClass::class, "tmethod"], - true, true, [MyClass::class, "tmethod"], - true, true, [MyClass::class, "tmethod"], - ], - [[MyClass::class, "->tmethod"], + [["xxx", "->tmissing"], false, null, null, false, null, null, ], - [[MyClass::class, "tmissing"], - false, null, null, - true, true, [MyClass::class, "tmissing"], + [[SC::class, "tstatic"], + true, true, [SC::class, "tstatic"], + true, true, [SC::class, "tstatic"], ], - [[MyClass::class, "::tmissing"], - false, null, null, - true, true, [MyClass::class, "tmissing"], + [[SC::class, "::tstatic"], + true, true, [SC::class, "tstatic"], + true, true, [SC::class, "tstatic"], ], - [[MyClass::class, "->tmissing"], + [[SC::class, "tmethod"], + true, true, [SC::class, "tmethod"], + true, true, [SC::class, "tmethod"], + ], + [[SC::class, "->tmethod"], + false, null, null, + false, null, null, + ], + [[SC::class, "tmissing"], + false, null, null, + true, true, [SC::class, "tmissing"], + ], + [[SC::class, "::tmissing"], + false, null, null, + true, true, [SC::class, "tmissing"], + ], + [[SC::class, "->tmissing"], false, null, null, false, null, null, ], @@ -534,6 +593,9 @@ namespace nur\sery\wip\php { $verifix1, $bound1, $func1, $verifix2, $bound2, $func2, ] = $args; + if ($func === ["", "tsimple"]) { + //echo "breakpoint"; + } $workf = $func; $msg = var_export($func, true)." (strict)"; @@ -603,21 +665,29 @@ namespace nur\sery\wip\php { true, false, [null, "tmissing"], true, false, [null, "tmissing"], ], - [MyClass::class."::tstatic", + ["xxx::tmissing", false, null, null, false, null, null, ], - [MyClass::class."->tmethod", - true, true, [MyClass::class, "tmethod"], - true, true, [MyClass::class, "tmethod"], + ["xxx->tmissing", + false, null, null, + true, true, ["xxx", "tmissing"], ], - [MyClass::class."::tmissing", + [SC::class."::tstatic", false, null, null, false, null, null, ], - [MyClass::class."->tmissing", + [SC::class."->tmethod", + true, true, [SC::class, "tmethod"], + true, true, [SC::class, "tmethod"], + ], + [SC::class."::tmissing", false, null, null, - true, true, [MyClass::class, "tmissing"], + false, null, null, + ], + [SC::class."->tmissing", + false, null, null, + true, true, [SC::class, "tmissing"], ], # tableaux avec un seul scalaire [[], @@ -668,21 +738,29 @@ namespace nur\sery\wip\php { true, false, [null, "tmissing"], true, false, [null, "tmissing"], ], - [[MyClass::class."::tstatic"], + [["xxx::tmissing"], false, null, null, false, null, null, ], - [[MyClass::class."->tmethod"], - true, true, [MyClass::class, "tmethod"], - true, true, [MyClass::class, "tmethod"], + [["xxx->tmissing"], + false, null, null, + true, true, ["xxx", "tmissing"], ], - [[MyClass::class."::tmissing"], + [[SC::class."::tstatic"], false, null, null, false, null, null, ], - [[MyClass::class."->tmissing"], + [[SC::class."->tmethod"], + true, true, [SC::class, "tmethod"], + true, true, [SC::class, "tmethod"], + ], + [[SC::class."::tmissing"], false, null, null, - true, true, [MyClass::class, "tmissing"], + false, null, null, + ], + [[SC::class."->tmissing"], + false, null, null, + true, true, [SC::class, "tmissing"], ], # tableaux avec deux scalaires [[null, "tsimple"], @@ -742,60 +820,72 @@ namespace nur\sery\wip\php { false, null, null, ], [["", "tsimple"], - true, false, [null, "tsimple"], - true, false, [null, "tsimple"], + false, null, null, + false, null, null, ], [["", 'nur\sery\wip\php\impl\ntsimple'], false, null, null, false, null, null, ], [["", "tmissing"], - true, false, [null, "tmissing"], - true, false, [null, "tmissing"], + false, null, null, + false, null, null, ], [["", "::tstatic"], false, null, null, false, null, null, ], [["", "->tmethod"], - true, false, [null, "tmethod"], - true, false, [null, "tmethod"], + false, null, null, + false, null, null, ], [["", "::tmissing"], false, null, null, false, null, null, ], [["", "->tmissing"], - true, false, [null, "tmissing"], - true, false, [null, "tmissing"], - ], - [[MyClass::class, "tstatic"], - true, true, [MyClass::class, "tstatic"], - true, true, [MyClass::class, "tstatic"], - ], - [[MyClass::class, "::tstatic"], false, null, null, false, null, null, ], - [[MyClass::class, "tmethod"], - true, true, [MyClass::class, "tmethod"], - true, true, [MyClass::class, "tmethod"], - ], - [[MyClass::class, "->tmethod"], - true, true, [MyClass::class, "tmethod"], - true, true, [MyClass::class, "tmethod"], - ], - [[MyClass::class, "tmissing"], + [["xxx", "tmissing"], false, null, null, - true, true, [MyClass::class, "tmissing"], + true, true, ["xxx", "tmissing"], ], - [[MyClass::class, "::tmissing"], + [["xxx", "::tmissing"], false, null, null, false, null, null, ], - [[MyClass::class, "->tmissing"], + [["xxx", "->tmissing"], false, null, null, - true, true, [MyClass::class, "tmissing"], + true, true, ["xxx", "tmissing"], + ], + [[SC::class, "tstatic"], + true, true, [SC::class, "tstatic"], + true, true, [SC::class, "tstatic"], + ], + [[SC::class, "::tstatic"], + false, null, null, + false, null, null, + ], + [[SC::class, "tmethod"], + true, true, [SC::class, "tmethod"], + true, true, [SC::class, "tmethod"], + ], + [[SC::class, "->tmethod"], + true, true, [SC::class, "tmethod"], + true, true, [SC::class, "tmethod"], + ], + [[SC::class, "tmissing"], + false, null, null, + true, true, [SC::class, "tmissing"], + ], + [[SC::class, "::tmissing"], + false, null, null, + false, null, null, + ], + [[SC::class, "->tmissing"], + false, null, null, + true, true, [SC::class, "tmissing"], ], ]; diff --git a/tests/wip/php/impl/CC.php b/tests/wip/php/impl/CC.php new file mode 100644 index 0000000..defc10c --- /dev/null +++ b/tests/wip/php/impl/CC.php @@ -0,0 +1,15 @@ +") !== false) return false; - if ($strict) { - if (class_exists($f)) return false; - if (!function_exists($f)) return false; - } - return true; + private static function _is_invalid(?string $f): bool { + return $f === null || $f === "" || $f === "::" || $f === "->"; } - /** - * vérifier que $func est une fonction simple avec les règles de - * {@link self::verifix_simple()} - */ - static function is_simple($func, bool $strict=true): bool { - return self::verifix_simple($func, $strict); - } - - private static function _is_invalid(?string $m): bool { - return $m === null || $m === "" || $m === "::" || $m === "->"; - } - - private static function _is_nfunction(?string $m): bool { - return strpos($m, "\\") !== false; + private static function _is_nfunction(?string $f): bool { + return strpos($f, "\\") !== false; } private static function _parse_static(?string &$m): bool { @@ -89,6 +46,116 @@ class func { return true; } + ############################################################################# + # Fonctions + + /** + * vérifier que $func est une fonction simple et la normaliser le cas échéant. + * retourner true si c'est une fonction simple, false sinon + * + * les formes suivantes sont supportées: + * - "function" si une classe du même nom n'existe pas déjà + * - [false, "function", ...$args] c'est la forme normalisée + * + * @param bool $strict vérifier l'inexistence de la classe et l'existence de + * la fonction (ne pas uniquement faire une vérification syntaxique) + */ + static function verifix_function(&$func, bool $strict=true, ?string &$reason=null): bool { + if ($strict) { + $msg = var_export($func, true); + $reason = null; + } + if ($func instanceof ReflectionFunction) return true; + if (is_string($func)) { + $func = [false, $func]; + } elseif (is_array($func)) { + if (!array_key_exists(0, $func)) return false; + if (!array_key_exists(1, $func)) return false; + } else { + return false; + } + if ($func[0] !== false) return false; + $f = $func[1]; + if (!is_string($f)) return false; + if (self::_is_invalid($f)) return false; + if (self::_parse_static($f)) return false; + if (self::_parse_method($f)) return false; + if ($strict) { + $reason = null; + if (class_exists($f)) { + $reason = "$msg: is a class"; + return false; + } + if (!function_exists($f)) { + $reason = "$msg: function not found"; + return false; + } + } + return true; + } + + /** + * vérifier que $func est une fonction simple avec les règles de + * {@link self::verifix_function()} + */ + static function is_function($func, bool $strict=true, ?string &$reason=null): bool { + return self::verifix_function($func, $strict, $reason); + } + + ############################################################################# + # Classes + + /** + * vérifier que $func est une classe et la normaliser le cas échéant. + * retourner true si c'est une classe, false sinon + * + * les formes suivantes sont supportées: + * - "class" + * - ["class", false, ...$args] c'est la forme normalisée + * + * @param bool $strict vérifier l'existence de la classe (ne pas uniquement + * faire une vérification syntaxique) + */ + static function verifix_class(&$func, bool $strict=true, ?string &$reason=null): bool { + if ($strict) { + $msg = var_export($func, true); + $reason = null; + } + if ($func instanceof ReflectionClass) return true; + if (is_string($func)) { + $func = [$func, false]; + } elseif (is_array($func)) { + if (!array_key_exists(0, $func)) return false; + if (!array_key_exists(1, $func)) return false; + } else { + return false; + } + $c = $func[0]; + if (!is_string($c)) return false; + if (self::_is_invalid($c)) return false; + if (self::_parse_static($f)) return false; + if (self::_parse_method($f)) return false; + if ($func[1] !== false) return false; + if ($strict) { + if (!class_exists($c)) { + $reason = "$msg: class not found"; + return false; + } + } + return true; + } + + /** + * vérifier que $func est une classe avec les règles de + * {@link self::verifix_class()} + */ + static function is_class($func, bool $strict=true, ?string &$reason=null): bool { + return self::verifix_class($func, $strict, $reason); + } + + ############################################################################# + # Méthodes statiques + private static function _parse_class_s(?string $cs, ?string &$c, ?string &$s): bool { if (self::_is_invalid($cs) || self::_parse_method($cs)) return false; $pos = strpos($cs, "::"); @@ -136,7 +203,15 @@ class func { * @param bool $strict vérifier l'existence de la classe et de la méthode si * la méthode est liée (ne pas uniquement faire une vérification syntaxique) */ - static function verifix_static(&$func, bool $strict=true, ?bool &$bound=null): bool { + static function verifix_static(&$func, bool $strict=true, ?bool &$bound=null, ?string &$reason=null): bool { + if ($strict) { + $msg = var_export($func, true); + $reason = null; + } + if ($func instanceof ReflectionMethod) { + $bound = false; + return true; + } if (is_string($func)) { if (!self::_parse_c_static($func, $c, $f, $bound)) return false; $func = [$c, $f]; @@ -144,21 +219,27 @@ class func { if (!array_key_exists(0, $func)) return false; $c = $func[0]; if ($c === false) return false; - if (self::_parse_class_s($c, $c, $f)) { - $func[0] = $c; - if ($f !== null) { - # ["class::method"] --> ["class", "method"] - array_splice($func, 1, 0, [$f]); + if (is_object($c)) $c = get_class($c); + if (is_string($c)) { + if (self::_is_invalid($c)) return false; + if (self::_parse_class_s($c, $c, $f)) { + $func[0] = $c; + if ($f !== null) { + # ["class::method"] --> ["class", "method"] + array_splice($func, 1, 0, [$f]); + } + $bound = true; + } elseif (self::_parse_c_static($c, $c, $f, $bound)) { + # ["::method"] --> [null, "method"] + array_splice($func, 0, 0, [null]); + $func[1] = $f; + } else { + $func[0] = $c; + $bound = is_string($c); } - $bound = true; - } elseif (self::_parse_c_static($c, $c, $f, $bound)) { - # ["::method"] --> [null, "method"] - array_splice($func, 0, 0, [null]); - $func[1] = $f; } else { - if (self::_is_invalid($c)) $c = null; - $func[0] = $c; - $bound = is_string($c); + $func[0] = null; + $bound = false; } # if (!array_key_exists(1, $func)) return false; @@ -169,19 +250,31 @@ class func { $c = $rc; $bound = $rbound; } - } elseif (self::_is_invalid($f)) { - return false; - } elseif (self::_is_nfunction($f)) { - return false; - } elseif (self::_parse_method($f)) { - return false; - } elseif (self::_parse_static($f)) { + } else { + if (self::_is_invalid($f)) return false; + if (self::_is_nfunction($f)) return false; + if (self::_parse_method($f)) return false; + self::_parse_static($f); } $func[1] = $f; } else { return false; } - if ($strict && $bound && !method_exists($c, $f)) return false; + if ($strict) { + $reason = null; + if ($bound) { + if (!class_exists($c)) { + $reason = "$msg: class not found"; + return false; + } + if (!method_exists($c, $f)) { + $reason = "$msg: method not found"; + return false; + } + } else { + $reason = "$msg: not bound"; + } + } return true; } @@ -189,10 +282,13 @@ class func { * vérifier que $func est une méthode statique avec les règles de * {@link self::verifix_static()} */ - static function is_static($func, bool $strict=true, ?bool &$bound=null): bool { - return self::verifix_static($func, $strict, $bound); + static function is_static($func, bool $strict=true, ?bool &$bound=null, ?string &$reason=null): bool { + return self::verifix_static($func, $strict, $bound, $reason); } + ############################################################################# + # Méthodes non statiques + private static function _parse_class_m(?string $cm, ?string &$c, ?string &$m): bool { if (self::_is_invalid($cm) || self::_parse_static($cm)) return false; $pos = strpos($cm, "->"); @@ -240,7 +336,15 @@ class func { * @param bool $strict vérifier l'existence de la classe et de la méthode si * la méthode est liée (ne pas uniquement faire une vérification syntaxique) */ - static function verifix_method(&$func, bool $strict=true, ?bool &$bound=null): bool { + static function verifix_method(&$func, bool $strict=true, ?bool &$bound=null, ?string &$reason=null): bool { + if ($strict) { + $msg = var_export($func, true); + $reason = null; + } + if ($func instanceof ReflectionMethod) { + $bound = false; + return true; + } if (is_string($func)) { if (!self::_parse_c_method($func, $c, $f, $bound)) return false; $func = [$c, $f]; @@ -248,21 +352,28 @@ class func { if (!array_key_exists(0, $func)) return false; $c = $func[0]; if ($c === false) return false; - if (self::_parse_class_m($c, $c, $f)) { - $func[0] = $c; - if ($f !== null) { - # ["class->method"] --> ["class", "method"] - array_splice($func, 1, 0, [$f]); - } + if (is_object($c)) { $bound = true; - } elseif (self::_parse_c_method($c, $c, $f, $bound)) { - # ["->method"] --> [null, "method"] - array_splice($func, 0, 0, [null]); - $func[1] = $f; + } elseif (is_string($c)) { + if (self::_is_invalid($c)) return false; + if (self::_parse_class_m($c, $c, $f)) { + $func[0] = $c; + if ($f !== null) { + # ["class->method"] --> ["class", "method"] + array_splice($func, 1, 0, [$f]); + } + $bound = true; + } elseif (self::_parse_c_method($c, $c, $f, $bound)) { + # ["->method"] --> [null, "method"] + array_splice($func, 0, 0, [null]); + $func[1] = $f; + } else { + $func[0] = $c; + $bound = is_string($c); + } } else { - if (self::_is_invalid($c)) $c = null; - $func[0] = $c; - $bound = is_string($c); + $func[0] = null; + $bound = false; } # if (!array_key_exists(1, $func)) return false; @@ -273,19 +384,31 @@ class func { $c = $rc; $bound = $rbound; } - } elseif (self::_is_invalid($f)) { - return false; - } elseif (self::_is_nfunction($f)) { - return false; - } elseif (self::_parse_static($f)) { - return false; - } elseif (self::_parse_method($f)) { + } else { + if (self::_is_invalid($f)) return false; + if (self::_is_nfunction($f)) return false; + if (self::_parse_static($f)) return false; + self::_parse_method($f); } $func[1] = $f; } else { return false; } - if ($strict && $bound && !method_exists($c, $f)) return false; + if ($strict) { + $reason = null; + if ($bound) { + if (!is_object($c) && !class_exists($c)) { + $reason = "$msg: class not found"; + return false; + } + if (!method_exists($c, $f)) { + $reason = "$msg: method not found"; + return false; + } + } else { + $reason = "$msg: not bound"; + } + } return true; } @@ -293,37 +416,30 @@ class func { * vérifier que $func est une méthode non statique avec les règles de * {@link self::verifix_method()} */ - static function is_method($func, bool $strict=true, ?bool &$bound=null): bool { - return self::verifix_method($func, $strict, $bound); - } - - static function verifix_cons(&$func, bool $strict=true): bool { - if (is_string($func)) { - - } elseif (is_array($func)) { - - } else { - return false; - } - return false;#XXX + static function is_method($func, bool $strict=true, ?bool &$bound=null, ?string &$reason=null): bool { + return self::verifix_method($func, $strict, $bound, $reason); } + ############################################################################# + # func + static function with($func, bool $strict=true): self { if ($func instanceof Closure) { return new self($func); - } elseif (self::verifix_simple($func, $strict)) { + } elseif (self::verifix_function($func, $strict, $reason)) { return new self($func); - } elseif (self::verifix_cons($func, $strict)) { + } elseif (self::verifix_class($func, $strict, $reason)) { return new self($func); - } else { - if (self::verifix_static($func, $strict, $bound)) { - } elseif (self::verifix_method($func, $strict, $bound)) { - } else { - throw ValueException::invalid_type($func, "callable"); - } - if (!$bound) throw ValueException::invalid_value($func, null, "is not bound"); + } elseif (self::verifix_static($func, $strict, $bound, $reason)) { + return new self($func); + } elseif (self::verifix_method($func, $strict, $bound, $reason)) { return new self($func); } + if ($reason === null) { + $msg = var_export($func, true); + $reason = "$msg: not a callable"; + } + throw new ValueException($reason); } static function call($func, ...$args) { @@ -333,40 +449,57 @@ class func { static function with_object($func, object $object, bool $rebind=false, bool $strict=true): self { if ($func instanceof Closure) { return new self($func); - } elseif (self::verifix_simple($func, $strict)) { + } elseif (self::verifix_function($func, $strict, $reason)) { return new self($func); - } elseif (self::verifix_cons($func, $strict)) { + } elseif (self::verifix_class($func, $strict, $reason)) { return new self($func); - } else { - if (self::verifix_method($func, $strict, $bound)) { - } elseif (self::verifix_static($func, $strict, $bound)) { - } else { - throw ValueException::invalid_type($func, "callable"); - } + } elseif (self::verifix_method($func, $strict, $bound, $reason)) { + if (!$bound || $rebind) $func[0] = $object; + return new self($func); + } elseif (self::verifix_static($func, $strict, $bound, $reason)) { if (!$bound || $rebind) $func[0] = $object; return new self($func); } + if ($reason === null) { + $msg = var_export($func, true); + $reason = "$msg: not a callable"; + } + throw new ValueException($reason); + } + + static function call_object($func, $object, ...$args) { + return self::with_object($func, $object)->invoke($args); } static function with_class($func, $class, bool $rebind=false, bool $strict=true): self { if ($func instanceof Closure) { return new self($func); - } elseif (self::verifix_simple($func, $strict)) { + } elseif (self::verifix_function($func, $strict, $reason)) { return new self($func); - } elseif (self::verifix_cons($func, $strict)) { + } elseif (self::verifix_class($func, $strict, $reason)) { return new self($func); - } else { - if (self::verifix_method($func, $strict, $bound)) { - } elseif (self::verifix_static($func, $strict, $bound)) { - } else { - throw ValueException::invalid_type($func, "callable"); + } elseif (self::verifix_method($func, $strict, $bound, $reason)) { + if (!$bound || $rebind) { + if (is_object($class)) $class = get_class($class); + $func[0] = $class; } + return new self($func); + } elseif (self::verifix_static($func, $strict, $bound, $reason)) { if (!$bound || $rebind) { if (is_object($class)) $class = get_class($class); $func[0] = $class; } return new self($func); } + if ($reason === null) { + $msg = var_export($func, true); + $reason = "$msg: not a callable"; + } + throw new ValueException($reason); + } + + static function call_class($func, $class, ...$args) { + return self::with_class($func, $class)->invoke($args); } ############################################################################# @@ -378,8 +511,8 @@ class func { $prefixArgs = []; if ($func instanceof Closure) { $type = self::TYPE_CLOSURE; - $reflection = new ReflectionFunction($func); $object = $func; + $reflection = new ReflectionFunction($func); } elseif ($func instanceof ReflectionFunction) { $type = self::TYPE_SIMPLE; $reflection = $func;