Browse Source

Merge remote branch 'vicb/service-event'

* vicb/service-event:
  [FrameworkBundle] Optimization of the method ContainerAwareEventDispacther::dispatch()
  [FrameworkBundle] Fix an issue with ContainerAwareEventDispatcher when re-entering a scope
Fabien Potencier 14 years ago
parent
commit
59c6609aec

+ 16 - 1
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;
             }
         }
 

+ 43 - 2
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');
     }
 }