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 |
TraceableEventDispatcher.php
001 <?php
002
003 /*
004 * This file is part of the Symfony package.
005 *
006 * (c) Fabien Potencier <fabien@symfony.com>
007 *
008 * For the full copyright and license information, please view the LICENSE
009 * file that was distributed with this source code.
010 */
011
012 namespace Symfony\Component\EventDispatcher\Debug;
013
014 use Psr\Log\LoggerInterface;
015 use Symfony\Component\EventDispatcher\Event;
016 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
017 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
018 use Symfony\Component\Stopwatch\Stopwatch;
019
020 /**
021 * Collects some data about event listeners.
022 *
023 * This event dispatcher delegates the dispatching to another one.
024 *
025 * @author Fabien Potencier <fabien@symfony.com>
026 */
027 class TraceableEventDispatcher implements TraceableEventDispatcherInterface
028 {
029 protected $logger;
030 protected $stopwatch;
031
032 private $callStack;
033 private $dispatcher;
034 private $wrappedListeners;
035
036 public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null)
037 {
038 $this->dispatcher = $dispatcher;
039 $this->stopwatch = $stopwatch;
040 $this->logger = $logger;
041 $this->wrappedListeners = [];
042 }
043
044 /**
045 * {@inheritdoc}
046 */
047 public function addListener($eventName, $listener, $priority = 0)
048 {
049 $this->dispatcher->addListener($eventName, $listener, $priority);
050 }
051
052 /**
053 * {@inheritdoc}
054 */
055 public function addSubscriber(EventSubscriberInterface $subscriber)
056 {
057 $this->dispatcher->addSubscriber($subscriber);
058 }
059
060 /**
061 * {@inheritdoc}
062 */
063 public function removeListener($eventName, $listener)
064 {
065 if (isset($this->wrappedListeners[$eventName])) {
066 foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) {
067 if ($wrappedListener->getWrappedListener() === $listener) {
068 $listener = $wrappedListener;
069 unset($this->wrappedListeners[$eventName][$index]);
070 break;
071 }
072 }
073 }
074
075 return $this->dispatcher->removeListener($eventName, $listener);
076 }
077
078 /**
079 * {@inheritdoc}
080 */
081 public function removeSubscriber(EventSubscriberInterface $subscriber)
082 {
083 return $this->dispatcher->removeSubscriber($subscriber);
084 }
085
086 /**
087 * {@inheritdoc}
088 */
089 public function getListeners($eventName = null)
090 {
091 return $this->dispatcher->getListeners($eventName);
092 }
093
094 /**
095 * {@inheritdoc}
096 */
097 public function getListenerPriority($eventName, $listener)
098 {
099 // we might have wrapped listeners for the event (if called while dispatching)
100 // in that case get the priority by wrapper
101 if (isset($this->wrappedListeners[$eventName])) {
102 foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) {
103 if ($wrappedListener->getWrappedListener() === $listener) {
104 return $this->dispatcher->getListenerPriority($eventName, $wrappedListener);
105 }
106 }
107 }
108
109 return $this->dispatcher->getListenerPriority($eventName, $listener);
110 }
111
112 /**
113 * {@inheritdoc}
114 */
115 public function hasListeners($eventName = null)
116 {
117 return $this->dispatcher->hasListeners($eventName);
118 }
119
120 /**
121 * {@inheritdoc}
122 */
123 public function dispatch($eventName, Event $event = null)
124 {
125 if (null === $this->callStack) {
126 $this->callStack = new \SplObjectStorage();
127 }
128
129 if (null === $event) {
130 $event = new Event();
131 }
132
133 if (null !== $this->logger && $event->isPropagationStopped()) {
134 $this->logger->debug(sprintf('The "%s" event is already stopped. No listeners have been called.', $eventName));
135 }
136
137 $this->preProcess($eventName);
138 try {
139 $this->preDispatch($eventName, $event);
140 try {
141 $e = $this->stopwatch->start($eventName, 'section');
142 try {
143 $this->dispatcher->dispatch($eventName, $event);
144 } finally {
145 if ($e->isStarted()) {
146 $e->stop();
147 }
148 }
149 } finally {
150 $this->postDispatch($eventName, $event);
151 }
152 } finally {
153 $this->postProcess($eventName);
154 }
155
156 return $event;
157 }
158
159 /**
160 * {@inheritdoc}
161 */
162 public function getCalledListeners()
163 {
164 if (null === $this->callStack) {
165 return [];
166 }
167
168 $called = [];
169 foreach ($this->callStack as $listener) {
170 list($eventName) = $this->callStack->getInfo();
171
172 $called[] = $listener->getInfo($eventName);
173 }
174
175 return $called;
176 }
177
178 /**
179 * {@inheritdoc}
180 */
181 public function getNotCalledListeners()
182 {
183 try {
184 $allListeners = $this->getListeners();
185 } catch (\Exception $e) {
186 if (null !== $this->logger) {
187 $this->logger->info('An exception was thrown while getting the uncalled listeners.', ['exception' => $e]);
188 }
189
190 // unable to retrieve the uncalled listeners
191 return [];
192 }
193
194 $calledListeners = [];
195
196 if (null !== $this->callStack) {
197 foreach ($this->callStack as $calledListener) {
198 $calledListeners[] = $calledListener->getWrappedListener();
199 }
200 }
201
202 $notCalled = [];
203 foreach ($allListeners as $eventName => $listeners) {
204 foreach ($listeners as $listener) {
205 if (!\in_array($listener, $calledListeners, true)) {
206 if (!$listener instanceof WrappedListener) {
207 $listener = new WrappedListener($listener, null, $this->stopwatch, $this);
208 }
209 $notCalled[] = $listener->getInfo($eventName);
210 }
211 }
212 }
213
214 uasort($notCalled, [$this, 'sortNotCalledListeners']);
215
216 return $notCalled;
217 }
218
219 public function reset()
220 {
221 $this->callStack = null;
222 }
223
224 /**
225 * Proxies all method calls to the original event dispatcher.
226 *
227 * @param string $method The method name
228 * @param array $arguments The method arguments
229 *
230 * @return mixed
231 */
232 public function __call($method, $arguments)
233 {
234 return \call_user_func_array([$this->dispatcher, $method], $arguments);
235 }
236
237 /**
238 * Called before dispatching the event.
239 *
240 * @param string $eventName The event name
241 * @param Event $event The event
242 */
243 protected function preDispatch($eventName, Event $event)
244 {
245 }
246
247 /**
248 * Called after dispatching the event.
249 *
250 * @param string $eventName The event name
251 * @param Event $event The event
252 */
253 protected function postDispatch($eventName, Event $event)
254 {
255 }
256
257 private function preProcess($eventName)
258 {
259 foreach ($this->dispatcher->getListeners($eventName) as $listener) {
260 $priority = $this->getListenerPriority($eventName, $listener);
261 $wrappedListener = new WrappedListener($listener instanceof WrappedListener ? $listener->getWrappedListener() : $listener, null, $this->stopwatch, $this);
262 $this->wrappedListeners[$eventName][] = $wrappedListener;
263 $this->dispatcher->removeListener($eventName, $listener);
264 $this->dispatcher->addListener($eventName, $wrappedListener, $priority);
265 $this->callStack->attach($wrappedListener, [$eventName]);
266 }
267 }
268
269 private function postProcess($eventName)
270 {
271 unset($this->wrappedListeners[$eventName]);
272 $skipped = false;
273 foreach ($this->dispatcher->getListeners($eventName) as $listener) {
274 if (!$listener instanceof WrappedListener) { // #12845: a new listener was added during dispatch.
275 continue;
276 }
277 // Unwrap listener
278 $priority = $this->getListenerPriority($eventName, $listener);
279 $this->dispatcher->removeListener($eventName, $listener);
280 $this->dispatcher->addListener($eventName, $listener->getWrappedListener(), $priority);
281
282 if (null !== $this->logger) {
283 $context = ['event' => $eventName, 'listener' => $listener->getPretty()];
284 }
285
286 if ($listener->wasCalled()) {
287 if (null !== $this->logger) {
288 $this->logger->debug('Notified event "{event}" to listener "{listener}".', $context);
289 }
290 } else {
291 $this->callStack->detach($listener);
292 }
293
294 if (null !== $this->logger && $skipped) {
295 $this->logger->debug('Listener "{listener}" was not called for event "{event}".', $context);
296 }
297
298 if ($listener->stoppedPropagation()) {
299 if (null !== $this->logger) {
300 $this->logger->debug('Listener "{listener}" stopped propagation of the event "{event}".', $context);
301 }
302
303 $skipped = true;
304 }
305 }
306 }
307
308 private function sortNotCalledListeners(array $a, array $b)
309 {
310 if (0 !== $cmp = strcmp($a['event'], $b['event'])) {
311 return $cmp;
312 }
313
314 if (\is_int($a['priority']) && !\is_int($b['priority'])) {
315 return 1;
316 }
317
318 if (!\is_int($a['priority']) && \is_int($b['priority'])) {
319 return -1;
320 }
321
322 if ($a['priority'] === $b['priority']) {
323 return 0;
324 }
325
326 if ($a['priority'] > $b['priority']) {
327 return -1;
328 }
329
330 return 1;
331 }
332 }
333