@@ -28,11 +28,9 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
2828{
2929 protected $ logger ;
3030 protected $ stopwatch ;
31- private $ called = array ();
31+
32+ private $ called ;
3233 private $ dispatcher ;
33- private $ wrappedListeners = array ();
34- private $ firstCalledEvent = array ();
35- private $ lastEventId = 0 ;
3634
3735 /**
3836 * Constructor.
@@ -46,6 +44,7 @@ public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $sto
4644 $ this ->dispatcher = $ dispatcher ;
4745 $ this ->stopwatch = $ stopwatch ;
4846 $ this ->logger = $ logger ;
47+ $ this ->called = array ();
4948 }
5049
5150 /**
@@ -105,47 +104,19 @@ public function dispatch($eventName, Event $event = null)
105104 $ event = new Event ();
106105 }
107106
108- $ eventId = ++$ this ->lastEventId ;
109-
110- // Wrap all listeners before they are called
111- $ this ->wrappedListeners [$ eventId ] = new \SplObjectStorage ();
112-
113- $ listeners = $ this ->dispatcher ->getListeners ($ eventName );
114-
115- foreach ($ listeners as $ listener ) {
116- $ this ->dispatcher ->removeListener ($ eventName , $ listener );
117- $ wrapped = $ this ->wrapListener ($ eventName , $ eventId , $ listener );
118- $ this ->wrappedListeners [$ eventId ][$ wrapped ] = $ listener ;
119- $ this ->dispatcher ->addListener ($ eventName , $ wrapped );
120- }
121-
107+ $ this ->preProcess ($ eventName );
122108 $ this ->preDispatch ($ eventName , $ event );
123109
124110 $ e = $ this ->stopwatch ->start ($ eventName , 'section ' );
125111
126- $ this ->firstCalledEvent [$ eventName ] = $ this ->stopwatch ->start ($ eventName .'.loading ' , 'event_listener_loading ' );
127-
128- if (!$ this ->dispatcher ->hasListeners ($ eventName )) {
129- $ this ->firstCalledEvent [$ eventName ]->stop ();
130- }
131-
132112 $ this ->dispatcher ->dispatch ($ eventName , $ event );
133113
134- unset($ this ->firstCalledEvent [$ eventName ]);
135-
136114 if ($ e ->isStarted ()) {
137115 $ e ->stop ();
138116 }
139117
140118 $ this ->postDispatch ($ eventName , $ event );
141-
142- // Unwrap all listeners after they are called
143- foreach ($ this ->wrappedListeners [$ eventId ] as $ wrapped ) {
144- $ this ->dispatcher ->removeListener ($ eventName , $ wrapped );
145- $ this ->dispatcher ->addListener ($ eventName , $ this ->wrappedListeners [$ eventId ][$ wrapped ]);
146- }
147-
148- unset($ this ->wrappedListeners [$ eventId ]);
119+ $ this ->postProcess ($ eventName );
149120
150121 return $ event ;
151122 }
@@ -155,7 +126,15 @@ public function dispatch($eventName, Event $event = null)
155126 */
156127 public function getCalledListeners ()
157128 {
158- return $ this ->called ;
129+ $ called = array ();
130+ foreach ($ this ->called as $ eventName => $ listeners ) {
131+ foreach ($ listeners as $ listener ) {
132+ $ info = $ this ->getListenerInfo ($ listener ->getWrappedListener (), $ eventName );
133+ $ called [$ eventName .'. ' .$ info ['pretty ' ]] = $ info ;
134+ }
135+ }
136+
137+ return $ called ;
159138 }
160139
161140 /**
@@ -164,12 +143,22 @@ public function getCalledListeners()
164143 public function getNotCalledListeners ()
165144 {
166145 $ notCalled = array ();
167-
168- foreach ($ this ->getListeners () as $ name => $ listeners ) {
146+ foreach ($ this ->getListeners () as $ eventName => $ listeners ) {
169147 foreach ($ listeners as $ listener ) {
170- $ info = $ this ->getListenerInfo ($ listener , $ name , null );
171- if (!isset ($ this ->called [$ name .'. ' .$ info ['pretty ' ]])) {
172- $ notCalled [$ name .'. ' .$ info ['pretty ' ]] = $ info ;
148+ $ called = false ;
149+ if (isset ($ this ->called [$ eventName ])) {
150+ foreach ($ this ->called [$ eventName ] as $ l ) {
151+ if ($ l ->getWrappedListener () === $ listener ) {
152+ $ called = true ;
153+
154+ break ;
155+ }
156+ }
157+ }
158+
159+ if (!$ called ) {
160+ $ info = $ this ->getListenerInfo ($ listener , $ eventName );
161+ $ notCalled [$ eventName .'. ' .$ info ['pretty ' ]] = $ info ;
173162 }
174163 }
175164 }
@@ -191,64 +180,68 @@ public function __call($method, $arguments)
191180 }
192181
193182 /**
194- * This is a private method and must not be used .
183+ * Called before dispatching the event .
195184 *
196- * This method is public because it is used in a closure.
197- * Whenever Symfony will require PHP 5.4, this could be changed
198- * to a proper private method.
185+ * @param string $eventName The event name
186+ * @param Event $event The event
199187 */
200- public function logSkippedListeners ($ eventName , $ eventId , Event $ event, $ listener )
188+ protected function preDispatch ($ eventName , Event $ event )
201189 {
202- if (null === $ this ->logger ) {
203- return ;
204- }
205-
206- $ info = $ this ->getListenerInfo ($ listener , $ eventName , $ eventId );
207-
208- $ this ->logger ->debug (sprintf ('Listener "%s" stopped propagation of the event "%s". ' , $ info ['pretty ' ], $ eventName ));
209-
210- $ skippedListeners = $ this ->getListeners ($ eventName );
211- $ skipped = false ;
212-
213- foreach ($ skippedListeners as $ skippedListener ) {
214- $ skippedListener = $ this ->unwrapListener ($ skippedListener , $ eventId );
215-
216- if ($ skipped ) {
217- $ info = $ this ->getListenerInfo ($ skippedListener , $ eventName , $ eventId );
218- $ this ->logger ->debug (sprintf ('Listener "%s" was not called for event "%s". ' , $ info ['pretty ' ], $ eventName ));
219- }
220-
221- if ($ skippedListener === $ listener ) {
222- $ skipped = true ;
223- }
224- }
225190 }
226191
227192 /**
228- * This is a private method .
193+ * Called after dispatching the event .
229194 *
230- * This method is public because it is used in a closure.
231- * Whenever Symfony will require PHP 5.4, this could be changed
232- * to a proper private method.
195+ * @param string $eventName The event name
196+ * @param Event $event The event
233197 */
234- public function preListenerCall ($ eventName , $ eventId , $ listener )
198+ protected function postDispatch ($ eventName , Event $ event )
235199 {
236- // is it the first called listener?
237- if (isset ($ this ->firstCalledEvent [$ eventName ])) {
238- $ this ->firstCalledEvent [$ eventName ]->stop ();
200+ }
239201
240- unset($ this ->firstCalledEvent [$ eventName ]);
202+ private function preProcess ($ eventName )
203+ {
204+ foreach ($ this ->dispatcher ->getListeners ($ eventName ) as $ listener ) {
205+ $ this ->dispatcher ->removeListener ($ eventName , $ listener );
206+ $ info = $ this ->getListenerInfo ($ listener , $ eventName );
207+ $ name = isset ($ info ['class ' ]) ? $ info ['class ' ] : $ info ['type ' ];
208+ $ this ->dispatcher ->addListener ($ eventName , new WrappedListener ($ listener , $ name , $ this ->stopwatch ));
241209 }
210+ }
242211
243- $ info = $ this ->getListenerInfo ($ listener , $ eventName , $ eventId );
212+ private function postProcess ($ eventName )
213+ {
214+ $ skipped = false ;
215+ foreach ($ this ->dispatcher ->getListeners ($ eventName ) as $ listener ) {
216+ // Unwrap listener
217+ $ this ->dispatcher ->removeListener ($ eventName , $ listener );
218+ $ this ->dispatcher ->addListener ($ eventName , $ listener ->getWrappedListener ());
244219
245- if (null !== $ this ->logger ) {
246- $ this ->logger ->debug (sprintf ('Notified event "%s" to listener "%s". ' , $ eventName , $ info ['pretty ' ]));
247- }
220+ $ info = $ this ->getListenerInfo ($ listener ->getWrappedListener (), $ eventName );
221+ if ($ listener ->wasCalled ()) {
222+ if (null !== $ this ->logger ) {
223+ $ this ->logger ->debug (sprintf ('Notified event "%s" to listener "%s". ' , $ eventName , $ info ['pretty ' ]));
224+ }
225+
226+ if (!isset ($ this ->called [$ eventName ])) {
227+ $ this ->called [$ eventName ] = new \SplObjectStorage ();
228+ }
248229
249- $ this ->called [$ eventName .'. ' .$ info ['pretty ' ]] = $ info ;
230+ $ this ->called [$ eventName ]->attach ($ listener );
231+ }
232+
233+ if (null !== $ this ->logger && $ skipped ) {
234+ $ this ->logger ->debug (sprintf ('Listener "%s" was not called for event "%s". ' , $ info ['pretty ' ], $ eventName ));
235+ }
250236
251- return $ this ->stopwatch ->start (isset ($ info ['class ' ]) ? $ info ['class ' ] : $ info ['type ' ], 'event_listener ' );
237+ if ($ listener ->stoppedPropagation ()) {
238+ if (null !== $ this ->logger ) {
239+ $ this ->logger ->debug (sprintf ('Listener "%s" stopped propagation of the event "%s". ' , $ info ['pretty ' ], $ eventName ));
240+ }
241+
242+ $ skipped = true ;
243+ }
244+ }
252245 }
253246
254247 /**
@@ -259,10 +252,8 @@ public function preListenerCall($eventName, $eventId, $listener)
259252 *
260253 * @return array Information about the listener
261254 */
262- private function getListenerInfo ($ listener , $ eventName, $ eventId )
255+ private function getListenerInfo ($ listener , $ eventName )
263256 {
264- $ listener = $ this ->unwrapListener ($ listener , $ eventId );
265-
266257 $ info = array (
267258 'event ' => $ eventName ,
268259 );
@@ -312,61 +303,4 @@ private function getListenerInfo($listener, $eventName, $eventId)
312303
313304 return $ info ;
314305 }
315-
316- /**
317- * Called before dispatching the event.
318- *
319- * @param string $eventName The event name
320- * @param Event $event The event
321- */
322- protected function preDispatch ($ eventName , Event $ event )
323- {
324- }
325-
326- /**
327- * Called after dispatching the event.
328- *
329- * @param string $eventName The event name
330- * @param Event $event The event
331- */
332- protected function postDispatch ($ eventName , Event $ event )
333- {
334- }
335-
336- private function wrapListener ($ eventName , $ eventId , $ listener )
337- {
338- $ self = $ this ;
339-
340- return function (Event $ event ) use ($ self , $ eventName , $ eventId , $ listener ) {
341- $ e = $ self ->preListenerCall ($ eventName , $ eventId , $ listener );
342-
343- call_user_func ($ listener , $ event , $ eventName , $ self );
344-
345- if ($ e ->isStarted ()) {
346- $ e ->stop ();
347- }
348-
349- if ($ event ->isPropagationStopped ()) {
350- $ self ->logSkippedListeners ($ eventName , $ eventId , $ event , $ listener );
351- }
352- };
353- }
354-
355- private function unwrapListener ($ listener , $ eventId )
356- {
357- // get the original listener
358- if (is_object ($ listener )) {
359- if (null === $ eventId ) {
360- foreach (array_keys ($ this ->wrappedListeners ) as $ eventId ) {
361- if (isset ($ this ->wrappedListeners [$ eventId ][$ listener ])) {
362- return $ this ->wrappedListeners [$ eventId ][$ listener ];
363- }
364- }
365- } elseif (isset ($ this ->wrappedListeners [$ eventId ][$ listener ])) {
366- return $ this ->wrappedListeners [$ eventId ][$ listener ];
367- }
368- }
369-
370- return $ listener ;
371- }
372306}
0 commit comments