diff --git a/src/Symfony/Bundle/FrameworkBundle/ContainerAwareEventDispatcher.php b/src/Symfony/Bundle/FrameworkBundle/ContainerAwareEventDispatcher.php index 87479a0aa6..238dc7090b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/ContainerAwareEventDispatcher.php +++ b/src/Symfony/Bundle/FrameworkBundle/ContainerAwareEventDispatcher.php @@ -36,6 +36,12 @@ class ContainerAwareEventDispatcher extends EventDispatcher */ private $listenerIds = array(); + /** + * The services registered as listeners + * @var array + */ + private $listeners = array(); + /** * Constructor. * @@ -79,7 +85,16 @@ class ContainerAwareEventDispatcher extends EventDispatcher { if (isset($this->listenerIds[$eventName])) { foreach ($this->listenerIds[$eventName] as $serviceId => $priority) { - $this->addListener($eventName, $this->container->get($serviceId), $priority); + $listener = $this->container->get($serviceId); + + if (!isset($this->listeners[$eventName][$serviceId])) { + $this->addListener($eventName, $listener, $priority); + } elseif ($listener !== $this->listeners[$eventName][$serviceId]) { + $this->removeListener($eventName, $this->listeners[$eventName][$serviceId]); + $this->addListener($eventName, $listener, $priority); + } + + $this->listeners[$eventName][$serviceId] = $listener; } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/ContainerAwareEventDispatcherTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/ContainerAwareEventDispatcherTest.php index ea06810311..bd48fbaa70 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/ContainerAwareEventDispatcherTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/ContainerAwareEventDispatcherTest.php @@ -60,17 +60,58 @@ class ContainerAwareEventDispatcherTest extends \PHPUnit_Framework_TestCase $service = $this->getMock('Symfony\Bundle\FrameworkBundle\Tests\Service'); $scope = new Scope('scope'); - $container = new Container(); $container->addScope($scope); $container->enterScope('scope'); + $container->set('service.listener', $service, 'scope'); $dispatcher = new ContainerAwareEventDispatcher($container); $dispatcher->addListenerService('onEvent', 'service.listener'); $container->leaveScope('scope'); - $dispatcher->dispatch('onEvent'); + $dispatcher->dispatch('onEvent'); + } + + public function testReEnteringAScope() + { + $event = new Event(); + + $service1 = $this->getMock('Symfony\Bundle\FrameworkBundle\Tests\Service'); + + $service1 + ->expects($this->exactly(2)) + ->method('onEvent') + ->with($event) + ; + + $scope = new Scope('scope'); + $container = new Container(); + $container->addScope($scope); + $container->enterScope('scope'); + + $container->set('service.listener', $service1, 'scope'); + + $dispatcher = new ContainerAwareEventDispatcher($container); + $dispatcher->addListenerService('onEvent', 'service.listener'); + $dispatcher->dispatch('onEvent', $event); + + $service2 = $this->getMock('Symfony\Bundle\FrameworkBundle\Tests\Service'); + + $service2 + ->expects($this->once()) + ->method('onEvent') + ->with($event) + ; + + $container->enterScope('scope'); + $container->set('service.listener', $service2, 'scope'); + + $dispatcher->dispatch('onEvent', $event); + + $container->leaveScope('scope'); + + $dispatcher->dispatch('onEvent'); } }