diff --git a/lib/Cake/Event/CakeEventManager.php b/lib/Cake/Event/CakeEventManager.php index 22d79315654..5fe7cc65dd3 100644 --- a/lib/Cake/Event/CakeEventManager.php +++ b/lib/Cake/Event/CakeEventManager.php @@ -88,6 +88,9 @@ public function attach($callable, $eventKey = null, $options = array()) { * @return void */ public function detach($callable, $eventKey = null) { + if ($callable instanceof CakeEventListener) { + return $this->_detachSubscriber($callable, $eventKey); + } if (empty($eventKey)) { foreach (array_keys($this->_listeners) as $eventKey) { $this->detach($callable, $eventKey); @@ -107,6 +110,28 @@ public function detach($callable, $eventKey = null) { } } +/** + * Auxiliary function to help detach all listeners provided by an object implementing CakeEventListener + * + * @param CakeEventListener $subscriber the subscriber to be detached + * @param string $eventKey optional event key name to unsubscribe the listener from + * @return void + */ + protected function _detachSubscriber(CakeEventListener $subscriber, $eventKey = null) { + $events = $subscriber->implementedEvents(); + if (!empty($eventKey) && empty($events[$eventKey])) { + return; + } else if (!empty($eventKey)) { + $events = array($eventKey => $events[$eventKey]); + } + foreach ($events as $key => $function) { + if (is_array($function)) { + $function = $function['callable']; + } + $this->detach(array($subscriber, $function), $key); + } + } + /** * Dispatches a new event to all configured listeners * diff --git a/lib/Cake/Test/Case/Event/CakeEventManagerTest.php b/lib/Cake/Test/Case/Event/CakeEventManagerTest.php index 555c2609edb..40295cc6c99 100644 --- a/lib/Cake/Test/Case/Event/CakeEventManagerTest.php +++ b/lib/Cake/Test/Case/Event/CakeEventManagerTest.php @@ -251,4 +251,26 @@ public function testAttachSubscriber() { $event = new CakeEvent('another.event', $this, array('some' => 'data')); $manager->dispatch($event); } + +/** + * Tests subscribing a listener object and firing the events it subscribed to + * + * @return void + */ + public function testDetachSubscriber() { + $manager = new CakeEventManager; + $listener = $this->getMock('CustomTestEventListerner', array('secondListenerFunction')); + $manager->attach($listener); + $expected = array( + array('callable' => array($listener, 'secondListenerFunction'), 'passParams' => true) + ); + $this->assertEquals($expected, $manager->listeners('another.event')); + $expected = array( + array('callable' => array($listener, 'listenerFunction'), 'passParams' => false) + ); + $this->assertEquals($expected, $manager->listeners('fake.event')); + $manager->detach($listener); + $this->assertEquals(array(), $manager->listeners('fake.event')); + $this->assertEquals(array(), $manager->listeners('another.event')); + } } \ No newline at end of file