Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 370379f

Browse files
committed
[EventDispatcher] Fix lazy listeners registration
1 parent 7093fc1 commit 370379f

File tree

2 files changed

+71
-18
lines changed

2 files changed

+71
-18
lines changed

src/Symfony/Component/EventDispatcher/EventDispatcher.php

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
class EventDispatcher implements EventDispatcherInterface
3030
{
3131
private $listeners = array();
32+
private $factories = array();
3233
private $sorted = array();
3334

3435
/**
@@ -53,19 +54,24 @@ public function dispatch($eventName, Event $event = null)
5354
public function getListeners($eventName = null)
5455
{
5556
if (null !== $eventName) {
57+
if (!empty($this->factories[$eventName])) {
58+
$this->registerLazyListeners($eventName);
59+
}
60+
5661
if (empty($this->listeners[$eventName])) {
5762
return array();
5863
}
5964

60-
if (!isset($this->sorted[$eventName])) {
65+
if (!isset($this->sorted[$eventName]) && !empty($this->listeners[$eventName])) {
6166
$this->sortListeners($eventName);
6267
}
6368

6469
return $this->sorted[$eventName];
6570
}
6671

72+
$this->registerLazyListeners();
6773
foreach ($this->listeners as $eventName => $eventListeners) {
68-
if (!isset($this->sorted[$eventName])) {
74+
if (!isset($this->sorted[$eventName]) && !empty($this->listeners[$eventName])) {
6975
$this->sortListeners($eventName);
7076
}
7177
}
@@ -78,6 +84,10 @@ public function getListeners($eventName = null)
7884
*/
7985
public function getListenerPriority($eventName, $listener)
8086
{
87+
if (!empty($this->factories[$eventName])) {
88+
$this->registerLazyListeners($eventName);
89+
}
90+
8191
if (empty($this->listeners[$eventName])) {
8292
return;
8393
}
@@ -88,10 +98,6 @@ public function getListenerPriority($eventName, $listener)
8898

8999
foreach ($this->listeners[$eventName] as $priority => $listeners) {
90100
foreach ($listeners as $k => $v) {
91-
if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
92-
$v[0] = $v[0]();
93-
$this->listeners[$eventName][$priority][$k] = $v;
94-
}
95101
if ($v === $listener) {
96102
return $priority;
97103
}
@@ -105,7 +111,7 @@ public function getListenerPriority($eventName, $listener)
105111
public function hasListeners($eventName = null)
106112
{
107113
if (null !== $eventName) {
108-
return !empty($this->listeners[$eventName]);
114+
return !empty($this->listeners[$eventName]) || !empty($this->factories[$eventName]);
109115
}
110116

111117
foreach ($this->listeners as $eventListeners) {
@@ -114,6 +120,12 @@ public function hasListeners($eventName = null)
114120
}
115121
}
116122

123+
foreach ($this->factories as $eventListeners) {
124+
if ($eventListeners) {
125+
return true;
126+
}
127+
}
128+
117129
return false;
118130
}
119131

@@ -122,6 +134,12 @@ public function hasListeners($eventName = null)
122134
*/
123135
public function addListener($eventName, $listener, $priority = 0)
124136
{
137+
if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
138+
$this->factories[$eventName][] = array($listener[0], $listener[1], $priority);
139+
140+
return;
141+
}
142+
125143
$this->listeners[$eventName][$priority][] = $listener;
126144
unset($this->sorted[$eventName]);
127145
}
@@ -131,6 +149,10 @@ public function addListener($eventName, $listener, $priority = 0)
131149
*/
132150
public function removeListener($eventName, $listener)
133151
{
152+
if (!empty($this->factories[$eventName])) {
153+
$this->registerLazyListeners($eventName);
154+
}
155+
134156
if (empty($this->listeners[$eventName])) {
135157
return;
136158
}
@@ -141,9 +163,6 @@ public function removeListener($eventName, $listener)
141163

142164
foreach ($this->listeners[$eventName] as $priority => $listeners) {
143165
foreach ($listeners as $k => $v) {
144-
if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
145-
$v[0] = $v[0]();
146-
}
147166
if ($v === $listener) {
148167
unset($listeners[$k], $this->sorted[$eventName]);
149168
} else {
@@ -221,16 +240,28 @@ protected function doDispatch($listeners, $eventName, Event $event)
221240
private function sortListeners($eventName)
222241
{
223242
krsort($this->listeners[$eventName]);
224-
$this->sorted[$eventName] = array();
243+
$this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]);
244+
}
225245

226-
foreach ($this->listeners[$eventName] as $priority => $listeners) {
227-
foreach ($listeners as $k => $listener) {
228-
if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
229-
$listener[0] = $listener[0]();
230-
$this->listeners[$eventName][$priority][$k] = $listener;
231-
}
232-
$this->sorted[$eventName][] = $listener;
246+
private function registerLazyListeners($eventName = null)
247+
{
248+
if (null !== $eventName) {
249+
foreach ($this->factories[$eventName] as list($factory, $method, $priority)) {
250+
$this->listeners[$eventName][$priority][] = array($factory(), $method);
233251
}
252+
unset($this->factories[$eventName]);
253+
unset($this->sorted[$eventName]);
254+
255+
return;
234256
}
257+
258+
foreach ($this->factories as $event => $factories) {
259+
foreach ($factories as list($factory, $method, $priority)) {
260+
$this->listeners[$event][$priority][] = array($factory(), $method);
261+
}
262+
}
263+
264+
$this->sorted = array();
265+
$this->factories = array();
235266
}
236267
}

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,26 @@ protected function createEventDispatcher()
1919
{
2020
return new EventDispatcher();
2121
}
22+
23+
public function testAddListenerRegistersLazyListenersFactoriesSeparately()
24+
{
25+
$dispatcher = new EventDispatcher();
26+
$test = new TestWithDispatcher();
27+
$factory = function () use ($test) { return $test; };
28+
$getListeners = \Closure::bind(function ($dispatcher) {
29+
return array($dispatcher->listeners, $dispatcher->factories);
30+
}, null, EventDispatcher::class);
31+
32+
$dispatcher->addListener('foo', array($factory, 'foo'), 3);
33+
list($listeners, $factories) = $getListeners($dispatcher);
34+
$this->assertSame(array(), $listeners);
35+
$this->assertSame(array('foo' => array(array($factory, 'foo', 3))), $factories);
36+
37+
// trigger factories execution
38+
$dispatcher->getListeners();
39+
40+
list($listeners, $factories) = $getListeners($dispatcher);
41+
$this->assertSame(array('foo' => array(3 => array(array($test, 'foo')))), $listeners);
42+
$this->assertSame(array(), $factories);
43+
}
2244
}

0 commit comments

Comments
 (0)