modifs.mineures sans commentaires
This commit is contained in:
parent
a5d1485ecf
commit
b4de22cc74
|
@ -6,6 +6,8 @@
|
||||||
<sourceFolder url="file://$MODULE_DIR$/php/tests" isTestSource="true" packagePrefix="nulib\" />
|
<sourceFolder url="file://$MODULE_DIR$/php/tests" isTestSource="true" packagePrefix="nulib\" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/php/src_output" isTestSource="false" packagePrefix="nulib\output\" />
|
<sourceFolder url="file://$MODULE_DIR$/php/src_output" isTestSource="false" packagePrefix="nulib\output\" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/php/src_web" isTestSource="false" packagePrefix="nulib\web\" />
|
<sourceFolder url="file://$MODULE_DIR$/php/src_web" isTestSource="false" packagePrefix="nulib\web\" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/php/src_ref" isTestSource="false" packagePrefix="nulib\ref\" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/php/src_sys" isTestSource="false" packagePrefix="nulib\sys\" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/vendor" />
|
<excludeFolder url="file://$MODULE_DIR$/vendor" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"nulib\\": "php/src_base",
|
"nulib\\": "php/src_base",
|
||||||
|
"nulib\\ref\\": "php/src_ref",
|
||||||
|
"nulib\\sys\\": "php/src_sys",
|
||||||
"nulib\\output\\": "php/src_output",
|
"nulib\\output\\": "php/src_output",
|
||||||
"nulib\\web\\": "php/src_web"
|
"nulib\\web\\": "php/src_web"
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
namespace nulib\ref\sys;
|
||||||
|
|
||||||
|
class ref_func {
|
||||||
|
const CALL_ALL_PARAMS_SCHEMA = [
|
||||||
|
"prefix" => ["string", null, "Ne sélectionner que les méthode dont le nom commence par ce préfixe"],
|
||||||
|
"args" => ["?array", null, "Arguments avec lesquels appeler les méthodes"],
|
||||||
|
"static_only" => ["bool", false, "N'appeler que les méthodes statiques si un objet est spécifié"],
|
||||||
|
"include" => ["?array", null, "N'inclure que les méthodes dont le nom correspond à ce motif, qui peut être une sous-chaine ou une expression régulière"],
|
||||||
|
"exclude" => ["?array", null, "Exclure les méthodes dont le nom correspond à ce motif, qui peut être une sous-chaine ou une expression régulière"],
|
||||||
|
];
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
# nulib\sys
|
||||||
|
|
||||||
|
Ce package contient des services généraux spécifiques à PHP
|
||||||
|
|
||||||
|
-*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary
|
|
@ -0,0 +1,430 @@
|
||||||
|
<?php
|
||||||
|
namespace nulib\sys;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use nulib\cl;
|
||||||
|
use nulib\ValueException;
|
||||||
|
use nur\sery\ref\sys\ref_func;
|
||||||
|
use nur\sery\schema\Schema;
|
||||||
|
use ReflectionClass;
|
||||||
|
use ReflectionFunction;
|
||||||
|
use ReflectionMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class func: outils pour appeler des fonctions et méthodes dynamiquement
|
||||||
|
*/
|
||||||
|
class 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", ...]
|
||||||
|
*/
|
||||||
|
static final function is_static($func): bool {
|
||||||
|
if (is_string($func)) {
|
||||||
|
$pos = strpos($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 is_string($func[0]) && strlen($func[0]) > 0;
|
||||||
|
} elseif ($count > 1) {
|
||||||
|
if (!array_key_exists(1, $func)) return false;
|
||||||
|
return is_string($func[1]) && strlen($func[1]) > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* 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) && 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]];
|
||||||
|
return true;
|
||||||
|
} elseif ($count > 1 && $func[0] === null) {
|
||||||
|
$func[0] = $class;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** tester si $method est une chaine de la forme "->method" */
|
||||||
|
private static function isam($method): bool {
|
||||||
|
return is_string($method)
|
||||||
|
&& strlen($method) > 2
|
||||||
|
&& substr($method, 0, 2) == "->";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
} elseif (is_array($func) && array_key_exists(0, $func)) {
|
||||||
|
if (self::isam($func[0])) {
|
||||||
|
# ["->method", ...]
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (array_key_exists(1, $func) && self::isam($func[1])) {
|
||||||
|
# [anything, "->method", ...]
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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"],
|
||||||
|
* alors le remplacer par [$object, "method"]
|
||||||
|
*
|
||||||
|
* @return bool true si la correction a été faite
|
||||||
|
*/
|
||||||
|
static final function fix_method(&$func, $object): bool {
|
||||||
|
if (!is_object($object)) return false;
|
||||||
|
|
||||||
|
if (is_string($func)) {
|
||||||
|
if (self::isam($func)) {
|
||||||
|
$func = [$object, substr($func, 2)];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} 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;
|
||||||
|
$func[1] = substr($func[1], 2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* si $func est un tableau de plus de 2 éléments, alors déplacer les éléments
|
||||||
|
* supplémentaires au début de $args. par exemple:
|
||||||
|
* ~~~
|
||||||
|
* $func = ["class", "method", "arg1", "arg2"];
|
||||||
|
* $args = ["arg3"];
|
||||||
|
* func::fix_args($func, $args)
|
||||||
|
* # $func === ["class", "method"]
|
||||||
|
* # $args === ["arg1", "arg2", "arg3"]
|
||||||
|
* ~~~
|
||||||
|
*
|
||||||
|
* @return bool true si la correction a été faite
|
||||||
|
*/
|
||||||
|
static final function fix_args(&$func, ?array &$args): bool {
|
||||||
|
if ($args === null) $args = [];
|
||||||
|
if (is_array($func) && count($func) > 2) {
|
||||||
|
$prefix_args = array_slice($func, 2);
|
||||||
|
$func = array_slice($func, 0, 2);
|
||||||
|
$args = array_merge($prefix_args, $args);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* s'assurer que $func est un appel de méthode ou d'une méthode statique;
|
||||||
|
* et renseigner le cas échéant les arguments. si $func ne fait pas mention
|
||||||
|
* de la classe ou de l'objet, le renseigner avec $class_or_object.
|
||||||
|
*
|
||||||
|
* @return bool true si c'est une fonction valide. il ne reste plus qu'à
|
||||||
|
* l'appeler avec {@link call()}
|
||||||
|
*/
|
||||||
|
static final function check_func(&$func, $class_or_object, &$args=null): bool {
|
||||||
|
if ($func instanceof Closure) return true;
|
||||||
|
if (self::is_method($func)) {
|
||||||
|
# méthode
|
||||||
|
self::fix_method($func, $class_or_object);
|
||||||
|
self::fix_args($func, $args);
|
||||||
|
return true;
|
||||||
|
} elseif (self::is_static($func)) {
|
||||||
|
# méthode statique
|
||||||
|
self::fix_static($func, $class_or_object);
|
||||||
|
self::fix_args($func, $args);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comme {@link check_func()} mais lance une exception si la fonction est
|
||||||
|
* invalide
|
||||||
|
*
|
||||||
|
* @throws ValueException si $func n'est pas une fonction ou une méthode valide
|
||||||
|
*/
|
||||||
|
static final function ensure_func(&$func, $class_or_object, &$args=null): void {
|
||||||
|
if (!self::check_func($func, $class_or_object, $args)) {
|
||||||
|
throw ValueException::invalid_type($func, "callable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final function _prepare($func): array {
|
||||||
|
$object = null;
|
||||||
|
if (is_callable($func)) {
|
||||||
|
if (is_array($func)) {
|
||||||
|
$rf = new ReflectionMethod(...$func);
|
||||||
|
$object = $func[0];
|
||||||
|
if (is_string($object)) $object = null;
|
||||||
|
} elseif ($func instanceof Closure) {
|
||||||
|
$rf = new ReflectionFunction($func);
|
||||||
|
} elseif (is_string($func) && strpos($func, "::") === false) {
|
||||||
|
$rf = new ReflectionFunction($func);
|
||||||
|
} else {
|
||||||
|
$rf = new ReflectionMethod($func);
|
||||||
|
}
|
||||||
|
} elseif ($func instanceof ReflectionMethod) {
|
||||||
|
$rf = $func;
|
||||||
|
} elseif ($func instanceof ReflectionFunction) {
|
||||||
|
$rf = $func;
|
||||||
|
} elseif (is_array($func) && count($func) == 2 && isset($func[0]) && isset($func[1])
|
||||||
|
&& ($func[1] instanceof ReflectionMethod || $func[1] instanceof ReflectionFunction)) {
|
||||||
|
$object = $func[0];
|
||||||
|
if (is_string($object)) $object = null;
|
||||||
|
$rf = $func[1];
|
||||||
|
} elseif (is_string($func) && strpos($func, "::") === false) {
|
||||||
|
$rf = new ReflectionFunction($func);
|
||||||
|
} else {
|
||||||
|
throw ValueException::invalid_type($func, "callable");
|
||||||
|
}
|
||||||
|
$minArgs = $rf->getNumberOfRequiredParameters();
|
||||||
|
$maxArgs = $rf->getNumberOfParameters();
|
||||||
|
$variadic = $rf->isVariadic();
|
||||||
|
return [$rf instanceof ReflectionMethod, $object, $rf, $minArgs, $maxArgs, $variadic];
|
||||||
|
}
|
||||||
|
|
||||||
|
static final function _fill(array $context, array &$args): void {
|
||||||
|
$minArgs = $context[3];
|
||||||
|
$maxArgs = $context[4];
|
||||||
|
$variadic = $context[5];
|
||||||
|
if (!$variadic) $args = array_slice($args, 0, $maxArgs);
|
||||||
|
while (count($args) < $minArgs) $args[] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final function _call($context, array $args) {
|
||||||
|
self::_fill($context, $args);
|
||||||
|
$use_object = $context[0];
|
||||||
|
$object = $context[1];
|
||||||
|
$method = $context[2];
|
||||||
|
if ($use_object) {
|
||||||
|
if (count($args) === 0) return $method->invoke($object);
|
||||||
|
else return $method->invokeArgs($object, $args);
|
||||||
|
} else {
|
||||||
|
if (count($args) === 0) return $method->invoke();
|
||||||
|
else return $method->invokeArgs($args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appeler la fonction spécifiée avec les arguments spécifiés.
|
||||||
|
* Adapter $args en fonction du nombre réel d'arguments de $func
|
||||||
|
*
|
||||||
|
* @param callable|ReflectionFunction|ReflectionMethod $func
|
||||||
|
*/
|
||||||
|
static final function call($func, ...$args) {
|
||||||
|
return self::_call(self::_prepare($func), $args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** remplacer $value par $func($value, ...$args) */
|
||||||
|
static final function apply(&$value, $func, ...$args): void {
|
||||||
|
if ($func !== null) {
|
||||||
|
if ($args) $args = array_merge([$value], $args);
|
||||||
|
else $args = [$value];
|
||||||
|
$value = self::call($func, ...$args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const MASK_PS = ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_STATIC;
|
||||||
|
const MASK_P = ReflectionMethod::IS_PUBLIC;
|
||||||
|
const METHOD_PS = ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_STATIC;
|
||||||
|
const METHOD_P = ReflectionMethod::IS_PUBLIC;
|
||||||
|
|
||||||
|
private static final function matches(string $name, array $includes, array $excludes): bool {
|
||||||
|
if ($includes) {
|
||||||
|
$matches = false;
|
||||||
|
foreach ($includes as $include) {
|
||||||
|
if (substr($include, 0, 1) == "/") {
|
||||||
|
# expression régulière
|
||||||
|
if (preg_match($include, $name)) {
|
||||||
|
$matches = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
# tester la présence de la sous-chaine
|
||||||
|
if (strpos($name, $include) !== false) {
|
||||||
|
$matches = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$matches) return false;
|
||||||
|
}
|
||||||
|
foreach ($excludes as $exclude) {
|
||||||
|
if (substr($exclude, 0, 1) == "/") {
|
||||||
|
# expression régulière
|
||||||
|
if (preg_match($exclude, $name)) return false;
|
||||||
|
} else {
|
||||||
|
# tester la présence de la sous-chaine
|
||||||
|
if (strpos($name, $exclude) !== false) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retourner la liste des méthodes de $class_or_object qui correspondent au
|
||||||
|
* filtre $options. le filtre doit respecter le schéme {@link CALL_ALL_PARAMS_SCHEMA}
|
||||||
|
*/
|
||||||
|
static function get_all($class_or_object, $params=null): array {
|
||||||
|
Schema::nv($paramsv, $params, null, $schema, ref_func::CALL_ALL_PARAMS_SCHEMA);
|
||||||
|
if (is_callable($class_or_object, true) && is_array($class_or_object)) {
|
||||||
|
# callable sous forme de tableau
|
||||||
|
$class_or_object = $class_or_object[0];
|
||||||
|
}
|
||||||
|
if (is_string($class_or_object)) {
|
||||||
|
# lister les méthodes publiques statiques de la classe
|
||||||
|
$mask = self::MASK_PS;
|
||||||
|
$expected = self::METHOD_PS;
|
||||||
|
$c = new ReflectionClass($class_or_object);
|
||||||
|
} elseif (is_object($class_or_object)) {
|
||||||
|
# lister les méthodes publiques de la classe
|
||||||
|
$c = new ReflectionClass($class_or_object);
|
||||||
|
$mask = $params["static_only"]? self::MASK_PS: self::MASK_P;
|
||||||
|
$expected = $params["static_only"]? self::METHOD_PS: self::METHOD_P;
|
||||||
|
} else {
|
||||||
|
throw new ValueException("$class_or_object: vous devez spécifier une classe ou un objet");
|
||||||
|
}
|
||||||
|
$prefix = $params["prefix"]; $prefixlen = strlen($prefix);
|
||||||
|
$args = $params["args"];
|
||||||
|
$includes = $params["include"];
|
||||||
|
$excludes = $params["exclude"];
|
||||||
|
$methods = [];
|
||||||
|
foreach ($c->getMethods() as $m) {
|
||||||
|
if (($m->getModifiers() & $mask) != $expected) continue;
|
||||||
|
$name = $m->getName();
|
||||||
|
if (substr($name, 0, $prefixlen) != $prefix) continue;
|
||||||
|
if (!self::matches($name, $includes, $excludes)) continue;
|
||||||
|
$methods[] = cl::merge([$class_or_object, $name], $args);
|
||||||
|
}
|
||||||
|
return $methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appeler toutes les méthodes publiques de $object_or_class et retourner un
|
||||||
|
* tableau [$method_name => $return_value] des valeurs de retour.
|
||||||
|
*/
|
||||||
|
static final function call_all($class_or_object, $params=null): array {
|
||||||
|
$methods = self::get_all($class_or_object, $params);
|
||||||
|
$values = [];
|
||||||
|
foreach ($methods as $method) {
|
||||||
|
self::fix_args($method, $args);
|
||||||
|
$values[$method[1]] = self::call($method, ...$args);
|
||||||
|
}
|
||||||
|
return $values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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_class()} d'abord
|
||||||
|
*/
|
||||||
|
static final function is_class($class): bool {
|
||||||
|
if (is_string($class)) {
|
||||||
|
return class_exists($class);
|
||||||
|
} elseif (is_array($class) && array_key_exists(0, $class)) {
|
||||||
|
return class_exists($class[0]);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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", "arg1", "arg2"];
|
||||||
|
* $args = ["arg3"];
|
||||||
|
* func::fix_class_args($class, $args)
|
||||||
|
* # $class === "class"
|
||||||
|
* # $args === ["arg1", "arg2", "arg3"]
|
||||||
|
* ~~~
|
||||||
|
*
|
||||||
|
* @return bool true si la correction a été faite
|
||||||
|
*/
|
||||||
|
static final function fix_class_args(&$class, ?array &$args): bool {
|
||||||
|
if ($args === null) $args = [];
|
||||||
|
if (is_array($class)) {
|
||||||
|
if (count($class) > 1) {
|
||||||
|
$prefix_args = array_slice($class, 1);
|
||||||
|
$class = array_slice($class, 0, 1)[0];
|
||||||
|
$args = array_merge($prefix_args, $args);
|
||||||
|
} else {
|
||||||
|
$class = $class[0];
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* s'assurer que $class est une classe et renseigner le cas échéant les
|
||||||
|
* arguments.
|
||||||
|
*
|
||||||
|
* @return bool true si c'est une classe valide. il ne reste plus qu'à
|
||||||
|
* l'instancier avec {@link cons()}
|
||||||
|
*/
|
||||||
|
static final function check_class(&$class, &$args=null): bool {
|
||||||
|
if (self::is_class($class)) {
|
||||||
|
self::fix_class_args($class, $args);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instancier la classe avec les arguments spécifiés.
|
||||||
|
* Adapter $args en fonction du nombre réel d'arguments du constructeur
|
||||||
|
*/
|
||||||
|
static final function cons(string $class, ...$args) {
|
||||||
|
$c = new ReflectionClass($class);
|
||||||
|
$rf = $c->getConstructor();
|
||||||
|
if ($rf === null) {
|
||||||
|
return $c->newInstance();
|
||||||
|
} else {
|
||||||
|
if (!$rf->isVariadic()) {
|
||||||
|
$minArgs = $rf->getNumberOfRequiredParameters();
|
||||||
|
$maxArgs = $rf->getNumberOfParameters();
|
||||||
|
$args = array_slice($args, 0, $maxArgs);
|
||||||
|
while (count($args) < $minArgs) {
|
||||||
|
$args[] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $c->newInstanceArgs($args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,247 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
function func36() {
|
||||||
|
return 36;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace nulib\sys {
|
||||||
|
use nulib\tests\TestCase;
|
||||||
|
|
||||||
|
class funcTest extends TestCase {
|
||||||
|
function testIs_static() {
|
||||||
|
self::assertFalse(func::is_static(null));
|
||||||
|
self::assertFalse(func::is_static(""));
|
||||||
|
self::assertFalse(func::is_static("::"));
|
||||||
|
self::assertFalse(func::is_static("xxx::"));
|
||||||
|
self::assertTrue(func::is_static("::xxx"));
|
||||||
|
self::assertFalse(func::is_static([]));
|
||||||
|
self::assertFalse(func::is_static([""]));
|
||||||
|
self::assertTrue(func::is_static(["xxx"]));
|
||||||
|
self::assertFalse(func::is_static([null, ""]));
|
||||||
|
self::assertTrue(func::is_static([null, "yyy"]));
|
||||||
|
self::assertFalse(func::is_static(["xxx", ""]));
|
||||||
|
self::assertTrue(func::is_static(["xxx", "yyy"]));
|
||||||
|
self::assertTrue(func::is_static([null, "yyy", "aaa"]));
|
||||||
|
self::assertTrue(func::is_static(["xxx", "yyy", "aaa"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testFix_static() {
|
||||||
|
$class = "class";
|
||||||
|
$func = null;
|
||||||
|
func::fix_static($func, $class);
|
||||||
|
self::assertSame(null, $func);
|
||||||
|
$func = "";
|
||||||
|
func::fix_static($func, $class);
|
||||||
|
self::assertSame("", $func);
|
||||||
|
$func = "::";
|
||||||
|
func::fix_static($func, $class);
|
||||||
|
self::assertSame("class::", $func);
|
||||||
|
$func = "xxx::";
|
||||||
|
func::fix_static($func, $class);
|
||||||
|
self::assertSame("xxx::", $func);
|
||||||
|
$func = "::xxx";
|
||||||
|
func::fix_static($func, $class);
|
||||||
|
self::assertSame("class::xxx", $func);
|
||||||
|
$func = [];
|
||||||
|
func::fix_static($func, $class);
|
||||||
|
self::assertSame([], $func);
|
||||||
|
$func = [""];
|
||||||
|
func::fix_static($func, $class);
|
||||||
|
self::assertSame(["class", ""], $func);
|
||||||
|
$func = ["xxx"];
|
||||||
|
func::fix_static($func, $class);
|
||||||
|
self::assertSame(["class", "xxx"], $func);
|
||||||
|
$func = ["xxx", ""];
|
||||||
|
func::fix_static($func, $class);
|
||||||
|
self::assertSame(["xxx", ""], $func);
|
||||||
|
$func = [null, "yyy"];
|
||||||
|
func::fix_static($func, $class);
|
||||||
|
self::assertSame(["class", "yyy"], $func);
|
||||||
|
$func = ["xxx", "yyy"];
|
||||||
|
func::fix_static($func, $class);
|
||||||
|
self::assertSame(["xxx", "yyy"], $func);
|
||||||
|
$func = [null, "yyy", "aaa"];
|
||||||
|
func::fix_static($func, $class);
|
||||||
|
self::assertSame(["class", "yyy", "aaa"], $func);
|
||||||
|
$func = ["xxx", "yyy", "aaa"];
|
||||||
|
func::fix_static($func, $class);
|
||||||
|
self::assertSame(["xxx", "yyy", "aaa"], $func);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testIs_method() {
|
||||||
|
self::assertFalse(func::is_method(null));
|
||||||
|
self::assertFalse(func::is_method(""));
|
||||||
|
self::assertFalse(func::is_method("->"));
|
||||||
|
self::assertTrue(func::is_method("->xxx"));
|
||||||
|
self::assertFalse(func::is_method([]));
|
||||||
|
self::assertFalse(func::is_method([""]));
|
||||||
|
self::assertTrue(func::is_method(["->xxx"]));
|
||||||
|
self::assertTrue(func::is_method(["->xxx", "aaa"]));
|
||||||
|
self::assertFalse(func::is_method([null, "->"]));
|
||||||
|
self::assertTrue(func::is_method([null, "->yyy"]));
|
||||||
|
self::assertFalse(func::is_method(["xxx", "->"]));
|
||||||
|
self::assertTrue(func::is_method(["xxx", "->yyy"]));
|
||||||
|
self::assertTrue(func::is_method([null, "->yyy", "aaa"]));
|
||||||
|
self::assertTrue(func::is_method(["xxx", "->yyy", "aaa"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testFix_method() {
|
||||||
|
$object = new \stdClass();
|
||||||
|
$func= null;
|
||||||
|
func::fix_method($func, $object);
|
||||||
|
self::assertSame(null, $func);
|
||||||
|
$func= "";
|
||||||
|
func::fix_method($func, $object);
|
||||||
|
self::assertSame("", $func);
|
||||||
|
$func= "->";
|
||||||
|
func::fix_method($func, $object);
|
||||||
|
self::assertSame("->", $func);
|
||||||
|
$func= "->xxx";
|
||||||
|
func::fix_method($func, $object);
|
||||||
|
self::assertSame([$object, "xxx"], $func);
|
||||||
|
$func= [];
|
||||||
|
func::fix_method($func, $object);
|
||||||
|
self::assertSame([], $func);
|
||||||
|
$func= [""];
|
||||||
|
func::fix_method($func, $object);
|
||||||
|
self::assertSame([""], $func);
|
||||||
|
$func= ["->xxx"];
|
||||||
|
func::fix_method($func, $object);
|
||||||
|
self::assertSame([$object, "xxx"], $func);
|
||||||
|
$func= ["->xxx", "aaa"];
|
||||||
|
func::fix_method($func, $object);
|
||||||
|
self::assertSame([$object, "xxx", "aaa"], $func);
|
||||||
|
$func= [null, "->"];
|
||||||
|
func::fix_method($func, $object);
|
||||||
|
self::assertSame([null, "->"], $func);
|
||||||
|
$func= [null, "->yyy"];
|
||||||
|
func::fix_method($func, $object);
|
||||||
|
self::assertSame([$object, "yyy"], $func);
|
||||||
|
$func= ["xxx", "->"];
|
||||||
|
func::fix_method($func, $object);
|
||||||
|
self::assertSame(["xxx", "->"], $func);
|
||||||
|
$func= ["xxx", "->yyy"];
|
||||||
|
func::fix_method($func, $object);
|
||||||
|
self::assertSame([$object, "yyy"], $func);
|
||||||
|
$func= [null, "->yyy", "aaa"];
|
||||||
|
func::fix_method($func, $object);
|
||||||
|
self::assertSame([$object, "yyy", "aaa"], $func);
|
||||||
|
$func= ["xxx", "->yyy", "aaa"];
|
||||||
|
func::fix_method($func, $object);
|
||||||
|
self::assertSame([$object, "yyy", "aaa"], $func);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testCall() {
|
||||||
|
self::assertSame(36, func::call("func36"));
|
||||||
|
self::assertSame(12, func::call(TC::class."::method"));
|
||||||
|
self::assertSame(12, func::call([TC::class, "method"]));
|
||||||
|
$closure = function() {
|
||||||
|
return 21;
|
||||||
|
};
|
||||||
|
self::assertSame(21, func::call($closure));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testCall_all() {
|
||||||
|
$c1 = new C1();
|
||||||
|
$c2 = new C2();
|
||||||
|
$c3 = new C3();
|
||||||
|
|
||||||
|
self::assertSameValues([11, 12], func::call_all(C1::class));
|
||||||
|
self::assertSameValues([11, 12, 21, 22], func::call_all($c1));
|
||||||
|
self::assertSameValues([13, 11, 12], func::call_all(C2::class));
|
||||||
|
self::assertSameValues([13, 23, 11, 12, 21, 22], func::call_all($c2));
|
||||||
|
self::assertSameValues([111, 13, 12], func::call_all(C3::class));
|
||||||
|
self::assertSameValues([111, 121, 13, 23, 12, 22], func::call_all($c3));
|
||||||
|
|
||||||
|
$options = "conf";
|
||||||
|
self::assertSameValues([11], func::call_all(C1::class, $options));
|
||||||
|
self::assertSameValues([11, 21], func::call_all($c1, $options));
|
||||||
|
self::assertSameValues([11], func::call_all(C2::class, $options));
|
||||||
|
self::assertSameValues([11, 21], func::call_all($c2, $options));
|
||||||
|
self::assertSameValues([111], func::call_all(C3::class, $options));
|
||||||
|
self::assertSameValues([111, 121], func::call_all($c3, $options));
|
||||||
|
|
||||||
|
$options = ["prefix" => "conf"];
|
||||||
|
self::assertSameValues([11], func::call_all(C1::class, $options));
|
||||||
|
self::assertSameValues([11, 21], func::call_all($c1, $options));
|
||||||
|
self::assertSameValues([11], func::call_all(C2::class, $options));
|
||||||
|
self::assertSameValues([11, 21], func::call_all($c2, $options));
|
||||||
|
self::assertSameValues([111], func::call_all(C3::class, $options));
|
||||||
|
self::assertSameValues([111, 121], func::call_all($c3, $options));
|
||||||
|
|
||||||
|
self::assertSameValues([11, 12], func::call_all($c1, ["include" => "x"]));
|
||||||
|
self::assertSameValues([11, 21], func::call_all($c1, ["include" => "y"]));
|
||||||
|
self::assertSameValues([11, 12, 21], func::call_all($c1, ["include" => ["x", "y"]]));
|
||||||
|
|
||||||
|
self::assertSameValues([21, 22], func::call_all($c1, ["exclude" => "x"]));
|
||||||
|
self::assertSameValues([12, 22], func::call_all($c1, ["exclude" => "y"]));
|
||||||
|
self::assertSameValues([22], func::call_all($c1, ["exclude" => ["x", "y"]]));
|
||||||
|
|
||||||
|
self::assertSameValues([12], func::call_all($c1, ["include" => "x", "exclude" => "y"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testCons() {
|
||||||
|
$obj1 = func::cons(WoCons::class, 1, 2, 3);
|
||||||
|
self::assertInstanceOf(WoCons::class, $obj1);
|
||||||
|
|
||||||
|
$obj2 = func::cons(WithEmptyCons::class, 1, 2, 3);
|
||||||
|
self::assertInstanceOf(WithEmptyCons::class, $obj2);
|
||||||
|
|
||||||
|
$obj3 = func::cons(WithCons::class, 1, 2, 3);
|
||||||
|
self::assertInstanceOf(WithCons::class, $obj3);
|
||||||
|
self::assertSame(1, $obj3->first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WoCons {
|
||||||
|
}
|
||||||
|
class WithEmptyCons {
|
||||||
|
function __construct() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class WithCons {
|
||||||
|
public $first;
|
||||||
|
function __construct($first) {
|
||||||
|
$this->first = $first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TC {
|
||||||
|
static function method() {
|
||||||
|
return 12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class C1 {
|
||||||
|
static function confps1_xy() {
|
||||||
|
return 11;
|
||||||
|
}
|
||||||
|
static function ps2_x() {
|
||||||
|
return 12;
|
||||||
|
}
|
||||||
|
function confp1_y() {
|
||||||
|
return 21;
|
||||||
|
}
|
||||||
|
function p2() {
|
||||||
|
return 22;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class C2 extends C1 {
|
||||||
|
static function ps3() {
|
||||||
|
return 13;
|
||||||
|
}
|
||||||
|
function p3() {
|
||||||
|
return 23;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class C3 extends C2 {
|
||||||
|
static function confps1_xy() {
|
||||||
|
return 111;
|
||||||
|
}
|
||||||
|
function confp1_y() {
|
||||||
|
return 121;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue