diff --git a/src/Symfony/Component/EventDispatcher/EventDispatcher.php b/src/Symfony/Component/EventDispatcher/EventDispatcher.php index 1906f01b6135f..ad6287ed8cfe5 100644 --- a/src/Symfony/Component/EventDispatcher/EventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/EventDispatcher.php @@ -24,9 +24,9 @@ class EventDispatcher /** * Connects a listener to a given event name. * - * @param string $name An event name - * @param mixed $listener A PHP callable - * @param integer $priority The priority (between -10 and 10 -- defaults to 0) + * @param string|null $name An event name or null to make the listener listen to all events + * @param mixed $listener A PHP callable + * @param integer $priority The priority (between -10 and 10 -- defaults to 0) */ public function connect($name, $listener, $priority = 0) { @@ -40,17 +40,22 @@ public function connect($name, $listener, $priority = 0) /** * Disconnects a listener for a given event name. * - * @param string $name An event name - * @param mixed|null $listener A PHP callable or null to disconnect all listeners + * @param string|null $name An event name or null to disconnect a global listener + * @param mixed|null $listener A PHP callable or null to disconnect all listeners * * @return mixed false if listener does not exist, null otherwise */ - public function disconnect($name, $listener = null) + public function disconnect($name=null, $listener = null) { if (!isset($this->listeners[$name])) { return false; } + if (null === $listener) { + unset($this->listeners[$name]); + return; + } + foreach ($this->listeners[$name] as $priority => $callables) { foreach ($callables as $i => $callable) { if ($listener === $callable) { @@ -69,7 +74,7 @@ public function disconnect($name, $listener = null) */ public function notify(Event $event) { - foreach ($this->getListeners($event->getName()) as $listener) { + foreach ($this->getListeners($event->getName(), true) as $listener) { call_user_func($listener, $event); } @@ -85,7 +90,7 @@ public function notify(Event $event) */ public function notifyUntil(Event $event) { - foreach ($this->getListeners($event->getName()) as $listener) { + foreach ($this->getListeners($event->getName(), true) as $listener) { if (call_user_func($listener, $event)) { $event->setProcessed(true); break; @@ -105,7 +110,7 @@ public function notifyUntil(Event $event) */ public function filter(Event $event, $value) { - foreach ($this->getListeners($event->getName()) as $listener) { + foreach ($this->getListeners($event->getName(), true) as $listener) { $value = call_user_func($listener, $event, $value); } @@ -117,30 +122,47 @@ public function filter(Event $event, $value) /** * Returns true if the given event name has some listeners. * - * @param string $name The event name + * @param string $name The event name + * @param boolean $includeGlobals Flag whether the global listeners + * (name=null) should be included * * @return Boolean true if some listeners are connected, false otherwise */ - public function hasListeners($name) + public function hasListeners($name, $includeGlobals=false) { - return (Boolean) count($this->getListeners($name)); + return (Boolean) count($this->getListeners($name, $includeGlobals)); } /** * Returns all listeners associated with a given event name. * - * @param string $name The event name - * + * @param string $name The event name + * @param boolean $includeGlobals Flag whether the global listeners + * (name=null) should be included * @return array An array of listeners */ - public function getListeners($name) + public function getListeners($name, $includeGlobals=false) { if (!isset($this->listeners[$name])) { return array(); } - + $listeners = array(); $all = $this->listeners[$name]; + + // add global listeners if required and existing, but only if the + // it's not global collection which is requested + if (isset($this->listeners[null]) && $includeGlobals && $name != null) { + foreach ($this->listeners[null] as $prio => $globalListeners) { + if (isset($all[$prio])) { + $all[$prio] = array_merge($all[$prio], $globalListeners); + } else { + $all[$prio] = $globalListeners; + } + } + } + + // sort with respect to priority and flatten array ksort($all); foreach ($all as $l) { $listeners = array_merge($listeners, $l); diff --git a/tests/Symfony/Tests/Component/EventDispatcher/EventDispatcherTest.php b/tests/Symfony/Tests/Component/EventDispatcher/EventDispatcherTest.php index be6b7cf11e82d..bc5f5a5c420d4 100644 --- a/tests/Symfony/Tests/Component/EventDispatcher/EventDispatcherTest.php +++ b/tests/Symfony/Tests/Component/EventDispatcher/EventDispatcherTest.php @@ -30,6 +30,10 @@ public function testConnectAndDisconnect() $this->assertEquals(array('listenToBarBar'), $dispatcher->getListeners('barbar'), '->disconnect() disconnects a listener for an event name'); $this->assertFalse($dispatcher->disconnect('foobar', 'listen'), '->disconnect() returns false if the listener does not exist'); + + $dispatcher->disconnect('bar'); + $this->assertEquals(array(), $dispatcher->getListeners('bar'), '->disconnect() without a listener disconnects all listeners of for an event name'); + $this->assertEquals(array('listenToBarBar'), $dispatcher->getListeners('barbar'), '->disconnect() without a listener disconnects all listeners of for an event name'); } public function testGetHasListeners() @@ -100,6 +104,22 @@ public function testFilter() $e = $dispatcher->filter($event = new Event(new \stdClass(), 'foo'), 'foo'); $this->assertEquals('*-foo-*', $e->getReturnValue(), '->filter() filters a value'); } + + public function testGlobalConnectAndDisconnect() + { + $dispatcher = new EventDispatcher(); + $dispatcher->connect('bar', 'listenToBar'); + $dispatcher->connect('barbar', 'listenToBar'); + $dispatcher->connect(null, 'listenToBarBar'); + $this->assertEquals(array('listenToBar', 'listenToBarBar'), $dispatcher->getListeners('bar', true), '->connect() with event name null connects a global listener (1)'); + $this->assertEquals(array('listenToBar', 'listenToBarBar'), $dispatcher->getListeners('barbar', true), '->connect() with event name null connects a global listener (2)'); + $this->assertEquals(array('listenToBar'), $dispatcher->getListeners('bar', false), '->connect() with event name null connects a global listener (3)'); + $this->assertEquals(array('listenToBar'), $dispatcher->getListeners('barbar', false), '->connect() with event name null connects a global listener (4)'); + + $dispatcher->disconnect(null, 'listenToBarBar'); + $this->assertEquals(array('listenToBar'), $dispatcher->getListeners('bar', true), '->disconnect() with event name null disconnects a global listener'); + } + } class Listener
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: