66
77use Closure ;
88use Exception ;
9+ use Hypervel \Context \Context ;
910use Hypervel \Container \Container ;
1011use Hypervel \Contracts \Broadcasting \Factory as BroadcastFactory ;
1112use Hypervel \Contracts \Broadcasting \ShouldBroadcast ;
@@ -58,6 +59,13 @@ class Dispatcher implements DispatcherContract
5859 */
5960 protected array $ wildcardsCache = [];
6061
62+ /**
63+ * The cached prepared listeners.
64+ *
65+ * @var array<string, array<Closure>>
66+ */
67+ protected array $ listenersCache = [];
68+
6169 /**
6270 * The queue resolver instance.
6371 *
@@ -72,23 +80,6 @@ class Dispatcher implements DispatcherContract
7280 */
7381 protected $ transactionManagerResolver ;
7482
75- /**
76- * The currently deferred events.
77- */
78- protected array $ deferredEvents = [];
79-
80- /**
81- * Indicates if events should be deferred.
82- */
83- protected bool $ deferringEvents = false ;
84-
85- /**
86- * The specific events to defer (null means defer all events).
87- *
88- * @var null|string[]
89- */
90- protected ?array $ eventsToDefer = null ;
91-
9283 /**
9384 * Create a new event dispatcher instance.
9485 */
@@ -131,6 +122,8 @@ public function listen(QueuedClosure|Closure|array|string $events, QueuedClosure
131122 $ this ->listeners [$ event ][] = $ listener ;
132123 }
133124 }
125+
126+ $ this ->listenersCache = [];
134127 }
135128
136129 /**
@@ -141,6 +134,7 @@ protected function setupWildcardListen(string $event, Closure|string|array $list
141134 $ this ->wildcards [$ event ][] = $ listener ;
142135
143136 $ this ->wildcardsCache = [];
137+ $ this ->listenersCache = [];
144138 }
145139
146140 /**
@@ -243,7 +237,12 @@ public function dispatch(string|object $event, mixed $payload = [], bool $halt =
243237 ];
244238
245239 if ($ this ->shouldDeferEvent ($ parsedEvent )) {
246- $ this ->deferredEvents [] = func_get_args ();
240+ Context::override ('__events.deferred_events ' , function (?array $ events ) use ($ event , $ payload , $ halt ) {
241+ $ events = $ events ?? [];
242+ $ events [] = [$ event , $ payload , $ halt ];
243+
244+ return $ events ;
245+ });
247246
248247 return null ;
249248 }
@@ -345,14 +344,20 @@ protected function broadcastEvent(ShouldBroadcast $event): void
345344 */
346345 public function getListeners (string $ eventName ): array
347346 {
347+ if (isset ($ this ->listenersCache [$ eventName ])) {
348+ return $ this ->listenersCache [$ eventName ];
349+ }
350+
348351 $ listeners = array_merge (
349352 $ this ->prepareListeners ($ eventName ),
350353 $ this ->wildcardsCache [$ eventName ] ?? $ this ->getWildcardListeners ($ eventName )
351354 );
352355
353- return class_exists ($ eventName , false )
356+ $ listeners = class_exists ($ eventName , false )
354357 ? $ this ->addInterfaceListeners ($ eventName , $ listeners )
355358 : $ listeners ;
359+
360+ return $ this ->listenersCache [$ eventName ] = $ listeners ;
356361 }
357362
358363 /**
@@ -657,6 +662,8 @@ public function forget(string $event): void
657662 unset($ this ->wildcardsCache [$ key ]);
658663 }
659664 }
665+
666+ $ this ->listenersCache = [];
660667 }
661668
662669 /**
@@ -720,29 +727,29 @@ public function setTransactionManagerResolver(callable $resolver): static
720727 */
721728 public function defer (callable $ callback , ?array $ events = null ): mixed
722729 {
723- $ wasDeferring = $ this -> deferringEvents ;
724- $ previousDeferredEvents = $ this -> deferredEvents ;
725- $ previousEventsToDefer = $ this -> eventsToDefer ;
730+ $ wasDeferring = Context:: get ( ' __events.deferring ' , false ) ;
731+ $ previousDeferredEvents = Context:: get ( ' __events.deferred_events ' , []) ;
732+ $ previousEventsToDefer = Context:: get ( ' __events.events_to_defer ' , null ) ;
726733
727- $ this -> deferringEvents = true ;
728- $ this -> deferredEvents = [] ;
729- $ this -> eventsToDefer = $ events ;
734+ Context:: set ( ' __events.deferring ' , true ) ;
735+ Context:: set ( ' __events.deferred_events ' , []) ;
736+ Context:: set ( ' __events.events_to_defer ' , $ events) ;
730737
731738 try {
732739 $ result = $ callback ();
733740
734- $ this -> deferringEvents = false ;
741+ Context:: set ( ' __events.deferring ' , false ) ;
735742
736743 /* @phpstan-ignore foreach.emptyArray (callback may add deferred events) */
737- foreach ($ this -> deferredEvents as $ args ) {
744+ foreach (Context:: get ( ' __events.deferred_events ' , []) as $ args ) {
738745 $ this ->dispatch (...$ args );
739746 }
740747
741748 return $ result ;
742749 } finally {
743- $ this -> deferringEvents = $ wasDeferring ;
744- $ this -> deferredEvents = $ previousDeferredEvents ;
745- $ this -> eventsToDefer = $ previousEventsToDefer ;
750+ Context:: set ( ' __events.deferring ' , $ wasDeferring) ;
751+ Context:: set ( ' __events.deferred_events ' , $ previousDeferredEvents) ;
752+ Context:: set ( ' __events.events_to_defer ' , $ previousEventsToDefer) ;
746753 }
747754 }
748755
@@ -751,7 +758,17 @@ public function defer(callable $callback, ?array $events = null): mixed
751758 */
752759 protected function shouldDeferEvent (string $ event ): bool
753760 {
754- return $ this ->deferringEvents && ($ this ->eventsToDefer === null || in_array ($ event , $ this ->eventsToDefer ));
761+ if (! Context::get ('__events.deferring ' , false )) {
762+ return false ;
763+ }
764+
765+ $ eventsToDefer = Context::get ('__events.events_to_defer ' , null );
766+
767+ if ($ eventsToDefer === null ) {
768+ return true ;
769+ }
770+
771+ return in_array ($ event , $ eventsToDefer );
755772 }
756773
757774 /**
0 commit comments