4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\EventDispatcher\Tests
;
14 use Symfony\Component\EventDispatcher\Event
;
15 use Symfony\Component\EventDispatcher\EventDispatcher
;
16 use Symfony\Component\EventDispatcher\EventSubscriberInterface
;
18 class EventDispatcherTest
extends \PHPUnit_Framework_TestCase
20 /* Some pseudo events */
21 const preFoo
= 'pre.foo';
22 const postFoo
= 'post.foo';
23 const preBar
= 'pre.bar';
24 const postBar
= 'post.bar';
30 protected function setUp()
32 $this->dispatcher
= new EventDispatcher();
33 $this->listener
= new TestEventListener();
36 protected function tearDown()
38 $this->dispatcher
= null;
39 $this->listener
= null;
42 public function testInitialState()
44 $this->assertEquals(array(), $this->dispatcher
->getListeners());
45 $this->assertFalse($this->dispatcher
->hasListeners(self
::preFoo
));
46 $this->assertFalse($this->dispatcher
->hasListeners(self
::postFoo
));
49 public function testAddListener()
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());
60 public function testGetListenersSortsByPriority()
62 $listener1 = new TestEventListener();
63 $listener2 = new TestEventListener();
64 $listener3 = new TestEventListener();
65 $listener1->name
= '1';
66 $listener2->name
= '2';
67 $listener3->name
= '3';
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'));
74 array($listener2, 'preFoo'),
75 array($listener3, 'preFoo'),
76 array($listener1, 'preFoo'),
79 $this->assertSame($expected, $this->dispatcher
->getListeners('pre.foo'));
82 public function testGetAllListenersSortsByPriority()
84 $listener1 = new TestEventListener();
85 $listener2 = new TestEventListener();
86 $listener3 = new TestEventListener();
87 $listener4 = new TestEventListener();
88 $listener5 = new TestEventListener();
89 $listener6 = new TestEventListener();
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);
99 'pre.foo' => array($listener3, $listener2, $listener1),
100 'post.foo' => array($listener6, $listener5, $listener4),
103 $this->assertSame($expected, $this->dispatcher
->getListeners());
106 public function testDispatch()
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);
121 public function testDispatchForClosure()
124 $listener = function () use (&$invoked) {
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);
133 public function testStopEventPropagation()
135 $otherListener = new TestEventListener();
137 // postFoo() stops the propagation, so only one listener should
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
);
147 public function testDispatchByPriority()
150 $listener1 = function () use (&$invoked) {
153 $listener2 = function () use (&$invoked) {
156 $listener3 = function () use (&$invoked) {
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);
166 public function testRemoveListener()
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
);
175 public function testAddSubscriber()
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
));
183 public function testAddSubscriberWithPriorities()
185 $eventSubscriber = new TestEventSubscriber();
186 $this->dispatcher
->addSubscriber($eventSubscriber);
188 $eventSubscriber = new TestEventSubscriberWithPriorities();
189 $this->dispatcher
->addSubscriber($eventSubscriber);
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]);
197 public function testAddSubscriberWithMultipleListeners()
199 $eventSubscriber = new TestEventSubscriberWithMultipleListeners();
200 $this->dispatcher
->addSubscriber($eventSubscriber);
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]);
208 public function testRemoveSubscriber()
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
));
219 public function testRemoveSubscriberWithPriorities()
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
));
228 public function testRemoveSubscriberWithMultipleListeners()
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
));
238 public function testEventReceivesTheDispatcherInstance()
241 $this->dispatcher
->addListener('test', function ($event) use (&$dispatcher) {
242 $dispatcher = $event->getDispatcher();
244 $this->dispatcher
->dispatch('test');
245 $this->assertSame($this->dispatcher
, $dispatcher);
249 * @see https://bugs.php.net/bug.php?id=62976
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
256 public function testWorkaroundForPhpBug62976()
258 $dispatcher = new EventDispatcher();
259 $dispatcher->addListener('bug.62976', new CallableClass());
260 $dispatcher->removeListener('bug.62976', function() {});
261 $this->assertTrue($dispatcher->hasListeners('bug.62976'));
267 public function __invoke()
272 class TestEventListener
274 public $preFooInvoked = false;
275 public $postFooInvoked = false;
277 /* Listener methods */
279 public function preFoo(Event
$e)
281 $this->preFooInvoked
= true;
284 public function postFoo(Event
$e)
286 $this->postFooInvoked
= true;
288 $e->stopPropagation();
292 class TestEventSubscriber
implements EventSubscriberInterface
294 public static function getSubscribedEvents()
296 return array('pre.foo' => 'preFoo', 'post.foo' => 'postFoo');
300 class TestEventSubscriberWithPriorities
implements EventSubscriberInterface
302 public static function getSubscribedEvents()
305 'pre.foo' => array('preFoo', 10),
306 'post.foo' => array('postFoo'),
311 class TestEventSubscriberWithMultipleListeners
implements EventSubscriberInterface
313 public static function getSubscribedEvents()
315 return array('pre.foo' => array(