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. |
|
(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 Symfony\Component\EventDispatcher\EventDispatcherInterface;
015 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
016 use Symfony\Component\EventDispatcher\Event;
017 use Symfony\Component\Stopwatch\Stopwatch;
018 use Psr\Log\LoggerInterface;
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 $called;
033 private $dispatcher;
034 private $wrappedListeners;
035
036 /**
037 * Constructor.
038 *
039 * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
040 * @param Stopwatch $stopwatch A Stopwatch instance
041 * @param LoggerInterface $logger A LoggerInterface instance
042 */
043 public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null)
044 {
045 $this->dispatcher = $dispatcher;
046 $this->stopwatch = $stopwatch;
047 $this->logger = $logger;
048 $this->called = array();
049 $this->wrappedListeners = array();
050 }
051
052 /**
053 * {@inheritdoc}
054 */
055 public function addListener($eventName, $listener, $priority = 0)
056 {
057 $this->dispatcher->addListener($eventName, $listener, $priority);
058 }
059
060 /**
061 * {@inheritdoc}
062 */
063 public function addSubscriber(EventSubscriberInterface $subscriber)
064 {
065 $this->dispatcher->addSubscriber($subscriber);
066 }
067
068 /**
069 * {@inheritdoc}
070 */
071 public function removeListener($eventName, $listener)
072 {
073 if (isset($this->wrappedListeners[$eventName])) {
074 foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) {
075 if ($wrappedListener->getWrappedListener() === $listener) {
076 $listener = $wrappedListener;
077 unset($this->wrappedListeners[$eventName][$index]);
078 break;
079 }
080 }
081 }
082
083 return $this->dispatcher->removeListener($eventName, $listener);
084 }
085
086 /**
087 * {@inheritdoc}
088 */
089 public function removeSubscriber(EventSubscriberInterface $subscriber)
090 {
091 return $this->dispatcher->removeSubscriber($subscriber);
092 }
093
094 /**
095 * {@inheritdoc}
096 */
097 public function getListeners($eventName = null)
098 {
099 return $this->dispatcher->getListeners($eventName);
100 }
101
102 /**
103 * {@inheritdoc}
104 */
105 public function getListenerPriority($eventName, $listener)
106 {
107 if (!method_exists($this->dispatcher, 'getListenerPriority')) {
108 return 0;
109 }
110
111 return $this->dispatcher->getListenerPriority($eventName, $listener);
112 }
113
114 /**
115 * {@inheritdoc}
116 */
117 public function hasListeners($eventName = null)
118 {
119 return $this->dispatcher->hasListeners($eventName);
120 }
121
122 /**
123 * {@inheritdoc}
124 */
125 public function dispatch($eventName, Event $event = null)
126 {
127 if (null === $event) {
128 $event = new Event();
129 }
130
131 if (null !== $this->logger && $event->isPropagationStopped()) {
132 $this->logger->debug(sprintf('The "%s" event is already stopped. No listeners have been called.', $eventName));
133 }
134
135 $this->preProcess($eventName);
136 $this->preDispatch($eventName, $event);
137
138 $e = $this->stopwatch->start($eventName, 'section');
139
140 $this->dispatcher->dispatch($eventName, $event);
141
142 if ($e->isStarted()) {
143 $e->stop();
144 }
145
146 $this->postDispatch($eventName, $event);
147 $this->postProcess($eventName);
148
149 return $event;
150 }
151
152 /**
153 * {@inheritdoc}
154 */
155 public function getCalledListeners()
156 {
157 $called = array();
158 foreach ($this->called as $eventName => $listeners) {
159 foreach ($listeners as $listener) {
160 $info = $this->getListenerInfo($listener->getWrappedListener(), $eventName);
161 $called[$eventName.'.'.$info['pretty']] = $info;
162 }
163 }
164
165 return $called;
166 }
167
168 /**
169 * {@inheritdoc}
170 */
171 public function getNotCalledListeners()
172 {
173 try {
174 $allListeners = $this->getListeners();
175 } catch (\Exception $e) {
176 if (null !== $this->logger) {
177 $this->logger->info('An exception was thrown while getting the uncalled listeners.', array('exception' => $e));
178 }
179
180 // unable to retrieve the uncalled listeners
181 return array();
182 }
183
184 $notCalled = array();
185 foreach ($allListeners as $eventName => $listeners) {
186 foreach ($listeners as $listener) {
187 $called = false;
188 if (isset($this->called[$eventName])) {
189 foreach ($this->called[$eventName] as $l) {
190 if ($l->getWrappedListener() === $listener) {
191 $called = true;
192
193 break;
194 }
195 }
196 }
197
198 if (!$called) {
199 $info = $this->getListenerInfo($listener, $eventName);
200 $notCalled[$eventName.'.'.$info['pretty']] = $info;
201 }
202 }
203 }
204
205 uasort($notCalled, array($this, 'sortListenersByPriority'));
206
207 return $notCalled;
208 }
209
210 /**
211 * Proxies all method calls to the original event dispatcher.
212 *
213 * @param string $method The method name
214 * @param array $arguments The method arguments
215 *
216 * @return mixed
217 */
218 public function __call($method, $arguments)
219 {
220 return call_user_func_array(array($this->dispatcher, $method), $arguments);
221 }
222
223 /**
224 * Called before dispatching the event.
225 *
226 * @param string $eventName The event name
227 * @param Event $event The event
228 */
229 protected function preDispatch($eventName, Event $event)
230 {
231 }
232
233 /**
234 * Called after dispatching the event.
235 *
236 * @param string $eventName The event name
237 * @param Event $event The event
238 */
239 protected function postDispatch($eventName, Event $event)
240 {
241 }
242
243 private function preProcess($eventName)
244 {
245 foreach ($this->dispatcher->getListeners($eventName) as $listener) {
246 $info = $this->getListenerInfo($listener, $eventName);
247 $name = isset($info['class']) ? $info['class'] : $info['type'];
248 $wrappedListener = new WrappedListener($listener, $name, $this->stopwatch, $this);
249 $this->wrappedListeners[$eventName][] = $wrappedListener;
250 $this->dispatcher->removeListener($eventName, $listener);
251 $this->dispatcher->addListener($eventName, $wrappedListener, $info['priority']);
252 }
253 }
254
255 private function postProcess($eventName)
256 {
257 unset($this->wrappedListeners[$eventName]);
258 $skipped = false;
259 foreach ($this->dispatcher->getListeners($eventName) as $listener) {
260 if (!$listener instanceof WrappedListener) { // #12845: a new listener was added during dispatch.
261 continue;
262 }
263 // Unwrap listener
264 $priority = $this->getListenerPriority($eventName, $listener);
265 $this->dispatcher->removeListener($eventName, $listener);
266 $this->dispatcher->addListener($eventName, $listener->getWrappedListener(), $priority);
267
268 $info = $this->getListenerInfo($listener->getWrappedListener(), $eventName);
269 if ($listener->wasCalled()) {
270 if (null !== $this->logger) {
271 $this->logger->debug(sprintf('Notified event "%s" to listener "%s".', $eventName, $info['pretty']));
272 }
273
274 if (!isset($this->called[$eventName])) {
275 $this->called[$eventName] = new \SplObjectStorage();
276 }
277
278 $this->called[$eventName]->attach($listener);
279 }
280
281 if (null !== $this->logger && $skipped) {
282 $this->logger->debug(sprintf('Listener "%s" was not called for event "%s".', $info['pretty'], $eventName));
283 }
284
285 if ($listener->stoppedPropagation()) {
286 if (null !== $this->logger) {
287 $this->logger->debug(sprintf('Listener "%s" stopped propagation of the event "%s".', $info['pretty'], $eventName));
288 }
289
290 $skipped = true;
291 }
292 }
293 }
294
295 /**
296 * Returns information about the listener.
297 *
298 * @param object $listener The listener
299 * @param string $eventName The event name
300 *
301 * @return array Information about the listener
302 */
303 private function getListenerInfo($listener, $eventName)
304 {
305 $info = array(
306 'event' => $eventName,
307 'priority' => $this->getListenerPriority($eventName, $listener),
308 );
309 if ($listener instanceof \Closure) {
310 $info += array(
311 'type' => 'Closure',
312 'pretty' => 'closure',
313 );
314 } elseif (is_string($listener)) {
315 try {
316 $r = new \ReflectionFunction($listener);
317 $file = $r->getFileName();
318 $line = $r->getStartLine();
319 } catch (\ReflectionException $e) {
320 $file = null;
321 $line = null;
322 }
323 $info += array(
324 'type' => 'Function',
325 'function' => $listener,
326 'file' => $file,
327 'line' => $line,
328 'pretty' => $listener,
329 );
330 } elseif (is_array($listener) || (is_object($listener) && is_callable($listener))) {
331 if (!is_array($listener)) {
332 $listener = array($listener, '__invoke');
333 }
334 $class = is_object($listener[0]) ? get_class($listener[0]) : $listener[0];
335 try {
336 $r = new \ReflectionMethod($class, $listener[1]);
337 $file = $r->getFileName();
338 $line = $r->getStartLine();
339 } catch (\ReflectionException $e) {
340 $file = null;
341 $line = null;
342 }
343 $info += array(
344 'type' => 'Method',
345 'class' => $class,
346 'method' => $listener[1],
347 'file' => $file,
348 'line' => $line,
349 'pretty' => $class.'::'.$listener[1],
350 );
351 }
352
353 return $info;
354 }
355
356 private function sortListenersByPriority($a, $b)
357 {
358 if (is_int($a['priority']) && !is_int($b['priority'])) {
359 return 1;
360 }
361
362 if (!is_int($a['priority']) && is_int($b['priority'])) {
363 return -1;
364 }
365
366 if ($a['priority'] === $b['priority']) {
367 return 0;
368 }
369
370 if ($a['priority'] > $b['priority']) {
371 return -1;
372 }
373
374 return 1;
375 }
376 }
377