EventManagerTest.php 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112
  1. <?php
  2. /**
  3. * CakePHP : Rapid Development Framework (https://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11. * @link https://cakephp.org CakePHP Project
  12. * @since 2.1.0
  13. * @license https://opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\Event;
  16. use Cake\Event\Event;
  17. use Cake\Event\EventInterface;
  18. use Cake\Event\EventList;
  19. use Cake\Event\EventListenerInterface;
  20. use Cake\Event\EventManager;
  21. use Cake\TestSuite\TestCase;
  22. /**
  23. * TestEvent
  24. */
  25. class TestEvent implements EventInterface
  26. {
  27. /**
  28. * @var string
  29. */
  30. protected $name;
  31. /**
  32. * @param string $name
  33. */
  34. public function __construct($name)
  35. {
  36. $this->name = $name;
  37. }
  38. /**
  39. * @inheritDoc
  40. */
  41. public function getName()
  42. {
  43. return $this->name;
  44. }
  45. /**
  46. * @inheritDoc
  47. */
  48. public function getSubject()
  49. {
  50. // TODO: Implement getSubject() method.
  51. }
  52. /**
  53. * @inheritDoc
  54. */
  55. public function stopPropagation()
  56. {
  57. // TODO: Implement stopPropagation() method.
  58. }
  59. /**
  60. * @inheritDoc
  61. */
  62. public function isStopped()
  63. {
  64. // TODO: Implement isStopped() method.
  65. }
  66. /**
  67. * @inheritDoc
  68. */
  69. public function getResult()
  70. {
  71. // TODO: Implement getResult() method.
  72. }
  73. /**
  74. * @inheritDoc
  75. */
  76. public function setResult($value = null)
  77. {
  78. // TODO: Implement setResult() method.
  79. }
  80. /**
  81. * @inheritDoc
  82. */
  83. public function getData($key = null)
  84. {
  85. // TODO: Implement getData() method.
  86. }
  87. /**
  88. * @inheritDoc
  89. */
  90. public function setData($key, $value = null)
  91. {
  92. // TODO: Implement setData() method.
  93. }
  94. }
  95. /**
  96. * Mock class used to test event dispatching
  97. */
  98. class EventTestListener
  99. {
  100. public $callList = [];
  101. /**
  102. * Test function to be used in event dispatching
  103. *
  104. * @return void
  105. */
  106. public function listenerFunction()
  107. {
  108. $this->callList[] = __FUNCTION__;
  109. }
  110. /**
  111. * Test function to be used in event dispatching
  112. *
  113. * @return void
  114. */
  115. public function secondListenerFunction()
  116. {
  117. $this->callList[] = __FUNCTION__;
  118. }
  119. /**
  120. * Auxiliary function to help in stopPropagation testing
  121. *
  122. * @param \Cake\Event\Event $event
  123. * @return void
  124. */
  125. public function stopListener($event)
  126. {
  127. $event->stopPropagation();
  128. }
  129. }
  130. /**
  131. * Mock used for testing the subscriber objects
  132. */
  133. class CustomTestEventListenerInterface extends EventTestListener implements EventListenerInterface
  134. {
  135. public function implementedEvents()
  136. {
  137. return [
  138. 'fake.event' => 'listenerFunction',
  139. 'another.event' => ['callable' => 'secondListenerFunction'],
  140. 'multiple.handlers' => [
  141. ['callable' => 'listenerFunction'],
  142. ['callable' => 'thirdListenerFunction'],
  143. ],
  144. ];
  145. }
  146. /**
  147. * Test function to be used in event dispatching
  148. *
  149. * @return void
  150. */
  151. public function thirdListenerFunction()
  152. {
  153. $this->callList[] = __FUNCTION__;
  154. }
  155. }
  156. /**
  157. * Tests the Cake\Event\EventManager class functionality
  158. */
  159. class EventManagerTest extends TestCase
  160. {
  161. /**
  162. * @return void
  163. */
  164. public function testCustomEventImplementation()
  165. {
  166. $event = new TestEvent('fake.event');
  167. $listener = new CustomTestEventListenerInterface();
  168. $manager = new EventManager();
  169. $manager->on($listener);
  170. $manager->dispatch($event);
  171. }
  172. /**
  173. * Tests the attach() method for a single event key in multiple queues
  174. *
  175. * @group deprecated
  176. * @return void
  177. */
  178. public function testAttachListeners()
  179. {
  180. $this->deprecated(function () {
  181. $manager = new EventManager();
  182. $manager->attach('fakeFunction', 'fake.event');
  183. $expected = [
  184. ['callable' => 'fakeFunction'],
  185. ];
  186. $this->assertEquals($expected, $manager->listeners('fake.event'));
  187. $manager->attach('fakeFunction2', 'fake.event');
  188. $expected[] = ['callable' => 'fakeFunction2'];
  189. $this->assertEquals($expected, $manager->listeners('fake.event'));
  190. $manager->attach('inQ5', 'fake.event', ['priority' => 5]);
  191. $manager->attach('inQ1', 'fake.event', ['priority' => 1]);
  192. $manager->attach('otherInQ5', 'fake.event', ['priority' => 5]);
  193. $expected = array_merge(
  194. [
  195. ['callable' => 'inQ1'],
  196. ['callable' => 'inQ5'],
  197. ['callable' => 'otherInQ5'],
  198. ],
  199. $expected
  200. );
  201. $this->assertEquals($expected, $manager->listeners('fake.event'));
  202. });
  203. }
  204. /**
  205. * Test attach() with a listener interface.
  206. *
  207. * @group deprecated
  208. * @return void
  209. */
  210. public function testAttachListener()
  211. {
  212. $this->deprecated(function () {
  213. $manager = new EventManager();
  214. $listener = new CustomTestEventListenerInterface();
  215. $manager->on($listener);
  216. $expected = [
  217. ['callable' => [$listener, 'listenerFunction']],
  218. ];
  219. $this->assertEquals($expected, $manager->listeners('fake.event'));
  220. });
  221. }
  222. /**
  223. * Tests the attach() method for multiple event key in multiple queues
  224. *
  225. * @group deprecated
  226. * @return void
  227. */
  228. public function testAttachMultipleEventKeys()
  229. {
  230. $this->deprecated(function () {
  231. $manager = new EventManager();
  232. $manager->attach('fakeFunction', 'fake.event');
  233. $manager->attach('fakeFunction2', 'another.event');
  234. $manager->attach('fakeFunction3', 'another.event', ['priority' => 1]);
  235. $expected = [
  236. ['callable' => 'fakeFunction'],
  237. ];
  238. $this->assertEquals($expected, $manager->listeners('fake.event'));
  239. $expected = [
  240. ['callable' => 'fakeFunction3'],
  241. ['callable' => 'fakeFunction2'],
  242. ];
  243. $this->assertEquals($expected, $manager->listeners('another.event'));
  244. });
  245. }
  246. /**
  247. * Tests attached event listeners for matching key pattern
  248. *
  249. * @return void
  250. */
  251. public function testMatchingListeners()
  252. {
  253. $manager = new EventManager();
  254. $manager->on('fake.event', 'fakeFunction1');
  255. $manager->on('real.event', 'fakeFunction2');
  256. $manager->on('test.event', 'fakeFunction3');
  257. $manager->on('event.test', 'fakeFunction4');
  258. $this->assertArrayHasKey('fake.event', $manager->matchingListeners('fake.event'));
  259. $this->assertArrayHasKey('real.event', $manager->matchingListeners('real.event'));
  260. $this->assertArrayHasKey('test.event', $manager->matchingListeners('test.event'));
  261. $this->assertArrayHasKey('event.test', $manager->matchingListeners('event.test'));
  262. $this->assertArrayHasKey('fake.event', $manager->matchingListeners('fake'));
  263. $this->assertArrayHasKey('real.event', $manager->matchingListeners('real'));
  264. $this->assertArrayHasKey('test.event', $manager->matchingListeners('test'));
  265. $this->assertArrayHasKey('event.test', $manager->matchingListeners('test'));
  266. $this->assertArrayHasKey('fake.event', $manager->matchingListeners('event'));
  267. $this->assertArrayHasKey('real.event', $manager->matchingListeners('event'));
  268. $this->assertArrayHasKey('test.event', $manager->matchingListeners('event'));
  269. $this->assertArrayHasKey('event.test', $manager->matchingListeners('event'));
  270. $this->assertArrayHasKey('fake.event', $manager->matchingListeners('.event'));
  271. $this->assertArrayHasKey('real.event', $manager->matchingListeners('.event'));
  272. $this->assertArrayHasKey('test.event', $manager->matchingListeners('.event'));
  273. $this->assertArrayHasKey('test.event', $manager->matchingListeners('test.'));
  274. $this->assertArrayHasKey('event.test', $manager->matchingListeners('.test'));
  275. $this->assertEmpty($manager->matchingListeners('/test'));
  276. $this->assertEmpty($manager->matchingListeners('test/'));
  277. $this->assertEmpty($manager->matchingListeners('/test/'));
  278. $this->assertEmpty($manager->matchingListeners('test$'));
  279. $this->assertEmpty($manager->matchingListeners('ev.nt'));
  280. $this->assertEmpty($manager->matchingListeners('^test'));
  281. $this->assertEmpty($manager->matchingListeners('^event'));
  282. $this->assertEmpty($manager->matchingListeners('*event'));
  283. $this->assertEmpty($manager->matchingListeners('event*'));
  284. $this->assertEmpty($manager->matchingListeners('foo'));
  285. $expected = ['fake.event', 'real.event', 'test.event', 'event.test'];
  286. $result = $manager->matchingListeners('event');
  287. $this->assertNotEmpty($result);
  288. $this->assertSame($expected, array_keys($result));
  289. $expected = ['fake.event', 'real.event', 'test.event'];
  290. $result = $manager->matchingListeners('.event');
  291. $this->assertNotEmpty($result);
  292. $this->assertSame($expected, array_keys($result));
  293. $expected = ['test.event', 'event.test'];
  294. $result = $manager->matchingListeners('test');
  295. $this->assertNotEmpty($result);
  296. $this->assertSame($expected, array_keys($result));
  297. $expected = ['test.event'];
  298. $result = $manager->matchingListeners('test.');
  299. $this->assertNotEmpty($result);
  300. $this->assertSame($expected, array_keys($result));
  301. $expected = ['event.test'];
  302. $result = $manager->matchingListeners('.test');
  303. $this->assertNotEmpty($result);
  304. $this->assertSame($expected, array_keys($result));
  305. }
  306. /**
  307. * Test the on() method for basic callable types.
  308. *
  309. * @return void
  310. */
  311. public function testOn()
  312. {
  313. $count = 1;
  314. $manager = new EventManager();
  315. $manager->on('my.event', 'myfunc');
  316. $expected = [
  317. ['callable' => 'myfunc'],
  318. ];
  319. $this->assertSame($expected, $manager->listeners('my.event'));
  320. $manager->on('my.event', ['priority' => 1], 'func2');
  321. $expected = [
  322. ['callable' => 'func2'],
  323. ['callable' => 'myfunc'],
  324. ];
  325. $this->assertSame($expected, $manager->listeners('my.event'));
  326. $listener = new CustomTestEventListenerInterface();
  327. $manager->on($listener);
  328. $expected = [
  329. ['callable' => [$listener, 'listenerFunction']],
  330. ];
  331. $this->assertEquals($expected, $manager->listeners('fake.event'));
  332. }
  333. /**
  334. * Test the on() with invalid arguments
  335. *
  336. * @expectedException InvalidArgumentException
  337. * @expectedExceptionMessage Invalid arguments for EventManager::on(). Expected 1, 2 or 3 arguments.
  338. * @return void
  339. */
  340. public function testOnInvalidArgument()
  341. {
  342. $manager = new EventManager();
  343. $manager->on();
  344. }
  345. /**
  346. * Tests off'ing an event from a event key queue
  347. *
  348. * @return void
  349. */
  350. public function testOff()
  351. {
  352. $manager = new EventManager();
  353. $manager->on('fake.event', ['AClass', 'aMethod']);
  354. $manager->on('another.event', ['AClass', 'anotherMethod']);
  355. $manager->on('another.event', ['priority' => 1], 'fakeFunction');
  356. $manager->off('fake.event', ['AClass', 'aMethod']);
  357. $this->assertEquals([], $manager->listeners('fake.event'));
  358. $manager->off('another.event', ['AClass', 'anotherMethod']);
  359. $expected = [
  360. ['callable' => 'fakeFunction'],
  361. ];
  362. $this->assertEquals($expected, $manager->listeners('another.event'));
  363. $manager->off('another.event', 'fakeFunction');
  364. $this->assertEquals([], $manager->listeners('another.event'));
  365. }
  366. /**
  367. * Tests off'ing an event from all event queues
  368. *
  369. * @return void
  370. */
  371. public function testOffFromAll()
  372. {
  373. $manager = new EventManager();
  374. $manager->on('fake.event', ['AClass', 'aMethod']);
  375. $manager->on('another.event', ['AClass', 'aMethod']);
  376. $manager->on('another.event', ['priority' => 1], 'fakeFunction');
  377. $manager->off(['AClass', 'aMethod']);
  378. $expected = [
  379. ['callable' => 'fakeFunction'],
  380. ];
  381. $this->assertEquals($expected, $manager->listeners('another.event'));
  382. $this->assertEquals([], $manager->listeners('fake.event'));
  383. }
  384. /**
  385. * Tests off'ing all listeners for an event
  386. */
  387. public function testRemoveAllListeners()
  388. {
  389. $manager = new EventManager();
  390. $manager->on('fake.event', ['AClass', 'aMethod']);
  391. $manager->on('another.event', ['priority' => 1], 'fakeFunction');
  392. $manager->off('fake.event');
  393. $expected = [
  394. ['callable' => 'fakeFunction'],
  395. ];
  396. $this->assertEquals($expected, $manager->listeners('another.event'));
  397. $this->assertEquals([], $manager->listeners('fake.event'));
  398. }
  399. /**
  400. * Tests detaching an event from a event key queue
  401. *
  402. * @group deprecated
  403. * @return void
  404. */
  405. public function testDetach()
  406. {
  407. $this->deprecated(function () {
  408. $manager = new EventManager();
  409. $manager->attach(['AClass', 'aMethod'], 'fake.event');
  410. $manager->attach(['AClass', 'anotherMethod'], 'another.event');
  411. $manager->attach('fakeFunction', 'another.event', ['priority' => 1]);
  412. $manager->detach(['AClass', 'aMethod'], 'fake.event');
  413. $this->assertEquals([], $manager->listeners('fake.event'));
  414. $manager->detach(['AClass', 'anotherMethod'], 'another.event');
  415. $expected = [
  416. ['callable' => 'fakeFunction'],
  417. ];
  418. $this->assertEquals($expected, $manager->listeners('another.event'));
  419. $manager->detach('fakeFunction', 'another.event');
  420. $this->assertEquals([], $manager->listeners('another.event'));
  421. });
  422. }
  423. /**
  424. * Tests detaching an event from all event queues
  425. *
  426. * @group deprecated
  427. * @return void
  428. */
  429. public function testDetachFromAll()
  430. {
  431. $this->deprecated(function () {
  432. $manager = new EventManager();
  433. $manager->attach(['AClass', 'aMethod'], 'fake.event');
  434. $manager->attach(['AClass', 'aMethod'], 'another.event');
  435. $manager->attach('fakeFunction', 'another.event', ['priority' => 1]);
  436. $manager->detach(['AClass', 'aMethod']);
  437. $expected = [
  438. ['callable' => 'fakeFunction'],
  439. ];
  440. $this->assertEquals($expected, $manager->listeners('another.event'));
  441. $this->assertEquals([], $manager->listeners('fake.event'));
  442. });
  443. }
  444. /**
  445. * Tests event dispatching
  446. *
  447. * @return void
  448. * @triggers fake.event
  449. */
  450. public function testDispatch()
  451. {
  452. $manager = new EventManager();
  453. $listener = $this->getMockBuilder(__NAMESPACE__ . '\EventTestListener')
  454. ->getMock();
  455. $anotherListener = $this->getMockBuilder(__NAMESPACE__ . '\EventTestListener')
  456. ->getMock();
  457. $manager->on('fake.event', [$listener, 'listenerFunction']);
  458. $manager->on('fake.event', [$anotherListener, 'listenerFunction']);
  459. $event = new Event('fake.event');
  460. $listener->expects($this->once())->method('listenerFunction')->with($event);
  461. $anotherListener->expects($this->once())->method('listenerFunction')->with($event);
  462. $manager->dispatch($event);
  463. }
  464. /**
  465. * Tests event dispatching using event key name
  466. *
  467. * @return void
  468. */
  469. public function testDispatchWithKeyName()
  470. {
  471. $manager = new EventManager();
  472. $listener = new EventTestListener();
  473. $manager->on('fake.event', [$listener, 'listenerFunction']);
  474. $event = 'fake.event';
  475. $manager->dispatch($event);
  476. $expected = ['listenerFunction'];
  477. $this->assertEquals($expected, $listener->callList);
  478. }
  479. /**
  480. * Tests event dispatching with a return value
  481. *
  482. * @return void
  483. * @triggers fake.event
  484. */
  485. public function testDispatchReturnValue()
  486. {
  487. $manager = new EventManager();
  488. $listener = $this->getMockBuilder(__NAMESPACE__ . '\EventTestListener')
  489. ->getMock();
  490. $anotherListener = $this->getMockBuilder(__NAMESPACE__ . '\EventTestListener')
  491. ->getMock();
  492. $manager->on('fake.event', [$listener, 'listenerFunction']);
  493. $manager->on('fake.event', [$anotherListener, 'listenerFunction']);
  494. $event = new Event('fake.event');
  495. $listener->expects($this->at(0))->method('listenerFunction')
  496. ->with($event)
  497. ->will($this->returnValue('something special'));
  498. $anotherListener->expects($this->at(0))
  499. ->method('listenerFunction')
  500. ->with($event);
  501. $manager->dispatch($event);
  502. $this->assertEquals('something special', $event->getResult());
  503. $this->assertEquals('something special', $event->result);
  504. }
  505. /**
  506. * Tests that returning false in a callback stops the event
  507. *
  508. * @return void
  509. * @triggers fake.event
  510. */
  511. public function testDispatchFalseStopsEvent()
  512. {
  513. $manager = new EventManager();
  514. $listener = $this->getMockBuilder(__NAMESPACE__ . '\EventTestListener')
  515. ->getMock();
  516. $anotherListener = $this->getMockBuilder(__NAMESPACE__ . '\EventTestListener')
  517. ->getMock();
  518. $manager->on('fake.event', [$listener, 'listenerFunction']);
  519. $manager->on('fake.event', [$anotherListener, 'listenerFunction']);
  520. $event = new Event('fake.event');
  521. $listener->expects($this->at(0))->method('listenerFunction')
  522. ->with($event)
  523. ->will($this->returnValue(false));
  524. $anotherListener->expects($this->never())
  525. ->method('listenerFunction');
  526. $manager->dispatch($event);
  527. $this->assertTrue($event->isStopped());
  528. }
  529. /**
  530. * Tests event dispatching using priorities
  531. *
  532. * @return void
  533. * @triggers fake.event
  534. */
  535. public function testDispatchPrioritized()
  536. {
  537. $manager = new EventManager();
  538. $listener = new EventTestListener();
  539. $manager->on('fake.event', [$listener, 'listenerFunction']);
  540. $manager->on('fake.event', ['priority' => 5], [$listener, 'secondListenerFunction']);
  541. $event = new Event('fake.event');
  542. $manager->dispatch($event);
  543. $expected = ['secondListenerFunction', 'listenerFunction'];
  544. $this->assertEquals($expected, $listener->callList);
  545. }
  546. /**
  547. * Tests subscribing a listener object and firing the events it subscribed to
  548. *
  549. * @return void
  550. * @triggers fake.event
  551. * @triggers another.event $this, array(some => data)
  552. */
  553. public function testOnSubscriber()
  554. {
  555. $manager = new EventManager();
  556. $listener = $this->getMockBuilder(__NAMESPACE__ . '\CustomTestEventListenerInterface')
  557. ->setMethods(['secondListenerFunction'])
  558. ->getMock();
  559. $manager->on($listener);
  560. $event = new Event('fake.event');
  561. $manager->dispatch($event);
  562. $expected = ['listenerFunction'];
  563. $this->assertEquals($expected, $listener->callList);
  564. $event = new Event('another.event', $this, ['some' => 'data']);
  565. $listener->expects($this->at(0))
  566. ->method('secondListenerFunction')
  567. ->with($event, 'data');
  568. $manager->dispatch($event);
  569. }
  570. /**
  571. * Test implementedEvents binding multiple callbacks to the same event name.
  572. *
  573. * @return void
  574. * @triggers multiple.handlers
  575. */
  576. public function testOnSubscriberMultiple()
  577. {
  578. $manager = new EventManager();
  579. $listener = $this->getMockBuilder(__NAMESPACE__ . '\CustomTestEventListenerInterface')
  580. ->setMethods(['listenerFunction', 'thirdListenerFunction'])
  581. ->getMock();
  582. $manager->on($listener);
  583. $event = new Event('multiple.handlers');
  584. $listener->expects($this->once())
  585. ->method('listenerFunction')
  586. ->with($event);
  587. $listener->expects($this->once())
  588. ->method('thirdListenerFunction')
  589. ->with($event);
  590. $manager->dispatch($event);
  591. }
  592. /**
  593. * Tests subscribing a listener object and firing the events it subscribed to
  594. *
  595. * @return void
  596. */
  597. public function testDetachSubscriber()
  598. {
  599. $manager = new EventManager();
  600. $listener = $this->getMockBuilder(__NAMESPACE__ . '\CustomTestEventListenerInterface')
  601. ->setMethods(['secondListenerFunction'])
  602. ->getMock();
  603. $manager->on($listener);
  604. $expected = [
  605. ['callable' => [$listener, 'secondListenerFunction']],
  606. ];
  607. $this->assertEquals($expected, $manager->listeners('another.event'));
  608. $expected = [
  609. ['callable' => [$listener, 'listenerFunction']],
  610. ];
  611. $this->assertEquals($expected, $manager->listeners('fake.event'));
  612. $manager->off($listener);
  613. $this->assertEquals([], $manager->listeners('fake.event'));
  614. $this->assertEquals([], $manager->listeners('another.event'));
  615. }
  616. /**
  617. * Tests that it is possible to get/set the manager singleton
  618. *
  619. * @return void
  620. */
  621. public function testGlobalDispatcherGetter()
  622. {
  623. $this->assertInstanceOf('Cake\Event\EventManager', EventManager::instance());
  624. $manager = new EventManager();
  625. EventManager::instance($manager);
  626. $this->assertSame($manager, EventManager::instance());
  627. }
  628. /**
  629. * Tests that the global event manager gets the event too from any other manager
  630. *
  631. * @return void
  632. * @triggers fake.event
  633. */
  634. public function testDispatchWithGlobal()
  635. {
  636. $generalManager = $this->getMockBuilder('Cake\Event\EventManager')
  637. ->setMethods(['prioritisedListeners'])
  638. ->getMock();
  639. $manager = new EventManager();
  640. $event = new Event('fake.event');
  641. EventManager::instance($generalManager);
  642. $generalManager->expects($this->once())->method('prioritisedListeners')->with('fake.event');
  643. $manager->dispatch($event);
  644. EventManager::instance(new EventManager());
  645. }
  646. /**
  647. * Tests that stopping an event will not notify the rest of the listeners
  648. *
  649. * @return void
  650. * @triggers fake.event
  651. */
  652. public function testStopPropagation()
  653. {
  654. $generalManager = $this->getMockBuilder('Cake\Event\EventManager')->getMock();
  655. $manager = new EventManager();
  656. $listener = new EventTestListener();
  657. EventManager::instance($generalManager);
  658. $generalManager->expects($this->any())
  659. ->method('prioritisedListeners')
  660. ->with('fake.event')
  661. ->will($this->returnValue([]));
  662. $manager->on('fake.event', [$listener, 'listenerFunction']);
  663. $manager->on('fake.event', ['priority' => 8], [$listener, 'stopListener']);
  664. $manager->on('fake.event', ['priority' => 5], [$listener, 'secondListenerFunction']);
  665. $event = new Event('fake.event');
  666. $manager->dispatch($event);
  667. $expected = ['secondListenerFunction'];
  668. $this->assertEquals($expected, $listener->callList);
  669. EventManager::instance(new EventManager());
  670. }
  671. /**
  672. * Tests event dispatching using priorities
  673. *
  674. * @return void
  675. * @triggers fake.event
  676. */
  677. public function testDispatchPrioritizedWithGlobal()
  678. {
  679. $generalManager = $this->getMockBuilder('Cake\Event\EventManager')->getMock();
  680. $manager = new EventManager();
  681. $listener = new CustomTestEventListenerInterface();
  682. $event = new Event('fake.event');
  683. EventManager::instance($generalManager);
  684. $generalManager->expects($this->any())
  685. ->method('prioritisedListeners')
  686. ->with('fake.event')
  687. ->will($this->returnValue(
  688. [11 => [
  689. ['callable' => [$listener, 'secondListenerFunction']],
  690. ]]
  691. ));
  692. $manager->on('fake.event', [$listener, 'listenerFunction']);
  693. $manager->on('fake.event', ['priority' => 15], [$listener, 'thirdListenerFunction']);
  694. $manager->dispatch($event);
  695. $expected = ['listenerFunction', 'secondListenerFunction', 'thirdListenerFunction'];
  696. $this->assertEquals($expected, $listener->callList);
  697. EventManager::instance(new EventManager());
  698. }
  699. /**
  700. * Tests event dispatching using priorities
  701. *
  702. * @return void
  703. * @triggers fake.event
  704. */
  705. public function testDispatchGlobalBeforeLocal()
  706. {
  707. $generalManager = $this->getMockBuilder('Cake\Event\EventManager')->getMock();
  708. $manager = new EventManager();
  709. $listener = new CustomTestEventListenerInterface();
  710. $event = new Event('fake.event');
  711. EventManager::instance($generalManager);
  712. $generalManager->expects($this->any())
  713. ->method('prioritisedListeners')
  714. ->with('fake.event')
  715. ->will($this->returnValue(
  716. [10 => [
  717. ['callable' => [$listener, 'listenerFunction']],
  718. ]]
  719. ));
  720. $manager->on('fake.event', [$listener, 'secondListenerFunction']);
  721. $manager->dispatch($event);
  722. $expected = ['listenerFunction', 'secondListenerFunction'];
  723. $this->assertEquals($expected, $listener->callList);
  724. EventManager::instance(new EventManager());
  725. }
  726. /**
  727. * test callback
  728. *
  729. * @param Event $event
  730. */
  731. public function onMyEvent(Event $event)
  732. {
  733. $event->setData('callback', 'ok');
  734. }
  735. /**
  736. * Tests events dispatched by a local manager can be handled by
  737. * handler registered in the global event manager
  738. * @triggers my_event $manager
  739. */
  740. public function testDispatchLocalHandledByGlobal()
  741. {
  742. $callback = [$this, 'onMyEvent'];
  743. EventManager::instance()->on('my_event', $callback);
  744. $manager = new EventManager();
  745. $event = new Event('my_event', $manager);
  746. $manager->dispatch($event);
  747. $this->assertEquals('ok', $event->getData('callback'));
  748. }
  749. /**
  750. * Test that events are dispatched properly when there are global and local
  751. * listeners at the same priority.
  752. *
  753. * @return void
  754. * @triggers fake.event $this
  755. */
  756. public function testDispatchWithGlobalAndLocalEvents()
  757. {
  758. $listener = new CustomTestEventListenerInterface();
  759. EventManager::instance()->on($listener);
  760. $listener2 = new EventTestListener();
  761. $manager = new EventManager();
  762. $manager->on('fake.event', [$listener2, 'listenerFunction']);
  763. $manager->dispatch(new Event('fake.event', $this));
  764. $this->assertEquals(['listenerFunction'], $listener->callList);
  765. $this->assertEquals(['listenerFunction'], $listener2->callList);
  766. }
  767. /**
  768. * Test getting a list of dispatched events from the manager.
  769. *
  770. * @return void
  771. * @triggers my_event $this
  772. * @triggers my_second_event $this
  773. */
  774. public function testGetDispatchedEvents()
  775. {
  776. $eventList = new EventList();
  777. $event = new Event('my_event', $this);
  778. $event2 = new Event('my_second_event', $this);
  779. $manager = new EventManager();
  780. $manager->setEventList($eventList);
  781. $manager->dispatch($event);
  782. $manager->dispatch($event2);
  783. $result = $manager->getEventList();
  784. $this->assertInstanceOf('\Cake\Event\EventList', $result);
  785. $this->assertCount(2, $result);
  786. $this->assertEquals($result[0], $event);
  787. $this->assertEquals($result[1], $event2);
  788. $manager->getEventList()->flush();
  789. $result = $manager->getEventList();
  790. $this->assertCount(0, $result);
  791. $manager->unsetEventList();
  792. $manager->dispatch($event);
  793. $manager->dispatch($event2);
  794. $result = $manager->getEventList();
  795. $this->assertNull($result);
  796. }
  797. /**
  798. * Test that locally dispatched events are also added to the global manager's event list
  799. *
  800. * @return void
  801. * @triggers Event $this
  802. */
  803. public function testGetLocallyDispatchedEventsFromGlobal()
  804. {
  805. $localList = new EventList();
  806. $globalList = new EventList();
  807. $globalManager = EventManager::instance();
  808. $globalManager->setEventList($globalList);
  809. $localManager = new EventManager();
  810. $localManager->setEventList($localList);
  811. $globalEvent = new Event('GlobalEvent', $this);
  812. $globalManager->dispatch($globalEvent);
  813. $localEvent = new Event('LocalEvent', $this);
  814. $localManager->dispatch($localEvent);
  815. $this->assertTrue($globalList->hasEvent('GlobalEvent'));
  816. $this->assertFalse($localList->hasEvent('GlobalEvent'));
  817. $this->assertTrue($localList->hasEvent('LocalEvent'));
  818. $this->assertTrue($globalList->hasEvent('LocalEvent'));
  819. }
  820. /**
  821. * Test isTrackingEvents
  822. *
  823. * @return void
  824. */
  825. public function testIsTrackingEvents()
  826. {
  827. $this->assertFalse(EventManager::instance()->isTrackingEvents());
  828. $manager = new EventManager();
  829. $manager->setEventList(new EventList());
  830. $this->assertTrue($manager->isTrackingEvents());
  831. $manager->trackEvents(false);
  832. $this->assertFalse($manager->isTrackingEvents());
  833. }
  834. public function testDebugInfo()
  835. {
  836. $eventManager = new EventManager();
  837. $this->assertSame(
  838. [
  839. '_listeners' => [],
  840. '_isGlobal' => false,
  841. '_trackEvents' => false,
  842. '_generalManager' => '(object) EventManager',
  843. '_dispatchedEvents' => null,
  844. ],
  845. $eventManager->__debugInfo()
  846. );
  847. $eventManager->setEventList(new EventList());
  848. $eventManager->addEventToList(new Event('Foo', $this));
  849. $this->assertSame(
  850. [
  851. '_listeners' => [],
  852. '_isGlobal' => false,
  853. '_trackEvents' => true,
  854. '_generalManager' => '(object) EventManager',
  855. '_dispatchedEvents' => [
  856. 'Foo with subject Cake\Test\TestCase\Event\EventManagerTest',
  857. ],
  858. ],
  859. $eventManager->__debugInfo()
  860. );
  861. $eventManager->unsetEventList();
  862. $func = function () {
  863. };
  864. $eventManager->on('foo', $func);
  865. $this->assertSame(
  866. [
  867. '_listeners' => [
  868. 'foo' => '1 listener(s)',
  869. ],
  870. '_isGlobal' => false,
  871. '_trackEvents' => false,
  872. '_generalManager' => '(object) EventManager',
  873. '_dispatchedEvents' => null,
  874. ],
  875. $eventManager->__debugInfo()
  876. );
  877. $eventManager->off('foo', $func);
  878. $this->assertSame(
  879. [
  880. '_listeners' => [
  881. 'foo' => '0 listener(s)',
  882. ],
  883. '_isGlobal' => false,
  884. '_trackEvents' => false,
  885. '_generalManager' => '(object) EventManager',
  886. '_dispatchedEvents' => null,
  887. ],
  888. $eventManager->__debugInfo()
  889. );
  890. $eventManager->on('bar', function () {
  891. });
  892. $eventManager->on('bar', function () {
  893. });
  894. $eventManager->on('bar', function () {
  895. });
  896. $eventManager->on('baz', function () {
  897. });
  898. $this->assertSame(
  899. [
  900. '_listeners' => [
  901. 'foo' => '0 listener(s)',
  902. 'bar' => '3 listener(s)',
  903. 'baz' => '1 listener(s)',
  904. ],
  905. '_isGlobal' => false,
  906. '_trackEvents' => false,
  907. '_generalManager' => '(object) EventManager',
  908. '_dispatchedEvents' => null,
  909. ],
  910. $eventManager->__debugInfo()
  911. );
  912. }
  913. /**
  914. * test debugInfo with an event list.
  915. *
  916. * @return void
  917. */
  918. public function testDebugInfoEventList()
  919. {
  920. $eventList = new EventList();
  921. $eventManager = new EventManager();
  922. $eventManager->setEventList($eventList);
  923. $eventManager->on('example', function () {
  924. });
  925. $eventManager->dispatch('example');
  926. $this->assertSame(
  927. [
  928. '_listeners' => [
  929. 'example' => '1 listener(s)',
  930. ],
  931. '_isGlobal' => false,
  932. '_trackEvents' => true,
  933. '_generalManager' => '(object) EventManager',
  934. '_dispatchedEvents' => [
  935. 'example with no subject',
  936. ],
  937. ],
  938. $eventManager->__debugInfo()
  939. );
  940. }
  941. /**
  942. * Test that chainable methods return correct values.
  943. *
  944. * @return void
  945. */
  946. public function testChainableMethods()
  947. {
  948. $eventManager = new EventManager();
  949. $listener = $this->createMock(EventListenerInterface::class);
  950. $callable = function () {
  951. };
  952. $returnValue = $eventManager->on($listener);
  953. $this->assertSame($eventManager, $returnValue);
  954. $returnValue = $eventManager->on('foo', $callable);
  955. $this->assertSame($eventManager, $returnValue);
  956. $returnValue = $eventManager->on('foo', [], $callable);
  957. $this->assertSame($eventManager, $returnValue);
  958. $returnValue = $eventManager->off($listener);
  959. $this->assertSame($eventManager, $returnValue);
  960. $returnValue = $eventManager->off('foo', $listener);
  961. $this->assertSame($eventManager, $returnValue);
  962. $returnValue = $eventManager->off('foo', $callable);
  963. $this->assertSame($eventManager, $returnValue);
  964. $returnValue = $eventManager->off('foo');
  965. $this->assertSame($eventManager, $returnValue);
  966. $returnValue = $eventManager->setEventList(new EventList());
  967. $this->assertSame($eventManager, $returnValue);
  968. $returnValue = $eventManager->addEventToList(new Event('foo'));
  969. $this->assertSame($eventManager, $returnValue);
  970. $returnValue = $eventManager->trackEvents(true);
  971. $this->assertSame($eventManager, $returnValue);
  972. $returnValue = $eventManager->unsetEventList();
  973. $this->assertSame($eventManager, $returnValue);
  974. }
  975. }