Skip to content

Commit c86271e

Browse files
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 ------- 9df4c7d [EventDispatcher] handle lazy-callable invokable
2 parents a721a50 + 9df4c7d commit c86271e

File tree

2 files changed

+31
-8
lines changed

2 files changed

+31
-8
lines changed

src/Symfony/Component/EventDispatcher/EventDispatcher.php

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,16 @@ public function getListenerPriority($eventName, $listener)
111111
return null;
112112
}
113113

114-
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
114+
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) {
115115
$listener[0] = $listener[0]();
116+
$listener[1] = $listener[1] ?? '__invoke';
116117
}
117118

118119
foreach ($this->listeners[$eventName] as $priority => &$listeners) {
119120
foreach ($listeners as &$v) {
120-
if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
121+
if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) {
121122
$v[0] = $v[0]();
123+
$v[1] = $v[1] ?? '__invoke';
122124
}
123125
if ($v === $listener) {
124126
return $priority;
@@ -165,14 +167,16 @@ public function removeListener($eventName, $listener)
165167
return;
166168
}
167169

168-
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
170+
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) {
169171
$listener[0] = $listener[0]();
172+
$listener[1] = $listener[1] ?? '__invoke';
170173
}
171174

172175
foreach ($this->listeners[$eventName] as $priority => &$listeners) {
173176
foreach ($listeners as $k => &$v) {
174-
if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
177+
if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) {
175178
$v[0] = $v[0]();
179+
$v[1] = $v[1] ?? '__invoke';
176180
}
177181
if ($v === $listener) {
178182
unset($listeners[$k], $this->sorted[$eventName], $this->optimized[$eventName]);
@@ -271,8 +275,9 @@ private function sortListeners(string $eventName)
271275

272276
foreach ($this->listeners[$eventName] as &$listeners) {
273277
foreach ($listeners as $k => $listener) {
274-
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
278+
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) {
275279
$listener[0] = $listener[0]();
280+
$listener[1] = $listener[1] ?? '__invoke';
276281
}
277282
$this->sorted[$eventName][] = $listener;
278283
}
@@ -290,10 +295,11 @@ private function optimizeListeners(string $eventName): array
290295
foreach ($this->listeners[$eventName] as &$listeners) {
291296
foreach ($listeners as &$listener) {
292297
$closure = &$this->optimized[$eventName][];
293-
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
298+
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) {
294299
$closure = static function (...$args) use (&$listener, &$closure) {
295300
if ($listener[0] instanceof \Closure) {
296301
$listener[0] = $listener[0]();
302+
$listener[1] = $listener[1] ?? '__invoke';
297303
}
298304
($closure = \Closure::fromCallable($listener))(...$args);
299305
};

src/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,17 +334,26 @@ public function testHasListenersIsLazy()
334334

335335
public function testDispatchLazyListener()
336336
{
337+
$dispatcher = new TestWithDispatcher();
337338
$called = 0;
338-
$factory = function () use (&$called) {
339+
$factory = function () use (&$called, $dispatcher) {
339340
++$called;
340341

341-
return new TestWithDispatcher();
342+
return $dispatcher;
342343
};
343344
$this->dispatcher->addListener('foo', [$factory, 'foo']);
344345
$this->assertSame(0, $called);
345346
$this->dispatcher->dispatch(new Event(), 'foo');
347+
$this->assertFalse($dispatcher->invoked);
346348
$this->dispatcher->dispatch(new Event(), 'foo');
347349
$this->assertSame(1, $called);
350+
351+
$this->dispatcher->addListener('bar', [$factory]);
352+
$this->assertSame(1, $called);
353+
$this->dispatcher->dispatch(new Event(), 'bar');
354+
$this->assertTrue($dispatcher->invoked);
355+
$this->dispatcher->dispatch(new Event(), 'bar');
356+
$this->assertSame(2, $called);
348357
}
349358

350359
public function testRemoveFindsLazyListeners()
@@ -472,12 +481,20 @@ class TestWithDispatcher
472481
{
473482
public $name;
474483
public $dispatcher;
484+
public $invoked = false;
475485

476486
public function foo($e, $name, $dispatcher)
477487
{
478488
$this->name = $name;
479489
$this->dispatcher = $dispatcher;
480490
}
491+
492+
public function __invoke($e, $name, $dispatcher)
493+
{
494+
$this->name = $name;
495+
$this->dispatcher = $dispatcher;
496+
$this->invoked = true;
497+
}
481498
}
482499

483500
class TestEventSubscriber implements EventSubscriberInterface

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy