PHP 8 Compatibility

This commit is contained in:
Frédéric Guillot
2022-02-05 11:49:03 -08:00
committed by GitHub
parent 61e63ef9e0
commit f5bb55bdb8
558 changed files with 6262 additions and 21691 deletions

View File

@@ -11,6 +11,10 @@
namespace Symfony\Component\EventDispatcher;
use Psr\EventDispatcher\StoppableEventInterface;
use Symfony\Component\EventDispatcher\Debug\WrappedListener;
use Symfony\Contracts\EventDispatcher\Event as ContractsEvent;
/**
* The EventDispatcherInterface is the central point of Symfony's event listener system.
*
@@ -28,20 +32,45 @@ namespace Symfony\Component\EventDispatcher;
*/
class EventDispatcher implements EventDispatcherInterface
{
private $listeners = array();
private $sorted = array();
private $listeners = [];
private $sorted = [];
private $optimized;
public function __construct()
{
if (__CLASS__ === static::class) {
$this->optimized = [];
}
}
/**
* {@inheritdoc}
*
* @param string|null $eventName
*/
public function dispatch($eventName, Event $event = null)
public function dispatch($event/*, string $eventName = null*/)
{
if (null === $event) {
$event = new Event();
$eventName = 1 < \func_num_args() ? func_get_arg(1) : null;
if (\is_object($event)) {
$eventName = $eventName ?? \get_class($event);
} elseif (\is_string($event) && (null === $eventName || $eventName instanceof ContractsEvent || $eventName instanceof Event)) {
@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.', EventDispatcherInterface::class), \E_USER_DEPRECATED);
$swap = $event;
$event = $eventName ?? new Event();
$eventName = $swap;
} else {
throw new \TypeError(sprintf('Argument 1 passed to "%s::dispatch()" must be an object, "%s" given.', EventDispatcherInterface::class, \is_object($event) ? \get_class($event) : \gettype($event)));
}
if ($listeners = $this->getListeners($eventName)) {
$this->doDispatch($listeners, $eventName, $event);
if (null !== $this->optimized && null !== $eventName) {
$listeners = $this->optimized[$eventName] ?? (empty($this->listeners[$eventName]) ? [] : $this->optimizeListeners($eventName));
} else {
$listeners = $this->getListeners($eventName);
}
if ($listeners) {
$this->callListeners($listeners, $eventName, $event);
}
return $event;
@@ -54,7 +83,7 @@ class EventDispatcher implements EventDispatcherInterface
{
if (null !== $eventName) {
if (empty($this->listeners[$eventName])) {
return array();
return [];
}
if (!isset($this->sorted[$eventName])) {
@@ -79,24 +108,27 @@ class EventDispatcher implements EventDispatcherInterface
public function getListenerPriority($eventName, $listener)
{
if (empty($this->listeners[$eventName])) {
return;
return null;
}
if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) {
$listener[0] = $listener[0]();
$listener[1] = $listener[1] ?? '__invoke';
}
foreach ($this->listeners[$eventName] as $priority => $listeners) {
foreach ($listeners as $k => $v) {
if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
foreach ($this->listeners[$eventName] as $priority => &$listeners) {
foreach ($listeners as &$v) {
if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) {
$v[0] = $v[0]();
$this->listeners[$eventName][$priority][$k] = $v;
$v[1] = $v[1] ?? '__invoke';
}
if ($v === $listener) {
return $priority;
}
}
}
return null;
}
/**
@@ -123,7 +155,7 @@ class EventDispatcher implements EventDispatcherInterface
public function addListener($eventName, $listener, $priority = 0)
{
$this->listeners[$eventName][$priority][] = $listener;
unset($this->sorted[$eventName]);
unset($this->sorted[$eventName], $this->optimized[$eventName]);
}
/**
@@ -135,25 +167,23 @@ class EventDispatcher implements EventDispatcherInterface
return;
}
if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) {
$listener[0] = $listener[0]();
$listener[1] = $listener[1] ?? '__invoke';
}
foreach ($this->listeners[$eventName] as $priority => $listeners) {
foreach ($listeners as $k => $v) {
if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
foreach ($this->listeners[$eventName] as $priority => &$listeners) {
foreach ($listeners as $k => &$v) {
if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) {
$v[0] = $v[0]();
$v[1] = $v[1] ?? '__invoke';
}
if ($v === $listener) {
unset($listeners[$k], $this->sorted[$eventName]);
} else {
$listeners[$k] = $v;
unset($listeners[$k], $this->sorted[$eventName], $this->optimized[$eventName]);
}
}
if ($listeners) {
$this->listeners[$eventName][$priority] = $listeners;
} else {
if (!$listeners) {
unset($this->listeners[$eventName][$priority]);
}
}
@@ -165,13 +195,13 @@ class EventDispatcher implements EventDispatcherInterface
public function addSubscriber(EventSubscriberInterface $subscriber)
{
foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
if (is_string($params)) {
$this->addListener($eventName, array($subscriber, $params));
} elseif (is_string($params[0])) {
$this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
if (\is_string($params)) {
$this->addListener($eventName, [$subscriber, $params]);
} elseif (\is_string($params[0])) {
$this->addListener($eventName, [$subscriber, $params[0]], $params[1] ?? 0);
} else {
foreach ($params as $listener) {
$this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
$this->addListener($eventName, [$subscriber, $listener[0]], $listener[1] ?? 0);
}
}
}
@@ -183,12 +213,12 @@ class EventDispatcher implements EventDispatcherInterface
public function removeSubscriber(EventSubscriberInterface $subscriber)
{
foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
if (is_array($params) && is_array($params[0])) {
if (\is_array($params) && \is_array($params[0])) {
foreach ($params as $listener) {
$this->removeListener($eventName, array($subscriber, $listener[0]));
$this->removeListener($eventName, [$subscriber, $listener[0]]);
}
} else {
$this->removeListener($eventName, array($subscriber, is_string($params) ? $params : $params[0]));
$this->removeListener($eventName, [$subscriber, \is_string($params) ? $params : $params[0]]);
}
}
}
@@ -201,7 +231,29 @@ class EventDispatcher implements EventDispatcherInterface
*
* @param callable[] $listeners The event listeners
* @param string $eventName The name of the event to dispatch
* @param Event $event The event object to pass to the event handlers/listeners
* @param object $event The event object to pass to the event handlers/listeners
*/
protected function callListeners(iterable $listeners, string $eventName, $event)
{
if ($event instanceof Event) {
$this->doDispatch($listeners, $eventName, $event);
return;
}
$stoppable = $event instanceof ContractsEvent || $event instanceof StoppableEventInterface;
foreach ($listeners as $listener) {
if ($stoppable && $event->isPropagationStopped()) {
break;
}
// @deprecated: the ternary operator is part of a BC layer and should be removed in 5.0
$listener($listener instanceof WrappedListener ? new LegacyEventProxy($event) : $event, $eventName, $this);
}
}
/**
* @deprecated since Symfony 4.3, use callListeners() instead
*/
protected function doDispatch($listeners, $eventName, Event $event)
{
@@ -209,28 +261,54 @@ class EventDispatcher implements EventDispatcherInterface
if ($event->isPropagationStopped()) {
break;
}
\call_user_func($listener, $event, $eventName, $this);
$listener($event, $eventName, $this);
}
}
/**
* Sorts the internal list of listeners for the given event by priority.
*
* @param string $eventName The name of the event
*/
private function sortListeners($eventName)
private function sortListeners(string $eventName)
{
krsort($this->listeners[$eventName]);
$this->sorted[$eventName] = array();
$this->sorted[$eventName] = [];
foreach ($this->listeners[$eventName] as $priority => $listeners) {
foreach ($listeners as $k => $listener) {
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
foreach ($this->listeners[$eventName] as &$listeners) {
foreach ($listeners as $k => &$listener) {
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) {
$listener[0] = $listener[0]();
$this->listeners[$eventName][$priority][$k] = $listener;
$listener[1] = $listener[1] ?? '__invoke';
}
$this->sorted[$eventName][] = $listener;
}
}
}
/**
* Optimizes the internal list of listeners for the given event by priority.
*/
private function optimizeListeners(string $eventName): array
{
krsort($this->listeners[$eventName]);
$this->optimized[$eventName] = [];
foreach ($this->listeners[$eventName] as &$listeners) {
foreach ($listeners as &$listener) {
$closure = &$this->optimized[$eventName][];
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) {
$closure = static function (...$args) use (&$listener, &$closure) {
if ($listener[0] instanceof \Closure) {
$listener[0] = $listener[0]();
$listener[1] = $listener[1] ?? '__invoke';
}
($closure = \Closure::fromCallable($listener))(...$args);
};
} else {
$closure = $listener instanceof \Closure || $listener instanceof WrappedListener ? $listener : \Closure::fromCallable($listener);
}
}
}
return $this->optimized[$eventName];
}
}