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. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
EventManager.php
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