Skip to content

Commit 6a4d765

Browse files
committed
bug symfony#10191 [HttpKernel] fixed wrong reference in TraceableEventDispatcher (fabpot)
This PR was merged into the 2.3 branch. Discussion ---------- [HttpKernel] fixed wrong reference in TraceableEventDispatcher | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | symfony#9748, symfony#9727 | License | MIT | Doc PR | n/a This PR fixes symfony#9748 and symfony#9727 by removing the `id` state. Only private method signatures have been changed, so that qualifies for a fix in 2.3. The `getNotCalledListeners()` is a bit special as it tries to get non-called listeners. It passes `null` as the event id as if a listener has been called more than once, getting the first call is enough. Commits ------- acd3317 [HttpKernel] fixed wrong reference in TraceableEventDispatcher
2 parents 5e12d74 + acd3317 commit 6a4d765

File tree

1 file changed

+35
-31
lines changed

1 file changed

+35
-31
lines changed

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

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ class TraceableEventDispatcher implements EventDispatcherInterface, TraceableEve
3838
private $dispatcher;
3939
private $wrappedListeners;
4040
private $firstCalledEvent;
41-
private $id;
4241
private $lastEventId = 0;
4342

4443
/**
@@ -125,9 +124,9 @@ public function dispatch($eventName, Event $event = null)
125124
$event = new Event();
126125
}
127126

128-
$this->id = $eventId = ++$this->lastEventId;
127+
$eventId = ++$this->lastEventId;
129128

130-
$this->preDispatch($eventName, $event);
129+
$this->preDispatch($eventName, $eventId, $event);
131130

132131
$e = $this->stopwatch->start($eventName, 'section');
133132

@@ -139,14 +138,11 @@ public function dispatch($eventName, Event $event = null)
139138

140139
$this->dispatcher->dispatch($eventName, $event);
141140

142-
// reset the id as another event might have been dispatched during the dispatching of this event
143-
$this->id = $eventId;
144-
145141
unset($this->firstCalledEvent[$eventName]);
146142

147143
$e->stop();
148144

149-
$this->postDispatch($eventName, $event);
145+
$this->postDispatch($eventName, $eventId, $event);
150146

151147
return $event;
152148
}
@@ -168,7 +164,7 @@ public function getNotCalledListeners()
168164

169165
foreach ($this->getListeners() as $name => $listeners) {
170166
foreach ($listeners as $listener) {
171-
$info = $this->getListenerInfo($listener, $name);
167+
$info = $this->getListenerInfo($listener, null, $name);
172168
if (!isset($this->called[$name.'.'.$info['pretty']])) {
173169
$notCalled[$name.'.'.$info['pretty']] = $info;
174170
}
@@ -198,24 +194,24 @@ public function __call($method, $arguments)
198194
* Whenever Symfony will require PHP 5.4, this could be changed
199195
* to a proper private method.
200196
*/
201-
public function logSkippedListeners($eventName, Event $event, $listener)
197+
public function logSkippedListeners($eventName, $eventId, Event $event, $listener)
202198
{
203199
if (null === $this->logger) {
204200
return;
205201
}
206202

207-
$info = $this->getListenerInfo($listener, $eventName);
203+
$info = $this->getListenerInfo($listener, $eventId, $eventName);
208204

209205
$this->logger->debug(sprintf('Listener "%s" stopped propagation of the event "%s".', $info['pretty'], $eventName));
210206

211207
$skippedListeners = $this->getListeners($eventName);
212208
$skipped = false;
213209

214210
foreach ($skippedListeners as $skippedListener) {
215-
$skippedListener = $this->unwrapListener($skippedListener);
211+
$skippedListener = $this->unwrapListener($skippedListener, $eventId);
216212

217213
if ($skipped) {
218-
$info = $this->getListenerInfo($skippedListener, $eventName);
214+
$info = $this->getListenerInfo($skippedListener, $eventId, $eventName);
219215
$this->logger->debug(sprintf('Listener "%s" was not called for event "%s".', $info['pretty'], $eventName));
220216
}
221217

@@ -232,7 +228,7 @@ public function logSkippedListeners($eventName, Event $event, $listener)
232228
* Whenever Symfony will require PHP 5.4, this could be changed
233229
* to a proper private method.
234230
*/
235-
public function preListenerCall($eventName, $listener)
231+
public function preListenerCall($eventName, $eventId, $listener)
236232
{
237233
// is it the first called listener?
238234
if (isset($this->firstCalledEvent[$eventName])) {
@@ -241,7 +237,7 @@ public function preListenerCall($eventName, $listener)
241237
unset($this->firstCalledEvent[$eventName]);
242238
}
243239

244-
$info = $this->getListenerInfo($listener, $eventName);
240+
$info = $this->getListenerInfo($listener, $eventId, $eventName);
245241

246242
if (null !== $this->logger) {
247243
$this->logger->debug(sprintf('Notified event "%s" to listener "%s".', $eventName, $info['pretty']));
@@ -260,9 +256,9 @@ public function preListenerCall($eventName, $listener)
260256
*
261257
* @return array Information about the listener
262258
*/
263-
private function getListenerInfo($listener, $eventName)
259+
private function getListenerInfo($listener, $eventId, $eventName)
264260
{
265-
$listener = $this->unwrapListener($listener);
261+
$listener = $this->unwrapListener($listener, $eventId);
266262

267263
$info = array(
268264
'event' => $eventName,
@@ -365,17 +361,17 @@ private function saveInfoInProfile(Profile $profile, $updateChildren)
365361
}
366362
}
367363

368-
private function preDispatch($eventName, Event $event)
364+
private function preDispatch($eventName, $eventId, Event $event)
369365
{
370366
// wrap all listeners before they are called
371-
$this->wrappedListeners[$this->id] = new \SplObjectStorage();
367+
$this->wrappedListeners[$eventId] = new \SplObjectStorage();
372368

373369
$listeners = $this->dispatcher->getListeners($eventName);
374370

375371
foreach ($listeners as $listener) {
376372
$this->dispatcher->removeListener($eventName, $listener);
377-
$wrapped = $this->wrapListener($eventName, $listener);
378-
$this->wrappedListeners[$this->id][$wrapped] = $listener;
373+
$wrapped = $this->wrapListener($eventName, $eventId, $listener);
374+
$this->wrappedListeners[$eventId][$wrapped] = $listener;
379375
$this->dispatcher->addListener($eventName, $wrapped);
380376
}
381377

@@ -404,7 +400,7 @@ private function preDispatch($eventName, Event $event)
404400
}
405401
}
406402

407-
private function postDispatch($eventName, Event $event)
403+
private function postDispatch($eventName, $eventId, Event $event)
408404
{
409405
switch ($eventName) {
410406
case KernelEvents::CONTROLLER:
@@ -433,36 +429,44 @@ private function postDispatch($eventName, Event $event)
433429
break;
434430
}
435431

436-
foreach ($this->wrappedListeners[$this->id] as $wrapped) {
432+
foreach ($this->wrappedListeners[$eventId] as $wrapped) {
437433
$this->dispatcher->removeListener($eventName, $wrapped);
438-
$this->dispatcher->addListener($eventName, $this->wrappedListeners[$this->id][$wrapped]);
434+
$this->dispatcher->addListener($eventName, $this->wrappedListeners[$eventId][$wrapped]);
439435
}
440436

441-
unset($this->wrappedListeners[$this->id]);
437+
unset($this->wrappedListeners[$eventId]);
442438
}
443439

444-
private function wrapListener($eventName, $listener)
440+
private function wrapListener($eventName, $eventId, $listener)
445441
{
446442
$self = $this;
447443

448-
return function (Event $event) use ($self, $eventName, $listener) {
449-
$e = $self->preListenerCall($eventName, $listener);
444+
return function (Event $event) use ($self, $eventName, $eventId, $listener) {
445+
$e = $self->preListenerCall($eventName, $eventId, $listener);
450446

451447
call_user_func($listener, $event);
452448

453449
$e->stop();
454450

455451
if ($event->isPropagationStopped()) {
456-
$self->logSkippedListeners($eventName, $event, $listener);
452+
$self->logSkippedListeners($eventName, $eventId, $event, $listener);
457453
}
458454
};
459455
}
460456

461-
private function unwrapListener($listener)
457+
private function unwrapListener($listener, $eventId)
462458
{
463459
// get the original listener
464-
if (is_object($listener) && isset($this->wrappedListeners[$this->id][$listener])) {
465-
return $this->wrappedListeners[$this->id][$listener];
460+
if (is_object($listener)) {
461+
if (null === $eventId) {
462+
foreach (array_keys($this->wrappedListeners) as $eventId) {
463+
if (isset($this->wrappedListeners[$eventId][$listener])) {
464+
return $this->wrappedListeners[$eventId][$listener];
465+
}
466+
}
467+
} elseif (isset($this->wrappedListeners[$eventId][$listener])) {
468+
return $this->wrappedListeners[$eventId][$listener];
469+
}
466470
}
467471

468472
return $listener;

0 commit comments

Comments
 (0)