Browse Source

Disable event stacking by default.

This needs to be explicitly enable because otherwise it could cause memory issues for people without that they'll know the cause.
Florian Krämer 9 years ago
parent
commit
1a36c882ec
2 changed files with 68 additions and 2 deletions
  1. 54 2
      src/Event/EventManager.php
  2. 14 0
      tests/TestCase/Event/EventManagerTest.php

+ 54 - 2
src/Event/EventManager.php

@@ -61,6 +61,13 @@ class EventManager
     protected $_dispatchedEvents = [];
 
     /**
+     * Enables or disables the stacking of dispatched events
+     *
+     * @var bool
+     */
+    protected $_eventStacking = false;
+
+    /**
      * Returns the globally available instance of a Cake\Event\EventManager
      * this is used for dispatching events attached from outside the scope
      * other managers were created. Usually for creating hook systems or inter-class
@@ -353,7 +360,7 @@ class EventManager
 
         $listeners = $this->listeners($event->name());
         if (empty($listeners)) {
-            $this->_dispatchedEvents[] = $event;
+            $this->stackEvent($event);
             return $event;
         }
 
@@ -369,7 +376,8 @@ class EventManager
                 $event->result = $result;
             }
         }
-        $this->_dispatchedEvents[] = $event;
+
+        $this->stackEvent($event);
         return $event;
     }
 
@@ -480,6 +488,50 @@ class EventManager
     }
 
     /**
+     * Enables the stacking of dispatched events.
+     *
+     * @return void
+     */
+    public function enableEventStacking()
+    {
+        $this->_eventStacking = true;
+    }
+
+    /**
+     * Disables the stacking of dispatched events.
+     *
+     * @return void
+     */
+    public function disableEventStacking()
+    {
+        $this->_eventStacking = false;
+        $this->flushEventStack();
+    }
+
+    /**
+     * Empties the stack of dispatched events.
+     *
+     * @return void
+     */
+    public function flushEventStack()
+    {
+        $this->_dispatchedEvents = [];
+    }
+
+    /**
+     * Adds an event to the stack when stacking is enabled.
+     *
+     * @param \Cake\Event\Event An event to stack.
+     * @return void
+     */
+    protected function stackEvent(Event $event)
+    {
+        if ($this->_eventStacking === true) {
+            $this->_dispatchedEvents[] = $event;
+        }
+    }
+
+    /**
      * Debug friendly object properties.
      *
      * @return array

+ 14 - 0
tests/TestCase/Event/EventManagerTest.php

@@ -724,6 +724,7 @@ class EventManagerTest extends TestCase
         $event2 = new Event('my_second_event', $this);
 
         $manager = new EventManager();
+        $manager->enableEventStacking();
         $manager->dispatch($event);
         $manager->dispatch($event2);
 
@@ -731,5 +732,18 @@ class EventManagerTest extends TestCase
         $this->assertCount(2, $result);
         $this->assertEquals($result[0], $event);
         $this->assertEquals($result[1], $event2);
+
+        $manager->flushEventStack();
+        $result = $manager->getDispatchedEvents();
+        $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, []);
     }
 }