24
24
* @author Fabien Potencier <fabien@symfony.com>
25
25
* @author Jordi Boggiano <j.boggiano@seld.be>
26
26
* @author Jordan Alliot <jordan.alliot@gmail.com>
27
+ * @author Nicolas Grekas <p@tchwork.com>
27
28
*/
28
29
class EventDispatcher implements EventDispatcherInterface
29
30
{
@@ -86,14 +87,47 @@ public function getListenerPriority($eventName, $listener)
86
87
return $ priority ;
87
88
}
88
89
}
90
+
91
+ if (is_array ($ listener ) && isset ($ listener [0 ]) && $ listener [0 ] instanceof \Closure) {
92
+ $ listener [0 ] = $ listener [0 ]();
93
+ foreach ($ this ->listeners [$ eventName ] as $ priority => $ listeners ) {
94
+ if (false !== in_array ($ listener , $ listeners , true )) {
95
+ return $ priority ;
96
+ }
97
+ }
98
+ } elseif (!isset ($ this ->sorted [$ eventName ])) {
99
+ foreach ($ this ->listeners [$ eventName ] as $ priority => $ listeners ) {
100
+ foreach ($ listeners as $ k => $ v ) {
101
+ if (!is_array ($ v ) || !isset ($ v [0 ]) || !$ v [0 ] instanceof \Closure) {
102
+ continue ;
103
+ }
104
+ $ v [0 ] = $ v [0 ]();
105
+ $ this ->listeners [$ eventName ][$ priority ][$ k ] = $ v ;
106
+
107
+ if ($ v === $ listener ) {
108
+ return $ priority ;
109
+ }
110
+ }
111
+ }
112
+ }
89
113
}
90
114
91
115
/**
92
116
* {@inheritdoc}
93
117
*/
94
118
public function hasListeners ($ eventName = null )
95
119
{
96
- return (bool ) $ this ->getListeners ($ eventName );
120
+ if (null !== $ eventName ) {
121
+ return isset ($ this ->listeners [$ eventName ]) && !empty (array_filter ($ this ->listeners [$ eventName ]));
122
+ }
123
+
124
+ foreach ($ this ->listeners as $ eventListeners ) {
125
+ if (!empty (array_filter ($ eventListeners ))) {
126
+ return true ;
127
+ }
128
+ }
129
+
130
+ return false ;
97
131
}
98
132
99
133
/**
@@ -113,10 +147,44 @@ public function removeListener($eventName, $listener)
113
147
if (!isset ($ this ->listeners [$ eventName ])) {
114
148
return ;
115
149
}
150
+ $ found = false ;
116
151
117
152
foreach ($ this ->listeners [$ eventName ] as $ priority => $ listeners ) {
118
153
if (false !== ($ key = array_search ($ listener , $ listeners , true ))) {
119
154
unset($ this ->listeners [$ eventName ][$ priority ][$ key ], $ this ->sorted [$ eventName ]);
155
+ $ found = true ;
156
+ }
157
+ }
158
+
159
+ if (is_array ($ listener ) && isset ($ listener [0 ]) && $ listener [0 ] instanceof \Closure) {
160
+ $ listener [0 ] = $ listener [0 ]();
161
+ foreach ($ this ->listeners [$ eventName ] as $ priority => $ listeners ) {
162
+ if (false !== ($ key = array_search ($ listener , $ listeners , true ))) {
163
+ unset($ this ->listeners [$ eventName ][$ priority ][$ key ], $ this ->sorted [$ eventName ]);
164
+ $ found = true ;
165
+ }
166
+ }
167
+ }
168
+
169
+ if ($ found || isset ($ this ->sorted [$ eventName ])) {
170
+ // There might be more matches encapsed in closures,
171
+ // but we don't want to instanciate the world
172
+ // to remove a listener that already matched.
173
+ return ;
174
+ }
175
+
176
+ foreach ($ this ->listeners [$ eventName ] as $ priority => $ listeners ) {
177
+ foreach ($ listeners as $ k => $ v ) {
178
+ if (!is_array ($ v ) || !isset ($ v [0 ]) || !$ v [0 ] instanceof \Closure) {
179
+ continue ;
180
+ }
181
+ $ v [0 ] = $ v [0 ]();
182
+
183
+ if ($ v === $ listener ) {
184
+ unset($ this ->listeners [$ eventName ][$ priority ][$ k ], $ this ->sorted [$ eventName ]);
185
+ } else {
186
+ $ this ->listeners [$ eventName ][$ priority ][$ k ] = $ v ;
187
+ }
120
188
}
121
189
}
122
190
}
@@ -183,6 +251,16 @@ protected function doDispatch($listeners, $eventName, Event $event)
183
251
private function sortListeners ($ eventName )
184
252
{
185
253
krsort ($ this ->listeners [$ eventName ]);
186
- $ this ->sorted [$ eventName ] = call_user_func_array ('array_merge ' , $ this ->listeners [$ eventName ]);
254
+ $ this ->sorted [$ eventName ] = array ();
255
+
256
+ foreach ($ this ->listeners [$ eventName ] as $ priority => $ listeners ) {
257
+ foreach ($ listeners as $ k => $ listener ) {
258
+ if (is_array ($ listener ) && isset ($ listener [0 ]) && $ listener [0 ] instanceof \Closure) {
259
+ $ listener [0 ] = $ listener [0 ]();
260
+ $ this ->listeners [$ eventName ][$ priority ][$ k ] = $ listener ;
261
+ }
262
+ $ this ->sorted [$ eventName ][] = $ listener ;
263
+ }
264
+ }
187
265
}
188
266
}
0 commit comments