Parcourir la source

[FrameworkBundle] ContainerAwareEventDispatcher::removeListener() (closes #3115)

Fabien Potencier il y a 13 ans
Parent
commit
f758884c2b

+ 28 - 1
src/Symfony/Bundle/FrameworkBundle/ContainerAwareEventDispatcher.php

@@ -71,6 +71,33 @@ class ContainerAwareEventDispatcher extends EventDispatcher
         $this->listenerIds[$eventName][] = array($callback[0], $callback[1], $priority);
     }
 
+    public function removeListener($eventName, $listener)
+    {
+        $this->lazyLoad($eventName);
+
+        if (isset($this->listeners[$eventName])) {
+            foreach ($this->listeners[$eventName] as $key => $l) {
+                foreach ($this->listenerIds[$eventName] as $i => $args) {
+                    list($serviceId, $method, $priority) = $args;
+                    if ($key === $serviceId.'.'.$method) {
+                        if ($listener === array($l, $method)) {
+                            unset($this->listeners[$eventName][$key]);
+                            if (empty($this->listeners[$eventName])) {
+                                unset($this->listeners[$eventName]);
+                            }
+                            unset($this->listenerIds[$eventName][$i]);
+                            if (empty($this->listenerIds[$eventName])) {
+                                unset($this->listenerIds[$eventName]);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        parent::removeListener($eventName, $listener);
+    }
+
     /**
      * @see EventDispatcherInterface::hasListeners
      */
@@ -137,7 +164,7 @@ class ContainerAwareEventDispatcher extends EventDispatcher
                 if (!isset($this->listeners[$eventName][$key])) {
                     $this->addListener($eventName, array($listener, $method), $priority);
                 } elseif ($listener !== $this->listeners[$eventName][$key]) {
-                    $this->removeListener($eventName, array($this->listeners[$eventName][$key], $method));
+                    parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method));
                     $this->addListener($eventName, array($listener, $method), $priority);
                 }
 

+ 33 - 0
src/Symfony/Bundle/FrameworkBundle/Tests/ContainerAwareEventDispatcherTest.php

@@ -166,6 +166,39 @@ class ContainerAwareEventDispatcherTest extends \PHPUnit_Framework_TestCase
 
         $this->assertEquals(1, count($dispatcher->getListeners('onEvent')));
     }
+
+    public function testRemoveAfterDispatch()
+    {
+        $event = new Event();
+
+        $service = $this->getMock('Symfony\Bundle\FrameworkBundle\Tests\Service');
+
+        $container = new Container();
+        $container->set('service.listener', $service);
+
+        $dispatcher = new ContainerAwareEventDispatcher($container);
+        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));
+
+        $dispatcher->dispatch('onEvent', new Event());
+        $dispatcher->removeListener('onEvent', array($container->get('service.listener'), 'onEvent'));
+        $this->assertFalse($dispatcher->hasListeners('onEvent'));
+    }
+
+    public function testRemoveBeforeDispatch()
+    {
+        $event = new Event();
+
+        $service = $this->getMock('Symfony\Bundle\FrameworkBundle\Tests\Service');
+
+        $container = new Container();
+        $container->set('service.listener', $service);
+
+        $dispatcher = new ContainerAwareEventDispatcher($container);
+        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));
+
+        $dispatcher->removeListener('onEvent', array($container->get('service.listener'), 'onEvent'));
+        $this->assertFalse($dispatcher->hasListeners('onEvent'));
+    }
 }
 
 class Service