EntityTest.php 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://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. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since 3.0.0
  13. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  14. */
  15. namespace Cake\Test\TestCase\ORM;
  16. use Cake\ORM\Entity;
  17. use Cake\TestSuite\TestCase;
  18. use Cake\Validation\Validator;
  19. /**
  20. * Entity test case.
  21. */
  22. class EntityTest extends TestCase {
  23. /**
  24. * Tests setting a single property in an entity without custom setters
  25. *
  26. * @return void
  27. */
  28. public function testSetOneParamNoSetters() {
  29. $entity = new Entity;
  30. $entity->set('foo', 'bar');
  31. $this->assertEquals('bar', $entity->foo);
  32. $entity->set('foo', 'baz');
  33. $this->assertEquals('baz', $entity->foo);
  34. $entity->set('id', 1);
  35. $this->assertSame(1, $entity->id);
  36. }
  37. /**
  38. * Tests setting multiple properties without custom setters
  39. *
  40. * @return void
  41. */
  42. public function testSetMultiplePropertiesNoSetters() {
  43. $entity = new Entity;
  44. $entity->accessible('*', true);
  45. $entity->set(['foo' => 'bar', 'id' => 1]);
  46. $this->assertEquals('bar', $entity->foo);
  47. $this->assertSame(1, $entity->id);
  48. $entity->set(['foo' => 'baz', 'id' => 2, 'thing' => 3]);
  49. $this->assertEquals('baz', $entity->foo);
  50. $this->assertSame(2, $entity->id);
  51. $this->assertSame(3, $entity->thing);
  52. }
  53. /**
  54. * Tests setting a single property using a setter function
  55. *
  56. * @return void
  57. */
  58. public function testSetOneParamWithSetter() {
  59. $entity = $this->getMock('\Cake\ORM\Entity', ['setName']);
  60. $entity->expects($this->once())->method('setName')
  61. ->with('Jones')
  62. ->will($this->returnCallback(function($name) {
  63. $this->assertEquals('Jones', $name);
  64. return 'Dr. ' . $name;
  65. }));
  66. $entity->set('name', 'Jones');
  67. $this->assertEquals('Dr. Jones', $entity->name);
  68. }
  69. /**
  70. * Tests setting multiple properties using a setter function
  71. *
  72. * @return void
  73. */
  74. public function testMultipleWithSetter() {
  75. $entity = $this->getMock('\Cake\ORM\Entity', ['setName', 'setStuff']);
  76. $entity->accessible('*', true);
  77. $entity->expects($this->once())->method('setName')
  78. ->with('Jones')
  79. ->will($this->returnCallback(function($name) {
  80. $this->assertEquals('Jones', $name);
  81. return 'Dr. ' . $name;
  82. }));
  83. $entity->expects($this->once())->method('setStuff')
  84. ->with(['a', 'b'])
  85. ->will($this->returnCallback(function($stuff) {
  86. $this->assertEquals(['a', 'b'], $stuff);
  87. return ['c', 'd'];
  88. }));
  89. $entity->set(['name' => 'Jones', 'stuff' => ['a', 'b']]);
  90. $this->assertEquals('Dr. Jones', $entity->name);
  91. $this->assertEquals(['c', 'd'], $entity->stuff);
  92. }
  93. /**
  94. * Tests that it is possible to bypass the setters
  95. *
  96. * @return void
  97. */
  98. public function testBypassSetters() {
  99. $entity = $this->getMock('\Cake\ORM\Entity', ['setName', 'setStuff']);
  100. $entity->accessible('*', true);
  101. $entity->expects($this->never())->method('setName');
  102. $entity->expects($this->never())->method('setStuff');
  103. $entity->set('name', 'Jones', ['setter' => false]);
  104. $this->assertEquals('Jones', $entity->name);
  105. $entity->set('stuff', 'Thing', ['setter' => false]);
  106. $this->assertEquals('Thing', $entity->stuff);
  107. $entity->set(['name' => 'foo', 'stuff' => 'bar'], ['setter' => false]);
  108. $this->assertEquals('bar', $entity->stuff);
  109. }
  110. /**
  111. * Tests that the constructor will set initial properties
  112. *
  113. * @return void
  114. */
  115. public function testConstructor() {
  116. $entity = $this->getMockBuilder('\Cake\ORM\Entity')
  117. ->setMethods(['set'])
  118. ->disableOriginalConstructor()
  119. ->getMock();
  120. $entity->expects($this->at(0))
  121. ->method('set')
  122. ->with(['a' => 'b', 'c' => 'd'], ['setter' => true, 'guard' => false]);
  123. $entity->expects($this->at(1))
  124. ->method('set')
  125. ->with(['foo' => 'bar'], ['setter' => false, 'guard' => false]);
  126. $entity->__construct(['a' => 'b', 'c' => 'd']);
  127. $entity->__construct(['foo' => 'bar'], ['useSetters' => false]);
  128. }
  129. /**
  130. * Tests that the constructor will set initial properties and pass the guard
  131. * option along
  132. *
  133. * @return void
  134. */
  135. public function testConstructorWithGuard() {
  136. $entity = $this->getMockBuilder('\Cake\ORM\Entity')
  137. ->setMethods(['set'])
  138. ->disableOriginalConstructor()
  139. ->getMock();
  140. $entity->expects($this->once())
  141. ->method('set')
  142. ->with(['foo' => 'bar'], ['setter' => true, 'guard' => true]);
  143. $entity->__construct(['foo' => 'bar'], ['guard' => true]);
  144. }
  145. /**
  146. * Tests getting properties with no custom getters
  147. *
  148. * @return void
  149. */
  150. public function testGetNoGetters() {
  151. $entity = new Entity(['id' => 1, 'foo' => 'bar']);
  152. $this->assertSame(1, $entity->get('id'));
  153. $this->assertSame('bar', $entity->get('foo'));
  154. }
  155. /**
  156. * Tests get with custom getter
  157. *
  158. * @return void
  159. */
  160. public function testGetCustomGetters() {
  161. $entity = $this->getMock('\Cake\ORM\Entity', ['getName']);
  162. $entity->expects($this->once())->method('getName')
  163. ->with('Jones')
  164. ->will($this->returnCallback(function($name) {
  165. $this->assertSame('Jones', $name);
  166. return 'Dr. ' . $name;
  167. }));
  168. $entity->set('name', 'Jones');
  169. $this->assertEquals('Dr. Jones', $entity->get('name'));
  170. }
  171. /**
  172. * Test magic property setting with no custom setter
  173. *
  174. * @return void
  175. */
  176. public function testMagicSet() {
  177. $entity = new Entity;
  178. $entity->name = 'Jones';
  179. $this->assertEquals('Jones', $entity->name);
  180. $entity->name = 'George';
  181. $this->assertEquals('George', $entity->name);
  182. }
  183. /**
  184. * Tests magic set with custom setter function
  185. *
  186. * @return void
  187. */
  188. public function testMagicSetWithSetter() {
  189. $entity = $this->getMock('\Cake\ORM\Entity', ['setName']);
  190. $entity->expects($this->once())->method('setName')
  191. ->with('Jones')
  192. ->will($this->returnCallback(function($name) {
  193. $this->assertEquals('Jones', $name);
  194. return 'Dr. ' . $name;
  195. }));
  196. $entity->name = 'Jones';
  197. $this->assertEquals('Dr. Jones', $entity->name);
  198. }
  199. /**
  200. * Tests the magic getter with a custom getter function
  201. *
  202. * @return void
  203. */
  204. public function testMagicGetWithGetter() {
  205. $entity = $this->getMock('\Cake\ORM\Entity', ['getName']);
  206. $entity->expects($this->once())->method('getName')
  207. ->with('Jones')
  208. ->will($this->returnCallback(function($name) {
  209. $this->assertSame('Jones', $name);
  210. return 'Dr. ' . $name;
  211. }));
  212. $entity->set('name', 'Jones');
  213. $this->assertEquals('Dr. Jones', $entity->name);
  214. }
  215. /**
  216. * Test indirectly modifying internal properties
  217. *
  218. * @return void
  219. */
  220. public function testIndirectModification() {
  221. $entity = new Entity;
  222. $entity->things = ['a', 'b'];
  223. $entity->things[] = 'c';
  224. $this->assertEquals(['a', 'b', 'c'], $entity->things);
  225. }
  226. /**
  227. * Test indirectly modifying internal properties with a getter
  228. *
  229. * @return void
  230. */
  231. public function testIndirectModificationWithGetter() {
  232. $entity = $this->getMock('\Cake\ORM\Entity', ['getThings']);
  233. $entity->expects($this->atLeastOnce())->method('getThings')
  234. ->will($this->returnArgument(0));
  235. $entity->things = ['a', 'b'];
  236. $entity->things[] = 'c';
  237. $this->assertEquals(['a', 'b', 'c'], $entity->things);
  238. }
  239. /**
  240. * Tests has() method
  241. *
  242. * @return void
  243. */
  244. public function testHas() {
  245. $entity = new Entity(['id' => 1, 'name' => 'Juan', 'foo' => null]);
  246. $this->assertTrue($entity->has('id'));
  247. $this->assertTrue($entity->has('name'));
  248. $this->assertFalse($entity->has('foo'));
  249. $this->assertFalse($entity->has('last_name'));
  250. $entity = $this->getMock('\Cake\ORM\Entity', ['getThings']);
  251. $entity->expects($this->once())->method('getThings')
  252. ->will($this->returnValue(0));
  253. $this->assertTrue($entity->has('things'));
  254. }
  255. /**
  256. * Tests unsetProperty one property at a time
  257. *
  258. * @return void
  259. */
  260. public function testUnset() {
  261. $entity = new Entity(['id' => 1, 'name' => 'bar']);
  262. $entity->unsetProperty('id');
  263. $this->assertFalse($entity->has('id'));
  264. $this->assertTrue($entity->has('name'));
  265. $entity->unsetProperty('name');
  266. $this->assertFalse($entity->has('id'));
  267. }
  268. /**
  269. * Tests unsetProperty whith multiple properties
  270. *
  271. * @return void
  272. */
  273. public function testUnsetMultiple() {
  274. $entity = new Entity(['id' => 1, 'name' => 'bar', 'thing' => 2]);
  275. $entity->unsetProperty(['id', 'thing']);
  276. $this->assertFalse($entity->has('id'));
  277. $this->assertTrue($entity->has('name'));
  278. $this->assertFalse($entity->has('thing'));
  279. }
  280. /**
  281. * Tests the magic __isset() method
  282. *
  283. * @return void
  284. */
  285. public function testMagicIsset() {
  286. $entity = new Entity(['id' => 1, 'name' => 'Juan', 'foo' => null]);
  287. $this->assertTrue(isset($entity->id));
  288. $this->assertTrue(isset($entity->name));
  289. $this->assertFalse(isset($entity->foo));
  290. $this->assertFalse(isset($entity->thing));
  291. }
  292. /**
  293. * Tests the magic __unset() method
  294. *
  295. * @return void
  296. */
  297. public function testMagicUnset() {
  298. $entity = $this->getMock('\Cake\ORM\Entity', ['unsetProperty']);
  299. $entity->expects($this->at(0))
  300. ->method('unsetProperty')
  301. ->with('foo');
  302. unset($entity->foo);
  303. }
  304. /**
  305. * Tests isset with array access
  306. *
  307. * @return void
  308. */
  309. public function testIssetArrayAccess() {
  310. $entity = new Entity(['id' => 1, 'name' => 'Juan', 'foo' => null]);
  311. $this->assertTrue(isset($entity['id']));
  312. $this->assertTrue(isset($entity['name']));
  313. $this->assertFalse(isset($entity['foo']));
  314. $this->assertFalse(isset($entity['thing']));
  315. }
  316. /**
  317. * Tests get property with array access
  318. *
  319. * @return void
  320. */
  321. public function testGetArrayAccess() {
  322. $entity = $this->getMock('\Cake\ORM\Entity', ['get']);
  323. $entity->expects($this->at(0))
  324. ->method('get')
  325. ->with('foo')
  326. ->will($this->returnValue('worked'));
  327. $entity->expects($this->at(1))
  328. ->method('get')
  329. ->with('bar')
  330. ->will($this->returnValue('worked too'));
  331. $this->assertEquals('worked', $entity['foo']);
  332. $this->assertEquals('worked too', $entity['bar']);
  333. }
  334. /**
  335. * Tests set with array access
  336. *
  337. * @return void
  338. */
  339. public function testSetArrayAccess() {
  340. $entity = $this->getMock('\Cake\ORM\Entity', ['set']);
  341. $entity->accessible('*', true);
  342. $entity->expects($this->at(0))
  343. ->method('set')
  344. ->with('foo', 1)
  345. ->will($this->returnSelf());
  346. $entity->expects($this->at(1))
  347. ->method('set')
  348. ->with('bar', 2)
  349. ->will($this->returnSelf());
  350. $entity['foo'] = 1;
  351. $entity['bar'] = 2;
  352. }
  353. /**
  354. * Tests unset with array access
  355. *
  356. * @return void
  357. */
  358. public function testUnsetArrayAccess() {
  359. $entity = $this->getMock('\Cake\ORM\Entity', ['unsetProperty']);
  360. $entity->expects($this->at(0))
  361. ->method('unsetProperty')
  362. ->with('foo');
  363. unset($entity['foo']);
  364. }
  365. /**
  366. * Tests that the method cache will only report the methods for the called class,
  367. * this is, calling methods defined in another entity will not cause a fatal error
  368. * when trying to call directly an inexistent method in another class
  369. *
  370. * @return void
  371. */
  372. public function testMethodCache() {
  373. $entity = $this->getMock('\Cake\ORM\Entity', ['setFoo', 'getBar']);
  374. $entity2 = $this->getMock('\Cake\ORM\Entity', ['setBar']);
  375. $entity->expects($this->once())->method('setFoo');
  376. $entity->expects($this->once())->method('getBar');
  377. $entity2->expects($this->once())->method('setBar');
  378. $entity->set('foo', 1);
  379. $entity->get('bar');
  380. $entity2->set('bar', 1);
  381. }
  382. /**
  383. * Tests that long properties in the entity are inflected correctly
  384. *
  385. * @return void
  386. */
  387. public function testSetGetLongProperyNames() {
  388. $entity = $this->getMock('\Cake\ORM\Entity', ['getVeryLongProperty', 'setVeryLongProperty']);
  389. $entity->expects($this->once())->method('getVeryLongProperty');
  390. $entity->expects($this->once())->method('setVeryLongProperty');
  391. $entity->get('very_long_property');
  392. $entity->set('very_long_property', 1);
  393. }
  394. /**
  395. * Tests serializing an entity as json
  396. *
  397. * @return void
  398. */
  399. public function testJsonSerialize() {
  400. $data = ['name' => 'James', 'age' => 20, 'phones' => ['123', '457']];
  401. $entity = new Entity($data);
  402. $this->assertEquals(json_encode($data), json_encode($entity));
  403. }
  404. /**
  405. * Tests the extract method
  406. *
  407. * @return void
  408. */
  409. public function testExtract() {
  410. $entity = new Entity([
  411. 'id' => 1,
  412. 'title' => 'Foo',
  413. 'author_id' => 3
  414. ]);
  415. $expected = ['author_id' => 3, 'title' => 'Foo', ];
  416. $this->assertEquals($expected, $entity->extract(['author_id', 'title']));
  417. $expected = ['id' => 1];
  418. $this->assertEquals($expected, $entity->extract(['id']));
  419. $expected = [];
  420. $this->assertEquals($expected, $entity->extract([]));
  421. $expected = ['id' => 1, 'crazyness' => null];
  422. $this->assertEquals($expected, $entity->extract(['id', 'crazyness']));
  423. }
  424. /**
  425. * Tests dirty() method on a newly created object
  426. *
  427. * @return void
  428. */
  429. public function testDirty() {
  430. $entity = new Entity([
  431. 'id' => 1,
  432. 'title' => 'Foo',
  433. 'author_id' => 3
  434. ]);
  435. $this->assertTrue($entity->dirty('id'));
  436. $this->assertTrue($entity->dirty('title'));
  437. $this->assertTrue($entity->dirty('author_id'));
  438. $this->assertTrue($entity->dirty());
  439. $entity->dirty('id', false);
  440. $this->assertFalse($entity->dirty('id'));
  441. $this->assertTrue($entity->dirty('title'));
  442. $entity->dirty('title', false);
  443. $this->assertFalse($entity->dirty('title'));
  444. $this->assertTrue($entity->dirty());
  445. $entity->dirty('author_id', false);
  446. $this->assertFalse($entity->dirty());
  447. }
  448. /**
  449. * Tests dirty() when altering properties values and adding new ones
  450. *
  451. * @return void
  452. */
  453. public function testDirtyChangingProperties() {
  454. $entity = new Entity([
  455. 'title' => 'Foo',
  456. ]);
  457. $entity->dirty('title', false);
  458. $this->assertFalse($entity->dirty('title'));
  459. $entity->set('title', 'Foo');
  460. $this->assertTrue($entity->dirty('title'));
  461. $entity->set('title', 'Foo');
  462. $this->assertTrue($entity->dirty('title'));
  463. $entity->set('something', 'else');
  464. $this->assertTrue($entity->dirty('something'));
  465. }
  466. /**
  467. * Tests extract only dirty properties
  468. *
  469. * @return void
  470. */
  471. public function testExtractDirty() {
  472. $entity = new Entity([
  473. 'id' => 1,
  474. 'title' => 'Foo',
  475. 'author_id' => 3
  476. ]);
  477. $entity->dirty('id', false);
  478. $entity->dirty('title', false);
  479. $expected = ['author_id' => 3];
  480. $result = $entity->extract(['id', 'title', 'author_id'], true);
  481. $this->assertEquals($expected, $result);
  482. }
  483. /**
  484. * Tests the clean method
  485. *
  486. * @return void
  487. */
  488. public function testClean() {
  489. $entity = new Entity([
  490. 'id' => 1,
  491. 'title' => 'Foo',
  492. 'author_id' => 3
  493. ]);
  494. $this->assertTrue($entity->dirty('id'));
  495. $this->assertTrue($entity->dirty('title'));
  496. $this->assertTrue($entity->dirty('author_id'));
  497. $entity->clean();
  498. $this->assertFalse($entity->dirty('id'));
  499. $this->assertFalse($entity->dirty('title'));
  500. $this->assertFalse($entity->dirty('author_id'));
  501. }
  502. /**
  503. * Tests the isNew method
  504. *
  505. * @return void
  506. */
  507. public function testIsNew() {
  508. $entity = new Entity([
  509. 'id' => 1,
  510. 'title' => 'Foo',
  511. 'author_id' => 3
  512. ]);
  513. $this->assertNull($entity->isNew());
  514. $entity->isNew(true);
  515. $this->assertTrue($entity->isNew());
  516. $entity->isNew(false);
  517. $this->assertFalse($entity->isNew());
  518. }
  519. /**
  520. * Tests the constructor when passing the markClean option
  521. *
  522. * @return void
  523. */
  524. public function testConstructorWithClean() {
  525. $entity = $this->getMockBuilder('\Cake\ORM\Entity')
  526. ->setMethods(['clean'])
  527. ->disableOriginalConstructor()
  528. ->getMock();
  529. $entity->expects($this->never())->method('clean');
  530. $entity->__construct(['a' => 'b', 'c' => 'd']);
  531. $entity = $this->getMockBuilder('\Cake\ORM\Entity')
  532. ->setMethods(['clean'])
  533. ->disableOriginalConstructor()
  534. ->getMock();
  535. $entity->expects($this->once())->method('clean');
  536. $entity->__construct(['a' => 'b', 'c' => 'd'], ['markClean' => true]);
  537. }
  538. /**
  539. * Tests the constructor when passing the markClean option
  540. *
  541. * @return void
  542. */
  543. public function testConstructorWithMarkNew() {
  544. $entity = $this->getMockBuilder('\Cake\ORM\Entity')
  545. ->setMethods(['isNew'])
  546. ->disableOriginalConstructor()
  547. ->getMock();
  548. $entity->expects($this->never())->method('clean');
  549. $entity->__construct(['a' => 'b', 'c' => 'd']);
  550. $entity = $this->getMockBuilder('\Cake\ORM\Entity')
  551. ->setMethods(['isNew'])
  552. ->disableOriginalConstructor()
  553. ->getMock();
  554. $entity->expects($this->once())->method('isNew');
  555. $entity->__construct(['a' => 'b', 'c' => 'd'], ['markNew' => true]);
  556. }
  557. /**
  558. * Test toArray method.
  559. *
  560. * @return void
  561. */
  562. public function testToArray() {
  563. $data = ['name' => 'James', 'age' => 20, 'phones' => ['123', '457']];
  564. $entity = new Entity($data);
  565. $this->assertEquals($data, $entity->toArray());
  566. }
  567. /**
  568. * Test toArray recursive.
  569. *
  570. * @return void
  571. */
  572. public function testToArrayRecursive() {
  573. $data = ['id' => 1, 'name' => 'James', 'age' => 20, 'phones' => ['123', '457']];
  574. $user = new Entity($data);
  575. $comments = [
  576. new Entity(['user_id' => 1, 'body' => 'Comment 1']),
  577. new Entity(['user_id' => 1, 'body' => 'Comment 2']),
  578. ];
  579. $user->comments = $comments;
  580. $user->profile = new Entity(['email' => 'mark@example.com']);
  581. $expected = [
  582. 'id' => 1,
  583. 'name' => 'James',
  584. 'age' => 20,
  585. 'phones' => ['123', '457'],
  586. 'profile' => ['email' => 'mark@example.com'],
  587. 'comments' => [
  588. ['user_id' => 1, 'body' => 'Comment 1'],
  589. ['user_id' => 1, 'body' => 'Comment 2'],
  590. ]
  591. ];
  592. $this->assertEquals($expected, $user->toArray());
  593. }
  594. /**
  595. * Test that get accessors are called when converting to arrays.
  596. *
  597. * @return void
  598. */
  599. public function testToArrayWithAccessor() {
  600. $entity = $this->getMock('\Cake\ORM\Entity', ['getName']);
  601. $entity->accessible('*', true);
  602. $entity->set(['name' => 'Mark', 'email' => 'mark@example.com']);
  603. $entity->expects($this->any())
  604. ->method('getName')
  605. ->will($this->returnValue('Jose'));
  606. $expected = ['name' => 'Jose', 'email' => 'mark@example.com'];
  607. $this->assertEquals($expected, $entity->toArray());
  608. }
  609. /**
  610. * Test that toArray respects hidden properties.
  611. *
  612. * @return void
  613. */
  614. public function testToArrayHiddenProperties() {
  615. $data = ['secret' => 'sauce', 'name' => 'mark', 'id' => 1];
  616. $entity = new Entity($data);
  617. $entity->hiddenProperties(['secret']);
  618. $this->assertEquals(['name' => 'mark', 'id' => 1], $entity->toArray());
  619. }
  620. /**
  621. * Test toArray includes 'virtual' properties.
  622. *
  623. * @return void
  624. */
  625. public function testToArrayVirtualProperties() {
  626. $entity = $this->getMock('\Cake\ORM\Entity', ['getName']);
  627. $entity->accessible('*', true);
  628. $entity->expects($this->any())
  629. ->method('getName')
  630. ->will($this->returnValue('Jose'));
  631. $entity->set(['email' => 'mark@example.com']);
  632. $entity->virtualProperties(['name']);
  633. $expected = ['name' => 'Jose', 'email' => 'mark@example.com'];
  634. $this->assertEquals($expected, $entity->toArray());
  635. $this->assertEquals(['name'], $entity->virtualProperties());
  636. $entity->hiddenProperties(['name']);
  637. $expected = ['email' => 'mark@example.com'];
  638. $this->assertEquals($expected, $entity->toArray());
  639. $this->assertEquals(['name'], $entity->hiddenProperties());
  640. }
  641. /**
  642. * Tests that missing fields will not be passed as null to the validator
  643. *
  644. * @return void
  645. */
  646. public function testValidateMissingFields() {
  647. $entity = $this->getMockBuilder('\Cake\ORM\Entity')
  648. ->setMethods(['getSomething'])
  649. ->disableOriginalConstructor()
  650. ->getMock();
  651. $entity->accessible('*', true);
  652. $validator = $this->getMock('\Cake\Validation\Validator');
  653. $entity->set('a', 'b');
  654. $validator->expects($this->once())
  655. ->method('provider')
  656. ->with('entity', $entity);
  657. $validator->expects($this->once())->method('errors')
  658. ->with(['a' => 'b'], true)
  659. ->will($this->returnValue(['a' => ['not valid']]));
  660. $this->assertFalse($entity->validate($validator));
  661. $this->assertEquals(['a' => ['not valid']], $entity->errors());
  662. }
  663. /**
  664. * Tests validate when the validator returns no errors
  665. *
  666. * @return void
  667. */
  668. public function testValidateSuccess() {
  669. $validator = $this->getMock('\Cake\Validation\Validator');
  670. $data = [
  671. 'a' => 'b',
  672. 'cool' => false,
  673. 'something' => true
  674. ];
  675. $entity = new Entity($data);
  676. $entity->isNew(true);
  677. $validator->expects($this->once())
  678. ->method('provider')
  679. ->with('entity', $entity);
  680. $validator->expects($this->once())->method('errors')
  681. ->with($data, true)
  682. ->will($this->returnValue([]));
  683. $this->assertTrue($entity->validate($validator));
  684. $this->assertEquals([], $entity->errors());
  685. }
  686. /**
  687. * Tests the errors method
  688. *
  689. * @return void
  690. */
  691. public function testErrors() {
  692. $entity = new Entity;
  693. $this->assertEmpty($entity->errors());
  694. $this->assertSame($entity, $entity->errors('foo', 'bar'));
  695. $this->assertEquals(['bar'], $entity->errors('foo'));
  696. $entity->errors('foo', 'other error');
  697. $this->assertEquals(['other error'], $entity->errors('foo'));
  698. $entity->errors('bar', ['something', 'bad']);
  699. $this->assertEquals(['something', 'bad'], $entity->errors('bar'));
  700. $expected = ['foo' => ['other error'], 'bar' => ['something', 'bad']];
  701. $this->assertEquals($expected, $entity->errors());
  702. $errors = ['foo' => ['something'], 'bar' => 'else', 'baz' => ['error']];
  703. $this->assertSame($entity, $entity->errors($errors));
  704. $errors['bar'] = ['else'];
  705. $this->assertEquals($errors, $entity->errors());
  706. }
  707. /**
  708. * Tests that it is possible to get errors for nested entities
  709. *
  710. * @return void
  711. */
  712. public function testErrorsDeep() {
  713. $entity2 = new Entity;
  714. $entity3 = new Entity;
  715. $entity = new Entity([
  716. 'foo' => 'bar',
  717. 'thing' => 'baz',
  718. 'user' => $entity2,
  719. 'owner' => $entity3
  720. ]);
  721. $entity->errors('thing', ['this is a mistake']);
  722. $entity2->errors(['a' => ['error1'], 'b' => ['error2']]);
  723. $entity3->errors(['c' => ['error3'], 'd' => ['error4']]);
  724. $expected = ['a' => ['error1'], 'b' => ['error2']];
  725. $this->assertEquals($expected, $entity->errors('user'));
  726. $expected = ['c' => ['error3'], 'd' => ['error4']];
  727. $this->assertEquals($expected, $entity->errors('owner'));
  728. $entity->set('multiple', [$entity2, $entity3]);
  729. $expected = [
  730. ['a' => ['error1'], 'b' => ['error2']],
  731. ['c' => ['error3'], 'd' => ['error4']]
  732. ];
  733. $this->assertEquals($expected, $entity->errors('multiple'));
  734. }
  735. /**
  736. * Tests that changing the value of a property will remove errors
  737. * stored for it
  738. *
  739. * @return void
  740. */
  741. public function testDirtyRemovesError() {
  742. $entity = new Entity(['a' => 'b']);
  743. $entity->errors('a', 'is not good');
  744. $entity->set('a', 'c');
  745. $this->assertEmpty($entity->errors('a'));
  746. $entity->errors('a', 'is not good');
  747. $entity->dirty('a', true);
  748. $this->assertEmpty($entity->errors('a'));
  749. }
  750. /**
  751. * Tests that marking an entity as clean will remove errors too
  752. *
  753. * @return void
  754. */
  755. public function testCleanRemovesErrors() {
  756. $entity = new Entity(['a' => 'b']);
  757. $entity->errors('a', 'is not good');
  758. $entity->clean();
  759. $this->assertEmpty($entity->errors());
  760. }
  761. /**
  762. * Tests accessible() method as a getter and setter
  763. *
  764. * @return void
  765. */
  766. public function testAccessible() {
  767. $entity = new Entity;
  768. $entity->accessible('*', false);
  769. $this->assertFalse($entity->accessible('foo'));
  770. $this->assertFalse($entity->accessible('bar'));
  771. $this->assertSame($entity, $entity->accessible('foo', true));
  772. $this->assertTrue($entity->accessible('foo'));
  773. $this->assertFalse($entity->accessible('bar'));
  774. $this->assertSame($entity, $entity->accessible('bar', true));
  775. $this->assertTrue($entity->accessible('foo'));
  776. $this->assertTrue($entity->accessible('bar'));
  777. $this->assertSame($entity, $entity->accessible('foo', false));
  778. $this->assertFalse($entity->accessible('foo'));
  779. $this->assertTrue($entity->accessible('bar'));
  780. $this->assertSame($entity, $entity->accessible('bar', false));
  781. $this->assertFalse($entity->accessible('foo'));
  782. $this->assertFalse($entity->accessible('bar'));
  783. }
  784. /**
  785. * Tests that an array can be used to set
  786. *
  787. * @return void
  788. */
  789. public function testAccessibleAsArray() {
  790. $entity = new Entity;
  791. $entity->accessible(['foo', 'bar', 'baz'], true);
  792. $this->assertTrue($entity->accessible('foo'));
  793. $this->assertTrue($entity->accessible('bar'));
  794. $this->assertTrue($entity->accessible('baz'));
  795. $entity->accessible('foo', false);
  796. $this->assertFalse($entity->accessible('foo'));
  797. $this->assertTrue($entity->accessible('bar'));
  798. $this->assertTrue($entity->accessible('baz'));
  799. $entity->accessible(['foo', 'bar', 'baz'], false);
  800. $this->assertFalse($entity->accessible('foo'));
  801. $this->assertFalse($entity->accessible('bar'));
  802. $this->assertFalse($entity->accessible('baz'));
  803. }
  804. /**
  805. * Tests that a wildcard can be used for setting accesible properties
  806. *
  807. * @return void
  808. */
  809. public function testAccessibleWildcard() {
  810. $entity = new Entity;
  811. $entity->accessible(['foo', 'bar', 'baz'], true);
  812. $this->assertTrue($entity->accessible('foo'));
  813. $this->assertTrue($entity->accessible('bar'));
  814. $this->assertTrue($entity->accessible('baz'));
  815. $entity->accessible('*', false);
  816. $this->assertFalse($entity->accessible('foo'));
  817. $this->assertFalse($entity->accessible('bar'));
  818. $this->assertFalse($entity->accessible('baz'));
  819. $this->assertFalse($entity->accessible('newOne'));
  820. $entity->accessible('*', true);
  821. $this->assertTrue($entity->accessible('foo'));
  822. $this->assertTrue($entity->accessible('bar'));
  823. $this->assertTrue($entity->accessible('baz'));
  824. $this->assertTrue($entity->accessible('newOne2'));
  825. }
  826. /**
  827. * Tests that only accessible properties can be set
  828. *
  829. * @return void
  830. */
  831. public function testSetWithAccessible() {
  832. $entity = new Entity(['foo' => 1, 'bar' => 2]);
  833. $options = ['guard' => true];
  834. $entity->accessible('*', false);
  835. $entity->accessible('foo', true);
  836. $entity->set('bar', 3, $options);
  837. $entity->set('foo', 4, $options);
  838. $this->assertEquals(2, $entity->get('bar'));
  839. $this->assertEquals(4, $entity->get('foo'));
  840. $entity->accessible('bar', true);
  841. $entity->set('bar', 3, $options);
  842. $this->assertEquals(3, $entity->get('bar'));
  843. }
  844. /**
  845. * Tests that only accessible properties can be set
  846. *
  847. * @return void
  848. */
  849. public function testSetWithAccessibleWithArray() {
  850. $entity = new Entity(['foo' => 1, 'bar' => 2]);
  851. $options = ['guard' => true];
  852. $entity->accessible('*', false);
  853. $entity->accessible('foo', true);
  854. $entity->set(['bar' => 3, 'foo' => 4], $options);
  855. $this->assertEquals(2, $entity->get('bar'));
  856. $this->assertEquals(4, $entity->get('foo'));
  857. $entity->accessible('bar', true);
  858. $entity->set(['bar' => 3, 'foo' => 5], $options);
  859. $this->assertEquals(3, $entity->get('bar'));
  860. $this->assertEquals(5, $entity->get('foo'));
  861. }
  862. /**
  863. * Test that accessible() and single property setting works.
  864. *
  865. * @return void
  866. */
  867. public function testSetWithAccessibleSingleProperty() {
  868. $entity = new Entity(['foo' => 1, 'bar' => 2]);
  869. $entity->accessible('*', false);
  870. $entity->accessible('title', true);
  871. $entity->set(['title' => 'test', 'body' => 'Nope']);
  872. $this->assertEquals('test', $entity->title);
  873. $this->assertNull($entity->body);
  874. $entity->body = 'Yep';
  875. $this->assertEquals('Yep', $entity->body, 'Single set should bypass guards.');
  876. $entity->set('body', 'Yes');
  877. $this->assertEquals('Yes', $entity->body, 'Single set should bypass guards.');
  878. }
  879. /**
  880. * Tests the entity's __toString method
  881. *
  882. * @return void
  883. */
  884. public function testToString() {
  885. $entity = new Entity(['foo' => 1, 'bar' => 2]);
  886. $this->assertEquals(json_encode($entity, JSON_PRETTY_PRINT), (string)$entity);
  887. }
  888. /**
  889. * Tests __debugInfo
  890. *
  891. * @return void
  892. */
  893. public function testDebugInfo() {
  894. $entity = new Entity(['foo' => 'bar'], ['markClean' => true]);
  895. $entity->accessible('name', true);
  896. $entity->virtualProperties(['baz']);
  897. $entity->dirty('foo', true);
  898. $entity->errors('foo', ['An error']);
  899. $entity->source('foos');
  900. $result = $entity->__debugInfo();
  901. $expected = [
  902. 'new' => null,
  903. 'accessible' => ['*' => true, 'name' => true],
  904. 'properties' => ['foo' => 'bar'],
  905. 'dirty' => ['foo' => true],
  906. 'virtual' => ['baz'],
  907. 'errors' => ['foo' => ['An error']],
  908. 'repository' => 'foos'
  909. ];
  910. $this->assertSame($expected, $result);
  911. }
  912. /**
  913. * Tests the source method
  914. *
  915. * @return void
  916. */
  917. public function testSource() {
  918. $entity = new Entity;
  919. $this->assertNull($entity->source());
  920. $entity->source('foos');
  921. $this->assertEquals('foos', $entity->source());
  922. }
  923. /**
  924. * Provides empty values
  925. *
  926. * @return void
  927. */
  928. public function emptyNamesProvider() {
  929. return [[''], [null], [false]];
  930. }
  931. /**
  932. * Tests that trying to get an empty propery name throws exception
  933. *
  934. * @dataProvider emptyNamesProvider
  935. * @expectedException \InvalidArgumentException
  936. * @return void
  937. */
  938. public function testEmptyProperties($property) {
  939. $entity = new Entity();
  940. $entity->get($property);
  941. }
  942. /**
  943. * Tests that setitng an empty property name does nothing
  944. *
  945. * @expectedException \InvalidArgumentException
  946. * @dataProvider emptyNamesProvider
  947. * @return void
  948. */
  949. public function testSetEmptyPropertyName($property) {
  950. $entity = new Entity();
  951. $entity->set($property, 'bar');
  952. }
  953. }