Skip to content

Commit 9ff6a95

Browse files
committed
[EventDispatcher] TraceableEventDispatcher resets listener priorities
1 parent 6eda9ad commit 9ff6a95

File tree

3 files changed

+64
-2
lines changed

3 files changed

+64
-2
lines changed

src/Symfony/Component/EventDispatcher/EventDispatcher.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,29 @@ public function getListeners($eventName = null)
7575
return array_filter($this->sorted);
7676
}
7777

78+
/**
79+
* Gets the listener priority for a specific event.
80+
*
81+
* Returns null if the event or the listener does not exist.
82+
*
83+
* @param string $eventName The name of the event
84+
* @param callable $listener The listener
85+
*
86+
* @return int|null The event listener priority
87+
*/
88+
public function getListenerPriority($eventName, $listener)
89+
{
90+
if (!isset($this->listeners[$eventName])) {
91+
return;
92+
}
93+
94+
foreach ($this->listeners[$eventName] as $priority => $listeners) {
95+
if (false !== ($key = array_search($listener, $listeners, true))) {
96+
return $priority;
97+
}
98+
}
99+
}
100+
78101
/**
79102
* {@inheritdoc}
80103
*/

src/Symfony/Component/HttpKernel/Debug/TraceableEventDispatcher.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,25 @@ public function getListeners($eventName = null)
119119
return $this->dispatcher->getListeners($eventName);
120120
}
121121

122+
/**
123+
* Gets the listener priority for a specific event.
124+
*
125+
* Returns null if the event or the listener does not exist, or if the
126+
* underlying EventDispatcher does not implement getListenerPriority().
127+
*
128+
* @param string $eventName The name of the event
129+
* @param callable $listener The listener
130+
*
131+
* @return int|null The event listener priority
132+
*/
133+
public function getListenerPriority($eventName, $listener)
134+
{
135+
// For BC reaons, getListenerPriority() is not defined on EventDispatcherInterface.
136+
if (method_exists($this->dispatcher, 'getListenerPriority')) {
137+
return $this->dispatcher->getListenerPriority($eventName, $listener);
138+
}
139+
}
140+
122141
/**
123142
* {@inheritdoc}
124143
*/
@@ -392,10 +411,11 @@ private function preDispatch($eventName, $eventId, Event $event)
392411
$listeners = $this->dispatcher->getListeners($eventName);
393412

394413
foreach ($listeners as $listener) {
414+
$priority = $this->getListenerPriority($eventName, $listener);
395415
$this->dispatcher->removeListener($eventName, $listener);
396416
$wrapped = $this->wrapListener($eventName, $eventId, $listener);
397417
$this->wrappedListeners[$eventId][$wrapped] = $listener;
398-
$this->dispatcher->addListener($eventName, $wrapped);
418+
$this->dispatcher->addListener($eventName, $wrapped, $priority);
399419
}
400420

401421
switch ($eventName) {
@@ -455,8 +475,10 @@ private function postDispatch($eventName, $eventId, Event $event)
455475
}
456476

457477
foreach ($this->wrappedListeners[$eventId] as $wrapped) {
478+
$listener = $this->wrappedListeners[$eventId][$wrapped];
479+
$priority = $this->getListenerPriority($eventName, $wrapped);
458480
$this->dispatcher->removeListener($eventName, $wrapped);
459-
$this->dispatcher->addListener($eventName, $this->wrappedListeners[$eventId][$wrapped]);
481+
$this->dispatcher->addListener($eventName, $listener, $priority);
460482
}
461483

462484
unset($this->wrappedListeners[$eventId]);

src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,23 @@ public function testHasListeners()
5858
$this->assertTrue($tdispatcher->hasListeners('foo'));
5959
}
6060

61+
public function testGetListenerPriority()
62+
{
63+
$dispatcher = new EventDispatcher();
64+
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
65+
66+
$tdispatcher->addListener('foo', function () {}, 123);
67+
68+
$listeners = $dispatcher->getListeners('foo');
69+
$this->assertSame(123, $tdispatcher->getListenerPriority('foo', $listeners[0]));
70+
71+
// Verify that priority is preserved when listener is removed and re-added
72+
// in preProcess() and postProcess().
73+
$tdispatcher->dispatch('foo', new Event());
74+
$listeners = $dispatcher->getListeners('foo');
75+
$this->assertSame(123, $tdispatcher->getListenerPriority('foo', $listeners[0]));
76+
}
77+
6178
public function testAddRemoveSubscriber()
6279
{
6380
$dispatcher = new EventDispatcher();

0 commit comments

Comments
 (0)