Security update for Core, with self-updated composer
[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     public function testDispatchForClosure()
142     {
143         $invoked = 0;
144         $listener = function () use (&$invoked) {
145             ++$invoked;
146         };
147         $this->dispatcher->addListener('pre.foo', $listener);
148         $this->dispatcher->addListener('post.foo', $listener);
149         $this->dispatcher->dispatch(self::preFoo);
150         $this->assertEquals(1, $invoked);
151     }
152
153     public function testStopEventPropagation()
154     {
155         $otherListener = new TestEventListener();
156
157         // postFoo() stops the propagation, so only one listener should
158         // be executed
159         // Manually set priority to enforce $this->listener to be called first
160         $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo'), 10);
161         $this->dispatcher->addListener('post.foo', array($otherListener, 'preFoo'));
162         $this->dispatcher->dispatch(self::postFoo);
163         $this->assertTrue($this->listener->postFooInvoked);
164         $this->assertFalse($otherListener->postFooInvoked);
165     }
166
167     public function testDispatchByPriority()
168     {
169         $invoked = array();
170         $listener1 = function () use (&$invoked) {
171             $invoked[] = '1';
172         };
173         $listener2 = function () use (&$invoked) {
174             $invoked[] = '2';
175         };
176         $listener3 = function () use (&$invoked) {
177             $invoked[] = '3';
178         };
179         $this->dispatcher->addListener('pre.foo', $listener1, -10);
180         $this->dispatcher->addListener('pre.foo', $listener2);
181         $this->dispatcher->addListener('pre.foo', $listener3, 10);
182         $this->dispatcher->dispatch(self::preFoo);
183         $this->assertEquals(array('3', '2', '1'), $invoked);
184     }
185
186     public function testRemoveListener()
187     {
188         $this->dispatcher->addListener('pre.bar', $this->listener);
189         $this->assertTrue($this->dispatcher->hasListeners(self::preBar));
190         $this->dispatcher->removeListener('pre.bar', $this->listener);
191         $this->assertFalse($this->dispatcher->hasListeners(self::preBar));
192         $this->dispatcher->removeListener('notExists', $this->listener);
193     }
194
195     public function testAddSubscriber()
196     {
197         $eventSubscriber = new TestEventSubscriber();
198         $this->dispatcher->addSubscriber($eventSubscriber);
199         $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
200         $this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
201     }
202
203     public function testAddSubscriberWithPriorities()
204     {
205         $eventSubscriber = new TestEventSubscriber();
206         $this->dispatcher->addSubscriber($eventSubscriber);
207
208         $eventSubscriber = new TestEventSubscriberWithPriorities();
209         $this->dispatcher->addSubscriber($eventSubscriber);
210
211         $listeners = $this->dispatcher->getListeners('pre.foo');
212         $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
213         $this->assertCount(2, $listeners);
214         $this->assertInstanceOf('Symfony\Component\EventDispatcher\Tests\TestEventSubscriberWithPriorities', $listeners[0][0]);
215     }
216
217     public function testAddSubscriberWithMultipleListeners()
218     {
219         $eventSubscriber = new TestEventSubscriberWithMultipleListeners();
220         $this->dispatcher->addSubscriber($eventSubscriber);
221
222         $listeners = $this->dispatcher->getListeners('pre.foo');
223         $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
224         $this->assertCount(2, $listeners);
225         $this->assertEquals('preFoo2', $listeners[0][1]);
226     }
227
228     public function testRemoveSubscriber()
229     {
230         $eventSubscriber = new TestEventSubscriber();
231         $this->dispatcher->addSubscriber($eventSubscriber);
232         $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
233         $this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
234         $this->dispatcher->removeSubscriber($eventSubscriber);
235         $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
236         $this->assertFalse($this->dispatcher->hasListeners(self::postFoo));
237     }
238
239     public function testRemoveSubscriberWithPriorities()
240     {
241         $eventSubscriber = new TestEventSubscriberWithPriorities();
242         $this->dispatcher->addSubscriber($eventSubscriber);
243         $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
244         $this->dispatcher->removeSubscriber($eventSubscriber);
245         $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
246     }
247
248     public function testRemoveSubscriberWithMultipleListeners()
249     {
250         $eventSubscriber = new TestEventSubscriberWithMultipleListeners();
251         $this->dispatcher->addSubscriber($eventSubscriber);
252         $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
253         $this->assertCount(2, $this->dispatcher->getListeners(self::preFoo));
254         $this->dispatcher->removeSubscriber($eventSubscriber);
255         $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
256     }
257
258     public function testEventReceivesTheDispatcherInstanceAsArgument()
259     {
260         $listener = new TestWithDispatcher();
261         $this->dispatcher->addListener('test', array($listener, 'foo'));
262         $this->assertNull($listener->name);
263         $this->assertNull($listener->dispatcher);
264         $this->dispatcher->dispatch('test');
265         $this->assertEquals('test', $listener->name);
266         $this->assertSame($this->dispatcher, $listener->dispatcher);
267     }
268
269     /**
270      * @see https://bugs.php.net/bug.php?id=62976
271      *
272      * This bug affects:
273      *  - The PHP 5.3 branch for versions < 5.3.18
274      *  - The PHP 5.4 branch for versions < 5.4.8
275      *  - The PHP 5.5 branch is not affected
276      */
277     public function testWorkaroundForPhpBug62976()
278     {
279         $dispatcher = $this->createEventDispatcher();
280         $dispatcher->addListener('bug.62976', new CallableClass());
281         $dispatcher->removeListener('bug.62976', function () {});
282         $this->assertTrue($dispatcher->hasListeners('bug.62976'));
283     }
284
285     public function testHasListenersWhenAddedCallbackListenerIsRemoved()
286     {
287         $listener = function () {};
288         $this->dispatcher->addListener('foo', $listener);
289         $this->dispatcher->removeListener('foo', $listener);
290         $this->assertFalse($this->dispatcher->hasListeners());
291     }
292
293     public function testGetListenersWhenAddedCallbackListenerIsRemoved()
294     {
295         $listener = function () {};
296         $this->dispatcher->addListener('foo', $listener);
297         $this->dispatcher->removeListener('foo', $listener);
298         $this->assertSame(array(), $this->dispatcher->getListeners());
299     }
300
301     public function testHasListenersWithoutEventsReturnsFalseAfterHasListenersWithEventHasBeenCalled()
302     {
303         $this->assertFalse($this->dispatcher->hasListeners('foo'));
304         $this->assertFalse($this->dispatcher->hasListeners());
305     }
306 }
307
308 class CallableClass
309 {
310     public function __invoke()
311     {
312     }
313 }
314
315 class TestEventListener
316 {
317     public $preFooInvoked = false;
318     public $postFooInvoked = false;
319
320     /* Listener methods */
321
322     public function preFoo(Event $e)
323     {
324         $this->preFooInvoked = true;
325     }
326
327     public function postFoo(Event $e)
328     {
329         $this->postFooInvoked = true;
330
331         $e->stopPropagation();
332     }
333 }
334
335 class TestWithDispatcher
336 {
337     public $name;
338     public $dispatcher;
339
340     public function foo(Event $e, $name, $dispatcher)
341     {
342         $this->name = $name;
343         $this->dispatcher = $dispatcher;
344     }
345 }
346
347 class TestEventSubscriber implements EventSubscriberInterface
348 {
349     public static function getSubscribedEvents()
350     {
351         return array('pre.foo' => 'preFoo', 'post.foo' => 'postFoo');
352     }
353 }
354
355 class TestEventSubscriberWithPriorities implements EventSubscriberInterface
356 {
357     public static function getSubscribedEvents()
358     {
359         return array(
360             'pre.foo' => array('preFoo', 10),
361             'post.foo' => array('postFoo'),
362             );
363     }
364 }
365
366 class TestEventSubscriberWithMultipleListeners implements EventSubscriberInterface
367 {
368     public static function getSubscribedEvents()
369     {
370         return array('pre.foo' => array(
371             array('preFoo1'),
372             array('preFoo2', 10),
373         ));
374     }
375 }