@@ -28,11 +28,9 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
2828{
2929protected $ logger ;
3030protected $ stopwatch ;
31- private $ called =array ();
31+
32+ private $ called ;
3233private $ 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 ($ listenersas $ 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-
136114if ($ 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
150121return $ event ;
151122 }
@@ -155,7 +126,15 @@ public function dispatch($eventName, Event $event = null)
155126 */
156127public function getCalledListeners ()
157128 {
158- return $ this ->called ;
129+ $ called =array ();
130+ foreach ($ this ->called as $ eventName =>$ listeners ) {
131+ foreach ($ listenersas $ 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()
164143public function getNotCalledListeners ()
165144 {
166145$ notCalled =array ();
167-
168- foreach ($ this ->getListeners ()as $ name =>$ listeners ) {
146+ foreach ($ this ->getListeners ()as $ eventName =>$ listeners ) {
169147foreach ($ listenersas $ 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 ($ skippedListenersas $ 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
313304return $ 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}