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 12namespace Symfony\Component\EventDispatcher; 13 14use Psr\EventDispatcher\StoppableEventInterface; 15use Symfony\Contracts\EventDispatcher\Event as ContractsEvent; 16use Symfony\Contracts\EventDispatcher\EventDispatcherInterface as ContractsEventDispatcherInterface; 17 18/** 19 * A helper class to provide BC/FC with the legacy signature of EventDispatcherInterface::dispatch(). 20 * 21 * This class should be deprecated in Symfony 5.1 22 * 23 * @author Nicolas Grekas <p@tchwork.com> 24 */ 25final class LegacyEventDispatcherProxy implements EventDispatcherInterface 26{ 27 private $dispatcher; 28 29 public static function decorate(?ContractsEventDispatcherInterface $dispatcher): ?ContractsEventDispatcherInterface 30 { 31 if (null === $dispatcher) { 32 return null; 33 } 34 $r = new \ReflectionMethod($dispatcher, 'dispatch'); 35 $param2 = $r->getParameters()[1] ?? null; 36 37 if (!$param2 || !$param2->hasType() || $param2->getType()->isBuiltin()) { 38 return $dispatcher; 39 } 40 41 @trigger_error(sprintf('The signature of the "%s::dispatch()" method should be updated to "dispatch($event, string $eventName = null)", not doing so is deprecated since Symfony 4.3.', $r->class), \E_USER_DEPRECATED); 42 43 $self = new self(); 44 $self->dispatcher = $dispatcher; 45 46 return $self; 47 } 48 49 /** 50 * {@inheritdoc} 51 * 52 * @param string|null $eventName 53 * 54 * @return object 55 */ 56 public function dispatch($event/*, string $eventName = null*/) 57 { 58 $eventName = 1 < \func_num_args() ? func_get_arg(1) : null; 59 60 if (\is_object($event)) { 61 $eventName = $eventName ?? \get_class($event); 62 } elseif (\is_string($event) && (null === $eventName || $eventName instanceof ContractsEvent || $eventName instanceof Event)) { 63 @trigger_error(sprintf('Calling the "%s::dispatch()" method with the event name as the first argument is deprecated since Symfony 4.3, pass it as the second argument and provide the event object as the first argument instead.', ContractsEventDispatcherInterface::class), \E_USER_DEPRECATED); 64 $swap = $event; 65 $event = $eventName ?? new Event(); 66 $eventName = $swap; 67 } else { 68 throw new \TypeError(sprintf('Argument 1 passed to "%s::dispatch()" must be an object, "%s" given.', ContractsEventDispatcherInterface::class, \is_object($event) ? \get_class($event) : \gettype($event))); 69 } 70 71 $listeners = $this->getListeners($eventName); 72 $stoppable = $event instanceof Event || $event instanceof ContractsEvent || $event instanceof StoppableEventInterface; 73 74 foreach ($listeners as $listener) { 75 if ($stoppable && $event->isPropagationStopped()) { 76 break; 77 } 78 $listener($event, $eventName, $this); 79 } 80 81 return $event; 82 } 83 84 /** 85 * {@inheritdoc} 86 */ 87 public function addListener($eventName, $listener, $priority = 0) 88 { 89 return $this->dispatcher->addListener($eventName, $listener, $priority); 90 } 91 92 /** 93 * {@inheritdoc} 94 */ 95 public function addSubscriber(EventSubscriberInterface $subscriber) 96 { 97 return $this->dispatcher->addSubscriber($subscriber); 98 } 99 100 /** 101 * {@inheritdoc} 102 */ 103 public function removeListener($eventName, $listener) 104 { 105 return $this->dispatcher->removeListener($eventName, $listener); 106 } 107 108 /** 109 * {@inheritdoc} 110 */ 111 public function removeSubscriber(EventSubscriberInterface $subscriber) 112 { 113 return $this->dispatcher->removeSubscriber($subscriber); 114 } 115 116 /** 117 * {@inheritdoc} 118 */ 119 public function getListeners($eventName = null): array 120 { 121 return $this->dispatcher->getListeners($eventName); 122 } 123 124 /** 125 * {@inheritdoc} 126 */ 127 public function getListenerPriority($eventName, $listener): ?int 128 { 129 return $this->dispatcher->getListenerPriority($eventName, $listener); 130 } 131 132 /** 133 * {@inheritdoc} 134 */ 135 public function hasListeners($eventName = null): bool 136 { 137 return $this->dispatcher->hasListeners($eventName); 138 } 139 140 /** 141 * Proxies all method calls to the original event dispatcher. 142 */ 143 public function __call($method, $arguments) 144 { 145 return $this->dispatcher->{$method}(...$arguments); 146 } 147} 148