EntityTest.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020
  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 CakePHP(tm) v 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. $this->assertFalse($entity->accessible('foo'));
  769. $this->assertFalse($entity->accessible('bar'));
  770. $this->assertSame($entity, $entity->accessible('foo', true));
  771. $this->assertTrue($entity->accessible('foo'));
  772. $this->assertFalse($entity->accessible('bar'));
  773. $this->assertSame($entity, $entity->accessible('bar', true));
  774. $this->assertTrue($entity->accessible('foo'));
  775. $this->assertTrue($entity->accessible('bar'));
  776. $this->assertSame($entity, $entity->accessible('foo', false));
  777. $this->assertFalse($entity->accessible('foo'));
  778. $this->assertTrue($entity->accessible('bar'));
  779. $this->assertSame($entity, $entity->accessible('bar', false));
  780. $this->assertFalse($entity->accessible('foo'));
  781. $this->assertFalse($entity->accessible('bar'));
  782. }
  783. /**
  784. * Tests that an array can be used to set
  785. *
  786. * @return void
  787. */
  788. public function testAccessibleAsArray() {
  789. $entity = new Entity;
  790. $entity->accessible(['foo', 'bar', 'baz'], true);
  791. $this->assertTrue($entity->accessible('foo'));
  792. $this->assertTrue($entity->accessible('bar'));
  793. $this->assertTrue($entity->accessible('baz'));
  794. $entity->accessible('foo', false);
  795. $this->assertFalse($entity->accessible('foo'));
  796. $this->assertTrue($entity->accessible('bar'));
  797. $this->assertTrue($entity->accessible('baz'));
  798. $entity->accessible(['foo', 'bar', 'baz'], false);
  799. $this->assertFalse($entity->accessible('foo'));
  800. $this->assertFalse($entity->accessible('bar'));
  801. $this->assertFalse($entity->accessible('baz'));
  802. }
  803. /**
  804. * Tests that a wildcard can be used for setting accesible properties
  805. *
  806. * @return void
  807. */
  808. public function testAccessibleWildcard() {
  809. $entity = new Entity;
  810. $entity->accessible(['foo', 'bar', 'baz'], true);
  811. $this->assertTrue($entity->accessible('foo'));
  812. $this->assertTrue($entity->accessible('bar'));
  813. $this->assertTrue($entity->accessible('baz'));
  814. $entity->accessible('*', false);
  815. $this->assertFalse($entity->accessible('foo'));
  816. $this->assertFalse($entity->accessible('bar'));
  817. $this->assertFalse($entity->accessible('baz'));
  818. $this->assertFalse($entity->accessible('newOne'));
  819. $entity->accessible('*', true);
  820. $this->assertTrue($entity->accessible('foo'));
  821. $this->assertTrue($entity->accessible('bar'));
  822. $this->assertTrue($entity->accessible('baz'));
  823. $this->assertTrue($entity->accessible('newOne2'));
  824. }
  825. /**
  826. * Tests that only accessible properties can be set
  827. *
  828. * @return void
  829. */
  830. public function testSetWithAccessible() {
  831. $entity = new Entity(['foo' => 1, 'bar' => 2]);
  832. $options = ['guard' => true];
  833. $entity->accessible('foo', true);
  834. $entity->set('bar', 3, $options);
  835. $entity->set('foo', 4, $options);
  836. $this->assertEquals(2, $entity->get('bar'));
  837. $this->assertEquals(4, $entity->get('foo'));
  838. $entity->accessible('bar', true);
  839. $entity->set('bar', 3, $options);
  840. $this->assertEquals(3, $entity->get('bar'));
  841. }
  842. /**
  843. * Tests that only accessible properties can be set
  844. *
  845. * @return void
  846. */
  847. public function testSetWithAccessibleWithArray() {
  848. $entity = new Entity(['foo' => 1, 'bar' => 2]);
  849. $options = ['guard' => true];
  850. $entity->accessible('foo', true);
  851. $entity->set(['bar' => 3, 'foo' => 4], $options);
  852. $this->assertEquals(2, $entity->get('bar'));
  853. $this->assertEquals(4, $entity->get('foo'));
  854. $entity->accessible('bar', true);
  855. $entity->set(['bar' => 3, 'foo' => 5], $options);
  856. $this->assertEquals(3, $entity->get('bar'));
  857. $this->assertEquals(5, $entity->get('foo'));
  858. }
  859. /**
  860. * Test that accessible() and single property setting works.
  861. *
  862. * @return void
  863. */
  864. public function testSetWithAccessibleSingleProperty() {
  865. $entity = new Entity(['foo' => 1, 'bar' => 2]);
  866. $entity->accessible('title', true);
  867. $entity->set(['title' => 'test', 'body' => 'Nope']);
  868. $this->assertEquals('test', $entity->title);
  869. $this->assertNull($entity->body);
  870. $entity->body = 'Yep';
  871. $this->assertEquals('Yep', $entity->body, 'Single set should bypass guards.');
  872. $entity->set('body', 'Yes');
  873. $this->assertEquals('Yes', $entity->body, 'Single set should bypass guards.');
  874. }
  875. /**
  876. * Tests the entity's __toString method
  877. *
  878. * @return void
  879. */
  880. public function testToString() {
  881. $entity = new Entity(['foo' => 1, 'bar' => 2]);
  882. $this->assertEquals(json_encode($entity, JSON_PRETTY_PRINT), (string)$entity);
  883. }
  884. /**
  885. * Tests __debugInfo
  886. *
  887. * @return void
  888. */
  889. public function testDebugInfo() {
  890. $entity = new Entity(['foo' => 'bar'], ['markClean' => true]);
  891. $entity->accessible('name', true);
  892. $entity->virtualProperties(['baz']);
  893. $entity->errors('foo', ['An error']);
  894. $result = $entity->__debugInfo();
  895. $expected = [
  896. 'new' => true,
  897. 'accessible' => ['name'],
  898. 'properties' => ['foo' => 'bar'],
  899. 'dirty' => ['foo' => true],
  900. 'virtual' => ['baz'],
  901. 'errors' => ['foo' => ['An error']]
  902. ];
  903. }
  904. }