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

This commit is contained in:
Jose Lorenzo Rodriguez 2011-12-13 00:55:28 -04:30
parent e8044cd528
commit bef20e6175
4 changed files with 94 additions and 23 deletions

View file

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

View file

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

View file

@ -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);