Browse Source

Moving the event stack into a separate object.

Florian Krämer 10 years ago
parent
commit
77649650cc

+ 25 - 40
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 @@ class EventManager
 
         $listeners = $this->listeners($event->name());
         if (empty($listeners)) {
-            $this->stackEvent($event);
+            $this->_stackEvent($event);
             return $event;
         }
 
@@ -377,7 +370,7 @@ class EventManager
             }
         }
 
-        $this->stackEvent($event);
+        $this->_stackEvent($event);
         return $event;
     }
 
@@ -478,57 +471,47 @@ class EventManager
     }
 
     /**
-     * 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 @@ class EventManager
         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;
     }

+ 136 - 0
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);
+    }
+}

+ 8 - 8
tests/TestCase/Event/EventManagerTest.php

@@ -17,6 +17,7 @@ namespace Cake\Test\TestCase\Event;
 use Cake\Event\Event;
 use Cake\Event\EventListenerInterface;
 use Cake\Event\EventManager;
+use Cake\Event\EventStack;
 use Cake\TestSuite\TestCase;
 
 /**
@@ -720,30 +721,29 @@ class EventManagerTest extends TestCase
      */
     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);
     }
 }

+ 49 - 0
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);
+    }
+}