[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/symfony/event-dispatcher/Debug/ -> TraceableEventDispatcher.php (source)

   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 $called;
  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->called = array();
  42          $this->wrappedListeners = array();
  43      }
  44  
  45      /**
  46       * {@inheritdoc}
  47       */
  48      public function addListener($eventName, $listener, $priority = 0)
  49      {
  50          $this->dispatcher->addListener($eventName, $listener, $priority);
  51      }
  52  
  53      /**
  54       * {@inheritdoc}
  55       */
  56      public function addSubscriber(EventSubscriberInterface $subscriber)
  57      {
  58          $this->dispatcher->addSubscriber($subscriber);
  59      }
  60  
  61      /**
  62       * {@inheritdoc}
  63       */
  64      public function removeListener($eventName, $listener)
  65      {
  66          if (isset($this->wrappedListeners[$eventName])) {
  67              foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) {
  68                  if ($wrappedListener->getWrappedListener() === $listener) {
  69                      $listener = $wrappedListener;
  70                      unset($this->wrappedListeners[$eventName][$index]);
  71                      break;
  72                  }
  73              }
  74          }
  75  
  76          return $this->dispatcher->removeListener($eventName, $listener);
  77      }
  78  
  79      /**
  80       * {@inheritdoc}
  81       */
  82      public function removeSubscriber(EventSubscriberInterface $subscriber)
  83      {
  84          return $this->dispatcher->removeSubscriber($subscriber);
  85      }
  86  
  87      /**
  88       * {@inheritdoc}
  89       */
  90      public function getListeners($eventName = null)
  91      {
  92          return $this->dispatcher->getListeners($eventName);
  93      }
  94  
  95      /**
  96       * {@inheritdoc}
  97       */
  98      public function getListenerPriority($eventName, $listener)
  99      {
 100          if (!method_exists($this->dispatcher, 'getListenerPriority')) {
 101              return 0;
 102          }
 103  
 104          return $this->dispatcher->getListenerPriority($eventName, $listener);
 105      }
 106  
 107      /**
 108       * {@inheritdoc}
 109       */
 110      public function hasListeners($eventName = null)
 111      {
 112          return $this->dispatcher->hasListeners($eventName);
 113      }
 114  
 115      /**
 116       * {@inheritdoc}
 117       */
 118      public function dispatch($eventName, Event $event = null)
 119      {
 120          if (null === $event) {
 121              $event = new Event();
 122          }
 123  
 124          if (null !== $this->logger && $event->isPropagationStopped()) {
 125              $this->logger->debug(sprintf('The "%s" event is already stopped. No listeners have been called.', $eventName));
 126          }
 127  
 128          $this->preProcess($eventName);
 129          $this->preDispatch($eventName, $event);
 130  
 131          $e = $this->stopwatch->start($eventName, 'section');
 132  
 133          $this->dispatcher->dispatch($eventName, $event);
 134  
 135          if ($e->isStarted()) {
 136              $e->stop();
 137          }
 138  
 139          $this->postDispatch($eventName, $event);
 140          $this->postProcess($eventName);
 141  
 142          return $event;
 143      }
 144  
 145      /**
 146       * {@inheritdoc}
 147       */
 148      public function getCalledListeners()
 149      {
 150          $called = array();
 151          foreach ($this->called as $eventName => $listeners) {
 152              foreach ($listeners as $listener) {
 153                  $info = $this->getListenerInfo($listener->getWrappedListener(), $eventName);
 154                  $called[$eventName.'.'.$info['pretty']] = $info;
 155              }
 156          }
 157  
 158          return $called;
 159      }
 160  
 161      /**
 162       * {@inheritdoc}
 163       */
 164      public function getNotCalledListeners()
 165      {
 166          try {
 167              $allListeners = $this->getListeners();
 168          } catch (\Exception $e) {
 169              if (null !== $this->logger) {
 170                  $this->logger->info('An exception was thrown while getting the uncalled listeners.', array('exception' => $e));
 171              }
 172  
 173              // unable to retrieve the uncalled listeners
 174              return array();
 175          }
 176  
 177          $notCalled = array();
 178          foreach ($allListeners as $eventName => $listeners) {
 179              foreach ($listeners as $listener) {
 180                  $called = false;
 181                  if (isset($this->called[$eventName])) {
 182                      foreach ($this->called[$eventName] as $l) {
 183                          if ($l->getWrappedListener() === $listener) {
 184                              $called = true;
 185  
 186                              break;
 187                          }
 188                      }
 189                  }
 190  
 191                  if (!$called) {
 192                      $info = $this->getListenerInfo($listener, $eventName);
 193                      $notCalled[$eventName.'.'.$info['pretty']] = $info;
 194                  }
 195              }
 196          }
 197  
 198          uasort($notCalled, array($this, 'sortListenersByPriority'));
 199  
 200          return $notCalled;
 201      }
 202  
 203      /**
 204       * Proxies all method calls to the original event dispatcher.
 205       *
 206       * @param string $method    The method name
 207       * @param array  $arguments The method arguments
 208       *
 209       * @return mixed
 210       */
 211      public function __call($method, $arguments)
 212      {
 213          return \call_user_func_array(array($this->dispatcher, $method), $arguments);
 214      }
 215  
 216      /**
 217       * Called before dispatching the event.
 218       *
 219       * @param string $eventName The event name
 220       * @param Event  $event     The event
 221       */
 222      protected function preDispatch($eventName, Event $event)
 223      {
 224      }
 225  
 226      /**
 227       * Called after dispatching the event.
 228       *
 229       * @param string $eventName The event name
 230       * @param Event  $event     The event
 231       */
 232      protected function postDispatch($eventName, Event $event)
 233      {
 234      }
 235  
 236      private function preProcess($eventName)
 237      {
 238          foreach ($this->dispatcher->getListeners($eventName) as $listener) {
 239              $info = $this->getListenerInfo($listener, $eventName);
 240              $name = isset($info['class']) ? $info['class'] : $info['type'];
 241              $wrappedListener = new WrappedListener($listener, $name, $this->stopwatch, $this);
 242              $this->wrappedListeners[$eventName][] = $wrappedListener;
 243              $this->dispatcher->removeListener($eventName, $listener);
 244              $this->dispatcher->addListener($eventName, $wrappedListener, $info['priority']);
 245          }
 246      }
 247  
 248      private function postProcess($eventName)
 249      {
 250          unset($this->wrappedListeners[$eventName]);
 251          $skipped = false;
 252          foreach ($this->dispatcher->getListeners($eventName) as $listener) {
 253              if (!$listener instanceof WrappedListener) { // #12845: a new listener was added during dispatch.
 254                  continue;
 255              }
 256              // Unwrap listener
 257              $priority = $this->getListenerPriority($eventName, $listener);
 258              $this->dispatcher->removeListener($eventName, $listener);
 259              $this->dispatcher->addListener($eventName, $listener->getWrappedListener(), $priority);
 260  
 261              $info = $this->getListenerInfo($listener->getWrappedListener(), $eventName);
 262              if ($listener->wasCalled()) {
 263                  if (null !== $this->logger) {
 264                      $this->logger->debug(sprintf('Notified event "%s" to listener "%s".', $eventName, $info['pretty']));
 265                  }
 266  
 267                  if (!isset($this->called[$eventName])) {
 268                      $this->called[$eventName] = new \SplObjectStorage();
 269                  }
 270  
 271                  $this->called[$eventName]->attach($listener);
 272              }
 273  
 274              if (null !== $this->logger && $skipped) {
 275                  $this->logger->debug(sprintf('Listener "%s" was not called for event "%s".', $info['pretty'], $eventName));
 276              }
 277  
 278              if ($listener->stoppedPropagation()) {
 279                  if (null !== $this->logger) {
 280                      $this->logger->debug(sprintf('Listener "%s" stopped propagation of the event "%s".', $info['pretty'], $eventName));
 281                  }
 282  
 283                  $skipped = true;
 284              }
 285          }
 286      }
 287  
 288      /**
 289       * Returns information about the listener.
 290       *
 291       * @param object $listener  The listener
 292       * @param string $eventName The event name
 293       *
 294       * @return array Information about the listener
 295       */
 296      private function getListenerInfo($listener, $eventName)
 297      {
 298          $info = array(
 299              'event' => $eventName,
 300              'priority' => $this->getListenerPriority($eventName, $listener),
 301          );
 302  
 303          // unwrap for correct listener info
 304          if ($listener instanceof WrappedListener) {
 305              $listener = $listener->getWrappedListener();
 306          }
 307  
 308          if ($listener instanceof \Closure) {
 309              $info += array(
 310                  'type' => 'Closure',
 311                  'pretty' => 'closure',
 312              );
 313          } elseif (\is_string($listener)) {
 314              try {
 315                  $r = new \ReflectionFunction($listener);
 316                  $file = $r->getFileName();
 317                  $line = $r->getStartLine();
 318              } catch (\ReflectionException $e) {
 319                  $file = null;
 320                  $line = null;
 321              }
 322              $info += array(
 323                  'type' => 'Function',
 324                  'function' => $listener,
 325                  'file' => $file,
 326                  'line' => $line,
 327                  'pretty' => $listener,
 328              );
 329          } elseif (\is_array($listener) || (\is_object($listener) && \is_callable($listener))) {
 330              if (!\is_array($listener)) {
 331                  $listener = array($listener, '__invoke');
 332              }
 333              $class = \is_object($listener[0]) ? \get_class($listener[0]) : $listener[0];
 334              try {
 335                  $r = new \ReflectionMethod($class, $listener[1]);
 336                  $file = $r->getFileName();
 337                  $line = $r->getStartLine();
 338              } catch (\ReflectionException $e) {
 339                  $file = null;
 340                  $line = null;
 341              }
 342              $info += array(
 343                  'type' => 'Method',
 344                  'class' => $class,
 345                  'method' => $listener[1],
 346                  'file' => $file,
 347                  'line' => $line,
 348                  'pretty' => $class.'::'.$listener[1],
 349              );
 350          }
 351  
 352          return $info;
 353      }
 354  
 355      private function sortListenersByPriority($a, $b)
 356      {
 357          if (\is_int($a['priority']) && !\is_int($b['priority'])) {
 358              return 1;
 359          }
 360  
 361          if (!\is_int($a['priority']) && \is_int($b['priority'])) {
 362              return -1;
 363          }
 364  
 365          if ($a['priority'] === $b['priority']) {
 366              return 0;
 367          }
 368  
 369          if ($a['priority'] > $b['priority']) {
 370              return -1;
 371          }
 372  
 373          return 1;
 374      }
 375  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1