Merge pull request #17480 from tunbola/email-template-perms
[civicrm-core.git] / Civi / Core / CiviEventDispatcher.php
index b5e307dece2d9ca59c1b7e0b2c8f74642ce4d3b3..ac104537d81bfe8968015ea37004a6447634aeb1 100644 (file)
@@ -2,7 +2,7 @@
 
 namespace Civi\Core;
 
-use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher;
+use Symfony\Component\EventDispatcher\EventDispatcher;
 use Symfony\Component\EventDispatcher\Event;
 
 /**
@@ -15,7 +15,7 @@ use Symfony\Component\EventDispatcher\Event;
  *
  * @see \CRM_Utils_Hook
  */
-class CiviEventDispatcher extends ContainerAwareEventDispatcher {
+class CiviEventDispatcher extends EventDispatcher {
 
   const DEFAULT_HOOK_PRIORITY = -100;
 
@@ -29,12 +29,22 @@ class CiviEventDispatcher extends ContainerAwareEventDispatcher {
   private $autoListeners = [];
 
   /**
+   * A list of dispatch-policies (based on an exact-match to the event name).
+   *
+   * Note: $dispatchPolicyExact and $dispatchPolicyRegex should coexist; e.g.
+   * if one is NULL, then both are NULL. If one is an array, then both are arrays.
+   *
    * @var array|null
    *   Array(string $eventName => string $action)
    */
   private $dispatchPolicyExact = NULL;
 
   /**
+   * A list of dispatch-policies (based on an regex-match to the event name).
+   *
+   * Note: $dispatchPolicyExact and $dispatchPolicyRegex should coexist; e.g.
+   * if one is NULL, then both are NULL. If one is an array, then both are arrays.
+   *
    * @var array|null
    *   Array(string $eventRegex => string $action)
    */
@@ -51,6 +61,34 @@ class CiviEventDispatcher extends ContainerAwareEventDispatcher {
     return (substr($eventName, 0, 5) === 'hook_') && (strpos($eventName, '::') === FALSE);
   }
 
+  /**
+   * Adds a service as event listener.
+   *
+   * This provides partial backwards compatibility with ContainerAwareEventDispatcher.
+   *
+   * @param string $eventName Event for which the listener is added
+   * @param array $callback The service ID of the listener service & the method
+   *                        name that has to be called
+   * @param int $priority The higher this value, the earlier an event listener
+   *                      will be triggered in the chain.
+   *                      Defaults to 0.
+   *
+   * @throws \InvalidArgumentException
+   */
+  public function addListenerService($eventName, $callback, $priority = 0) {
+    if (!\is_array($callback) || 2 !== \count($callback)) {
+      throw new \InvalidArgumentException('Expected an array("service", "method") argument');
+    }
+
+    $this->addListener($eventName, function($event) use ($callback) {
+      static $svc;
+      if ($svc === NULL) {
+        $svc = \Civi::container()->get($callback[0]);
+      }
+      return call_user_func([$svc, $callback[1]], $event);
+    }, $priority);
+  }
+
   /**
    * @inheritDoc
    */
@@ -79,6 +117,9 @@ class CiviEventDispatcher extends ContainerAwareEventDispatcher {
         case 'fail':
           throw new \RuntimeException("The dispatch policy prohibits event \"$eventName\".");
 
+        case 'not-ready':
+          throw new \RuntimeException("CiviCRM has not bootstrapped sufficiently to fire event \"$eventName\".");
+
         default:
           throw new \RuntimeException("The dispatch policy for \"$eventName\" is unrecognized ($mode).");
 
@@ -155,6 +196,8 @@ class CiviEventDispatcher extends ContainerAwareEventDispatcher {
   }
 
   /**
+   * Attach any pattern-based listeners which may be interested in $eventName.
+   *
    * @param string $eventName
    *   Ex: 'civi.api.resolve' or 'hook_civicrm_dashboard'.
    */
@@ -174,7 +217,7 @@ class CiviEventDispatcher extends ContainerAwareEventDispatcher {
   }
 
   /**
-   * The dispatch policy allows you to filter certain events.
+   * Set the dispatch policy. This allows you to filter certain events.
    * This can be useful during upgrades or debugging.
    *
    * Enforcement will add systemic overhead, so this should normally be NULL.
@@ -219,7 +262,10 @@ class CiviEventDispatcher extends ContainerAwareEventDispatcher {
   //  }
 
   /**
+   * Determine whether the dispatch policy applies to a given event.
+   *
    * @param string $eventName
+   *   Ex: 'civi.api.resolve' or 'hook_civicrm_dashboard'.
    * @return string
    *   Ex: 'run', 'drop', 'fail'
    */