Permalink
Browse files

Starting to add subscriber classes support, inverted the parameter or…

…der for CakeEventManager::attach()
  • Loading branch information...
1 parent e8044cd commit bef20e61756245d6d2744bb3c153168f9c834de9 @lorenzo lorenzo committed Dec 13, 2011
@@ -0,0 +1,47 @@
+<?php
+/**
+ *
+ * PHP 5
+ *
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link http://cakephp.org CakePHP(tm) Project
+ * @package Cake.Observer
+ * @since CakePHP(tm) v 2.1
+ * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
+ */
+
+/**
+ * Objects implementing this interface should declare the `implementedEvents` function
+ * to hint the event manager what methods should be called when an event is triggered.
+ *
+ * @package Cake.Event
+ */
+interface CakeEventListener {
+
+/**
+ * Returns a list of events this object is implementing, when the class is registered
+ * in an event manager, each individual method will be associated to the respective event.
+ *
+ * ## Example:
+ *
+ * {{{
+ * public function implementedEvents() {
+ * return array(
+ * 'Order.complete' => 'sendEmail',
+ * 'Article.afterBuy' => 'decrementInventory',
+ * 'User.onRegister' => array('callable' => 'logRegistration', 'priority' => 20, 'passParams' => true)
+ * );
+ * }
+ * }}}
+ *
+ * @return array associative array or event key names pointing to the function
+ * that should be called in the object when the respective event is fired
+ */
+ public function implementedEvents();
+}
@@ -16,6 +16,7 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
+App::uses('CakeEventListener', 'Event');
/**
* The event manager is responsible for keeping track of event listeners and pass the correct
@@ -44,12 +45,35 @@ class CakeEventManager {
/**
* Adds a new listener to an event. Listeners
*
- * @param mixed $eventKey The event unique identifier name to with the callback will be associated
- * @param callback|CakeListener PHP valid callback type or instance of CakeListener to be called
+ * @param callback|CakeEventListener $callable PHP valid callback type or instance of CakeListener to be called
* when the event named with $eventKey is triggered.
+ * @param mixed $eventKey The event unique identifier name to with the callback will be associated. If $callable
+ * is an instance of CakeEventListener this argument will be ignored
+ * @param array $options used to set the `priority` and `passParams` flags to the listener.
+ * Priorities are handled like queues, and multiple attachments into the same priority queue will be treated in
+ * the order of insertion. `passParams` means that the event data property will be converted to function arguments
+ * when the listener is called. If $called is an instance of CakeEventListener, this parameter will be ignored
* @return void
*/
- public function attach($eventKey, $callable, $options = array()) {
+ public function attach($callable, $eventKey = null, $options = array()) {
+ if (!$eventKey && !($callable instanceof CakeEventListener)) {
+ throw new InvalidArgumentException(__d('cake_dev', 'The eventKey variable is required'));
+ }
+ if ($callable instanceof CakeEventListener) {
+ foreach ($callable->implementedEvents() as $eventKey => $function) {
+ $options = array();
+ $method = null;
+ if (is_array($function)) {
+ $method = array($callable, $function['callable']);
+ unset($function['callable']);
+ $options = $function;
+ } else {
+ $method = array($callable, $function);
+ }
+ $this->attach($method, $eventKey, $options);
+ }
+ return;
+ }
$options = $options + array('priority' => self::$defaultPriority, 'passParams' => false);
$this->_listeners[$eventKey][$options['priority']][] = array(
'callable' => $callable,
No changes.
@@ -63,19 +63,19 @@ class CakeEventManagerTest extends CakeTestCase {
*/
public function testAttachListeners() {
$manager = new CakeEventManager;
- $manager->attach('fake.event', 'fakeFunction');
+ $manager->attach('fakeFunction', 'fake.event');
$expected = array(
array('callable' => 'fakeFunction', 'passParams' => false)
);
$this->assertEquals($expected, $manager->listeners('fake.event'));
- $manager->attach('fake.event', 'fakeFunction2');
+ $manager->attach('fakeFunction2', 'fake.event');
$expected[] = array('callable' => 'fakeFunction2', 'passParams' => false);
$this->assertEquals($expected, $manager->listeners('fake.event'));
- $manager->attach('fake.event', 'inQ5', array('priority' => 5));
- $manager->attach('fake.event', 'inQ1', array('priority' => 1));
- $manager->attach('fake.event', 'otherInQ5', array('priority' => 5));
+ $manager->attach('inQ5', 'fake.event', array('priority' => 5));
+ $manager->attach('inQ1', 'fake.event', array('priority' => 1));
+ $manager->attach('otherInQ5', 'fake.event', array('priority' => 5));
$expected = array_merge(
array(
@@ -95,9 +95,9 @@ public function testAttachListeners() {
*/
public function testAttachMultipleEventKeys() {
$manager = new CakeEventManager;
- $manager->attach('fake.event', 'fakeFunction');
- $manager->attach('another.event', 'fakeFunction2');
- $manager->attach('another.event', 'fakeFunction3', array('priority' => 1, 'passParams' => true));
+ $manager->attach('fakeFunction', 'fake.event');
+ $manager->attach('fakeFunction2', 'another.event');
+ $manager->attach('fakeFunction3', 'another.event', array('priority' => 1, 'passParams' => true));
$expected = array(
array('callable' => 'fakeFunction', 'passParams' => false)
);
@@ -117,9 +117,9 @@ public function testAttachMultipleEventKeys() {
*/
public function testDetach() {
$manager = new CakeEventManager;
- $manager->attach('fake.event', array('AClass', 'aMethod'));
- $manager->attach('another.event', array('AClass', 'anotherMethod'));
- $manager->attach('another.event', 'fakeFunction', array('priority' => 1));
+ $manager->attach(array('AClass', 'aMethod'), 'fake.event');
+ $manager->attach(array('AClass', 'anotherMethod'), 'another.event');
+ $manager->attach('fakeFunction', 'another.event', array('priority' => 1));
$manager->detach(array('AClass', 'aMethod'), 'fake.event');
$this->assertEquals(array(), $manager->listeners('fake.event'));
@@ -141,9 +141,9 @@ public function testDetach() {
*/
public function testDetachFromAll() {
$manager = new CakeEventManager;
- $manager->attach('fake.event', array('AClass', 'aMethod'));
- $manager->attach('another.event', array('AClass', 'aMethod'));
- $manager->attach('another.event', 'fakeFunction', array('priority' => 1));
+ $manager->attach(array('AClass', 'aMethod'), 'fake.event');
+ $manager->attach(array('AClass', 'aMethod'), 'another.event');
+ $manager->attach('fakeFunction', 'another.event', array('priority' => 1));
$manager->detach(array('AClass', 'aMethod'));
$expected = array(
@@ -162,8 +162,8 @@ public function testDispatch() {
$manager = new CakeEventManager;
$listener = $this->getMock('CakeEventTestListener');
$anotherListener = $this->getMock('CakeEventTestListener');
- $manager->attach('fake.event', array($listener, 'listenerFunction'));
- $manager->attach('fake.event', array($anotherListener, 'listenerFunction'));
+ $manager->attach(array($listener, 'listenerFunction'), 'fake.event');
+ $manager->attach(array($anotherListener, 'listenerFunction'), 'fake.event');
$event = new CakeEvent('fake.event');
$listener->expects($this->once())->method('listenerFunction')->with($event);
@@ -179,8 +179,8 @@ public function testDispatch() {
public function testDispatchPrioritized() {
$manager = new CakeEventManager;
$listener = new CakeEventTestListener;
- $manager->attach('fake.event', array($listener, 'listenerFunction'));
- $manager->attach('fake.event', array($listener, 'secondListenerFunction'), array('priority' => 5));
+ $manager->attach(array($listener, 'listenerFunction'), 'fake.event');
+ $manager->attach(array($listener, 'secondListenerFunction'), 'fake.event', array('priority' => 5));
$event = new CakeEvent('fake.event');
$manager->dispatch($event);
@@ -197,8 +197,8 @@ public function testDispatchPassingParams() {
$manager = new CakeEventManager;
$listener = $this->getMock('CakeEventTestListener');
$anotherListener = $this->getMock('CakeEventTestListener');
- $manager->attach('fake.event', array($listener, 'listenerFunction'));
- $manager->attach('fake.event', array($anotherListener, 'secondListenerFunction'), array('passParams' => true));
+ $manager->attach(array($listener, 'listenerFunction'), 'fake.event');
+ $manager->attach(array($anotherListener, 'secondListenerFunction'), 'fake.event', array('passParams' => true));
$event = new CakeEvent('fake.event', $this, array('some' => 'data'));
$listener->expects($this->once())->method('listenerFunction')->with($event);

0 comments on commit bef20e6

Please sign in to comment.