Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

EventManager.php

Zuletzt modifiziert: 09.10.2024, 12:55 - Dateigröße: 17.01 KiB


 001  <?php
 002  /**
 003   * Zend Framework (http://framework.zend.com/)
 004   *
 005   * @link      http://github.com/zendframework/zf2 for the canonical source repository
 006   * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
 007   * @license   http://framework.zend.com/license/new-bsd New BSD License
 008   */
 009   
 010  namespace Zend\EventManager;
 011   
 012  use ArrayAccess;
 013  use ArrayObject;
 014  use Traversable;
 015  use Zend\Stdlib\CallbackHandler;
 016  use Zend\Stdlib\PriorityQueue;
 017   
 018  /**
 019   * Event manager: notification system
 020   *
 021   * Use the EventManager when you want to create a per-instance notification
 022   * system for your objects.
 023   */
 024  class EventManager implements EventManagerInterface
 025  {
 026      /**
 027       * Subscribed events and their listeners
 028       * @var array Array of PriorityQueue objects
 029       */
 030      protected $events = array();
 031   
 032      /**
 033       * @var string Class representing the event being emitted
 034       */
 035      protected $eventClass = 'Zend\EventManager\Event';
 036   
 037      /**
 038       * Identifiers, used to pull shared signals from SharedEventManagerInterface instance
 039       * @var array
 040       */
 041      protected $identifiers = array();
 042   
 043      /**
 044       * Shared event manager
 045       * @var false|null|SharedEventManagerInterface
 046       */
 047      protected $sharedManager = null;
 048   
 049      /**
 050       * Constructor
 051       *
 052       * Allows optionally specifying identifier(s) to use to pull signals from a
 053       * SharedEventManagerInterface.
 054       *
 055       * @param  null|string|int|array|Traversable $identifiers
 056       */
 057      public function __construct($identifiers = null)
 058      {
 059          $this->setIdentifiers($identifiers);
 060      }
 061   
 062      /**
 063       * Set the event class to utilize
 064       *
 065       * @param  string $class
 066       * @return EventManager
 067       */
 068      public function setEventClass($class)
 069      {
 070          $this->eventClass = $class;
 071          return $this;
 072      }
 073   
 074      /**
 075       * Set shared event manager
 076       *
 077       * @param SharedEventManagerInterface $sharedEventManager
 078       * @return EventManager
 079       */
 080      public function setSharedManager(SharedEventManagerInterface $sharedEventManager)
 081      {
 082          $this->sharedManager = $sharedEventManager;
 083          StaticEventManager::setInstance($sharedEventManager);
 084          return $this;
 085      }
 086   
 087      /**
 088       * Remove any shared event manager currently attached
 089       *
 090       * @return void
 091       */
 092      public function unsetSharedManager()
 093      {
 094          $this->sharedManager = false;
 095      }
 096   
 097      /**
 098       * Get shared event manager
 099       *
 100       * If one is not defined, but we have a static instance in
 101       * StaticEventManager, that one will be used and set in this instance.
 102       *
 103       * If none is available in the StaticEventManager, a boolean false is
 104       * returned.
 105       *
 106       * @return false|SharedEventManagerInterface
 107       */
 108      public function getSharedManager()
 109      {
 110          // "false" means "I do not want a shared manager; don't try and fetch one"
 111          if (false === $this->sharedManager
 112              || $this->sharedManager instanceof SharedEventManagerInterface
 113          ) {
 114              return $this->sharedManager;
 115          }
 116   
 117          if (!StaticEventManager::hasInstance()) {
 118              return false;
 119          }
 120   
 121          $this->sharedManager = StaticEventManager::getInstance();
 122          return $this->sharedManager;
 123      }
 124   
 125      /**
 126       * Get the identifier(s) for this EventManager
 127       *
 128       * @return array
 129       */
 130      public function getIdentifiers()
 131      {
 132          return $this->identifiers;
 133      }
 134   
 135      /**
 136       * Set the identifiers (overrides any currently set identifiers)
 137       *
 138       * @param string|int|array|Traversable $identifiers
 139       * @return EventManager Provides a fluent interface
 140       */
 141      public function setIdentifiers($identifiers)
 142      {
 143          if (is_array($identifiers) || $identifiers instanceof Traversable) {
 144              $this->identifiers = array_unique((array) $identifiers);
 145          } elseif ($identifiers !== null) {
 146              $this->identifiers = array($identifiers);
 147          }
 148          return $this;
 149      }
 150   
 151      /**
 152       * Add some identifier(s) (appends to any currently set identifiers)
 153       *
 154       * @param string|int|array|Traversable $identifiers
 155       * @return EventManager Provides a fluent interface
 156       */
 157      public function addIdentifiers($identifiers)
 158      {
 159          if (is_array($identifiers) || $identifiers instanceof Traversable) {
 160              $this->identifiers = array_unique(array_merge($this->identifiers, (array) $identifiers));
 161          } elseif ($identifiers !== null) {
 162              $this->identifiers = array_unique(array_merge($this->identifiers, array($identifiers)));
 163          }
 164          return $this;
 165      }
 166   
 167      /**
 168       * Trigger all listeners for a given event
 169       *
 170       * @param  string|EventInterface $event
 171       * @param  string|object     $target   Object calling emit, or symbol describing target (such as static method name)
 172       * @param  array|ArrayAccess $argv     Array of arguments; typically, should be associative
 173       * @param  null|callable     $callback Trigger listeners until return value of this callback evaluate to true
 174       * @return ResponseCollection All listener return values
 175       * @throws Exception\InvalidCallbackException
 176       */
 177      public function trigger($event, $target = null, $argv = array(), $callback = null)
 178      {
 179          if ($event instanceof EventInterface) {
 180              $e        = $event;
 181              $event    = $e->getName();
 182              $callback = $target;
 183          } elseif ($target instanceof EventInterface) {
 184              $e = $target;
 185              $e->setName($event);
 186              $callback = $argv;
 187          } elseif ($argv instanceof EventInterface) {
 188              $e = $argv;
 189              $e->setName($event);
 190              $e->setTarget($target);
 191          } else {
 192              $e = new $this->eventClass();
 193              $e->setName($event);
 194              $e->setTarget($target);
 195              $e->setParams($argv);
 196          }
 197   
 198          if ($callback && !is_callable($callback)) {
 199              throw new Exception\InvalidCallbackException('Invalid callback provided');
 200          }
 201   
 202          // Initial value of stop propagation flag should be false
 203          $e->stopPropagation(false);
 204   
 205          return $this->triggerListeners($event, $e, $callback);
 206      }
 207   
 208      /**
 209       * Trigger listeners until return value of one causes a callback to
 210       * evaluate to true
 211       *
 212       * Triggers listeners until the provided callback evaluates the return
 213       * value of one as true, or until all listeners have been executed.
 214       *
 215       * @param  string|EventInterface $event
 216       * @param  string|object $target Object calling emit, or symbol describing target (such as static method name)
 217       * @param  array|ArrayAccess $argv Array of arguments; typically, should be associative
 218       * @param  callable $callback
 219       * @return ResponseCollection
 220       * @deprecated Please use trigger()
 221       * @throws Exception\InvalidCallbackException if invalid callable provided
 222       */
 223      public function triggerUntil($event, $target, $argv = null, $callback = null)
 224      {
 225          trigger_error(
 226              'This method is deprecated and will be removed in the future. Please use trigger() instead.',
 227              E_USER_DEPRECATED
 228          );
 229          return $this->trigger($event, $target, $argv, $callback);
 230      }
 231   
 232      /**
 233       * Attach a listener to an event
 234       *
 235       * The first argument is the event, and the next argument describes a
 236       * callback that will respond to that event. A CallbackHandler instance
 237       * describing the event listener combination will be returned.
 238       *
 239       * The last argument indicates a priority at which the event should be
 240       * executed. By default, this value is 1; however, you may set it for any
 241       * integer value. Higher values have higher priority (i.e., execute first).
 242       *
 243       * You can specify "*" for the event name. In such cases, the listener will
 244       * be triggered for every event.
 245       *
 246       * @param  string|array|ListenerAggregateInterface $event An event or array of event names. If a ListenerAggregateInterface, proxies to {@link attachAggregate()}.
 247       * @param  callable|int $callback If string $event provided, expects PHP callback; for a ListenerAggregateInterface $event, this will be the priority
 248       * @param  int $priority If provided, the priority at which to register the callable
 249       * @return CallbackHandler|mixed CallbackHandler if attaching callable (to allow later unsubscribe); mixed if attaching aggregate
 250       * @throws Exception\InvalidArgumentException
 251       */
 252      public function attach($event, $callback = null, $priority = 1)
 253      {
 254          // Proxy ListenerAggregateInterface arguments to attachAggregate()
 255          if ($event instanceof ListenerAggregateInterface) {
 256              return $this->attachAggregate($event, $callback);
 257          }
 258   
 259          // Null callback is invalid
 260          if (null === $callback) {
 261              throw new Exception\InvalidArgumentException(sprintf(
 262                  '%s: expects a callback; none provided',
 263                  __METHOD__
 264              ));
 265          }
 266   
 267          // Array of events should be registered individually, and return an array of all listeners
 268          if (is_array($event)) {
 269              $listeners = array();
 270              foreach ($event as $name) {
 271                  $listeners[] = $this->attach($name, $callback, $priority);
 272              }
 273              return $listeners;
 274          }
 275   
 276          // If we don't have a priority queue for the event yet, create one
 277          if (empty($this->events[$event])) {
 278              $this->events[$event] = new PriorityQueue();
 279          }
 280   
 281          // Create a callback handler, setting the event and priority in its metadata
 282          $listener = new CallbackHandler($callback, array('event' => $event, 'priority' => $priority));
 283   
 284          // Inject the callback handler into the queue
 285          $this->events[$event]->insert($listener, $priority);
 286          return $listener;
 287      }
 288   
 289      /**
 290       * Attach a listener aggregate
 291       *
 292       * Listener aggregates accept an EventManagerInterface instance, and call attach()
 293       * one or more times, typically to attach to multiple events using local
 294       * methods.
 295       *
 296       * @param  ListenerAggregateInterface $aggregate
 297       * @param  int $priority If provided, a suggested priority for the aggregate to use
 298       * @return mixed return value of {@link ListenerAggregateInterface::attach()}
 299       */
 300      public function attachAggregate(ListenerAggregateInterface $aggregate, $priority = 1)
 301      {
 302          return $aggregate->attach($this, $priority);
 303      }
 304   
 305      /**
 306       * Unsubscribe a listener from an event
 307       *
 308       * @param  CallbackHandler|ListenerAggregateInterface $listener
 309       * @return bool Returns true if event and listener found, and unsubscribed; returns false if either event or listener not found
 310       * @throws Exception\InvalidArgumentException if invalid listener provided
 311       */
 312      public function detach($listener)
 313      {
 314          if ($listener instanceof ListenerAggregateInterface) {
 315              return $this->detachAggregate($listener);
 316          }
 317   
 318          if (!$listener instanceof CallbackHandler) {
 319              throw new Exception\InvalidArgumentException(sprintf(
 320                  '%s: expected a ListenerAggregateInterface or CallbackHandler; received "%s"',
 321                  __METHOD__,
 322                  (is_object($listener) ? get_class($listener) : gettype($listener))
 323              ));
 324          }
 325   
 326          $event = $listener->getMetadatum('event');
 327          if (!$event || empty($this->events[$event])) {
 328              return false;
 329          }
 330          $return = $this->events[$event]->remove($listener);
 331          if (!$return) {
 332              return false;
 333          }
 334          if (!count($this->events[$event])) {
 335              unset($this->events[$event]);
 336          }
 337          return true;
 338      }
 339   
 340      /**
 341       * Detach a listener aggregate
 342       *
 343       * Listener aggregates accept an EventManagerInterface instance, and call detach()
 344       * of all previously attached listeners.
 345       *
 346       * @param  ListenerAggregateInterface $aggregate
 347       * @return mixed return value of {@link ListenerAggregateInterface::detach()}
 348       */
 349      public function detachAggregate(ListenerAggregateInterface $aggregate)
 350      {
 351          return $aggregate->detach($this);
 352      }
 353   
 354      /**
 355       * Retrieve all registered events
 356       *
 357       * @return array
 358       */
 359      public function getEvents()
 360      {
 361          return array_keys($this->events);
 362      }
 363   
 364      /**
 365       * Retrieve all listeners for a given event
 366       *
 367       * @param  string $event
 368       * @return PriorityQueue
 369       */
 370      public function getListeners($event)
 371      {
 372          if (!array_key_exists($event, $this->events)) {
 373              return new PriorityQueue();
 374          }
 375          return $this->events[$event];
 376      }
 377   
 378      /**
 379       * Clear all listeners for a given event
 380       *
 381       * @param  string $event
 382       * @return void
 383       */
 384      public function clearListeners($event)
 385      {
 386          if (!empty($this->events[$event])) {
 387              unset($this->events[$event]);
 388          }
 389      }
 390   
 391      /**
 392       * Prepare arguments
 393       *
 394       * Use this method if you want to be able to modify arguments from within a
 395       * listener. It returns an ArrayObject of the arguments, which may then be
 396       * passed to trigger().
 397       *
 398       * @param  array $args
 399       * @return ArrayObject
 400       */
 401      public function prepareArgs(array $args)
 402      {
 403          return new ArrayObject($args);
 404      }
 405   
 406      /**
 407       * Trigger listeners
 408       *
 409       * Actual functionality for triggering listeners, to which trigger() delegate.
 410       *
 411       * @param  string           $event Event name
 412       * @param  EventInterface $e
 413       * @param  null|callable    $callback
 414       * @return ResponseCollection
 415       */
 416      protected function triggerListeners($event, EventInterface $e, $callback = null)
 417      {
 418          $responses = new ResponseCollection;
 419          $listeners = $this->getListeners($event);
 420   
 421          // Add shared/wildcard listeners to the list of listeners,
 422          // but don't modify the listeners object
 423          $sharedListeners         = $this->getSharedListeners($event);
 424          $sharedWildcardListeners = $this->getSharedListeners('*');
 425          $wildcardListeners       = $this->getListeners('*');
 426          if (count($sharedListeners) || count($sharedWildcardListeners) || count($wildcardListeners)) {
 427              $listeners = clone $listeners;
 428   
 429              // Shared listeners on this specific event
 430              $this->insertListeners($listeners, $sharedListeners);
 431   
 432              // Shared wildcard listeners
 433              $this->insertListeners($listeners, $sharedWildcardListeners);
 434   
 435              // Add wildcard listeners
 436              $this->insertListeners($listeners, $wildcardListeners);
 437          }
 438   
 439          foreach ($listeners as $listener) {
 440              $listenerCallback = $listener->getCallback();
 441   
 442              // Trigger the listener's callback, and push its result onto the
 443              // response collection
 444              $responses->push(call_user_func($listenerCallback, $e));
 445   
 446              // If the event was asked to stop propagating, do so
 447              if ($e->propagationIsStopped()) {
 448                  $responses->setStopped(true);
 449                  break;
 450              }
 451   
 452              // If the result causes our validation callback to return true,
 453              // stop propagation
 454              if ($callback && call_user_func($callback, $responses->last())) {
 455                  $responses->setStopped(true);
 456                  break;
 457              }
 458          }
 459   
 460          return $responses;
 461      }
 462   
 463      /**
 464       * Get list of all listeners attached to the shared event manager for
 465       * identifiers registered by this instance
 466       *
 467       * @param  string $event
 468       * @return array
 469       */
 470      protected function getSharedListeners($event)
 471      {
 472          if (!$sharedManager = $this->getSharedManager()) {
 473              return array();
 474          }
 475   
 476          $identifiers     = $this->getIdentifiers();
 477          //Add wildcard id to the search, if not already added
 478          if (!in_array('*', $identifiers)) {
 479              $identifiers[] = '*';
 480          }
 481          $sharedListeners = array();
 482   
 483          foreach ($identifiers as $id) {
 484              if (!$listeners = $sharedManager->getListeners($id, $event)) {
 485                  continue;
 486              }
 487   
 488              if (!is_array($listeners) && !($listeners instanceof Traversable)) {
 489                  continue;
 490              }
 491   
 492              foreach ($listeners as $listener) {
 493                  if (!$listener instanceof CallbackHandler) {
 494                      continue;
 495                  }
 496                  $sharedListeners[] = $listener;
 497              }
 498          }
 499   
 500          return $sharedListeners;
 501      }
 502   
 503      /**
 504       * Add listeners to the master queue of listeners
 505       *
 506       * Used to inject shared listeners and wildcard listeners.
 507       *
 508       * @param  PriorityQueue $masterListeners
 509       * @param  array|Traversable $listeners
 510       * @return void
 511       */
 512      protected function insertListeners($masterListeners, $listeners)
 513      {
 514          foreach ($listeners as $listener) {
 515              $priority = $listener->getMetadatum('priority');
 516              if (null === $priority) {
 517                  $priority = 1;
 518              } elseif (is_array($priority)) {
 519                  // If we have an array, likely using PriorityQueue. Grab first
 520                  // element of the array, as that's the actual priority.
 521                  $priority = array_shift($priority);
 522              }
 523              $masterListeners->insert($listener, $priority);
 524          }
 525      }
 526  }
 527