Add parameter support to event listeners
authorTim Düsterhus <duesterhus@woltlab.com>
Fri, 1 Aug 2014 19:51:25 +0000 (21:51 +0200)
committerTim Düsterhus <duesterhus@woltlab.com>
Fri, 1 Aug 2014 20:10:55 +0000 (22:10 +0200)
Note the additional `\listener` in the namespace of IEventListener
for parameterized event listeners.

wcfsetup/install/files/lib/system/event/EventHandler.class.php
wcfsetup/install/files/lib/system/event/IEventListener.class.php
wcfsetup/install/files/lib/system/event/listener/IEventListener.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/event/listener/PreParserAtUserListener.class.php
wcfsetup/install/files/lib/system/event/listener/SessionAccessLogListener.class.php

index a19515498a150aec6c1e6c9b107171e20377c1d1..e3164f9dcc4887f662f4e383001f73d912392874 100644 (file)
@@ -1,6 +1,8 @@
 <?php
 namespace wcf\system\event;
 use wcf\system\cache\builder\EventListenerCacheBuilder;
+use wcf\system\event\listener\IEventListener;
+use wcf\system\event\IEventListener as ILegacyEventListener;
 use wcf\system\exception\SystemException;
 use wcf\system\SingletonFactory;
 use wcf\util\ClassUtil;
@@ -8,7 +10,7 @@ use wcf\util\ClassUtil;
 /**
  * EventHandler executes all registered actions for a specific event.
  * 
- * @author     Marcel Werk
+ * @author     Tim Duesterhus, Marcel Werk
  * @copyright  2001-2014 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
@@ -76,8 +78,9 @@ class EventHandler extends SingletonFactory {
         * @param       string          $eventName
         * @param       string          $className
         * @param       string          $name
+        * @param       array           &$parameters
         */
-       protected function executeInheritedActions($eventObj, $eventName, $className, $name) {
+       protected function executeInheritedActions($eventObj, $eventName, $className, $name, array &$parameters) {
                // create objects of the actions
                if (!isset($this->inheritedActionsObjects[$name]) || !is_array($this->inheritedActionsObjects[$name])) {
                        $this->inheritedActionsObjects[$name] = array();
@@ -107,8 +110,11 @@ class EventHandler extends SingletonFactory {
                                                                if (!class_exists($action['listenerClassName'])) {
                                                                        throw new SystemException("Unable to find class '".$action['listenerClassName']."'");
                                                                }
-                                                               if (!ClassUtil::isInstanceOf($action['listenerClassName'], 'wcf\system\event\IEventListener')) {
-                                                                       throw new SystemException("'".$action['listenerClassName']."' does not implement 'wcf\system\event\IEventListener'");
+                                                               if (!ClassUtil::isInstanceOf($action['listenerClassName'], 'wcf\system\event\listener\IEventListener')) {
+                                                                       // legacy event listeners
+                                                                       if (!ClassUtil::isInstanceOf($action['listenerClassName'], 'wcf\system\event\IEventListener')) {
+                                                                               throw new SystemException("'".$action['listenerClassName']."' does not implement 'wcf\system\event\listener\IEventListener'");
+                                                                       }
                                                                }
                                                                
                                                                $object = new $action['listenerClassName'];
@@ -124,17 +130,32 @@ class EventHandler extends SingletonFactory {
                
                // execute actions
                foreach ($this->inheritedActionsObjects[$name] as $actionObj) {
-                       $actionObj->execute($eventObj, $className, $eventName);
+                       if ($actionObj instanceof IEventListener) {
+                               $actionObj->execute($eventObj, $className, $eventName, $parameters);
+                               
+                               if (!is_array($parameters)) {
+                                       throw new SystemException("'".get_class($actionObj)."' breaks the '\$parameters' array!");
+                               }
+                       }
+                       else if ($actionObj instanceof ILegacyEventListener) {
+                               $actionObj->execute($eventObj, $className, $eventName);
+                       }
                }
        }
        
        /**
         * Executes all registered listeners for the given event.
         * 
+        * $parameters is an optional array of parameters. Event listeners
+        * are able to modify these. Any modification will be passed on to
+        * the next event listener and be available after execution of every
+        * event listener.
+        * 
         * @param       mixed           $eventObj
         * @param       string          $eventName
+        * @param       array           &$parameters
         */
-       public function fireAction($eventObj, $eventName) {
+       public function fireAction($eventObj, $eventName, array &$parameters = array()) {
                // get class name
                if (is_object($eventObj)) $className = get_class($eventObj);
                else $className = $eventObj;
@@ -149,7 +170,7 @@ class EventHandler extends SingletonFactory {
                
                // execute inherited actions first
                if (!empty($this->inheritedActions)) {
-                       $this->executeInheritedActions($eventObj, $eventName, $className, $name);
+                       $this->executeInheritedActions($eventObj, $eventName, $className, $name, $parameters);
                }
                
                // create objects of the actions
@@ -172,8 +193,11 @@ class EventHandler extends SingletonFactory {
                                        if (!class_exists($action['listenerClassName'])) {
                                                throw new SystemException("Unable to find class '".$action['listenerClassName']."'");
                                        }
-                                       if (!ClassUtil::isInstanceOf($action['listenerClassName'], 'wcf\system\event\IEventListener')) {
-                                               throw new SystemException("'".$action['listenerClassName']."' does not implement 'wcf\system\event\IEventListener'");
+                                       if (!ClassUtil::isInstanceOf($action['listenerClassName'], 'wcf\system\event\listener\IEventListener')) {
+                                               // legacy event listeners
+                                               if (!ClassUtil::isInstanceOf($action['listenerClassName'], 'wcf\system\event\IEventListener')) {
+                                                       throw new SystemException("'".$action['listenerClassName']."' does not implement 'wcf\system\event\listener\IEventListener'");
+                                               }
                                        }
                                        
                                        $object = new $action['listenerClassName'];
@@ -186,7 +210,16 @@ class EventHandler extends SingletonFactory {
                
                // execute actions
                foreach ($this->actionsObjects[$name] as $actionObj) {
-                       $actionObj->execute($eventObj, $className, $eventName);
+                       if ($actionObj instanceof IEventListener) {
+                               $actionObj->execute($eventObj, $className, $eventName, $parameters);
+                               
+                               if (!is_array($parameters)) {
+                                       throw new SystemException("'".get_class($actionObj)."' breaks the '\$parameters' array!");
+                               }
+                       }
+                       else if ($actionObj instanceof ILegacyEventListener) {
+                               $actionObj->execute($eventObj, $className, $eventName);
+                       }
                }
        }
        
index 97be76ab79a7c3c3bfd3212bbf60c11b9c0bab40..575abbea98339334056e609e5e76a68f3035d6e4 100644 (file)
@@ -2,8 +2,10 @@
 namespace wcf\system\event;
 
 /**
+ * *DEPRECATED*
  * EventListeners can be registered for a specific event in many controller objects.
  * 
+ * @deprecated since 2.1, use \wcf\system\event\listener\IEventListener
  * @author     Marcel Werk
  * @copyright  2001-2014 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
diff --git a/wcfsetup/install/files/lib/system/event/listener/IEventListener.class.php b/wcfsetup/install/files/lib/system/event/listener/IEventListener.class.php
new file mode 100644 (file)
index 0000000..208ba82
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+namespace wcf\system\event\listener;
+
+/**
+ * EventListeners can be registered for a specific event in many controller objects.
+ * 
+ * @author     Tim Duesterhus, Marcel Werk
+ * @copyright  2001-2014 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.event.listener
+ * @category   Community Framework
+ */
+interface IEventListener {
+       /**
+        * Executes this action.
+        * 
+        * @param       object          $eventObj       Object firing the event
+        * @param       string          $className      class name of $eventObj
+        * @param       string          $eventName      name of the event fired
+        * @param       array           &$parameters    given parameters
+        */
+       public function execute($eventObj, $className, $eventName, array &$parameters);
+}
index 43610bbede8dfac30bb52fd808774e65eaa68e52..3c92a13bb481925e9fed614aae22101dbee2af6f 100644 (file)
@@ -2,7 +2,6 @@
 namespace wcf\system\event\listener;
 use wcf\data\bbcode\BBCode;
 use wcf\data\user\UserList;
-use wcf\system\event\IEventListener;
 use wcf\system\request\LinkHandler;
 use wcf\system\Callback;
 use wcf\system\Regex;
@@ -20,9 +19,9 @@ use wcf\util\StringStack;
  */
 class PreParserAtUserListener implements IEventListener {
        /**
-        * @see \wcf\system\event\IEventListener::execute()
+        * @see \wcf\system\event\listener\IEventListener::execute()
         */
-       public function execute($eventObj, $className, $eventName) {
+       public function execute($eventObj, $className, $eventName, array &$parameters) {
                if (!$eventObj->text) return;
                
                // check if needed url BBCode is allowed
index d5819858873595990b1ec14572cd36679cfd78f2..9f6d488de69e57704ce5a3c3a1aa03b2f80c61d9 100644 (file)
@@ -3,7 +3,6 @@ namespace wcf\system\event\listener;
 use wcf\data\acp\session\access\log\ACPSessionAccessLogEditor;
 use wcf\data\acp\session\log\ACPSessionLog;
 use wcf\data\acp\session\log\ACPSessionLogEditor;
-use wcf\system\event\IEventListener;
 use wcf\system\WCF;
 use wcf\util\UserUtil;
 
@@ -19,9 +18,9 @@ use wcf\util\UserUtil;
  */
 class SessionAccessLogListener implements IEventListener {
        /**
-        * @see \wcf\system\event\IEventListener::execute()
+        * @see \wcf\system\event\listener\IEventListener::execute()
         */
-       public function execute($eventObj, $className, $eventName) {
+       public function execute($eventObj, $className, $eventName, array &$parameters) {
                if (WCF::getUser()->userID && WCF::getSession()->getPermission('admin.general.canUseAcp') && !defined(get_class($eventObj).'::DO_NOT_LOG')) {
                        // try to find existing session log
                        $sql = "SELECT  sessionLogID