Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

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: 02.04.2025, 15:02 - Dateigröße: 9.36 KiB


001  <?php
002  /**
003   * Zend Framework (http://framework.zend.com/)
004   *
005   * @link      http://github.com/zendframework/zend-eventmanager for the canonical source repository
006   * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
007   * @license   https://github.com/zendframework/zend-eventmanager/blob/master/LICENSE.md
008   */
009   
010  namespace Zend\EventManager;
011   
012  use ArrayObject;
013   
014  /**
015   * Event manager: notification system
016   *
017   * Use the EventManager when you want to create a per-instance notification
018   * system for your objects.
019   */
020  class EventManager implements EventManagerInterface
021  {
022      /**
023       * Subscribed events and their listeners
024       *
025       * STRUCTURE:
026       * [
027       *     <string name> => [
028       *         <int priority> => [
029       *             0 => [<callable listener>, ...]
030       *         ],
031       *         ...
032       *     ],
033       *     ...
034       * ]
035       *
036       * NOTE:
037       * This structure helps us to reuse the list of listeners
038       * instead of first iterating over it and generating a new one
039       * -> In result it improves performance by up to 25% even if it looks a bit strange
040       *
041       * @var array[]
042       */
043      protected $events = [];
044   
045      /**
046       * @var EventInterface Prototype to use when creating an event at trigger().
047       */
048      protected $eventPrototype;
049   
050      /**
051       * Identifiers, used to pull shared signals from SharedEventManagerInterface instance
052       *
053       * @var array
054       */
055      protected $identifiers = [];
056   
057      /**
058       * Shared event manager
059       *
060       * @var null|SharedEventManagerInterface
061       */
062      protected $sharedManager = null;
063   
064      /**
065       * Constructor
066       *
067       * Allows optionally specifying identifier(s) to use to pull signals from a
068       * SharedEventManagerInterface.
069       *
070       * @param SharedEventManagerInterface $sharedEventManager
071       * @param array $identifiers
072       */
073      public function __construct(SharedEventManagerInterface $sharedEventManager = null, array $identifiers = [])
074      {
075          if ($sharedEventManager) {
076              $this->sharedManager = $sharedEventManager;
077              $this->setIdentifiers($identifiers);
078          }
079   
080          $this->eventPrototype = new Event();
081      }
082   
083      /**
084       * @inheritDoc
085       */
086      public function setEventPrototype(EventInterface $prototype)
087      {
088          $this->eventPrototype = $prototype;
089      }
090   
091      /**
092       * Retrieve the shared event manager, if composed.
093       *
094       * @return null|SharedEventManagerInterface $sharedEventManager
095       */
096      public function getSharedManager()
097      {
098          return $this->sharedManager;
099      }
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  }
344