fix closure for static method array callables

This commit is contained in:
Kacper Donat 2026-10-27 23:00:21 +01:00
parent 28408baa64
commit a09e6840d4
3 changed files with 28 additions and 4 deletions

View File

@ -41,13 +41,14 @@ function closure($callable)
case is_array($callable): case is_array($callable):
list($object, $method) = $callable; list($object, $method) = $callable;
$reflection = new \ReflectionObject($object); // A static method ([Foo::class, 'method']) is given by its class name, not an object.
$method = $reflection->getMethod($method); $class = is_string($object) ? $object : get_class($object);
$method = new \ReflectionMethod($object, $method);
if (!$method->isPublic()) { if (!$method->isPublic()) {
$backtrace = debug_backtrace(); $backtrace = debug_backtrace();
foreach ($backtrace as $trace) { foreach ($backtrace as $trace) {
if (isset($trace['class']) && $trace['class'] === $reflection->name) { if (isset($trace['class']) && $trace['class'] === $class) {
break; break;
} }
@ -58,7 +59,7 @@ function closure($callable)
} }
} }
return $method->getClosure($object); return $method->getClosure(is_string($object) ? null : $object);
default: default:
return \Closure::fromCallable($callable); return \Closure::fromCallable($callable);

View File

@ -62,6 +62,11 @@ class TransformsTest extends \PHPUnit\Framework\TestCase
$this->assertSeq(['x:1', 'y:2'], c\map(fn ($v, $k) => "$k:$v")(self::gen(['x' => 1, 'y' => 2]))); $this->assertSeq(['x:1', 'y:2'], c\map(fn ($v, $k) => "$k:$v")(self::gen(['x' => 1, 'y' => 2])));
} }
public function testMapWithStaticMethodArrayCallable()
{
$this->assertSame(['a' => 2, 'b' => 4], c\map([TransformsTestHelper::class, 'double'])(['a' => 1, 'b' => 2]));
}
public function testMapOnSetFollowsSetMap() public function testMapOnSetFollowsSetMap()
{ {
$result = c\map(fn ($v) => $v % 2)(new Set([1, 2, 3])); $result = c\map(fn ($v) => $v % 2)(new Set([1, 2, 3]));
@ -418,3 +423,11 @@ class TransformsTest extends \PHPUnit\Framework\TestCase
} }
} }
} }
class TransformsTestHelper
{
public static function double(int $value): int
{
return $value * 2;
}
}

View File

@ -28,10 +28,20 @@ class TestObject
{ {
return ref([$this, 'priv']); return ref([$this, 'priv']);
} }
public static function twice($x)
{
return $x * 2;
}
} }
class ReferencingTest extends \PHPUnit\Framework\TestCase class ReferencingTest extends \PHPUnit\Framework\TestCase
{ {
public function testReferenceStaticMethodArrayCallable()
{
$this->assertSame(4, ref([TestObject::class, 'twice'])(2));
}
public function testReferenceClosure() public function testReferenceClosure()
{ {
$f = function () { }; $f = function () { };