Skip to content
Browse files

[HttpKernel] fixed the traceable event dispatcher when an event of a …

…name is dispatched when an event of the same name is already being dispatched
  • Loading branch information...
1 parent 0f67dca commit 2be47200e0a017263e259b451b05b0ba9be84967 @fabpot fabpot committed Oct 4, 2012
View
28 src/Symfony/Component/HttpKernel/Debug/TraceableEventDispatcher.php
@@ -37,6 +37,7 @@ class TraceableEventDispatcher implements EventDispatcherInterface, TraceableEve
private $dispatcher;
private $wrappedListeners;
private $firstCalledEvent;
+ private $id;
/**
* Constructor.
@@ -118,6 +119,12 @@ public function hasListeners($eventName = null)
*/
public function dispatch($eventName, Event $event = null)
{
+ if (null === $event) {
+ $event = new Event();
+ }
+
+ $this->id = spl_object_hash($event);
+
$this->preDispatch($eventName, $event);
$e = $this->stopwatch->start($eventName, 'section');
@@ -126,6 +133,9 @@ public function dispatch($eventName, Event $event = null)
$this->dispatcher->dispatch($eventName, $event);
+ // reset the id as another event might have been dispatched during the dispatching of this event
+ $this->id = spl_object_hash($event);
+
unset($this->firstCalledEvent[$eventName]);
$e->stop();
@@ -342,17 +352,17 @@ private function getListenerAsString($listener)
return '[?] '.var_export($listener, true);
}
- private function preDispatch($eventName, Event $event = null)
+ private function preDispatch($eventName, Event $event)
{
// wrap all listeners before they are called
- $this->wrappedListeners[$eventName] = new \SplObjectStorage();
+ $this->wrappedListeners[$this->id] = new \SplObjectStorage();
$listeners = $this->dispatcher->getListeners($eventName);
foreach ($listeners as $listener) {
$this->dispatcher->removeListener($eventName, $listener);
$wrapped = $this->wrapListener($eventName, $listener);
- $this->wrappedListeners[$eventName][$wrapped] = $listener;
+ $this->wrappedListeners[$this->id][$wrapped] = $listener;
$this->dispatcher->addListener($eventName, $wrapped);
}
@@ -375,7 +385,7 @@ private function preDispatch($eventName, Event $event = null)
}
}
- private function postDispatch($eventName, Event $event = null)
+ private function postDispatch($eventName, Event $event)
{
switch ($eventName) {
case 'kernel.controller':
@@ -400,12 +410,12 @@ private function postDispatch($eventName, Event $event = null)
break;
}
- foreach ($this->wrappedListeners[$eventName] as $wrapped) {
+ foreach ($this->wrappedListeners[$this->id] as $wrapped) {
$this->dispatcher->removeListener($eventName, $wrapped);
- $this->dispatcher->addListener($eventName, $this->wrappedListeners[$eventName][$wrapped]);
+ $this->dispatcher->addListener($eventName, $this->wrappedListeners[$this->id][$wrapped]);
}
- unset($this->wrappedListeners[$eventName]);
+ unset($this->wrappedListeners[$this->id]);
}
private function wrapListener($eventName, $listener)
@@ -428,8 +438,8 @@ private function wrapListener($eventName, $listener)
private function unwrapListener($listener, $eventName)
{
// get the original listener
- if (is_object($listener) && isset($this->wrappedListeners[$eventName][$listener])) {
- return $this->wrappedListeners[$eventName][$listener];
+ if (is_object($listener) && isset($this->wrappedListeners[$this->id][$listener])) {
+ return $this->wrappedListeners[$this->id][$listener];
}
return $listener;
View
14 src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php
@@ -145,6 +145,20 @@ public function testDispatchCallListeners()
$this->assertEquals(array('foo1', 'foo2'), $called);
}
+ public function testDispatchNested()
+ {
+ $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
+ $loop = 1;
+ $dispatcher->addListener('foo', $listener1 = function () use ($dispatcher, &$loop) {
+ ++$loop;
+ if (2 == $loop) {
+ $dispatcher->dispatch('foo');
+ }
+ });
+
+ $dispatcher->dispatch('foo');
+ }
+
public function testStopwatchSections()
{
$dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch = new Stopwatch());

0 comments on commit 2be4720

Please sign in to comment.
Something went wrong with that request. Please try again.