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;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 |