[ Index ]

PHP Cross Reference of phpBB-3.3.11-deutsch

title

Body

[close]

/vendor/zendframework/zend-eventmanager/src/ -> EventManager.php (source)

   1  <?php
   2  /**
   3   * Zend Framework (http://framework.zend.com/)
   4   *
   5   * @link      http://github.com/zendframework/zend-eventmanager for the canonical source repository
   6   * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
   7   * @license   https://github.com/zendframework/zend-eventmanager/blob/master/LICENSE.md
   8   */
   9  
  10  namespace Zend\EventManager;
  11  
  12  use ArrayObject;
  13  
  14  /**
  15   * Event manager: notification system
  16   *
  17   * Use the EventManager when you want to create a per-instance notification
  18   * system for your objects.
  19   */
  20  class EventManager implements EventManagerInterface
  21  {
  22      /**
  23       * Subscribed events and their listeners
  24       *
  25       * STRUCTURE:
  26       * [
  27       *     <string name> => [
  28       *         <int priority> => [
  29       *             0 => [<callable listener>, ...]
  30       *         ],
  31       *         ...
  32       *     ],
  33       *     ...
  34       * ]
  35       *
  36       * NOTE:
  37       * This structure helps us to reuse the list of listeners
  38       * instead of first iterating over it and generating a new one
  39       * -> In result it improves performance by up to 25% even if it looks a bit strange
  40       *
  41       * @var array[]
  42       */
  43      protected $events = [];
  44  
  45      /**
  46       * @var EventInterface Prototype to use when creating an event at trigger().
  47       */
  48      protected $eventPrototype;
  49  
  50      /**
  51       * Identifiers, used to pull shared signals from SharedEventManagerInterface instance
  52       *
  53       * @var array
  54       */
  55      protected $identifiers = [];
  56  
  57      /**
  58       * Shared event manager
  59       *
  60       * @var null|SharedEventManagerInterface
  61       */
  62      protected $sharedManager = null;
  63  
  64      /**
  65       * Constructor
  66       *
  67       * Allows optionally specifying identifier(s) to use to pull signals from a
  68       * SharedEventManagerInterface.
  69       *
  70       * @param SharedEventManagerInterface $sharedEventManager
  71       * @param array $identifiers
  72       */
  73      public function __construct(SharedEventManagerInterface $sharedEventManager = null, array $identifiers = [])
  74      {
  75          if ($sharedEventManager) {
  76              $this->sharedManager = $sharedEventManager;
  77              $this->setIdentifiers($identifiers);
  78          }
  79  
  80          $this->eventPrototype = new Event();
  81      }
  82  
  83      /**
  84       * @inheritDoc
  85       */
  86      public function setEventPrototype(EventInterface $prototype)
  87      {
  88          $this->eventPrototype = $prototype;
  89      }
  90  
  91      /**
  92       * Retrieve the shared event manager, if composed.
  93       *
  94       * @return null|SharedEventManagerInterface $sharedEventManager
  95       */
  96      public function getSharedManager()
  97      {
  98          return $this->sharedManager;
  99      }
 100  
 101      /**
 102       * @inheritDoc
 103       */
 104      public function getIdentifiers()
 105      {
 106          return $this->identifiers;
 107      }
 108  
 109      /**
 110       * @inheritDoc
 111       */
 112      public function setIdentifiers(array $identifiers)
 113      {
 114          $this->identifiers = array_unique($identifiers);
 115      }
 116  
 117      /**
 118       * @inheritDoc
 119       */
 120      public function addIdentifiers(array $identifiers)
 121      {
 122          $this->identifiers = array_unique(array_merge(
 123              $this->identifiers,
 124              $identifiers
 125          ));
 126      }
 127  
 128      /**
 129       * @inheritDoc
 130       */
 131      public function trigger($eventName, $target = null, $argv = [])
 132      {
 133          $event = clone $this->eventPrototype;
 134          $event->setName($eventName);
 135  
 136          if ($target !== null) {
 137              $event->setTarget($target);
 138          }
 139  
 140          if ($argv) {
 141              $event->setParams($argv);
 142          }
 143  
 144          return $this->triggerListeners($event);
 145      }
 146  
 147      /**
 148       * @inheritDoc
 149       */
 150      public function triggerUntil(callable $callback, $eventName, $target = null, $argv = [])
 151      {
 152          $event = clone $this->eventPrototype;
 153          $event->setName($eventName);
 154  
 155          if ($target !== null) {
 156              $event->setTarget($target);
 157          }
 158  
 159          if ($argv) {
 160              $event->setParams($argv);
 161          }
 162  
 163          return $this->triggerListeners($event, $callback);
 164      }
 165  
 166      /**
 167       * @inheritDoc
 168       */
 169      public function triggerEvent(EventInterface $event)
 170      {
 171          return $this->triggerListeners($event);
 172      }
 173  
 174      /**
 175       * @inheritDoc
 176       */
 177      public function triggerEventUntil(callable $callback, EventInterface $event)
 178      {
 179          return $this->triggerListeners($event, $callback);
 180      }
 181  
 182      /**
 183       * @inheritDoc
 184       */
 185      public function attach($eventName, callable $listener, $priority = 1)
 186      {
 187          if (! is_string($eventName)) {
 188              throw new Exception\InvalidArgumentException(sprintf(
 189                  '%s expects a string for the event; received %s',
 190                  __METHOD__,
 191                  (is_object($eventName) ? get_class($eventName) : gettype($eventName))
 192              ));
 193          }
 194  
 195          $this->events[$eventName][(int) $priority][0][] = $listener;
 196          return $listener;
 197      }
 198  
 199      /**
 200       * @inheritDoc
 201       * @throws Exception\InvalidArgumentException for invalid event types.
 202       */
 203      public function detach(callable $listener, $eventName = null, $force = false)
 204      {
 205  
 206          // If event is wildcard, we need to iterate through each listeners
 207          if (null === $eventName || ('*' === $eventName && ! $force)) {
 208              foreach (array_keys($this->events) as $eventName) {
 209                  $this->detach($listener, $eventName, true);
 210              }
 211              return;
 212          }
 213  
 214          if (! is_string($eventName)) {
 215              throw new Exception\InvalidArgumentException(sprintf(
 216                  '%s expects a string for the event; received %s',
 217                  __METHOD__,
 218                  (is_object($eventName) ? get_class($eventName) : gettype($eventName))
 219              ));
 220          }
 221  
 222          if (! isset($this->events[$eventName])) {
 223              return;
 224          }
 225  
 226          foreach ($this->events[$eventName] as $priority => $listeners) {
 227              foreach ($listeners[0] as $index => $evaluatedListener) {
 228                  if ($evaluatedListener !== $listener) {
 229                      continue;
 230                  }
 231  
 232                  // Found the listener; remove it.
 233                  unset($this->events[$eventName][$priority][0][$index]);
 234  
 235                  // If the queue for the given priority is empty, remove it.
 236                  if (empty($this->events[$eventName][$priority][0])) {
 237                      unset($this->events[$eventName][$priority]);
 238                      break;
 239                  }
 240              }
 241          }
 242  
 243          // If the queue for the given event is empty, remove it.
 244          if (empty($this->events[$eventName])) {
 245              unset($this->events[$eventName]);
 246          }
 247      }
 248  
 249      /**
 250       * @inheritDoc
 251       */
 252      public function clearListeners($eventName)
 253      {
 254          if (isset($this->events[$eventName])) {
 255              unset($this->events[$eventName]);
 256          }
 257      }
 258  
 259      /**
 260       * Prepare arguments
 261       *
 262       * Use this method if you want to be able to modify arguments from within a
 263       * listener. It returns an ArrayObject of the arguments, which may then be
 264       * passed to trigger().
 265       *
 266       * @param  array $args
 267       * @return ArrayObject
 268       */
 269      public function prepareArgs(array $args)
 270      {
 271          return new ArrayObject($args);
 272      }
 273  
 274      /**
 275       * Trigger listeners
 276       *
 277       * Actual functionality for triggering listeners, to which trigger() delegate.
 278       *
 279       * @param  EventInterface $event
 280       * @param  null|callable $callback
 281       * @return ResponseCollection
 282       */
 283      protected function triggerListeners(EventInterface $event, callable $callback = null)
 284      {
 285          $name = $event->getName();
 286  
 287          if (empty($name)) {
 288              throw new Exception\RuntimeException('Event is missing a name; cannot trigger!');
 289          }
 290  
 291          if (isset($this->events[$name])) {
 292              $listOfListenersByPriority = $this->events[$name];
 293  
 294              if (isset($this->events['*'])) {
 295                  foreach ($this->events['*'] as $priority => $listOfListeners) {
 296                      $listOfListenersByPriority[$priority][] = $listOfListeners[0];
 297                  }
 298              }
 299          } elseif (isset($this->events['*'])) {
 300              $listOfListenersByPriority = $this->events['*'];
 301          } else {
 302              $listOfListenersByPriority = [];
 303          }
 304  
 305          if ($this->sharedManager) {
 306              foreach ($this->sharedManager->getListeners($this->identifiers, $name) as $priority => $listeners) {
 307                  $listOfListenersByPriority[$priority][] = $listeners;
 308              }
 309          }
 310  
 311          // Sort by priority in reverse order
 312          krsort($listOfListenersByPriority);
 313  
 314          // Initial value of stop propagation flag should be false
 315          $event->stopPropagation(false);
 316  
 317          // Execute listeners
 318          $responses = new ResponseCollection();
 319          foreach ($listOfListenersByPriority as $listOfListeners) {
 320              foreach ($listOfListeners as $listeners) {
 321                  foreach ($listeners as $listener) {
 322                      $response = $listener($event);
 323                      $responses->push($response);
 324  
 325                      // If the event was asked to stop propagating, do so
 326                      if ($event->propagationIsStopped()) {
 327                          $responses->setStopped(true);
 328                          return $responses;
 329                      }
 330  
 331                      // If the result causes our validation callback to return true,
 332                      // stop propagation
 333                      if ($callback && $callback($response)) {
 334                          $responses->setStopped(true);
 335                          return $responses;
 336                      }
 337                  }
 338              }
 339          }
 340  
 341          return $responses;
 342      }
 343  }


Generated: Sat Nov 4 14:26:03 2023 Cross-referenced by PHPXref 0.7.1