[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 3 /* 4 * This file is part of the Symfony package. 5 * 6 * (c) Fabien Potencier <fabien@symfony.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12 namespace Symfony\Component\EventDispatcher\Debug; 13 14 use Psr\Log\LoggerInterface; 15 use Symfony\Component\EventDispatcher\Event; 16 use Symfony\Component\EventDispatcher\EventDispatcherInterface; 17 use Symfony\Component\EventDispatcher\EventSubscriberInterface; 18 use Symfony\Component\Stopwatch\Stopwatch; 19 20 /** 21 * Collects some data about event listeners. 22 * 23 * This event dispatcher delegates the dispatching to another one. 24 * 25 * @author Fabien Potencier <fabien@symfony.com> 26 */ 27 class TraceableEventDispatcher implements TraceableEventDispatcherInterface 28 { 29 protected $logger; 30 protected $stopwatch; 31 32 private $callStack; 33 private $dispatcher; 34 private $wrappedListeners; 35 36 public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null) 37 { 38 $this->dispatcher = $dispatcher; 39 $this->stopwatch = $stopwatch; 40 $this->logger = $logger; 41 $this->wrappedListeners = []; 42 } 43 44 /** 45 * {@inheritdoc} 46 */ 47 public function addListener($eventName, $listener, $priority = 0) 48 { 49 $this->dispatcher->addListener($eventName, $listener, $priority); 50 } 51 52 /** 53 * {@inheritdoc} 54 */ 55 public function addSubscriber(EventSubscriberInterface $subscriber) 56 { 57 $this->dispatcher->addSubscriber($subscriber); 58 } 59 60 /** 61 * {@inheritdoc} 62 */ 63 public function removeListener($eventName, $listener) 64 { 65 if (isset($this->wrappedListeners[$eventName])) { 66 foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) { 67 if ($wrappedListener->getWrappedListener() === $listener) { 68 $listener = $wrappedListener; 69 unset($this->wrappedListeners[$eventName][$index]); 70 break; 71 } 72 } 73 } 74 75 return $this->dispatcher->removeListener($eventName, $listener); 76 } 77 78 /** 79 * {@inheritdoc} 80 */ 81 public function removeSubscriber(EventSubscriberInterface $subscriber) 82 { 83 return $this->dispatcher->removeSubscriber($subscriber); 84 } 85 86 /** 87 * {@inheritdoc} 88 */ 89 public function getListeners($eventName = null) 90 { 91 return $this->dispatcher->getListeners($eventName); 92 } 93 94 /** 95 * {@inheritdoc} 96 */ 97 public function getListenerPriority($eventName, $listener) 98 { 99 // 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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |