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