Yaffs site version 1.1
[yaffs-website] / vendor / symfony / event-dispatcher / Tests / AbstractEventDispatcherTest.php
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 PHPUnit\Framework\TestCase;
15 use Symfony\Component\EventDispatcher\Event;
16 use Symfony\Component\EventDispatcher\EventDispatcher;
17 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18
19 abstract class AbstractEventDispatcherTest extends TestCase
20 {
21     /* Some pseudo events */
22     const preFoo = 'pre.foo';
23     const postFoo = 'post.foo';
24     const preBar = 'pre.bar';
25     const postBar = 'post.bar';
26
27     /**
28      * @var EventDispatcher
29      */
30     private $dispatcher;
31
32     private $listener;
33
34     protected function setUp()
35     {
36         $this->dispatcher = $this->createEventDispatcher();
37         $this->listener = new TestEventListener();
38     }
39
40     protected function tearDown()
41     {
42         $this->dispatcher = null;
43         $this->listener = null;
44     }
45
46     abstract protected function createEventDispatcher();
47
48     public function testInitialState()
49     {
50         $this->assertEquals(array(), $this->dispatcher->getListeners());
51         $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
52         $this->assertFalse($this->dispatcher->hasListeners(self::postFoo));
53     }
54
55     public function testAddListener()
56     {
57         $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo'));
58         $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo'));
59         $this->assertTrue($this->dispatcher->hasListeners());
60         $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
61         $this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
62         $this->assertCount(1, $this->dispatcher->getListeners(self::preFoo));
63         $this->assertCount(1, $this->dispatcher->getListeners(self::postFoo));
64         $this->assertCount(2, $this->dispatcher->getListeners());
65     }
66
67     public function testGetListenersSortsByPriority()
68     {
69         $listener1 = new TestEventListener();
70         $listener2 = new TestEventListener();
71         $listener3 = new TestEventListener();
72         $listener1->name = '1';
73         $listener2->name = '2';
74         $listener3->name = '3';
75
76         $this->dispatcher->addListener('pre.foo', array($listener1, 'preFoo'), -10);
77         $this->dispatcher->addListener('pre.foo', array($listener2, 'preFoo'), 10);
78         $this->dispatcher->addListener('pre.foo', array($listener3, 'preFoo'));
79
80         $expected = array(
81             array($listener2, 'preFoo'),
82             array($listener3, 'preFoo'),
83             array($listener1, 'preFoo'),
84         );
85
86         $this->assertSame($expected, $this->dispatcher->getListeners('pre.foo'));
87     }
88
89     public function testGetAllListenersSortsByPriority()
90     {
91         $listener1 = new TestEventListener();
92         $listener2 = new TestEventListener();
93         $listener3 = new TestEventListener();
94         $listener4 = new TestEventListener();
95         $listener5 = new TestEventListener();
96         $listener6 = new TestEventListener();
97
98         $this->dispatcher->addListener('pre.foo', $listener1, -10);
99         $this->dispatcher->addListener('pre.foo', $listener2);
100         $this->dispatcher->addListener('pre.foo', $listener3, 10);
101         $this->dispatcher->addListener('post.foo', $listener4, -10);
102         $this->dispatcher->addListener('post.foo', $listener5);
103         $this->dispatcher->addListener('post.foo', $listener6, 10);
104
105         $expected = array(
106             'pre.foo' => array($listener3, $listener2, $listener1),
107             'post.foo' => array($listener6, $listener5, $listener4),
108         );
109
110         $this->assertSame($expected, $this->dispatcher->getListeners());
111     }
112
113     public function testGetListenerPriority()
114     {
115         $listener1 = new TestEventListener();
116         $listener2 = new TestEventListener();
117
118         $this->dispatcher->addListener('pre.foo', $listener1, -10);
119         $this->dispatcher->addListener('pre.foo', $listener2);
120
121         $this->assertSame(-10, $this->dispatcher->getListenerPriority('pre.foo', $listener1));
122         $this->assertSame(0, $this->dispatcher->getListenerPriority('pre.foo', $listener2));
123         $this->assertNull($this->dispatcher->getListenerPriority('pre.bar', $listener2));
124         $this->assertNull($this->dispatcher->getListenerPriority('pre.foo', function () {}));
125     }
126
127     public function testDispatch()
128     {
129         $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo'));
130         $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo'));
131         $this->dispatcher->dispatch(self::preFoo);
132         $this->assertTrue($this->listener->preFooInvoked);
133         $this->assertFalse($this->listener->postFooInvoked);
134         $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch('noevent'));
135         $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(self::preFoo));
136         $event = new Event();
137         $return = $this->dispatcher->dispatch(self::preFoo, $event);
138         $this->assertSame($event, $return);
139     }
140
141     /**
142      * @group legacy
143      */
144     public function testLegacyDispatch()
145     {
146         $event = new Event();
147         $this->dispatcher->dispatch(self::preFoo, $event);
148         $this->assertEquals('pre.foo', $event->getName());
149     }
150
151     public function testDispatchForClosure()
152     {
153         $invoked = 0;
154         $listener = function () use (&$invoked) {
155             ++$invoked;
156         };
157         $this->dispatcher->addListener('pre.foo', $listener);
158         $this->dispatcher->addListener('post.foo', $listener);
159         $this->dispatcher->dispatch(self::preFoo);
160         $this->assertEquals(1, $invoked);
161     }
162
163     public function testStopEventPropagation()
164     {
165         $otherListener = new TestEventListener();
166
167         // postFoo() stops the propagation, so only one listener should
168         // be executed
169         // Manually set priority to enforce $this->listener to be called first
170         $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo'), 10);
171         $this->dispatcher->addListener('post.foo', array($otherListener, 'preFoo'));
172         $this->dispatcher->dispatch(self::postFoo);
173         $this->assertTrue($this->listener->postFooInvoked);
174         $this->assertFalse($otherListener->postFooInvoked);
175     }
176
177     public function testDispatchByPriority()
178     {
179         $invoked = array();
180         $listener1 = function () use (&$invoked) {
181             $invoked[] = '1';
182         };
183         $listener2 = function () use (&$invoked) {
184             $invoked[] = '2';
185         };
186         $listener3 = function () use (&$invoked) {
187             $invoked[] = '3';
188         };
189         $this->dispatcher->addListener('pre.foo', $listener1, -10);
190         $this->dispatcher->addListener('pre.foo', $listener2);
191         $this->dispatcher->addListener('pre.foo', $listener3, 10);
192         $this->dispatcher->dispatch(self::preFoo);
193         $this->assertEquals(array('3', '2', '1'), $invoked);
194     }
195
196     public function testRemoveListener()
197     {
198         $this->dispatcher->addListener('pre.bar', $this->listener);
199         $this->assertTrue($this->dispatcher->hasListeners(self::preBar));
200         $this->dispatcher->removeListener('pre.bar', $this->listener);
201         $this->assertFalse($this->dispatcher->hasListeners(self::preBar));
202         $this->dispatcher->removeListener('notExists', $this->listener);
203     }
204
205     public function testAddSubscriber()
206     {
207         $eventSubscriber = new TestEventSubscriber();
208         $this->dispatcher->addSubscriber($eventSubscriber);
209         $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
210         $this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
211     }
212
213     public function testAddSubscriberWithPriorities()
214     {
215         $eventSubscriber = new TestEventSubscriber();
216         $this->dispatcher->addSubscriber($eventSubscriber);
217
218         $eventSubscriber = new TestEventSubscriberWithPriorities();
219         $this->dispatcher->addSubscriber($eventSubscriber);
220
221         $listeners = $this->dispatcher->getListeners('pre.foo');
222         $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
223         $this->assertCount(2, $listeners);
224         $this->assertInstanceOf('Symfony\Component\EventDispatcher\Tests\TestEventSubscriberWithPriorities', $listeners[0][0]);
225     }
226
227     public function testAddSubscriberWithMultipleListeners()
228     {
229         $eventSubscriber = new TestEventSubscriberWithMultipleListeners();
230         $this->dispatcher->addSubscriber($eventSubscriber);
231
232         $listeners = $this->dispatcher->getListeners('pre.foo');
233         $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
234         $this->assertCount(2, $listeners);
235         $this->assertEquals('preFoo2', $listeners[0][1]);
236     }
237
238     public function testRemoveSubscriber()
239     {
240         $eventSubscriber = new TestEventSubscriber();
241         $this->dispatcher->addSubscriber($eventSubscriber);
242         $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
243         $this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
244         $this->dispatcher->removeSubscriber($eventSubscriber);
245         $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
246         $this->assertFalse($this->dispatcher->hasListeners(self::postFoo));
247     }
248
249     public function testRemoveSubscriberWithPriorities()
250     {
251         $eventSubscriber = new TestEventSubscriberWithPriorities();
252         $this->dispatcher->addSubscriber($eventSubscriber);
253         $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
254         $this->dispatcher->removeSubscriber($eventSubscriber);
255         $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
256     }
257
258     public function testRemoveSubscriberWithMultipleListeners()
259     {
260         $eventSubscriber = new TestEventSubscriberWithMultipleListeners();
261         $this->dispatcher->addSubscriber($eventSubscriber);
262         $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
263         $this->assertCount(2, $this->dispatcher->getListeners(self::preFoo));
264         $this->dispatcher->removeSubscriber($eventSubscriber);
265         $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
266     }
267
268     /**
269      * @group legacy
270      */
271     public function testLegacyEventReceivesTheDispatcherInstance()
272     {
273         $dispatcher = null;
274         $this->dispatcher->addListener('test', function ($event) use (&$dispatcher) {
275             $dispatcher = $event->getDispatcher();
276         });
277         $this->dispatcher->dispatch('test');
278         $this->assertSame($this->dispatcher, $dispatcher);
279     }
280
281     public function testEventReceivesTheDispatcherInstanceAsArgument()
282     {
283         $listener = new TestWithDispatcher();
284         $this->dispatcher->addListener('test', array($listener, 'foo'));
285         $this->assertNull($listener->name);
286         $this->assertNull($listener->dispatcher);
287         $this->dispatcher->dispatch('test');
288         $this->assertEquals('test', $listener->name);
289         $this->assertSame($this->dispatcher, $listener->dispatcher);
290     }
291
292     /**
293      * @see https://bugs.php.net/bug.php?id=62976
294      *
295      * This bug affects:
296      *  - The PHP 5.3 branch for versions < 5.3.18
297      *  - The PHP 5.4 branch for versions < 5.4.8
298      *  - The PHP 5.5 branch is not affected
299      */
300     public function testWorkaroundForPhpBug62976()
301     {
302         $dispatcher = $this->createEventDispatcher();
303         $dispatcher->addListener('bug.62976', new CallableClass());
304         $dispatcher->removeListener('bug.62976', function () {});
305         $this->assertTrue($dispatcher->hasListeners('bug.62976'));
306     }
307
308     public function testHasListenersWhenAddedCallbackListenerIsRemoved()
309     {
310         $listener = function () {};
311         $this->dispatcher->addListener('foo', $listener);
312         $this->dispatcher->removeListener('foo', $listener);
313         $this->assertFalse($this->dispatcher->hasListeners());
314     }
315
316     public function testGetListenersWhenAddedCallbackListenerIsRemoved()
317     {
318         $listener = function () {};
319         $this->dispatcher->addListener('foo', $listener);
320         $this->dispatcher->removeListener('foo', $listener);
321         $this->assertSame(array(), $this->dispatcher->getListeners());
322     }
323
324     public function testHasListenersWithoutEventsReturnsFalseAfterHasListenersWithEventHasBeenCalled()
325     {
326         $this->assertFalse($this->dispatcher->hasListeners('foo'));
327         $this->assertFalse($this->dispatcher->hasListeners());
328     }
329 }
330
331 class CallableClass
332 {
333     public function __invoke()
334     {
335     }
336 }
337
338 class TestEventListener
339 {
340     public $preFooInvoked = false;
341     public $postFooInvoked = false;
342
343     /* Listener methods */
344
345     public function preFoo(Event $e)
346     {
347         $this->preFooInvoked = true;
348     }
349
350     public function postFoo(Event $e)
351     {
352         $this->postFooInvoked = true;
353
354         $e->stopPropagation();
355     }
356 }
357
358 class TestWithDispatcher
359 {
360     public $name;
361     public $dispatcher;
362
363     public function foo(Event $e, $name, $dispatcher)
364     {
365         $this->name = $name;
366         $this->dispatcher = $dispatcher;
367     }
368 }
369
370 class TestEventSubscriber implements EventSubscriberInterface
371 {
372     public static function getSubscribedEvents()
373     {
374         return array('pre.foo' => 'preFoo', 'post.foo' => 'postFoo');
375     }
376 }
377
378 class TestEventSubscriberWithPriorities implements EventSubscriberInterface
379 {
380     public static function getSubscribedEvents()
381     {
382         return array(
383             'pre.foo' => array('preFoo', 10),
384             'post.foo' => array('postFoo'),
385             );
386     }
387 }
388
389 class TestEventSubscriberWithMultipleListeners implements EventSubscriberInterface
390 {
391     public static function getSubscribedEvents()
392     {
393         return array('pre.foo' => array(
394             array('preFoo1'),
395             array('preFoo2', 10),
396         ));
397     }
398 }