diff --git a/src/Symfony/Bridge/Doctrine/ContainerAwareEventManager.php b/src/Symfony/Bridge/Doctrine/ContainerAwareEventManager.php index db5cc920f361f..be31c7218af5b 100644 --- a/src/Symfony/Bridge/Doctrine/ContainerAwareEventManager.php +++ b/src/Symfony/Bridge/Doctrine/ContainerAwareEventManager.php @@ -32,6 +32,7 @@ class ContainerAwareEventManager extends EventManager private $subscribers; private $initialized = []; private $initializedSubscribers = false; + private $initializedHashMapping = []; private $methods = []; private $container; @@ -138,6 +139,7 @@ public function addEventListener($events, $listener) if (\is_string($listener)) { unset($this->initialized[$event]); + unset($this->initializedHashMapping[$event][$hash]); } else { $this->methods[$event][$hash] = $this->getMethod($listener, $event); } @@ -158,6 +160,11 @@ public function removeEventListener($events, $listener) $hash = $this->getHash($listener); foreach ((array) $events as $event) { + if (isset($this->initializedHashMapping[$event][$hash])) { + $hash = $this->initializedHashMapping[$event][$hash]; + unset($this->initializedHashMapping[$event][$hash]); + } + // Check if we actually have this listener associated if (isset($this->listeners[$event][$hash])) { unset($this->listeners[$event][$hash]); @@ -190,13 +197,25 @@ public function removeEventSubscriber(EventSubscriber $subscriber): void private function initializeListeners(string $eventName) { $this->initialized[$eventName] = true; + + // We'll refill the whole array in order to keep the same order + $listeners = []; foreach ($this->listeners[$eventName] as $hash => $listener) { if (\is_string($listener)) { - $this->listeners[$eventName][$hash] = $listener = $this->container->get($listener); + $listener = $this->container->get($listener); + $newHash = $this->getHash($listener); + + $this->initializedHashMapping[$eventName][$hash] = $newHash; - $this->methods[$eventName][$hash] = $this->getMethod($listener, $eventName); + $listeners[$newHash] = $listener; + + $this->methods[$eventName][$newHash] = $this->getMethod($listener, $eventName); + } else { + $listeners[$hash] = $listener; } } + + $this->listeners[$eventName] = $listeners; } private function initializeSubscribers() diff --git a/src/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php b/src/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php index 9d86eeed54ef1..80d6e30a22453 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php @@ -202,6 +202,21 @@ public function testRemoveEventListener() $this->assertSame([], $this->evm->getListeners('foo')); } + public function testRemoveAllEventListener() + { + $this->container->set('lazy', new MyListener()); + $this->evm->addEventListener('foo', 'lazy'); + $this->evm->addEventListener('foo', new MyListener()); + + foreach ($this->evm->getAllListeners() as $event => $listeners) { + foreach ($listeners as $listener) { + $this->evm->removeEventListener($event, $listener); + } + } + + $this->assertSame([], $this->evm->getListeners('foo')); + } + public function testRemoveEventListenerAfterDispatchEvent() { $this->container->set('lazy', $listener1 = new MyListener());