Skip to content

Commit

Permalink
Moving the event stack into a separate object.
Browse files Browse the repository at this point in the history
  • Loading branch information
Florian Krämer committed May 22, 2016
1 parent 769e0b8 commit 7764965
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 48 deletions.
65 changes: 25 additions & 40 deletions src/Event/EventManager.php
Expand Up @@ -54,18 +54,11 @@ class EventManager
protected $_isGlobal = false; protected $_isGlobal = false;


/** /**
* A list of already dispatched events * The event stack object.
* *
* @var array * @var \Cake\Event\EventStack|null
*/ */
protected $_dispatchedEvents = []; protected $_eventStack;

/**
* Enables or disables the stacking of dispatched events
*
* @var bool
*/
protected $_eventStacking = false;


/** /**
* Returns the globally available instance of a Cake\Event\EventManager * Returns the globally available instance of a Cake\Event\EventManager
Expand Down Expand Up @@ -360,7 +353,7 @@ public function dispatch($event)


$listeners = $this->listeners($event->name()); $listeners = $this->listeners($event->name());
if (empty($listeners)) { if (empty($listeners)) {
$this->stackEvent($event); $this->_stackEvent($event);
return $event; return $event;
} }


Expand All @@ -377,7 +370,7 @@ public function dispatch($event)
} }
} }


$this->stackEvent($event); $this->_stackEvent($event);
return $event; return $event;
} }


Expand Down Expand Up @@ -478,57 +471,47 @@ public function matchingListeners($eventKeyPattern)
} }


/** /**
* Returns a list of dispatched event objects. * Returns the event stack.
* *
* @return array * @return array
*/ */
public function getDispatchedEvents() public function eventStack()
{ {
return $this->_dispatchedEvents; return $this->_eventStack;
} }


/** /**
* Enables the stacking of dispatched events. * Adds an event to the stack if the stack object is present.
* *
* @param \Cake\Event\Event $event An event to add to the stack.
* @return void * @return void
*/ */
public function enableEventStacking() public function _stackEvent(Event $event)
{ {
$this->_eventStacking = true; if ($this->_eventStack) {
} $this->_eventStack->add($event);

}
/**
* Disables the stacking of dispatched events.
*
* @return void
*/
public function disableEventStacking()
{
$this->_eventStacking = false;
$this->flushEventStack();
} }


/** /**
* Empties the stack of dispatched events. * Enables the stacking of dispatched events.
* *
* @param \Cake\Event\EventStack $eventStack The event stack object to use.
* @return void * @return void
*/ */
public function flushEventStack() public function enableEventStacking(EventStack $eventStack)
{ {
$this->_dispatchedEvents = []; $this->_eventStack = $eventStack;
} }


/** /**
* Adds an event to the stack when stacking is enabled. * Disables the stacking of dispatched events.
* *
* @param \Cake\Event\Event $event An event to stack.
* @return void * @return void
*/ */
protected function stackEvent(Event $event) public function disableEventStacking()
{ {
if ($this->_eventStacking === true) { $this->_eventStack = null;
$this->_dispatchedEvents[] = $event;
}
} }


/** /**
Expand All @@ -544,8 +527,10 @@ public function __debugInfo()
foreach ($this->_listeners as $key => $listeners) { foreach ($this->_listeners as $key => $listeners) {
$properties['_listeners'][$key] = count($listeners) . ' listener(s)'; $properties['_listeners'][$key] = count($listeners) . ' listener(s)';
} }
foreach ($this->_dispatchedEvents as $event) { if ($this->_eventStack) {
$properties['_dispatchedEvents'][] = $event->name() . ' with subject ' . get_class($event->subject()); foreach ($this->_eventStack as $event) {
$properties['_dispatchedEvents'][] = $event->name() . ' with subject ' . get_class($event->subject());
}
} }
return $properties; return $properties;
} }
Expand Down
136 changes: 136 additions & 0 deletions src/Event/EventStack.php
@@ -0,0 +1,136 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since 3.3.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Event;

use Cake\Event\Event;

/**
* The Event Stack
*/
class EventStack implements \ArrayAccess, \Countable
{

/**
* Events list
*
* @var array
*/
protected $_events = [];

/**
* Empties the stack of dispatched events.
*
* @return void
*/
public function flush()
{
$this->_events = [];
}

/**
* Adds an event to the stack when stacking is enabled.
*
* @param \Cake\Event\Event $event An event to stack.
* @return void
*/
public function add(Event $event)
{
$this->_events[] = $event;
}

/**
* Whether a offset exists
*
* @link http://php.net/manual/en/arrayaccess.offsetexists.php
* @param mixed $offset <p>
* An offset to check for.
* </p>
* @return boolean true on success or false on failure.
* </p>
* <p>
* The return value will be casted to boolean if non-boolean was returned.
* @since 5.0.0
*/
public function offsetExists($offset)
{
return isset($this->_events[$offset]);
}

/**
* Offset to retrieve
*
* @link http://php.net/manual/en/arrayaccess.offsetget.php
* @param mixed $offset <p>
* The offset to retrieve.
* </p>
* @return mixed Can return all value types.
* @since 5.0.0
*/
public function offsetGet($offset)
{
if ($this->offsetExists($offset)) {
return $this->_events[$offset];
}
return null;
}

/**
* Offset to set
*
* @link http://php.net/manual/en/arrayaccess.offsetset.php
* @param mixed $offset <p>
* The offset to assign the value to.
* </p>
* @param mixed $value <p>
* The value to set.
* </p>
* @return void
* @since 5.0.0
*/
public function offsetSet($offset, $value)
{
$this->_events[$offset] = $value;
}

/**
* Offset to unset
*
* @link http://php.net/manual/en/arrayaccess.offsetunset.php
* @param mixed $offset <p>
* The offset to unset.
* </p>
* @return void
* @since 5.0.0
*/
public function offsetUnset($offset)
{
unset($this->_events[$offset]);
}

/**
* Count elements of an object
*
* @link http://php.net/manual/en/countable.count.php
* @return int The custom count as an integer.
* </p>
* <p>
* The return value is cast to an integer.
* @since 5.1.0
*/
public function count()
{
return count($this->_events);
}
}
16 changes: 8 additions & 8 deletions tests/TestCase/Event/EventManagerTest.php
Expand Up @@ -17,6 +17,7 @@
use Cake\Event\Event; use Cake\Event\Event;
use Cake\Event\EventListenerInterface; use Cake\Event\EventListenerInterface;
use Cake\Event\EventManager; use Cake\Event\EventManager;
use Cake\Event\EventStack;
use Cake\TestSuite\TestCase; use Cake\TestSuite\TestCase;


/** /**
Expand Down Expand Up @@ -720,30 +721,29 @@ public function testDispatchWithGlobalAndLocalEvents()
*/ */
public function testGetDispatchedEvents() public function testGetDispatchedEvents()
{ {
$eventStack = new EventStack();
$event = new Event('my_event', $this); $event = new Event('my_event', $this);
$event2 = new Event('my_second_event', $this); $event2 = new Event('my_second_event', $this);


$manager = new EventManager(); $manager = new EventManager();
$manager->enableEventStacking(); $manager->enableEventStacking($eventStack);
$manager->dispatch($event); $manager->dispatch($event);
$manager->dispatch($event2); $manager->dispatch($event2);


$result = $manager->getDispatchedEvents(); $result = $manager->eventStack();
$this->assertCount(2, $result); $this->assertCount(2, $result);
$this->assertEquals($result[0], $event); $this->assertEquals($result[0], $event);
$this->assertEquals($result[1], $event2); $this->assertEquals($result[1], $event2);


$manager->flushEventStack(); $manager->eventStack()->flush();
$result = $manager->getDispatchedEvents(); $result = $manager->eventStack();
$this->assertCount(0, $result); $this->assertCount(0, $result);
$this->assertEquals($result, []);


$manager->disableEventStacking(); $manager->disableEventStacking();
$manager->dispatch($event); $manager->dispatch($event);
$manager->dispatch($event2); $manager->dispatch($event2);


$result = $manager->getDispatchedEvents(); $result = $manager->eventStack();
$this->assertCount(0, $result); $this->assertNull($result);
$this->assertEquals($result, []);
} }
} }
49 changes: 49 additions & 0 deletions tests/TestCase/Event/EventStackTest.php
@@ -0,0 +1,49 @@
<?php
/**
* CakePHP : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP Project
* @since 3.3.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Test\TestCase\Event;

use Cake\Event\Event;
use Cake\Event\EventStack;
use Cake\TestSuite\TestCase;

/**
* Tests the Cake\Event\EvenStack class functionality
*/
class EvenStackTest extends TestCase
{

/**
* testAddEventAndFlush
*
* @return void
*/
public function testAddEventAndFlush()
{
$eventStack = new EventStack();
$event = new Event('my_event', $this);
$event2 = new Event('my_second_event', $this);

$eventStack->add($event);
$eventStack->add($event2);
$this->assertCount(2, $eventStack);

$this->assertEquals($eventStack[0], $event);
$this->assertEquals($eventStack[1], $event2);

$eventStack->flush();

$this->assertCount(0, $eventStack);
}
}

0 comments on commit 7764965

Please sign in to comment.