diff --git a/src/event/Event.php b/src/event/Event.php index 49652fcc6..21b8ae36a 100644 --- a/src/event/Event.php +++ b/src/event/Event.php @@ -55,11 +55,11 @@ abstract class Event{ $timings = Timings::getEventTimings($this); $timings->startTiming(); - $handlerList = HandlerListManager::global()->getListFor(get_class($this)); + $handlers = HandlerListManager::global()->getHandlersFor(static::class); ++self::$eventCallDepth; try{ - foreach($handlerList->getListenerList() as $registration){ + foreach($handlers as $registration){ $registration->callEvent($this); } }finally{ @@ -75,6 +75,6 @@ abstract class Event{ * Usage: SomeEventClass::hasHandlers() */ public static function hasHandlers() : bool{ - return count(HandlerListManager::global()->getListFor(static::class)->getListenerList()) > 0; + return count(HandlerListManager::global()->getHandlersFor(static::class)) > 0; } } diff --git a/src/event/HandlerList.php b/src/event/HandlerList.php index 37811e959..74eedf3a4 100644 --- a/src/event/HandlerList.php +++ b/src/event/HandlerList.php @@ -33,8 +33,6 @@ class HandlerList{ /** @var RegisteredListener[][] */ private array $handlerSlots = []; - private RegisteredListenerCache $handlerCache; - /** @var RegisteredListenerCache[] */ private array $affectedHandlerCaches = []; @@ -44,9 +42,9 @@ class HandlerList{ */ public function __construct( private string $class, - private ?HandlerList $parentList + private ?HandlerList $parentList, + private RegisteredListenerCache $handlerCache = new RegisteredListenerCache() ){ - $this->handlerCache = new RegisteredListenerCache(); for($list = $this; $list !== null; $list = $list->parentList){ $list->affectedHandlerCaches[spl_object_id($this->handlerCache)] = $this->handlerCache; } diff --git a/src/event/HandlerListManager.php b/src/event/HandlerListManager.php index ab94674cf..047632f54 100644 --- a/src/event/HandlerListManager.php +++ b/src/event/HandlerListManager.php @@ -36,6 +36,11 @@ class HandlerListManager{ /** @var HandlerList[] classname => HandlerList */ private array $allLists = []; + /** + * @var RegisteredListenerCache[] event class name => cache + * @phpstan-var array, RegisteredListenerCache> + */ + private array $handlerCaches = []; /** * Unregisters all the listeners @@ -98,7 +103,25 @@ class HandlerListManager{ } $parent = self::resolveNearestHandleableParent($class); - return $this->allLists[$event] = new HandlerList($event, $parent !== null ? $this->getListFor($parent->getName()) : null); + $cache = new RegisteredListenerCache(); + $this->handlerCaches[$event] = $cache; + return $this->allLists[$event] = new HandlerList( + $event, + parentList: $parent !== null ? $this->getListFor($parent->getName()) : null, + handlerCache: $cache + ); + } + + /** + * @phpstan-template TEvent of Event + * @phpstan-param class-string $event + * + * @return RegisteredListener[] + */ + public function getHandlersFor(string $event) : array{ + $cache = $this->handlerCaches[$event] ?? null; + //getListFor() will populate the cache for the next call + return $cache?->list ?? $this->getListFor($event)->getListenerList(); } /**