]>
Commit | Line | Data |
---|---|---|
4f5b44bd NL |
1 | <?php |
2 | ||
3 | /* | |
4 | * This file is part of the Symfony package. | |
5 | * | |
6 | * (c) Fabien Potencier <fabien@symfony.com> | |
7 | * | |
8 | * For the full copyright and license information, please view the LICENSE | |
9 | * file that was distributed with this source code. | |
10 | */ | |
11 | ||
12 | namespace Symfony\Component\EventDispatcher\Tests; | |
13 | ||
14 | use Symfony\Component\EventDispatcher\Event; | |
15 | use Symfony\Component\EventDispatcher\EventDispatcher; | |
16 | use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |
17 | ||
18 | class EventDispatcherTest extends \PHPUnit_Framework_TestCase | |
19 | { | |
20 | /* Some pseudo events */ | |
21 | const preFoo = 'pre.foo'; | |
22 | const postFoo = 'post.foo'; | |
23 | const preBar = 'pre.bar'; | |
24 | const postBar = 'post.bar'; | |
25 | ||
26 | private $dispatcher; | |
27 | ||
28 | private $listener; | |
29 | ||
30 | protected function setUp() | |
31 | { | |
32 | $this->dispatcher = new EventDispatcher(); | |
33 | $this->listener = new TestEventListener(); | |
34 | } | |
35 | ||
36 | protected function tearDown() | |
37 | { | |
38 | $this->dispatcher = null; | |
39 | $this->listener = null; | |
40 | } | |
41 | ||
42 | public function testInitialState() | |
43 | { | |
44 | $this->assertEquals(array(), $this->dispatcher->getListeners()); | |
45 | $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); | |
46 | $this->assertFalse($this->dispatcher->hasListeners(self::postFoo)); | |
47 | } | |
48 | ||
49 | public function testAddListener() | |
50 | { | |
51 | $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo')); | |
52 | $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo')); | |
53 | $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); | |
54 | $this->assertTrue($this->dispatcher->hasListeners(self::postFoo)); | |
55 | $this->assertCount(1, $this->dispatcher->getListeners(self::preFoo)); | |
56 | $this->assertCount(1, $this->dispatcher->getListeners(self::postFoo)); | |
57 | $this->assertCount(2, $this->dispatcher->getListeners()); | |
58 | } | |
59 | ||
60 | public function testGetListenersSortsByPriority() | |
61 | { | |
62 | $listener1 = new TestEventListener(); | |
63 | $listener2 = new TestEventListener(); | |
64 | $listener3 = new TestEventListener(); | |
65 | $listener1->name = '1'; | |
66 | $listener2->name = '2'; | |
67 | $listener3->name = '3'; | |
68 | ||
69 | $this->dispatcher->addListener('pre.foo', array($listener1, 'preFoo'), -10); | |
70 | $this->dispatcher->addListener('pre.foo', array($listener2, 'preFoo'), 10); | |
71 | $this->dispatcher->addListener('pre.foo', array($listener3, 'preFoo')); | |
72 | ||
73 | $expected = array( | |
74 | array($listener2, 'preFoo'), | |
75 | array($listener3, 'preFoo'), | |
76 | array($listener1, 'preFoo'), | |
77 | ); | |
78 | ||
79 | $this->assertSame($expected, $this->dispatcher->getListeners('pre.foo')); | |
80 | } | |
81 | ||
82 | public function testGetAllListenersSortsByPriority() | |
83 | { | |
84 | $listener1 = new TestEventListener(); | |
85 | $listener2 = new TestEventListener(); | |
86 | $listener3 = new TestEventListener(); | |
87 | $listener4 = new TestEventListener(); | |
88 | $listener5 = new TestEventListener(); | |
89 | $listener6 = new TestEventListener(); | |
90 | ||
91 | $this->dispatcher->addListener('pre.foo', $listener1, -10); | |
92 | $this->dispatcher->addListener('pre.foo', $listener2); | |
93 | $this->dispatcher->addListener('pre.foo', $listener3, 10); | |
94 | $this->dispatcher->addListener('post.foo', $listener4, -10); | |
95 | $this->dispatcher->addListener('post.foo', $listener5); | |
96 | $this->dispatcher->addListener('post.foo', $listener6, 10); | |
97 | ||
98 | $expected = array( | |
99 | 'pre.foo' => array($listener3, $listener2, $listener1), | |
100 | 'post.foo' => array($listener6, $listener5, $listener4), | |
101 | ); | |
102 | ||
103 | $this->assertSame($expected, $this->dispatcher->getListeners()); | |
104 | } | |
105 | ||
106 | public function testDispatch() | |
107 | { | |
108 | $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo')); | |
109 | $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo')); | |
110 | $this->dispatcher->dispatch(self::preFoo); | |
111 | $this->assertTrue($this->listener->preFooInvoked); | |
112 | $this->assertFalse($this->listener->postFooInvoked); | |
113 | $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch('noevent')); | |
114 | $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(self::preFoo)); | |
115 | $event = new Event(); | |
116 | $return = $this->dispatcher->dispatch(self::preFoo, $event); | |
117 | $this->assertEquals('pre.foo', $event->getName()); | |
118 | $this->assertSame($event, $return); | |
119 | } | |
120 | ||
121 | public function testDispatchForClosure() | |
122 | { | |
123 | $invoked = 0; | |
124 | $listener = function () use (&$invoked) { | |
125 | $invoked++; | |
126 | }; | |
127 | $this->dispatcher->addListener('pre.foo', $listener); | |
128 | $this->dispatcher->addListener('post.foo', $listener); | |
129 | $this->dispatcher->dispatch(self::preFoo); | |
130 | $this->assertEquals(1, $invoked); | |
131 | } | |
132 | ||
133 | public function testStopEventPropagation() | |
134 | { | |
135 | $otherListener = new TestEventListener(); | |
136 | ||
137 | // postFoo() stops the propagation, so only one listener should | |
138 | // be executed | |
139 | // Manually set priority to enforce $this->listener to be called first | |
140 | $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo'), 10); | |
141 | $this->dispatcher->addListener('post.foo', array($otherListener, 'preFoo')); | |
142 | $this->dispatcher->dispatch(self::postFoo); | |
143 | $this->assertTrue($this->listener->postFooInvoked); | |
144 | $this->assertFalse($otherListener->postFooInvoked); | |
145 | } | |
146 | ||
147 | public function testDispatchByPriority() | |
148 | { | |
149 | $invoked = array(); | |
150 | $listener1 = function () use (&$invoked) { | |
151 | $invoked[] = '1'; | |
152 | }; | |
153 | $listener2 = function () use (&$invoked) { | |
154 | $invoked[] = '2'; | |
155 | }; | |
156 | $listener3 = function () use (&$invoked) { | |
157 | $invoked[] = '3'; | |
158 | }; | |
159 | $this->dispatcher->addListener('pre.foo', $listener1, -10); | |
160 | $this->dispatcher->addListener('pre.foo', $listener2); | |
161 | $this->dispatcher->addListener('pre.foo', $listener3, 10); | |
162 | $this->dispatcher->dispatch(self::preFoo); | |
163 | $this->assertEquals(array('3', '2', '1'), $invoked); | |
164 | } | |
165 | ||
166 | public function testRemoveListener() | |
167 | { | |
168 | $this->dispatcher->addListener('pre.bar', $this->listener); | |
169 | $this->assertTrue($this->dispatcher->hasListeners(self::preBar)); | |
170 | $this->dispatcher->removeListener('pre.bar', $this->listener); | |
171 | $this->assertFalse($this->dispatcher->hasListeners(self::preBar)); | |
172 | $this->dispatcher->removeListener('notExists', $this->listener); | |
173 | } | |
174 | ||
175 | public function testAddSubscriber() | |
176 | { | |
177 | $eventSubscriber = new TestEventSubscriber(); | |
178 | $this->dispatcher->addSubscriber($eventSubscriber); | |
179 | $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); | |
180 | $this->assertTrue($this->dispatcher->hasListeners(self::postFoo)); | |
181 | } | |
182 | ||
183 | public function testAddSubscriberWithPriorities() | |
184 | { | |
185 | $eventSubscriber = new TestEventSubscriber(); | |
186 | $this->dispatcher->addSubscriber($eventSubscriber); | |
187 | ||
188 | $eventSubscriber = new TestEventSubscriberWithPriorities(); | |
189 | $this->dispatcher->addSubscriber($eventSubscriber); | |
190 | ||
191 | $listeners = $this->dispatcher->getListeners('pre.foo'); | |
192 | $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); | |
193 | $this->assertCount(2, $listeners); | |
194 | $this->assertInstanceOf('Symfony\Component\EventDispatcher\Tests\TestEventSubscriberWithPriorities', $listeners[0][0]); | |
195 | } | |
196 | ||
197 | public function testAddSubscriberWithMultipleListeners() | |
198 | { | |
199 | $eventSubscriber = new TestEventSubscriberWithMultipleListeners(); | |
200 | $this->dispatcher->addSubscriber($eventSubscriber); | |
201 | ||
202 | $listeners = $this->dispatcher->getListeners('pre.foo'); | |
203 | $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); | |
204 | $this->assertCount(2, $listeners); | |
205 | $this->assertEquals('preFoo2', $listeners[0][1]); | |
206 | } | |
207 | ||
208 | public function testRemoveSubscriber() | |
209 | { | |
210 | $eventSubscriber = new TestEventSubscriber(); | |
211 | $this->dispatcher->addSubscriber($eventSubscriber); | |
212 | $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); | |
213 | $this->assertTrue($this->dispatcher->hasListeners(self::postFoo)); | |
214 | $this->dispatcher->removeSubscriber($eventSubscriber); | |
215 | $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); | |
216 | $this->assertFalse($this->dispatcher->hasListeners(self::postFoo)); | |
217 | } | |
218 | ||
219 | public function testRemoveSubscriberWithPriorities() | |
220 | { | |
221 | $eventSubscriber = new TestEventSubscriberWithPriorities(); | |
222 | $this->dispatcher->addSubscriber($eventSubscriber); | |
223 | $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); | |
224 | $this->dispatcher->removeSubscriber($eventSubscriber); | |
225 | $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); | |
226 | } | |
227 | ||
228 | public function testRemoveSubscriberWithMultipleListeners() | |
229 | { | |
230 | $eventSubscriber = new TestEventSubscriberWithMultipleListeners(); | |
231 | $this->dispatcher->addSubscriber($eventSubscriber); | |
232 | $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); | |
233 | $this->assertCount(2, $this->dispatcher->getListeners(self::preFoo)); | |
234 | $this->dispatcher->removeSubscriber($eventSubscriber); | |
235 | $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); | |
236 | } | |
237 | ||
238 | public function testEventReceivesTheDispatcherInstance() | |
239 | { | |
240 | $test = $this; | |
241 | $this->dispatcher->addListener('test', function ($event) use (&$dispatcher) { | |
242 | $dispatcher = $event->getDispatcher(); | |
243 | }); | |
244 | $this->dispatcher->dispatch('test'); | |
245 | $this->assertSame($this->dispatcher, $dispatcher); | |
246 | } | |
247 | ||
248 | /** | |
249 | * @see https://bugs.php.net/bug.php?id=62976 | |
250 | * | |
251 | * This bug affects: | |
252 | * - The PHP 5.3 branch for versions < 5.3.18 | |
253 | * - The PHP 5.4 branch for versions < 5.4.8 | |
254 | * - The PHP 5.5 branch is not affected | |
255 | */ | |
256 | public function testWorkaroundForPhpBug62976() | |
257 | { | |
258 | $dispatcher = new EventDispatcher(); | |
259 | $dispatcher->addListener('bug.62976', new CallableClass()); | |
260 | $dispatcher->removeListener('bug.62976', function() {}); | |
261 | $this->assertTrue($dispatcher->hasListeners('bug.62976')); | |
262 | } | |
263 | } | |
264 | ||
265 | class CallableClass | |
266 | { | |
267 | public function __invoke() | |
268 | { | |
269 | } | |
270 | } | |
271 | ||
272 | class TestEventListener | |
273 | { | |
274 | public $preFooInvoked = false; | |
275 | public $postFooInvoked = false; | |
276 | ||
277 | /* Listener methods */ | |
278 | ||
279 | public function preFoo(Event $e) | |
280 | { | |
281 | $this->preFooInvoked = true; | |
282 | } | |
283 | ||
284 | public function postFoo(Event $e) | |
285 | { | |
286 | $this->postFooInvoked = true; | |
287 | ||
288 | $e->stopPropagation(); | |
289 | } | |
290 | } | |
291 | ||
292 | class TestEventSubscriber implements EventSubscriberInterface | |
293 | { | |
294 | public static function getSubscribedEvents() | |
295 | { | |
296 | return array('pre.foo' => 'preFoo', 'post.foo' => 'postFoo'); | |
297 | } | |
298 | } | |
299 | ||
300 | class TestEventSubscriberWithPriorities implements EventSubscriberInterface | |
301 | { | |
302 | public static function getSubscribedEvents() | |
303 | { | |
304 | return array( | |
305 | 'pre.foo' => array('preFoo', 10), | |
306 | 'post.foo' => array('postFoo'), | |
307 | ); | |
308 | } | |
309 | } | |
310 | ||
311 | class TestEventSubscriberWithMultipleListeners implements EventSubscriberInterface | |
312 | { | |
313 | public static function getSubscribedEvents() | |
314 | { | |
315 | return array('pre.foo' => array( | |
316 | array('preFoo1'), | |
317 | array('preFoo2', 10) | |
318 | )); | |
319 | } | |
320 | } |