Browse Source

Starting to add subscriber classes support, inverted the parameter order for CakeEventManager::attach()

Jose Lorenzo Rodriguez 14 years ago
parent
commit
bef20e6175

+ 47 - 0
lib/Cake/Event/CakeEventListener.php

@@ -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();
+}

+ 27 - 3
lib/Cake/Event/CakeEventManager.php

@@ -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,

+ 0 - 0
lib/Cake/Event/CakeListener.php


+ 20 - 20
lib/Cake/Test/Case/Event/CakeEventManagerTest.php

@@ -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 @@ class CakeEventManagerTest extends CakeTestCase {
  */
 	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 @@ class CakeEventManagerTest extends CakeTestCase {
  */
 	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 @@ class CakeEventManagerTest extends CakeTestCase {
  */
 	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 @@ class CakeEventManagerTest extends CakeTestCase {
 		$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 @@ class CakeEventManagerTest extends CakeTestCase {
 	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 @@ class CakeEventManagerTest extends CakeTestCase {
 		$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);