modifs.mineures sans commentaires
This commit is contained in:
parent
f3c07d7665
commit
3ce2f8e134
|
@ -17,6 +17,7 @@ namespace nur\sery\wip\php\impl {
|
|||
|
||||
namespace nur\sery\wip\php {
|
||||
use nulib\tests\TestCase;
|
||||
use nur\sery\ValueException;
|
||||
use nur\sery\wip\php\impl\C0;
|
||||
use nur\sery\wip\php\impl\C1;
|
||||
use nur\sery\wip\php\impl\SC;
|
||||
|
@ -1034,36 +1035,112 @@ namespace nur\sery\wip\php {
|
|||
$func = func::with([SC::class, "tstatic"]);
|
||||
self::assertSame(10, $func->invoke());
|
||||
|
||||
$func = func::with([SC::class, "::tstatic"]);
|
||||
self::assertSame(10, $func->invoke());
|
||||
|
||||
$func = func::with([null, "tstatic"]);
|
||||
self::assertException(ValueException::class, function() use ($func) {
|
||||
$func->invoke();
|
||||
});
|
||||
|
||||
$func = func::with([null, "::tstatic"]);
|
||||
self::assertException(ValueException::class, function() use ($func) {
|
||||
$func->invoke();
|
||||
});
|
||||
|
||||
$func = func::with([null, "tstatic"]);
|
||||
self::assertSame(10, $func->bind(SC::class)->invoke());
|
||||
|
||||
$func = func::with([null, "tstatic"]);
|
||||
self::assertSame(10, $func->bind(new SC())->invoke());
|
||||
|
||||
$func = func::with([null, "::tstatic"]);
|
||||
self::assertSame(10, $func->bind(SC::class)->invoke());
|
||||
|
||||
$func = func::with([null, "::tstatic"]);
|
||||
self::assertSame(10, $func->bind(new SC())->invoke());
|
||||
|
||||
$func = func::with([SC::class, "tmethod"]);
|
||||
self::assertException(ReflectionException::class, function() use ($func) {
|
||||
$func->invoke();
|
||||
});
|
||||
|
||||
$func = func::with([null, "tstatic"]);
|
||||
$func = func::with([SC::class, "::tmethod"]);
|
||||
self::assertException(ReflectionException::class, function() use ($func) {
|
||||
$func->invoke();
|
||||
});
|
||||
|
||||
$func = func::with([null, "tmethod"]);
|
||||
self::assertException(ReflectionException::class, function() use ($func) {
|
||||
self::assertException(ValueException::class, function() use ($func) {
|
||||
$func->invoke();
|
||||
});
|
||||
|
||||
$func = func::with([null, "::tmethod"]);
|
||||
self::assertException(ValueException::class, function() use ($func) {
|
||||
$func->invoke();
|
||||
});
|
||||
|
||||
$func = func::with([null, "tmethod"]);
|
||||
self::assertException(ReflectionException::class, function() use ($func) {
|
||||
$func->bind(new SC())->invoke();
|
||||
});
|
||||
|
||||
$func = func::with([null, "::tmethod"]);
|
||||
self::assertException(ReflectionException::class, function() use ($func) {
|
||||
$func->bind(new SC())->invoke();
|
||||
});
|
||||
}
|
||||
|
||||
function testInvokeMethod() {
|
||||
$func = func::with([SC::class, "tstatic"]);
|
||||
self::assertSame(10, $func->invoke());
|
||||
|
||||
$func = func::with([new SC(), "tstatic"]);
|
||||
$func = func::with([SC::class, "->tstatic"]);
|
||||
self::assertSame(10, $func->invoke());
|
||||
|
||||
$func = func::with([null, "tstatic"]);
|
||||
self::assertException(ValueException::class, function() use ($func) {
|
||||
$func->invoke();
|
||||
});
|
||||
|
||||
$func = func::with([null, "->tstatic"]);
|
||||
self::assertException(ValueException::class, function() use ($func) {
|
||||
$func->invoke();
|
||||
});
|
||||
|
||||
$func = func::with([null, "tstatic"]);
|
||||
self::assertSame(10, $func->bind(new SC())->invoke());
|
||||
|
||||
$func = func::with([null, "->tstatic"]);
|
||||
self::assertSame(10, $func->bind(new SC())->invoke());
|
||||
|
||||
$func = func::with([SC::class, "tmethod"]);
|
||||
self::assertException(ReflectionException::class, function() use ($func) {
|
||||
$func->invoke();
|
||||
});
|
||||
|
||||
$func = func::with([new SC(), "tmethod"]);
|
||||
self::assertSame(11, $func->invoke());
|
||||
$func = func::with([SC::class, "->tmethod"]);
|
||||
self::assertException(ReflectionException::class, function() use ($func) {
|
||||
$func->invoke();
|
||||
});
|
||||
|
||||
$func = func::with([null, "tmethod"]);
|
||||
self::assertException(ValueException::class, function() use ($func) {
|
||||
$func->invoke();
|
||||
});
|
||||
|
||||
$func = func::with([null, "->tmethod"]);
|
||||
self::assertException(ValueException::class, function() use ($func) {
|
||||
$func->invoke();
|
||||
});
|
||||
|
||||
$func = func::with([null, "tmethod"]);
|
||||
self::assertException(ReflectionException::class, function() use ($func) {
|
||||
$func->bind(new SC())->invoke();
|
||||
});
|
||||
|
||||
$func = func::with([null, "->tmethod"]);
|
||||
self::assertSame(11, $func->bind(new SC())->invoke());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
176
wip/php/func.php
176
wip/php/func.php
|
@ -433,35 +433,54 @@ class func {
|
|||
#############################################################################
|
||||
# func
|
||||
|
||||
const TYPE_CLOSURE = 0, TYPE_SIMPLE = 1, TYPE_CLASS = 2, TYPE_STATIC = 3, TYPE_METHOD = 4;
|
||||
|
||||
protected static function not_a_callable($func, ?string $reason) {
|
||||
if ($reason === null) {
|
||||
$msg = var_export($func, true);
|
||||
$reason = "$msg: not a callable";
|
||||
}
|
||||
return new ValueException($reason);
|
||||
}
|
||||
|
||||
static function with($func, bool $strict=true): self {
|
||||
if (!is_array($func)) {
|
||||
if ($func instanceof Closure) {
|
||||
return new self($func, false, null);
|
||||
} elseif (self::verifix_function($func, $strict, $reason)) {
|
||||
return new self($func, false, $reason);
|
||||
return new self(self::TYPE_CLOSURE, $func);
|
||||
} elseif ($func instanceof ReflectionFunction) {
|
||||
return new self(self::TYPE_SIMPLE, $func);
|
||||
} elseif ($func instanceof ReflectionClass) {
|
||||
return new self(self::TYPE_CLASS, $func);
|
||||
} elseif ($func instanceof ReflectionMethod) {
|
||||
return new self(self::TYPE_METHOD, $func, false);
|
||||
}
|
||||
}
|
||||
if (self::verifix_function($func, $strict, $reason)) {
|
||||
return new self(self::TYPE_SIMPLE, $func, false, $reason);
|
||||
} elseif (self::verifix_class($func, $strict, $reason)) {
|
||||
return new self($func, false, $reason);
|
||||
return new self(self::TYPE_CLASS, $func, false, $reason);
|
||||
} else {
|
||||
$valid = true;
|
||||
if (is_array($func) && array_key_exists(0, $func) && is_object($func[0])) {
|
||||
if (self::verifix_method($func, $strict, $bound, $reason)) {
|
||||
$type = self::TYPE_METHOD;
|
||||
} elseif (self::verifix_static($func, $strict, $bound, $reason)) {
|
||||
$type = self::TYPE_STATIC;
|
||||
} else {
|
||||
$valid = false;
|
||||
}
|
||||
} else {
|
||||
if (self::verifix_static($func, $strict, $bound, $reason)) {
|
||||
$type = self::TYPE_STATIC;
|
||||
} elseif (self::verifix_method($func, $strict, $bound, $reason)) {
|
||||
$type = self::TYPE_METHOD;
|
||||
} else {
|
||||
$valid = false;
|
||||
}
|
||||
}
|
||||
if ($valid) return new self($func, $bound, $reason);
|
||||
if ($valid) return new self($type, $func, $bound, $reason);
|
||||
}
|
||||
if ($reason === null) {
|
||||
$msg = var_export($func, true);
|
||||
$reason = "$msg: not a callable";
|
||||
}
|
||||
throw new ValueException($reason);
|
||||
throw self::not_a_callable($func, $reason);
|
||||
}
|
||||
|
||||
static function call($func, ...$args) {
|
||||
|
@ -470,54 +489,74 @@ class func {
|
|||
|
||||
#############################################################################
|
||||
|
||||
const TYPE_CLOSURE = 0, TYPE_SIMPLE = 1, TYPE_CLASS = 2, TYPE_STATIC = 3, TYPE_METHOD = 4;
|
||||
|
||||
protected function __construct($func, bool $bound=false, ?string $reason=null) {
|
||||
protected function __construct(int $type, $func, bool $bound=false, ?string $reason=null) {
|
||||
$object = null;
|
||||
$prefixArgs = [];
|
||||
if ($func instanceof Closure) {
|
||||
$type = self::TYPE_CLOSURE;
|
||||
$object = $func;
|
||||
$reflection = new ReflectionFunction($func);
|
||||
} elseif ($func instanceof ReflectionFunction) {
|
||||
$type = self::TYPE_SIMPLE;
|
||||
if (!is_array($func)) {
|
||||
$reflection = $func;
|
||||
} elseif ($func instanceof ReflectionClass) {
|
||||
$type = self::TYPE_CLASS;
|
||||
$reflection = $func;
|
||||
} elseif ($func instanceof ReflectionMethod) {
|
||||
$type = self::TYPE_STATIC;
|
||||
$reflection = $func;
|
||||
} elseif (is_array($func)) {
|
||||
$func = null;
|
||||
} else {
|
||||
if (count($func) > 2) {
|
||||
$prefixArgs = array_slice($func, 2);
|
||||
$func = array_slice($func, 0, 2);
|
||||
}
|
||||
[$c, $f] = $func;
|
||||
if ($c === false) {
|
||||
# fonction simple
|
||||
$type = self::TYPE_SIMPLE;
|
||||
switch ($type) {
|
||||
case self::TYPE_SIMPLE:
|
||||
$reflection = new ReflectionFunction($f);
|
||||
} elseif ($f === false) {
|
||||
# classe
|
||||
$type = self::TYPE_CLASS;
|
||||
break;
|
||||
case self::TYPE_CLASS:
|
||||
$reflection = new ReflectionClass($c);
|
||||
} elseif ($c !== null) {
|
||||
# methode
|
||||
break;
|
||||
case self::TYPE_STATIC:
|
||||
case self::TYPE_METHOD:
|
||||
if ($c === null) {
|
||||
$reflection = null;
|
||||
} else {
|
||||
$reflection = new ReflectionMethod($c, $f);
|
||||
if (is_object($c)) {
|
||||
$type = self::TYPE_METHOD;
|
||||
$object = $c;
|
||||
} else {
|
||||
$type = self::TYPE_STATIC;
|
||||
if (is_object($c)) $object = $c;
|
||||
}
|
||||
} else {
|
||||
throw new StateException("invalid func");
|
||||
break;
|
||||
default:
|
||||
throw StateException::unexpected_state();
|
||||
}
|
||||
} else {
|
||||
throw new StateException("invalid func");
|
||||
}
|
||||
if ($reflection instanceof ReflectionClass) {
|
||||
|
||||
$this->type = $type;
|
||||
$this->func = $func;
|
||||
$this->bound = $bound;
|
||||
$this->reason = $reason;
|
||||
$this->object = $object;
|
||||
$this->prefixArgs = $prefixArgs;
|
||||
$this->updateReflection($reflection);
|
||||
}
|
||||
|
||||
protected int $type;
|
||||
|
||||
protected ?array $func;
|
||||
|
||||
protected bool $bound;
|
||||
|
||||
protected ?string $reason;
|
||||
|
||||
protected ?object $object;
|
||||
|
||||
protected array $prefixArgs;
|
||||
|
||||
/** @var Closure|ReflectionFunction|ReflectionMethod|ReflectionClass */
|
||||
protected $reflection;
|
||||
|
||||
protected bool $variadic;
|
||||
|
||||
protected int $minArgs;
|
||||
|
||||
protected int $maxArgs;
|
||||
|
||||
protected function updateReflection($reflection): void {
|
||||
$variadic = false;
|
||||
$minArgs = $maxArgs = 0;
|
||||
if ($reflection instanceof Closure) {
|
||||
} elseif ($reflection instanceof ReflectionClass) {
|
||||
$constructor = $reflection->getConstructor();
|
||||
if ($constructor === null) {
|
||||
$variadic = false;
|
||||
|
@ -527,42 +566,36 @@ class func {
|
|||
$minArgs = $constructor->getNumberOfRequiredParameters();
|
||||
$maxArgs = $constructor->getNumberOfParameters();
|
||||
}
|
||||
} else {
|
||||
} elseif ($reflection !== null) {
|
||||
$variadic = $reflection->isVariadic();
|
||||
$minArgs = $reflection->getNumberOfRequiredParameters();
|
||||
$maxArgs = $reflection->getNumberOfParameters();
|
||||
}
|
||||
|
||||
$this->type = $type;
|
||||
$this->reflection = $reflection;
|
||||
$this->variadic = $variadic;
|
||||
$this->minArgs = $minArgs;
|
||||
$this->maxArgs = $maxArgs;
|
||||
}
|
||||
|
||||
function bind($object, bool $rebind=false): self {
|
||||
if ($rebind || !$this->bound) {
|
||||
switch ($this->type) {
|
||||
case self::TYPE_STATIC:
|
||||
if (is_object($object)) $object = get_class($object);
|
||||
# pas de break, continuer à la section suivante
|
||||
case self::TYPE_METHOD:
|
||||
if ($this->reflection === null) {
|
||||
$this->func[0] = $object;
|
||||
$this->updateReflection(new ReflectionMethod(...$this->func));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (is_object($object)) {
|
||||
$this->object = $object;
|
||||
$this->prefixArgs = $prefixArgs;
|
||||
$this->bound = true;
|
||||
}
|
||||
|
||||
protected int $type;
|
||||
|
||||
/** @var ReflectionFunction|ReflectionMethod|ReflectionClass */
|
||||
protected $reflection;
|
||||
|
||||
protected bool $variadic;
|
||||
|
||||
protected int $minArgs;
|
||||
|
||||
protected int $maxArgs;
|
||||
|
||||
protected ?object $object;
|
||||
|
||||
protected array $prefixArgs;
|
||||
|
||||
function bind($objectOrClass, bool $rebind=false): self {
|
||||
|
||||
}
|
||||
|
||||
function bindClass($objectOrClass, bool $rebind=false): self {
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
function invoke(?array $args=null) {
|
||||
|
@ -574,7 +607,7 @@ class func {
|
|||
switch ($this->type) {
|
||||
case self::TYPE_CLOSURE:
|
||||
/** @var Closure $closure */
|
||||
$closure = $this->object;
|
||||
$closure = $this->reflection;
|
||||
return $closure(...$args);
|
||||
case self::TYPE_SIMPLE:
|
||||
/** @var ReflectionFunction $function */
|
||||
|
@ -584,11 +617,14 @@ class func {
|
|||
case self::TYPE_METHOD:
|
||||
/** @var ReflectionMethod $method */
|
||||
$method = $this->reflection;
|
||||
if ($method === null) throw self::not_a_callable($this->func, $this->reason);
|
||||
return $method->invoke($this->object, ...$args);
|
||||
case self::TYPE_CLASS:
|
||||
/** @var ReflectionClass $class */
|
||||
$class = $this->reflection;
|
||||
return $class->newInstance(...$args);
|
||||
default:
|
||||
throw StateException::unexpected_state();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue