modifs.mineures sans commentaires
This commit is contained in:
		
							parent
							
								
									afb6581b06
								
							
						
					
					
						commit
						97d7d1260a
					
				
							
								
								
									
										26
									
								
								bbnurse
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								bbnurse
									
									
									
									
									
								
							@ -37,9 +37,11 @@ function copy_mature() {
 | 
				
			|||||||
        srcdir="$MYDIR/src/$src"
 | 
					        srcdir="$MYDIR/src/$src"
 | 
				
			||||||
        path="$src"
 | 
					        path="$src"
 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
 | 
					    tsrcdir=
 | 
				
			||||||
    if [ -n "$path" ]; then
 | 
					    if [ -n "$path" ]; then
 | 
				
			||||||
        srcpackage="nur/sery/$path"; srcpackage="${srcpackage//\//\\}"
 | 
					        srcpackage="nur/sery/$path"; srcpackage="${srcpackage//\//\\}"
 | 
				
			||||||
        destpackage="nulib/$path"; destpackage="${destpackage//\//\\}"
 | 
					        destpackage="nulib/$path"; destpackage="${destpackage//\//\\}"
 | 
				
			||||||
 | 
					        [ -d "$MYDIR/tests/$path" ] && tsrcdir="$MYDIR/tests/$path"
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        srcpackage='nur\sery'
 | 
					        srcpackage='nur\sery'
 | 
				
			||||||
        destpackage='nulib'
 | 
					        destpackage='nulib'
 | 
				
			||||||
@ -59,10 +61,15 @@ function copy_mature() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    case "$libname" in
 | 
					    case "$libname" in
 | 
				
			||||||
    nulib)
 | 
					    nulib)
 | 
				
			||||||
        if [ -n "$path" ]; then
 | 
					        if [[ "$path" == */* ]]; then
 | 
				
			||||||
            destdir="$libdir/php/src_${path%%/*}"
 | 
					            destdir="$libdir/php/src_${path%%/*}/${path#*/}"
 | 
				
			||||||
 | 
					            [ -n "$tsrcdir" ] && tdestdir="$libdir/php/tests/$path"
 | 
				
			||||||
 | 
					        elif [ -n "$path" ]; then
 | 
				
			||||||
 | 
					            destdir="$libdir/php/src_$path"
 | 
				
			||||||
 | 
					            [ -n "$tsrcdir" ] && tdestdir="$libdir/php/tests/$path"
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            destdir="$libdir/php/src_base"
 | 
					            destdir="$libdir/php/src_base"
 | 
				
			||||||
 | 
					            [ -n "$tsrcdir" ] && tdestdir="$libdir/php/tests"
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if [ -n "$class" ]; then
 | 
					        if [ -n "$class" ]; then
 | 
				
			||||||
@ -70,9 +77,8 @@ function copy_mature() {
 | 
				
			|||||||
            die "TODO"
 | 
					            die "TODO"
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            # Maturation de toute un package
 | 
					            # Maturation de toute un package
 | 
				
			||||||
            pwd #XXX
 | 
					            etitle "Maturation de $srcpackage vers $destpackage"
 | 
				
			||||||
            einfo "$srcdir --> $destdir"
 | 
					            einfo "$srcdir --> $destdir"
 | 
				
			||||||
            einfo "Maturation de $srcpackage vers $destpackage"
 | 
					 | 
				
			||||||
            setx -a srcs=find "$srcdir" -type f
 | 
					            setx -a srcs=find "$srcdir" -type f
 | 
				
			||||||
            for src in "${srcs[@]}"; do
 | 
					            for src in "${srcs[@]}"; do
 | 
				
			||||||
                srcname="${src#$srcdir/}"
 | 
					                srcname="${src#$srcdir/}"
 | 
				
			||||||
@ -81,6 +87,18 @@ function copy_mature() {
 | 
				
			|||||||
                mkdirof "$dest"
 | 
					                mkdirof "$dest"
 | 
				
			||||||
                sed "s|${srcpackage//\\/\\\\}|${destpackage//\\/\\\\}|g" <"$src" >"$dest"
 | 
					                sed "s|${srcpackage//\\/\\\\}|${destpackage//\\/\\\\}|g" <"$src" >"$dest"
 | 
				
			||||||
            done
 | 
					            done
 | 
				
			||||||
 | 
					            if [ -n "$tsrcdir" ]; then
 | 
				
			||||||
 | 
					                einfo "$tsrcdir --> $tdestdir"
 | 
				
			||||||
 | 
					                setx -a srcs=find "$tsrcdir" -type f
 | 
				
			||||||
 | 
					                for src in "${srcs[@]}"; do
 | 
				
			||||||
 | 
					                    srcname="${src#$tsrcdir/}"
 | 
				
			||||||
 | 
					                    dest="$tdestdir/$srcname"
 | 
				
			||||||
 | 
					                    estep "${src#$tsrcdir/}"
 | 
				
			||||||
 | 
					                    mkdirof "$dest"
 | 
				
			||||||
 | 
					                    sed "s|${srcpackage//\\/\\\\}|${destpackage//\\/\\\\}|g" <"$src" >"$dest"
 | 
				
			||||||
 | 
					                done
 | 
				
			||||||
 | 
					            fi
 | 
				
			||||||
 | 
					            eend
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
        ;;
 | 
					        ;;
 | 
				
			||||||
    esac
 | 
					    esac
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
namespace nur\sery\schema\ref;
 | 
					namespace nur\sery\ref\schema;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ref_analyze {
 | 
					class ref_analyze {
 | 
				
			||||||
  /** @var int résultat de l'analyse: valeur inexistante */
 | 
					  /** @var int résultat de l'analyse: valeur inexistante */
 | 
				
			||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
namespace nur\sery\schema\ref;
 | 
					namespace nur\sery\ref\schema;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ref_schema {
 | 
					class ref_schema {
 | 
				
			||||||
  /** @var array schéma des natures de schéma */
 | 
					  /** @var array schéma des natures de schéma */
 | 
				
			||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
namespace nur\sery\schema\ref;
 | 
					namespace nur\sery\ref\schema;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ref_types {
 | 
					class ref_types {
 | 
				
			||||||
  const ALIASES = [
 | 
					  const ALIASES = [
 | 
				
			||||||
							
								
								
									
										12
									
								
								src/ref/sys/ref_func.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/ref/sys/ref_func.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					namespace nur\sery\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"],
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -43,13 +43,13 @@ abstract class Schema implements ArrayAccess {
 | 
				
			|||||||
   * variable $dest (si $destKey===null) ou $dest[$destKey] si $destKey n'est
 | 
					   * variable $dest (si $destKey===null) ou $dest[$destKey] si $destKey n'est
 | 
				
			||||||
   * pas null
 | 
					   * pas null
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  static function nv(?Value &$value=null, &$dest=null, $destKey=null, &$schema=null, $definition=null): Value {
 | 
					  static function nv(?Value &$destv=null, &$dest=null, $destKey=null, &$schema=null, $definition=null): Value {
 | 
				
			||||||
    if ($definition === null) {
 | 
					    if ($definition === null) {
 | 
				
			||||||
      # bien que techniquement, $definition peut être null (il s'agit alors du
 | 
					      # bien que techniquement, $definition peut être null (il s'agit alors du
 | 
				
			||||||
      # schéma d'un scalaire quelconque), on ne l'autorise pas ici
 | 
					      # schéma d'un scalaire quelconque), on ne l'autorise pas ici
 | 
				
			||||||
      throw SchemaException::invalid_schema("definition is required");
 | 
					      throw SchemaException::invalid_schema("definition is required");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return self::ns($schema, $definition)->newValue($value, $dest, $destKey);
 | 
					    return self::ns($schema, $definition)->newValue($destv, $dest, $destKey);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
@ -68,7 +68,7 @@ abstract class Schema implements ArrayAccess {
 | 
				
			|||||||
  /** retourner true si le schéma est de nature scalaire */
 | 
					  /** retourner true si le schéma est de nature scalaire */
 | 
				
			||||||
  function isScalar(?ScalarSchema &$scalar=null): bool { return false; }
 | 
					  function isScalar(?ScalarSchema &$scalar=null): bool { return false; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  abstract function newValue(?Value &$value=null, &$dest=null, $destKey=null): Value;
 | 
					  abstract function newValue(?Value &$destv=null, &$dest=null, $destKey=null): Value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #############################################################################
 | 
					  #############################################################################
 | 
				
			||||||
  # key & properties
 | 
					  # key & properties
 | 
				
			||||||
 | 
				
			|||||||
@ -45,10 +45,10 @@ class AssocSchema extends Schema {
 | 
				
			|||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function newValue(?Value &$value=null, &$dest=null, $destKey=null): Value {
 | 
					  function newValue(?Value &$destv=null, &$dest=null, $destKey=null): Value {
 | 
				
			||||||
    if (!($value instanceof AssocValue)) $value = new AssocValue($this);
 | 
					    if (!($destv instanceof AssocValue)) $destv = new AssocValue($this);
 | 
				
			||||||
    if ($dest instanceof Input) $input = $dest;
 | 
					    if ($dest instanceof Input) $input = $dest;
 | 
				
			||||||
    else $input = new Input($dest);
 | 
					    else $input = new Input($dest);
 | 
				
			||||||
    return $value->reset($input, $destKey);
 | 
					    return $destv->reset($input, $destKey);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -45,8 +45,8 @@ class ListSchema extends Schema {
 | 
				
			|||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function newValue(?Value &$value=null, &$dest=null, $destKey=null): Value {
 | 
					  function newValue(?Value &$destv=null, &$dest=null, $destKey=null): Value {
 | 
				
			||||||
    if (!($value instanceof ListValue)) $value = new ListValue($this);
 | 
					    if (!($destv instanceof ListValue)) $destv = new ListValue($this);
 | 
				
			||||||
    return $value->reset($dest, $destKey);
 | 
					    return $destv->reset($dest, $destKey);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,8 +3,8 @@ namespace nur\sery\schema\_scalar;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use nulib\cl;
 | 
					use nulib\cl;
 | 
				
			||||||
use nulib\ValueException;
 | 
					use nulib\ValueException;
 | 
				
			||||||
use nur\sery\schema\ref\ref_analyze;
 | 
					use nur\sery\ref\schema\ref_analyze;
 | 
				
			||||||
use nur\sery\schema\ref\ref_schema;
 | 
					use nur\sery\ref\schema\ref_schema;
 | 
				
			||||||
use nur\sery\schema\Result;
 | 
					use nur\sery\schema\Result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
				
			|||||||
@ -2,8 +2,8 @@
 | 
				
			|||||||
namespace nur\sery\schema\_scalar;
 | 
					namespace nur\sery\schema\_scalar;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use nulib\cl;
 | 
					use nulib\cl;
 | 
				
			||||||
use nur\sery\schema\ref\ref_schema;
 | 
					use nur\sery\ref\schema\ref_schema;
 | 
				
			||||||
use nur\sery\schema\ref\ref_types;
 | 
					use nur\sery\ref\schema\ref_types;
 | 
				
			||||||
use nur\sery\schema\Schema;
 | 
					use nur\sery\schema\Schema;
 | 
				
			||||||
use nur\sery\schema\SchemaException;
 | 
					use nur\sery\schema\SchemaException;
 | 
				
			||||||
use nur\sery\schema\types\tarray;
 | 
					use nur\sery\schema\types\tarray;
 | 
				
			||||||
@ -180,9 +180,9 @@ class ScalarSchema extends Schema {
 | 
				
			|||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function newValue(?Value &$value=null, &$dest=null, $destKey=null): Value {
 | 
					  function newValue(?Value &$destv=null, &$dest=null, $destKey=null): Value {
 | 
				
			||||||
    if ($value instanceof ScalarValue) return $value->reset($dest, $destKey);
 | 
					    if ($destv instanceof ScalarValue) return $destv->reset($dest, $destKey);
 | 
				
			||||||
    else return ($value = new ScalarValue($this, $dest, $destKey));
 | 
					    else return ($destv = new ScalarValue($this, $dest, $destKey));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #############################################################################
 | 
					  #############################################################################
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@ namespace nur\sery\schema\_scalar;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use nulib\ValueException;
 | 
					use nulib\ValueException;
 | 
				
			||||||
use nur\sery\schema\input\Input;
 | 
					use nur\sery\schema\input\Input;
 | 
				
			||||||
use nur\sery\schema\ref\ref_analyze;
 | 
					use nur\sery\ref\schema\ref_analyze;
 | 
				
			||||||
use nur\sery\schema\Result;
 | 
					use nur\sery\schema\Result;
 | 
				
			||||||
use nur\sery\schema\types;
 | 
					use nur\sery\schema\types;
 | 
				
			||||||
use nur\sery\schema\types\IType;
 | 
					use nur\sery\schema\types\IType;
 | 
				
			||||||
@ -11,6 +11,11 @@ use nur\sery\schema\Value;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class ScalarValue extends Value {
 | 
					class ScalarValue extends Value {
 | 
				
			||||||
  function __construct(ScalarSchema $schema, &$dest=null, $destKey=null, bool $defaultVerifix=true, ?bool $defaultThrow=null) {
 | 
					  function __construct(ScalarSchema $schema, &$dest=null, $destKey=null, bool $defaultVerifix=true, ?bool $defaultThrow=null) {
 | 
				
			||||||
 | 
					    if ($dest !== null && $defaultThrow = null) {
 | 
				
			||||||
 | 
					      # Si $dest est null, ne pas lancer d'exception, parce qu'on considère que
 | 
				
			||||||
 | 
					      # c'est une initialisation sans conséquences
 | 
				
			||||||
 | 
					      $defaultThrow = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    $this->schema = $schema;
 | 
					    $this->schema = $schema;
 | 
				
			||||||
    $this->defaultVerifix = $defaultVerifix;
 | 
					    $this->defaultVerifix = $defaultVerifix;
 | 
				
			||||||
    $this->defaultThrow = $defaultThrow !== null? $defaultThrow: false;
 | 
					    $this->defaultThrow = $defaultThrow !== null? $defaultThrow: false;
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,6 @@ namespace nur\sery\schema\input;
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * cette implémentation lit depuis les paramètres de formulaire et écrit dans
 | 
					 * cette implémentation lit depuis les paramètres de formulaire et écrit dans
 | 
				
			||||||
 * une référence
 | 
					 * une référence
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class FormInput extends Input {
 | 
					class FormInput extends Input {
 | 
				
			||||||
  const ALLOW_EMPTY = false;
 | 
					  const ALLOW_EMPTY = false;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,6 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
namespace nur\sery\schema\input;
 | 
					namespace nur\sery\schema\input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#XXX available permet de préciser qu'une valeur doit exister et être non vide
 | 
					 | 
				
			||||||
# pour être considérée. en faire un paramètre, à moins que ce soit au niveau du
 | 
					 | 
				
			||||||
# type qu'il faille le gérer?
 | 
					 | 
				
			||||||
use nulib\cl;
 | 
					use nulib\cl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ use nur\sery\schema\Schema;
 | 
				
			|||||||
 * Interface IType: un type de données
 | 
					 * Interface IType: un type de données
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
interface IType {
 | 
					interface IType {
 | 
				
			||||||
  /** la donnée $input[$destKey] est-elle disponible? */
 | 
					  /** la donnée $input($destKey) est-elle disponible? */
 | 
				
			||||||
  function isAvailable(Input $input, $destKey): bool;
 | 
					  function isAvailable(Input $input, $destKey): bool;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** la valeur $value est-elle nulle? */
 | 
					  /** la valeur $value est-elle nulle? */
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,4 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Ce package contient des services généraux spécifiques à PHP
 | 
					Ce package contient des services généraux spécifiques à PHP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
exemples: func
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
-*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary
 | 
					-*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary
 | 
				
			||||||
							
								
								
									
										430
									
								
								src/sys/func.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										430
									
								
								src/sys/func.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,430 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					namespace nur\sery\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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -3,6 +3,7 @@ namespace nur\sery\values;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use nulib\cl;
 | 
					use nulib\cl;
 | 
				
			||||||
use nulib\str;
 | 
					use nulib\str;
 | 
				
			||||||
 | 
					use nur\sery\sys\func;
 | 
				
			||||||
use ReflectionClass;
 | 
					use ReflectionClass;
 | 
				
			||||||
use ReflectionException;
 | 
					use ReflectionException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										247
									
								
								tests/sys/funcTest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								tests/sys/funcTest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,247 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					  function func36() {
 | 
				
			||||||
 | 
					    return 36;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace nur\sery\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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user