| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626 |
- <?php
- /**
- * CakePHP : Rapid Development Framework (http://cakephp.org)
- * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
- * @link http://cakephp.org CakePHP Project
- * @since 2.1.0
- * @license http://www.opensource.org/licenses/mit-license.php MIT License
- */
- namespace Cake\Test\TestCase\Event;
- use Cake\Event\Event;
- use Cake\Event\EventListenerInterface;
- use Cake\Event\EventManager;
- use Cake\TestSuite\TestCase;
- /**
- * Mock class used to test event dispatching
- */
- class EventTestListener
- {
- public $callStack = [];
- /**
- * Test function to be used in event dispatching
- *
- * @return void
- */
- public function listenerFunction()
- {
- $this->callStack[] = __FUNCTION__;
- }
- /**
- * Test function to be used in event dispatching
- *
- * @return void
- */
- public function secondListenerFunction()
- {
- $this->callStack[] = __FUNCTION__;
- }
- /**
- * Auxiliary function to help in stopPropagation testing
- *
- * @param \Cake\Event\Event $event
- * @return void
- */
- public function stopListener($event)
- {
- $event->stopPropagation();
- }
- }
- /**
- * Mock used for testing the subscriber objects
- */
- class CustomTestEventListenerInterface extends EventTestListener implements EventListenerInterface
- {
- public function implementedEvents()
- {
- return [
- 'fake.event' => 'listenerFunction',
- 'another.event' => ['callable' => 'secondListenerFunction'],
- 'multiple.handlers' => [
- ['callable' => 'listenerFunction'],
- ['callable' => 'thirdListenerFunction']
- ]
- ];
- }
- /**
- * Test function to be used in event dispatching
- *
- * @return void
- */
- public function thirdListenerFunction()
- {
- $this->callStack[] = __FUNCTION__;
- }
- }
- /**
- * Tests the Cake\Event\EventManager class functionality
- *
- */
- class EventManagerTest extends TestCase
- {
- /**
- * Tests the attach() method for a single event key in multiple queues
- *
- * @return void
- */
- public function testAttachListeners()
- {
- $manager = new EventManager();
- $manager->attach('fakeFunction', 'fake.event');
- $expected = [
- ['callable' => 'fakeFunction']
- ];
- $this->assertEquals($expected, $manager->listeners('fake.event'));
- $manager->attach('fakeFunction2', 'fake.event');
- $expected[] = ['callable' => 'fakeFunction2'];
- $this->assertEquals($expected, $manager->listeners('fake.event'));
- $manager->attach('inQ5', 'fake.event', ['priority' => 5]);
- $manager->attach('inQ1', 'fake.event', ['priority' => 1]);
- $manager->attach('otherInQ5', 'fake.event', ['priority' => 5]);
- $expected = array_merge(
- [
- ['callable' => 'inQ1'],
- ['callable' => 'inQ5'],
- ['callable' => 'otherInQ5']
- ],
- $expected
- );
- $this->assertEquals($expected, $manager->listeners('fake.event'));
- }
- /**
- * Tests the attach() method for multiple event key in multiple queues
- *
- * @return void
- */
- public function testAttachMultipleEventKeys()
- {
- $manager = new EventManager();
- $manager->attach('fakeFunction', 'fake.event');
- $manager->attach('fakeFunction2', 'another.event');
- $manager->attach('fakeFunction3', 'another.event', ['priority' => 1]);
- $expected = [
- ['callable' => 'fakeFunction']
- ];
- $this->assertEquals($expected, $manager->listeners('fake.event'));
- $expected = [
- ['callable' => 'fakeFunction3'],
- ['callable' => 'fakeFunction2']
- ];
- $this->assertEquals($expected, $manager->listeners('another.event'));
- }
- /**
- * Test the on() method for basic callable types.
- *
- * @return void
- */
- public function testOn()
- {
- $count = 1;
- $manager = new EventManager();
- $manager->on('my.event', 'myfunc');
- $expected = [
- ['callable' => 'myfunc']
- ];
- $this->assertSame($expected, $manager->listeners('my.event'));
- $manager->on('my.event', ['priority' => 1], 'func2');
- $expected = [
- ['callable' => 'func2'],
- ['callable' => 'myfunc'],
- ];
- $this->assertSame($expected, $manager->listeners('my.event'));
- $listener = new CustomTestEventListenerInterface();
- $manager->on($listener);
- $expected = [
- ['callable' => [$listener, 'listenerFunction']],
- ];
- $this->assertEquals($expected, $manager->listeners('fake.event'));
- }
- /**
- * Tests off'ing an event from a event key queue
- *
- * @return void
- */
- public function testOff()
- {
- $manager = new EventManager();
- $manager->on('fake.event', ['AClass', 'aMethod']);
- $manager->on('another.event', ['AClass', 'anotherMethod']);
- $manager->on('another.event', ['priority' => 1], 'fakeFunction');
- $manager->off('fake.event', ['AClass', 'aMethod']);
- $this->assertEquals([], $manager->listeners('fake.event'));
- $manager->off('another.event', ['AClass', 'anotherMethod']);
- $expected = [
- ['callable' => 'fakeFunction']
- ];
- $this->assertEquals($expected, $manager->listeners('another.event'));
- $manager->off('another.event', 'fakeFunction');
- $this->assertEquals([], $manager->listeners('another.event'));
- }
- /**
- * Tests off'ing an event from all event queues
- *
- * @return void
- */
- public function testOffFromAll()
- {
- $manager = new EventManager();
- $manager->on('fake.event', ['AClass', 'aMethod']);
- $manager->on('another.event', ['AClass', 'aMethod']);
- $manager->on('another.event', ['priority' => 1], 'fakeFunction');
- $manager->off(['AClass', 'aMethod']);
- $expected = [
- ['callable' => 'fakeFunction']
- ];
- $this->assertEquals($expected, $manager->listeners('another.event'));
- $this->assertEquals([], $manager->listeners('fake.event'));
- }
- /**
- * Tests detaching an event from a event key queue
- *
- * @return void
- */
- public function testDetach()
- {
- $manager = new EventManager();
- $manager->attach(['AClass', 'aMethod'], 'fake.event');
- $manager->attach(['AClass', 'anotherMethod'], 'another.event');
- $manager->attach('fakeFunction', 'another.event', ['priority' => 1]);
- $manager->detach(['AClass', 'aMethod'], 'fake.event');
- $this->assertEquals([], $manager->listeners('fake.event'));
- $manager->detach(['AClass', 'anotherMethod'], 'another.event');
- $expected = [
- ['callable' => 'fakeFunction']
- ];
- $this->assertEquals($expected, $manager->listeners('another.event'));
- $manager->detach('fakeFunction', 'another.event');
- $this->assertEquals([], $manager->listeners('another.event'));
- }
- /**
- * Tests detaching an event from all event queues
- *
- * @return void
- */
- public function testDetachFromAll()
- {
- $manager = new EventManager();
- $manager->attach(['AClass', 'aMethod'], 'fake.event');
- $manager->attach(['AClass', 'aMethod'], 'another.event');
- $manager->attach('fakeFunction', 'another.event', ['priority' => 1]);
- $manager->detach(['AClass', 'aMethod']);
- $expected = [
- ['callable' => 'fakeFunction']
- ];
- $this->assertEquals($expected, $manager->listeners('another.event'));
- $this->assertEquals([], $manager->listeners('fake.event'));
- }
- /**
- * Tests event dispatching
- *
- * @return void
- * @triggers fake.event
- */
- public function testDispatch()
- {
- $manager = new EventManager();
- $listener = $this->getMock(__NAMESPACE__ . '\EventTestListener');
- $anotherListener = $this->getMock(__NAMESPACE__ . '\EventTestListener');
- $manager->attach([$listener, 'listenerFunction'], 'fake.event');
- $manager->attach([$anotherListener, 'listenerFunction'], 'fake.event');
- $event = new Event('fake.event');
- $listener->expects($this->once())->method('listenerFunction')->with($event);
- $anotherListener->expects($this->once())->method('listenerFunction')->with($event);
- $manager->dispatch($event);
- }
- /**
- * Tests event dispatching using event key name
- *
- * @return void
- */
- public function testDispatchWithKeyName()
- {
- $manager = new EventManager();
- $listener = new EventTestListener;
- $manager->attach([$listener, 'listenerFunction'], 'fake.event');
- $event = 'fake.event';
- $manager->dispatch($event);
- $expected = ['listenerFunction'];
- $this->assertEquals($expected, $listener->callStack);
- }
- /**
- * Tests event dispatching with a return value
- *
- * @return void
- * @triggers fake.event
- */
- public function testDispatchReturnValue()
- {
- $this->skipIf(
- version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<'),
- 'These tests fail in PHPUnit 3.6'
- );
- $manager = new EventManager;
- $listener = $this->getMock(__NAMESPACE__ . '\EventTestListener');
- $anotherListener = $this->getMock(__NAMESPACE__ . '\EventTestListener');
- $manager->attach([$listener, 'listenerFunction'], 'fake.event');
- $manager->attach([$anotherListener, 'listenerFunction'], 'fake.event');
- $event = new Event('fake.event');
- $listener->expects($this->at(0))->method('listenerFunction')
- ->with($event)
- ->will($this->returnValue('something special'));
- $anotherListener->expects($this->at(0))
- ->method('listenerFunction')
- ->with($event);
- $manager->dispatch($event);
- $this->assertEquals('something special', $event->result);
- }
- /**
- * Tests that returning false in a callback stops the event
- *
- * @return void
- * @triggers fake.event
- */
- public function testDispatchFalseStopsEvent()
- {
- $this->skipIf(
- version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<'),
- 'These tests fail in PHPUnit 3.6'
- );
- $manager = new EventManager();
- $listener = $this->getMock(__NAMESPACE__ . '\EventTestListener');
- $anotherListener = $this->getMock(__NAMESPACE__ . '\EventTestListener');
- $manager->attach([$listener, 'listenerFunction'], 'fake.event');
- $manager->attach([$anotherListener, 'listenerFunction'], 'fake.event');
- $event = new Event('fake.event');
- $listener->expects($this->at(0))->method('listenerFunction')
- ->with($event)
- ->will($this->returnValue(false));
- $anotherListener->expects($this->never())
- ->method('listenerFunction');
- $manager->dispatch($event);
- $this->assertTrue($event->isStopped());
- }
- /**
- * Tests event dispatching using priorities
- *
- * @return void
- * @triggers fake.event
- */
- public function testDispatchPrioritized()
- {
- $manager = new EventManager();
- $listener = new EventTestListener;
- $manager->attach([$listener, 'listenerFunction'], 'fake.event');
- $manager->attach([$listener, 'secondListenerFunction'], 'fake.event', ['priority' => 5]);
- $event = new Event('fake.event');
- $manager->dispatch($event);
- $expected = ['secondListenerFunction', 'listenerFunction'];
- $this->assertEquals($expected, $listener->callStack);
- }
- /**
- * Tests subscribing a listener object and firing the events it subscribed to
- *
- * @return void
- * @triggers fake.event
- * @triggers another.event $this, array(some => data)
- */
- public function testAttachSubscriber()
- {
- $manager = new EventManager();
- $listener = $this->getMock(__NAMESPACE__ . '\CustomTestEventListenerInterface', ['secondListenerFunction']);
- $manager->attach($listener);
- $event = new Event('fake.event');
- $manager->dispatch($event);
- $expected = ['listenerFunction'];
- $this->assertEquals($expected, $listener->callStack);
- $event = new Event('another.event', $this, ['some' => 'data']);
- $listener->expects($this->at(0))
- ->method('secondListenerFunction')
- ->with($event, 'data');
- $manager->dispatch($event);
- }
- /**
- * Test implementedEvents binding multiple callbacks to the same event name.
- *
- * @return void
- * @triggers multiple.handlers
- */
- public function testAttachSubscriberMultiple()
- {
- $manager = new EventManager();
- $listener = $this->getMock(__NAMESPACE__ . '\CustomTestEventListenerInterface', ['listenerFunction', 'thirdListenerFunction']);
- $manager->attach($listener);
- $event = new Event('multiple.handlers');
- $listener->expects($this->once())
- ->method('listenerFunction')
- ->with($event);
- $listener->expects($this->once())
- ->method('thirdListenerFunction')
- ->with($event);
- $manager->dispatch($event);
- }
- /**
- * Tests subscribing a listener object and firing the events it subscribed to
- *
- * @return void
- */
- public function testDetachSubscriber()
- {
- $manager = new EventManager();
- $listener = $this->getMock(__NAMESPACE__ . '\CustomTestEventListenerInterface', ['secondListenerFunction']);
- $manager->attach($listener);
- $expected = [
- ['callable' => [$listener, 'secondListenerFunction']]
- ];
- $this->assertEquals($expected, $manager->listeners('another.event'));
- $expected = [
- ['callable' => [$listener, 'listenerFunction']]
- ];
- $this->assertEquals($expected, $manager->listeners('fake.event'));
- $manager->detach($listener);
- $this->assertEquals([], $manager->listeners('fake.event'));
- $this->assertEquals([], $manager->listeners('another.event'));
- }
- /**
- * Tests that it is possible to get/set the manager singleton
- *
- * @return void
- */
- public function testGlobalDispatcherGetter()
- {
- $this->assertInstanceOf('Cake\Event\EventManager', EventManager::instance());
- $manager = new EventManager();
- EventManager::instance($manager);
- $this->assertSame($manager, EventManager::instance());
- }
- /**
- * Tests that the global event manager gets the event too from any other manager
- *
- * @return void
- * @triggers fake.event
- */
- public function testDispatchWithGlobal()
- {
- $generalManager = $this->getMock('Cake\Event\EventManager', ['prioritisedListeners']);
- $manager = new EventManager();
- $event = new Event('fake.event');
- EventManager::instance($generalManager);
- $generalManager->expects($this->once())->method('prioritisedListeners')->with('fake.event');
- $manager->dispatch($event);
- EventManager::instance(new EventManager());
- }
- /**
- * Tests that stopping an event will not notify the rest of the listeners
- *
- * @return void
- * @triggers fake.event
- */
- public function testStopPropagation()
- {
- $generalManager = $this->getMock('Cake\Event\EventManager');
- $manager = new EventManager();
- $listener = new EventTestListener();
- EventManager::instance($generalManager);
- $generalManager->expects($this->any())
- ->method('prioritisedListeners')
- ->with('fake.event')
- ->will($this->returnValue([]));
- $manager->attach([$listener, 'listenerFunction'], 'fake.event');
- $manager->attach([$listener, 'stopListener'], 'fake.event', ['priority' => 8]);
- $manager->attach([$listener, 'secondListenerFunction'], 'fake.event', ['priority' => 5]);
- $event = new Event('fake.event');
- $manager->dispatch($event);
- $expected = ['secondListenerFunction'];
- $this->assertEquals($expected, $listener->callStack);
- EventManager::instance(new EventManager());
- }
- /**
- * Tests event dispatching using priorities
- *
- * @return void
- * @triggers fake.event
- */
- public function testDispatchPrioritizedWithGlobal()
- {
- $generalManager = $this->getMock('Cake\Event\EventManager');
- $manager = new EventManager();
- $listener = new CustomTestEventListenerInterface();
- $event = new Event('fake.event');
- EventManager::instance($generalManager);
- $generalManager->expects($this->any())
- ->method('prioritisedListeners')
- ->with('fake.event')
- ->will($this->returnValue(
- [11 => [
- ['callable' => [$listener, 'secondListenerFunction']]
- ]]
- ));
- $manager->attach([$listener, 'listenerFunction'], 'fake.event');
- $manager->attach([$listener, 'thirdListenerFunction'], 'fake.event', ['priority' => 15]);
- $manager->dispatch($event);
- $expected = ['listenerFunction', 'secondListenerFunction', 'thirdListenerFunction'];
- $this->assertEquals($expected, $listener->callStack);
- EventManager::instance(new EventManager());
- }
- /**
- * Tests event dispatching using priorities
- *
- * @return void
- * @triggers fake.event
- */
- public function testDispatchGlobalBeforeLocal()
- {
- $generalManager = $this->getMock('Cake\Event\EventManager');
- $manager = new EventManager();
- $listener = new CustomTestEventListenerInterface();
- $event = new Event('fake.event');
- EventManager::instance($generalManager);
- $generalManager->expects($this->any())
- ->method('prioritisedListeners')
- ->with('fake.event')
- ->will($this->returnValue(
- [10 => [
- ['callable' => [$listener, 'listenerFunction']]
- ]]
- ));
- $manager->attach([$listener, 'secondListenerFunction'], 'fake.event');
- $manager->dispatch($event);
- $expected = ['listenerFunction', 'secondListenerFunction'];
- $this->assertEquals($expected, $listener->callStack);
- EventManager::instance(new EventManager());
- }
- /**
- * test callback
- */
- public function onMyEvent($event)
- {
- $event->data['callback'] = 'ok';
- }
- /**
- * Tests events dispatched by a local manager can be handled by
- * handler registered in the global event manager
- * @triggers my_event $manager
- */
- public function testDispatchLocalHandledByGlobal()
- {
- $callback = [$this, 'onMyEvent'];
- EventManager::instance()->attach($callback, 'my_event');
- $manager = new EventManager();
- $event = new Event('my_event', $manager);
- $manager->dispatch($event);
- $this->assertEquals('ok', $event->data['callback']);
- }
- /**
- * Test that events are dispatched properly when there are global and local
- * listeners at the same priority.
- *
- * @return void
- * @triggers fake.event $this)
- */
- public function testDispatchWithGlobalAndLocalEvents()
- {
- $listener = new CustomTestEventListenerInterface();
- EventManager::instance()->attach($listener);
- $listener2 = new EventTestListener();
- $manager = new EventManager();
- $manager->attach([$listener2, 'listenerFunction'], 'fake.event');
- $manager->dispatch(new Event('fake.event', $this));
- $this->assertEquals(['listenerFunction'], $listener->callStack);
- $this->assertEquals(['listenerFunction'], $listener2->callStack);
- }
- }
|