[EventDispatcher] handle lazy-callable invokable
This commit is contained in:
parent
f771faf925
commit
9df4c7d32b
@ -111,14 +111,16 @@ class EventDispatcher implements EventDispatcherInterface
|
||||
return null;
|
||||
}
|
||||
|
||||
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
|
||||
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) {
|
||||
$listener[0] = $listener[0]();
|
||||
$listener[1] = $listener[1] ?? '__invoke';
|
||||
}
|
||||
|
||||
foreach ($this->listeners[$eventName] as $priority => &$listeners) {
|
||||
foreach ($listeners as &$v) {
|
||||
if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
|
||||
if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) {
|
||||
$v[0] = $v[0]();
|
||||
$v[1] = $v[1] ?? '__invoke';
|
||||
}
|
||||
if ($v === $listener) {
|
||||
return $priority;
|
||||
@ -165,14 +167,16 @@ class EventDispatcher implements EventDispatcherInterface
|
||||
return;
|
||||
}
|
||||
|
||||
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
|
||||
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) {
|
||||
$listener[0] = $listener[0]();
|
||||
$listener[1] = $listener[1] ?? '__invoke';
|
||||
}
|
||||
|
||||
foreach ($this->listeners[$eventName] as $priority => &$listeners) {
|
||||
foreach ($listeners as $k => &$v) {
|
||||
if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
|
||||
if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) {
|
||||
$v[0] = $v[0]();
|
||||
$v[1] = $v[1] ?? '__invoke';
|
||||
}
|
||||
if ($v === $listener) {
|
||||
unset($listeners[$k], $this->sorted[$eventName], $this->optimized[$eventName]);
|
||||
@ -271,8 +275,9 @@ class EventDispatcher implements EventDispatcherInterface
|
||||
|
||||
foreach ($this->listeners[$eventName] as &$listeners) {
|
||||
foreach ($listeners as $k => $listener) {
|
||||
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
|
||||
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) {
|
||||
$listener[0] = $listener[0]();
|
||||
$listener[1] = $listener[1] ?? '__invoke';
|
||||
}
|
||||
$this->sorted[$eventName][] = $listener;
|
||||
}
|
||||
@ -290,10 +295,11 @@ class EventDispatcher implements EventDispatcherInterface
|
||||
foreach ($this->listeners[$eventName] as &$listeners) {
|
||||
foreach ($listeners as &$listener) {
|
||||
$closure = &$this->optimized[$eventName][];
|
||||
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
|
||||
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) {
|
||||
$closure = static function (...$args) use (&$listener, &$closure) {
|
||||
if ($listener[0] instanceof \Closure) {
|
||||
$listener[0] = $listener[0]();
|
||||
$listener[1] = $listener[1] ?? '__invoke';
|
||||
}
|
||||
($closure = \Closure::fromCallable($listener))(...$args);
|
||||
};
|
||||
|
@ -334,17 +334,26 @@ class EventDispatcherTest extends TestCase
|
||||
|
||||
public function testDispatchLazyListener()
|
||||
{
|
||||
$dispatcher = new TestWithDispatcher();
|
||||
$called = 0;
|
||||
$factory = function () use (&$called) {
|
||||
$factory = function () use (&$called, $dispatcher) {
|
||||
++$called;
|
||||
|
||||
return new TestWithDispatcher();
|
||||
return $dispatcher;
|
||||
};
|
||||
$this->dispatcher->addListener('foo', [$factory, 'foo']);
|
||||
$this->assertSame(0, $called);
|
||||
$this->dispatcher->dispatch(new Event(), 'foo');
|
||||
$this->assertFalse($dispatcher->invoked);
|
||||
$this->dispatcher->dispatch(new Event(), 'foo');
|
||||
$this->assertSame(1, $called);
|
||||
|
||||
$this->dispatcher->addListener('bar', [$factory]);
|
||||
$this->assertSame(1, $called);
|
||||
$this->dispatcher->dispatch(new Event(), 'bar');
|
||||
$this->assertTrue($dispatcher->invoked);
|
||||
$this->dispatcher->dispatch(new Event(), 'bar');
|
||||
$this->assertSame(2, $called);
|
||||
}
|
||||
|
||||
public function testRemoveFindsLazyListeners()
|
||||
@ -472,12 +481,20 @@ class TestWithDispatcher
|
||||
{
|
||||
public $name;
|
||||
public $dispatcher;
|
||||
public $invoked = false;
|
||||
|
||||
public function foo($e, $name, $dispatcher)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
public function __invoke($e, $name, $dispatcher)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->invoked = true;
|
||||
}
|
||||
}
|
||||
|
||||
class TestEventSubscriber implements EventSubscriberInterface
|
||||
|
Reference in New Issue
Block a user