From cc89d4b1a52695cf50de49635dcd651494e9e653 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Mon, 18 Apr 2011 14:51:56 +0200 Subject: [PATCH 1/2] [FrameworkBundle] Fix an issue with ContainerAwareEventDispatcher when re-entering a scope --- .../ContainerAwareEventDispatcher.php | 13 +++++- .../ContainerAwareEventDispatcherTest.php | 45 ++++++++++++++++++- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/ContainerAwareEventDispatcher.php b/src/Symfony/Bundle/FrameworkBundle/ContainerAwareEventDispatcher.php index 87479a0aa6..57f6ebe043 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,12 @@ class ContainerAwareEventDispatcher extends EventDispatcher { if (isset($this->listenerIds[$eventName])) { foreach ($this->listenerIds[$eventName] as $serviceId => $priority) { - $this->addListener($eventName, $this->container->get($serviceId), $priority); + if (isset($this->listeners[$eventName][$serviceId])) { + $this->removeListener($eventName, $this->listeners[$eventName][$serviceId]); + } + $listener = $this->container->get($serviceId); + $this->listeners[$eventName][$serviceId] = $listener; + $this->addListener($eventName, $listener, $priority); } } 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'); } } From 6ae61eb9ffa310ab9c1fa309d5d801dcf1138f6e Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Wed, 20 Apr 2011 15:05:22 +0200 Subject: [PATCH 2/2] [FrameworkBundle] Optimization of the method ContainerAwareEventDispacther::dispatch() --- .../ContainerAwareEventDispatcher.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/ContainerAwareEventDispatcher.php b/src/Symfony/Bundle/FrameworkBundle/ContainerAwareEventDispatcher.php index 57f6ebe043..238dc7090b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/ContainerAwareEventDispatcher.php +++ b/src/Symfony/Bundle/FrameworkBundle/ContainerAwareEventDispatcher.php @@ -85,12 +85,16 @@ class ContainerAwareEventDispatcher extends EventDispatcher { if (isset($this->listenerIds[$eventName])) { foreach ($this->listenerIds[$eventName] as $serviceId => $priority) { - if (isset($this->listeners[$eventName][$serviceId])) { - $this->removeListener($eventName, $this->listeners[$eventName][$serviceId]); - } $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; - $this->addListener($eventName, $listener, $priority); } }