minor #34027 [EventDispatcher] handle lazy-callable invokable (nicolas-grekas)
This PR was merged into the 4.4 branch.
Discussion
----------
[EventDispatcher] handle lazy-callable invokable
| Q | A
| ------------- | ---
| Branch? | 4.4
| Bug fix? | no
| New feature? | yes
| Deprecations? | no
| Tickets | -
| License | MIT
| Doc PR | -
Extracted from #34013, for consistency mostly.
Commits
-------
9df4c7d32b
[EventDispatcher] handle lazy-callable invokable
This commit is contained in:
commit
c86271e750
@ -111,14 +111,16 @@ class EventDispatcher implements EventDispatcherInterface
|
|||||||
return null;
|
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[0] = $listener[0]();
|
||||||
|
$listener[1] = $listener[1] ?? '__invoke';
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->listeners[$eventName] as $priority => &$listeners) {
|
foreach ($this->listeners[$eventName] as $priority => &$listeners) {
|
||||||
foreach ($listeners as &$v) {
|
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[0] = $v[0]();
|
||||||
|
$v[1] = $v[1] ?? '__invoke';
|
||||||
}
|
}
|
||||||
if ($v === $listener) {
|
if ($v === $listener) {
|
||||||
return $priority;
|
return $priority;
|
||||||
@ -165,14 +167,16 @@ class EventDispatcher implements EventDispatcherInterface
|
|||||||
return;
|
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[0] = $listener[0]();
|
||||||
|
$listener[1] = $listener[1] ?? '__invoke';
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->listeners[$eventName] as $priority => &$listeners) {
|
foreach ($this->listeners[$eventName] as $priority => &$listeners) {
|
||||||
foreach ($listeners as $k => &$v) {
|
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[0] = $v[0]();
|
||||||
|
$v[1] = $v[1] ?? '__invoke';
|
||||||
}
|
}
|
||||||
if ($v === $listener) {
|
if ($v === $listener) {
|
||||||
unset($listeners[$k], $this->sorted[$eventName], $this->optimized[$eventName]);
|
unset($listeners[$k], $this->sorted[$eventName], $this->optimized[$eventName]);
|
||||||
@ -271,8 +275,9 @@ class EventDispatcher implements EventDispatcherInterface
|
|||||||
|
|
||||||
foreach ($this->listeners[$eventName] as &$listeners) {
|
foreach ($this->listeners[$eventName] as &$listeners) {
|
||||||
foreach ($listeners as $k => $listener) {
|
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[0] = $listener[0]();
|
||||||
|
$listener[1] = $listener[1] ?? '__invoke';
|
||||||
}
|
}
|
||||||
$this->sorted[$eventName][] = $listener;
|
$this->sorted[$eventName][] = $listener;
|
||||||
}
|
}
|
||||||
@ -290,10 +295,11 @@ class EventDispatcher implements EventDispatcherInterface
|
|||||||
foreach ($this->listeners[$eventName] as &$listeners) {
|
foreach ($this->listeners[$eventName] as &$listeners) {
|
||||||
foreach ($listeners as &$listener) {
|
foreach ($listeners as &$listener) {
|
||||||
$closure = &$this->optimized[$eventName][];
|
$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) {
|
$closure = static function (...$args) use (&$listener, &$closure) {
|
||||||
if ($listener[0] instanceof \Closure) {
|
if ($listener[0] instanceof \Closure) {
|
||||||
$listener[0] = $listener[0]();
|
$listener[0] = $listener[0]();
|
||||||
|
$listener[1] = $listener[1] ?? '__invoke';
|
||||||
}
|
}
|
||||||
($closure = \Closure::fromCallable($listener))(...$args);
|
($closure = \Closure::fromCallable($listener))(...$args);
|
||||||
};
|
};
|
||||||
|
@ -334,17 +334,26 @@ class EventDispatcherTest extends TestCase
|
|||||||
|
|
||||||
public function testDispatchLazyListener()
|
public function testDispatchLazyListener()
|
||||||
{
|
{
|
||||||
|
$dispatcher = new TestWithDispatcher();
|
||||||
$called = 0;
|
$called = 0;
|
||||||
$factory = function () use (&$called) {
|
$factory = function () use (&$called, $dispatcher) {
|
||||||
++$called;
|
++$called;
|
||||||
|
|
||||||
return new TestWithDispatcher();
|
return $dispatcher;
|
||||||
};
|
};
|
||||||
$this->dispatcher->addListener('foo', [$factory, 'foo']);
|
$this->dispatcher->addListener('foo', [$factory, 'foo']);
|
||||||
$this->assertSame(0, $called);
|
$this->assertSame(0, $called);
|
||||||
$this->dispatcher->dispatch(new Event(), 'foo');
|
$this->dispatcher->dispatch(new Event(), 'foo');
|
||||||
|
$this->assertFalse($dispatcher->invoked);
|
||||||
$this->dispatcher->dispatch(new Event(), 'foo');
|
$this->dispatcher->dispatch(new Event(), 'foo');
|
||||||
$this->assertSame(1, $called);
|
$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()
|
public function testRemoveFindsLazyListeners()
|
||||||
@ -472,12 +481,20 @@ class TestWithDispatcher
|
|||||||
{
|
{
|
||||||
public $name;
|
public $name;
|
||||||
public $dispatcher;
|
public $dispatcher;
|
||||||
|
public $invoked = false;
|
||||||
|
|
||||||
public function foo($e, $name, $dispatcher)
|
public function foo($e, $name, $dispatcher)
|
||||||
{
|
{
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
$this->dispatcher = $dispatcher;
|
$this->dispatcher = $dispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function __invoke($e, $name, $dispatcher)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
$this->dispatcher = $dispatcher;
|
||||||
|
$this->invoked = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestEventSubscriber implements EventSubscriberInterface
|
class TestEventSubscriber implements EventSubscriberInterface
|
||||||
|
Reference in New Issue
Block a user