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