diff --git a/src/Event/EventManager.php b/src/Event/EventManager.php index afe097d7ab2..bfca82ede81 100644 --- a/src/Event/EventManager.php +++ b/src/Event/EventManager.php @@ -54,18 +54,11 @@ class EventManager protected $_isGlobal = false; /** - * A list of already dispatched events + * The event stack object. * - * @var array + * @var \Cake\Event\EventStack|null */ - protected $_dispatchedEvents = []; - - /** - * Enables or disables the stacking of dispatched events - * - * @var bool - */ - protected $_eventStacking = false; + protected $_eventStack; /** * Returns the globally available instance of a Cake\Event\EventManager @@ -360,7 +353,7 @@ public function dispatch($event) $listeners = $this->listeners($event->name()); if (empty($listeners)) { - $this->stackEvent($event); + $this->_stackEvent($event); return $event; } @@ -377,7 +370,7 @@ public function dispatch($event) } } - $this->stackEvent($event); + $this->_stackEvent($event); return $event; } @@ -478,57 +471,47 @@ public function matchingListeners($eventKeyPattern) } /** - * Returns a list of dispatched event objects. + * Returns the event stack. * * @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 */ - public function enableEventStacking() + public function _stackEvent(Event $event) { - $this->_eventStacking = true; - } - - /** - * Disables the stacking of dispatched events. - * - * @return void - */ - public function disableEventStacking() - { - $this->_eventStacking = false; - $this->flushEventStack(); + if ($this->_eventStack) { + $this->_eventStack->add($event); + } } /** - * 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 */ - 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 */ - protected function stackEvent(Event $event) + public function disableEventStacking() { - if ($this->_eventStacking === true) { - $this->_dispatchedEvents[] = $event; - } + $this->_eventStack = null; } /** @@ -544,8 +527,10 @@ public function __debugInfo() foreach ($this->_listeners as $key => $listeners) { $properties['_listeners'][$key] = count($listeners) . ' listener(s)'; } - foreach ($this->_dispatchedEvents as $event) { - $properties['_dispatchedEvents'][] = $event->name() . ' with subject ' . get_class($event->subject()); + if ($this->_eventStack) { + foreach ($this->_eventStack as $event) { + $properties['_dispatchedEvents'][] = $event->name() . ' with subject ' . get_class($event->subject()); + } } return $properties; } diff --git a/src/Event/EventStack.php b/src/Event/EventStack.php new file mode 100644 index 00000000000..868a0f47edc --- /dev/null +++ b/src/Event/EventStack.php @@ -0,0 +1,136 @@ +_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

+ * An offset to check for. + *

+ * @return boolean true on success or false on failure. + *

+ *

+ * 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

+ * The offset to retrieve. + *

+ * @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

+ * The offset to assign the value to. + *

+ * @param mixed $value

+ * The value to set. + *

+ * @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

+ * The offset to unset. + *

+ * @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. + *

+ *

+ * The return value is cast to an integer. + * @since 5.1.0 + */ + public function count() + { + return count($this->_events); + } +} diff --git a/tests/TestCase/Event/EventManagerTest.php b/tests/TestCase/Event/EventManagerTest.php index 72ddef9406e..6dc9e83ad74 100644 --- a/tests/TestCase/Event/EventManagerTest.php +++ b/tests/TestCase/Event/EventManagerTest.php @@ -17,6 +17,7 @@ use Cake\Event\Event; use Cake\Event\EventListenerInterface; use Cake\Event\EventManager; +use Cake\Event\EventStack; use Cake\TestSuite\TestCase; /** @@ -720,30 +721,29 @@ public function testDispatchWithGlobalAndLocalEvents() */ public function testGetDispatchedEvents() { + $eventStack = new EventStack(); $event = new Event('my_event', $this); $event2 = new Event('my_second_event', $this); $manager = new EventManager(); - $manager->enableEventStacking(); + $manager->enableEventStacking($eventStack); $manager->dispatch($event); $manager->dispatch($event2); - $result = $manager->getDispatchedEvents(); + $result = $manager->eventStack(); $this->assertCount(2, $result); $this->assertEquals($result[0], $event); $this->assertEquals($result[1], $event2); - $manager->flushEventStack(); - $result = $manager->getDispatchedEvents(); + $manager->eventStack()->flush(); + $result = $manager->eventStack(); $this->assertCount(0, $result); - $this->assertEquals($result, []); $manager->disableEventStacking(); $manager->dispatch($event); $manager->dispatch($event2); - $result = $manager->getDispatchedEvents(); - $this->assertCount(0, $result); - $this->assertEquals($result, []); + $result = $manager->eventStack(); + $this->assertNull($result); } } diff --git a/tests/TestCase/Event/EventStackTest.php b/tests/TestCase/Event/EventStackTest.php new file mode 100644 index 00000000000..2bf94c81fc6 --- /dev/null +++ b/tests/TestCase/Event/EventStackTest.php @@ -0,0 +1,49 @@ +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); + } +}