157 lines
4.6 KiB
PHP
157 lines
4.6 KiB
PHP
<?php
|
|
namespace nur\sery\wip\php;
|
|
|
|
use Closure;
|
|
use nur\sery\cv;
|
|
|
|
/**
|
|
* Class func: outils pour appeler fonctions et méthodes dynamiquement
|
|
*
|
|
* les fonctions supportées sont:
|
|
* - fonctions simples (globales ou dans un namespace)
|
|
* - fonctions statiques
|
|
* - méthodes
|
|
* - Closure
|
|
* - constructeur (l'appel de cette "fonction" provoque l'instanciation d'un
|
|
* objet)
|
|
*
|
|
* les fonctions statiques et les méthodes peuvent être liées (associées à une
|
|
* classe ou à un objet) ou non liées (il faut les lier avant de pouvoir les
|
|
* utiliser)
|
|
*/
|
|
class func {
|
|
/**
|
|
* 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_simple(&$func, bool $strict=true): bool {
|
|
if (is_string($func)) {
|
|
$func = [false, $func];
|
|
} elseif (is_array($func)) {
|
|
if (!array_key_exists(0, $func)) return false;
|
|
if ($func[0] !== false) return false;
|
|
if (!array_key_exists(1, $func)) return false;
|
|
if (!is_string($func[1])) return false;
|
|
} else {
|
|
return false;
|
|
}
|
|
$f = $func[1];
|
|
if (strpos($f, "::") !== false) return false;
|
|
if (strpos($f, "->") !== false) return false;
|
|
if ($strict) {
|
|
if (class_exists($f)) return false;
|
|
if (!function_exists($f)) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private static function parse_class(string $cf, ?string &$c, ?string &$f): bool {
|
|
if (strpos($cf, "->") !== false) return false;
|
|
if ($cf === "::") return false;
|
|
$pos = strpos($cf, "::");
|
|
if ($pos == 0) return false; # inclus $pos === false
|
|
$c = substr($cf, 0, $pos);
|
|
$f = cv::vn(substr($cf, $pos + 2));
|
|
return true;
|
|
}
|
|
|
|
private static function parse_static(string $cf, ?string &$c, ?string &$f, ?bool &$bound): bool {
|
|
if (strpos($cf, "->") !== false) return false;
|
|
if ($cf === "::") return false;
|
|
$pos = strpos($cf, "::");
|
|
if ($pos === false) return false;
|
|
if ($pos == strlen($cf) - 2) return false;
|
|
if ($pos > 0) {
|
|
$c = substr($cf, 0, $pos);
|
|
$bound = true;
|
|
} else {
|
|
$c = null;
|
|
$bound = false;
|
|
}
|
|
$f = substr($cf, $pos + 2);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* vérifier que $func est une fonction statique, et la normaliser le cas
|
|
* échéant. retourner true si c'est une fonction statique, false sinon
|
|
*
|
|
* les formes suivantes sont supportées (XXX étant null ou n'importe quelle
|
|
* valeur scalaire de n'importe quel type)
|
|
* - "XXX::function"
|
|
* - ["XXX::function", ...$args]
|
|
* - [XXX, "::function", ...$args]
|
|
* - [XXX, "function", ...$args] c'est la forme normalisée
|
|
*
|
|
* Si XXX est une classe, la fonction statique est liée. sinon, elle doit être
|
|
* liée à une classe avant d'être utilisé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_static(&$func, bool $strict=true, ?bool &$bound=null): bool {
|
|
if (is_string($func)) {
|
|
if (!self::parse_static($func, $c, $f, $bound)) return false;
|
|
$func = [$c, $f];
|
|
} elseif (is_array($func)) {
|
|
if (!array_key_exists(0, $func)) return false;
|
|
$c = $func[0];
|
|
if (self::parse_class($c, $c, $f)) {
|
|
if ($f !== null) {
|
|
# ["class::method"]
|
|
array_splice($func, 1, 0, [$f]);
|
|
}
|
|
$bound = true;
|
|
} else {
|
|
$bound = false;
|
|
}
|
|
#
|
|
if (!array_key_exists(1, $func)) return false;
|
|
$f = $func[1];
|
|
if (!is_string($f)) return false;
|
|
if (!self::parse_static($f, $rc, $f, $rbound)) return false;
|
|
if ($rc !== null && $c === null) {
|
|
$c = $rc;
|
|
$bound = $rbound;
|
|
}
|
|
$func[0] = $c;
|
|
$func[1] = $f;
|
|
} else {
|
|
return false;
|
|
}
|
|
if ($strict && !method_exists($c, $f)) return false;
|
|
return true;
|
|
}
|
|
|
|
static function verifix_method(&$func): bool {
|
|
if (is_string($func)) {
|
|
|
|
return true;
|
|
} elseif (is_array($func)) {
|
|
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static function verifix_cons(&$func): bool {
|
|
if (is_string($func)) {
|
|
|
|
return true;
|
|
} elseif (is_array($func)) {
|
|
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
}
|