TableTest.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909
  1. <?php
  2. /**
  3. * PHP Version 5.4
  4. *
  5. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  6. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  7. *
  8. * Licensed under The MIT License
  9. * For full copyright and license information, please see the LICENSE.txt
  10. * Redistributions of files must retain the above copyright notice.
  11. *
  12. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  13. * @link http://cakephp.org CakePHP(tm) Project
  14. * @since CakePHP(tm) v 3.0.0
  15. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  16. */
  17. namespace Cake\Test\TestCase\ORM;
  18. use Cake\Core\Configure;
  19. use Cake\Database\ConnectionManager;
  20. use Cake\ORM\Table;
  21. use Cake\ORM\TableRegistry;
  22. /**
  23. * Used to test correct class is instantiated when using TableRegistry::get();
  24. */
  25. class UsersTable extends Table {
  26. }
  27. /**
  28. * Tests Table class
  29. *
  30. */
  31. class TableTest extends \Cake\TestSuite\TestCase {
  32. public $fixtures = [
  33. 'core.user', 'core.category', 'core.article', 'core.author',
  34. 'core.tag', 'core.articles_tag'
  35. ];
  36. public function setUp() {
  37. parent::setUp();
  38. $this->connection = ConnectionManager::get('test');
  39. Configure::write('App.namespace', 'TestApp');
  40. }
  41. public function tearDown() {
  42. parent::tearDown();
  43. TableRegistry::clear();
  44. }
  45. /**
  46. * Tests the table method
  47. *
  48. * @return void
  49. */
  50. public function testTableMethod() {
  51. $table = new Table(['table' => 'users']);
  52. $this->assertEquals('users', $table->table());
  53. $table = new UsersTable;
  54. $this->assertEquals('users', $table->table());
  55. $table = $this->getMockBuilder('\Cake\ORM\Table')
  56. ->setMethods(['find'])
  57. ->setMockClassName('SpecialThingTable')
  58. ->getMock();
  59. $this->assertEquals('special_things', $table->table());
  60. $table = new Table(['alias' => 'LoveBoat']);
  61. $this->assertEquals('love_boats', $table->table());
  62. $table->table('other');
  63. $this->assertEquals('other', $table->table());
  64. }
  65. /**
  66. * Tests the alias method
  67. *
  68. * @return void
  69. */
  70. public function testAliasMethod() {
  71. $table = new Table(['alias' => 'users']);
  72. $this->assertEquals('users', $table->alias());
  73. $table = new Table(['table' => 'stuffs']);
  74. $this->assertEquals('stuffs', $table->alias());
  75. $table = new UsersTable;
  76. $this->assertEquals('Users', $table->alias());
  77. $table = $this->getMockBuilder('\Cake\ORM\Table')
  78. ->setMethods(['find'])
  79. ->setMockClassName('SpecialThingTable')
  80. ->getMock();
  81. $this->assertEquals('SpecialThing', $table->alias());
  82. $table->alias('AnotherOne');
  83. $this->assertEquals('AnotherOne', $table->alias());
  84. }
  85. /**
  86. * Tests connection method
  87. *
  88. * @return void
  89. */
  90. public function testConnection() {
  91. $table = new Table(['table' => 'users']);
  92. $this->assertNull($table->connection());
  93. $table->connection($this->connection);
  94. $this->assertSame($this->connection, $table->connection());
  95. }
  96. /**
  97. * Tests primaryKey method
  98. *
  99. * @return void
  100. */
  101. public function testPrimaryKey() {
  102. $table = new Table(['table' => 'users']);
  103. $this->assertEquals('id', $table->primaryKey());
  104. $table->primaryKey('thingID');
  105. $this->assertEquals('thingID', $table->primaryKey());
  106. }
  107. /**
  108. * Tests that name will be selected as a displayField
  109. *
  110. * @return void
  111. */
  112. public function testDisplayFieldName() {
  113. $table = new Table([
  114. 'table' => 'users',
  115. 'schema' => [
  116. 'foo' => ['type' => 'string'],
  117. 'name' => ['type' => 'string']
  118. ]
  119. ]);
  120. $this->assertEquals('name', $table->displayField());
  121. }
  122. /**
  123. * Tests that title will be selected as a displayField
  124. *
  125. * @return void
  126. */
  127. public function testDisplayFieldTitle() {
  128. $table = new Table([
  129. 'table' => 'users',
  130. 'schema' => [
  131. 'foo' => ['type' => 'string'],
  132. 'title' => ['type' => 'string']
  133. ]
  134. ]);
  135. $this->assertEquals('title', $table->displayField());
  136. }
  137. /**
  138. * Tests that no displayField will fallback to primary key
  139. *
  140. * @return void
  141. */
  142. public function testDisplayFallback() {
  143. $table = new Table([
  144. 'table' => 'users',
  145. 'schema' => [
  146. 'id' => ['type' => 'string'],
  147. 'foo' => ['type' => 'string']
  148. ]
  149. ]);
  150. $this->assertEquals('id', $table->displayField());
  151. }
  152. /**
  153. * Tests that displayField can be changed
  154. *
  155. * @return void
  156. */
  157. public function testDisplaySet() {
  158. $table = new Table([
  159. 'table' => 'users',
  160. 'schema' => [
  161. 'id' => ['type' => 'string'],
  162. 'foo' => ['type' => 'string']
  163. ]
  164. ]);
  165. $this->assertEquals('id', $table->displayField());
  166. $table->displayField('foo');
  167. $this->assertEquals('foo', $table->displayField());
  168. }
  169. /**
  170. * Tests schema method
  171. *
  172. * @return void
  173. */
  174. public function testSchema() {
  175. $schema = $this->connection->schemaCollection()->describe('users');
  176. $table = new Table([
  177. 'table' => 'users',
  178. 'connection' => $this->connection,
  179. ]);
  180. $this->assertEquals($schema, $table->schema());
  181. $table = new Table(['table' => 'stuff']);
  182. $table->schema($schema);
  183. $this->assertSame($schema, $table->schema());
  184. $table = new Table(['table' => 'another']);
  185. $schema = ['id' => ['type' => 'integer']];
  186. $table->schema($schema);
  187. $this->assertEquals(
  188. new \Cake\Database\Schema\Table('another', $schema),
  189. $table->schema()
  190. );
  191. }
  192. /**
  193. * Tests that all fields for a table are added by default in a find when no
  194. * other fields are specified
  195. *
  196. * @return void
  197. */
  198. public function testFindAllNoFieldsAndNoHydration() {
  199. $table = new Table([
  200. 'table' => 'users',
  201. 'connection' => $this->connection,
  202. ]);
  203. $results = $table
  204. ->find('all')
  205. ->where(['id IN' => [1, 2]])
  206. ->order('id')
  207. ->hydrate(false)
  208. ->toArray();
  209. $expected = [
  210. [
  211. 'id' => 1,
  212. 'username' => 'mariano',
  213. 'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
  214. 'created' => new \DateTime('2007-03-17 01:16:23'),
  215. 'updated' => new \DateTime('2007-03-17 01:18:31'),
  216. ],
  217. [
  218. 'id' => 2,
  219. 'username' => 'nate',
  220. 'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
  221. 'created' => new \DateTime('2008-03-17 01:18:23'),
  222. 'updated' => new \DateTime('2008-03-17 01:20:31'),
  223. ],
  224. ];
  225. $this->assertEquals($expected, $results);
  226. }
  227. /**
  228. * Tests that it is possible to select only a few fields when finding over a table
  229. *
  230. * @return void
  231. */
  232. public function testFindAllSomeFieldsNoHydration() {
  233. $table = new Table([
  234. 'table' => 'users',
  235. 'connection' => $this->connection,
  236. ]);
  237. $results = $table->find('all')
  238. ->select(['username', 'password'])
  239. ->hydrate(false)
  240. ->order('username')->toArray();
  241. $expected = [
  242. ['username' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99'],
  243. ['username' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99'],
  244. ['username' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99'],
  245. ['username' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99'],
  246. ];
  247. $this->assertSame($expected, $results);
  248. $results = $table->find('all')
  249. ->select(['foo' => 'username', 'password'])
  250. ->order('username')
  251. ->hydrate(false)
  252. ->toArray();
  253. $expected = [
  254. ['foo' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99'],
  255. ['foo' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99'],
  256. ['foo' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99'],
  257. ['foo' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99'],
  258. ];
  259. $this->assertSame($expected, $results);
  260. }
  261. /**
  262. * Tests that the query will automatically casts complex conditions to the correct
  263. * types when the columns belong to the default table
  264. *
  265. * @return void
  266. */
  267. public function testFindAllConditionAutoTypes() {
  268. $table = new Table([
  269. 'table' => 'users',
  270. 'connection' => $this->connection,
  271. ]);
  272. $query = $table->find('all')
  273. ->select(['id', 'username'])
  274. ->where(['created >=' => new \DateTime('2010-01-22 00:00')])
  275. ->hydrate(false)
  276. ->order('id');
  277. $expected = [
  278. ['id' => 3, 'username' => 'larry'],
  279. ['id' => 4, 'username' => 'garrett']
  280. ];
  281. $this->assertSame($expected, $query->toArray());
  282. $query->orWhere(['users.created' => new \DateTime('2008-03-17 01:18:23')]);
  283. $expected = [
  284. ['id' => 2, 'username' => 'nate'],
  285. ['id' => 3, 'username' => 'larry'],
  286. ['id' => 4, 'username' => 'garrett']
  287. ];
  288. $this->assertSame($expected, $query->toArray());
  289. }
  290. /**
  291. * Test that beforeFind events can mutate the query.
  292. *
  293. * @return void
  294. */
  295. public function testFindBeforeFindEventMutateQuery() {
  296. $table = new Table([
  297. 'table' => 'users',
  298. 'connection' => $this->connection,
  299. ]);
  300. $table->getEventManager()->attach(function ($event, $query, $options) {
  301. $query->limit(1);
  302. }, 'Model.beforeFind');
  303. $result = $table->find('all')->execute();
  304. $this->assertCount(1, $result, 'Should only have 1 record, limit 1 applied.');
  305. }
  306. /**
  307. * Test that beforeFind events are fired and can stop the find and
  308. * return custom results.
  309. *
  310. * @return void
  311. */
  312. public function testFindBeforeFindEventOverrideReturn() {
  313. $table = new Table([
  314. 'table' => 'users',
  315. 'connection' => $this->connection,
  316. ]);
  317. $expected = ['One', 'Two', 'Three'];
  318. $table->getEventManager()->attach(function ($event, $query, $options) use ($expected) {
  319. $query->setResult($expected);
  320. $event->stopPropagation();
  321. }, 'Model.beforeFind');
  322. $query = $table->find('all');
  323. $query->limit(1);
  324. $this->assertEquals($expected, $query->execute());
  325. }
  326. /**
  327. * Tests that belongsTo() creates and configures correctly the association
  328. *
  329. * @return void
  330. */
  331. public function testBelongsTo() {
  332. $options = ['foreignKey' => 'fake_id', 'conditions' => ['a' => 'b']];
  333. $table = new Table(['table' => 'dates']);
  334. $belongsTo = $table->belongsTo('user', $options);
  335. $this->assertInstanceOf('\Cake\ORM\Association\BelongsTo', $belongsTo);
  336. $this->assertSame($belongsTo, $table->association('user'));
  337. $this->assertEquals('user', $belongsTo->name());
  338. $this->assertEquals('fake_id', $belongsTo->foreignKey());
  339. $this->assertEquals(['a' => 'b'], $belongsTo->conditions());
  340. $this->assertSame($table, $belongsTo->source());
  341. }
  342. /**
  343. * Tests that hasOne() creates and configures correctly the association
  344. *
  345. * @return void
  346. */
  347. public function testHasOne() {
  348. $options = ['foreignKey' => 'user_id', 'conditions' => ['b' => 'c']];
  349. $table = new Table(['table' => 'users']);
  350. $hasOne = $table->hasOne('profile', $options);
  351. $this->assertInstanceOf('\Cake\ORM\Association\HasOne', $hasOne);
  352. $this->assertSame($hasOne, $table->association('profile'));
  353. $this->assertEquals('profile', $hasOne->name());
  354. $this->assertEquals('user_id', $hasOne->foreignKey());
  355. $this->assertEquals(['b' => 'c'], $hasOne->conditions());
  356. $this->assertSame($table, $hasOne->source());
  357. }
  358. /**
  359. * Tests that hasMany() creates and configures correctly the association
  360. *
  361. * @return void
  362. */
  363. public function testHasMany() {
  364. $options = [
  365. 'foreignKey' => 'author_id',
  366. 'conditions' => ['b' => 'c'],
  367. 'sort' => ['foo' => 'asc']
  368. ];
  369. $table = new Table(['table' => 'authors']);
  370. $hasMany = $table->hasMany('article', $options);
  371. $this->assertInstanceOf('\Cake\ORM\Association\HasMany', $hasMany);
  372. $this->assertSame($hasMany, $table->association('article'));
  373. $this->assertEquals('article', $hasMany->name());
  374. $this->assertEquals('author_id', $hasMany->foreignKey());
  375. $this->assertEquals(['b' => 'c'], $hasMany->conditions());
  376. $this->assertEquals(['foo' => 'asc'], $hasMany->sort());
  377. $this->assertSame($table, $hasMany->source());
  378. }
  379. /**
  380. * Tests that BelongsToMany() creates and configures correctly the association
  381. *
  382. * @return void
  383. */
  384. public function testBelongsToMany() {
  385. $options = [
  386. 'foreignKey' => 'thing_id',
  387. 'joinTable' => 'things_tags',
  388. 'conditions' => ['b' => 'c'],
  389. 'sort' => ['foo' => 'asc']
  390. ];
  391. $table = new Table(['table' => 'authors', 'connection' => $this->connection]);
  392. $belongsToMany = $table->belongsToMany('tag', $options);
  393. $this->assertInstanceOf('\Cake\ORM\Association\BelongsToMany', $belongsToMany);
  394. $this->assertSame($belongsToMany, $table->association('tag'));
  395. $this->assertEquals('tag', $belongsToMany->name());
  396. $this->assertEquals('thing_id', $belongsToMany->foreignKey());
  397. $this->assertEquals(['b' => 'c'], $belongsToMany->conditions());
  398. $this->assertEquals(['foo' => 'asc'], $belongsToMany->sort());
  399. $this->assertSame($table, $belongsToMany->source());
  400. $this->assertSame('things_tags', $belongsToMany->pivot()->table());
  401. }
  402. /**
  403. * Test basic multi row updates.
  404. *
  405. * @return void
  406. */
  407. public function testUpdateAll() {
  408. $table = new Table([
  409. 'table' => 'users',
  410. 'connection' => $this->connection,
  411. ]);
  412. $fields = ['username' => 'mark'];
  413. $result = $table->updateAll($fields, ['id <' => 4]);
  414. $this->assertTrue($result);
  415. $result = $table->find('all')
  416. ->select(['username'])
  417. ->order(['id' => 'asc'])
  418. ->hydrate(false)
  419. ->toArray();
  420. $expected = array_fill(0, 3, $fields);
  421. $expected[] = ['username' => 'garrett'];
  422. $this->assertEquals($expected, $result);
  423. }
  424. /**
  425. * Test that exceptions from the Query bubble up.
  426. *
  427. * @expectedException Cake\Database\Exception
  428. */
  429. public function testUpdateAllFailure() {
  430. $table = $this->getMock(
  431. 'Cake\ORM\Table',
  432. ['_buildQuery'],
  433. [['table' => 'users']]
  434. );
  435. $query = $this->getMock('Cake\ORM\Query', ['executeStatement'], [$this->connection, null]);
  436. $table->expects($this->once())
  437. ->method('_buildQuery')
  438. ->will($this->returnValue($query));
  439. $query->expects($this->once())
  440. ->method('executeStatement')
  441. ->will($this->throwException(new \Cake\Database\Exception('Not good')));
  442. $table->updateAll(['username' => 'mark'], []);
  443. }
  444. /**
  445. * Test deleting many records.
  446. *
  447. * @return void
  448. */
  449. public function testDeleteAll() {
  450. $table = new Table([
  451. 'table' => 'users',
  452. 'connection' => $this->connection,
  453. ]);
  454. $result = $table->deleteAll(['id <' => 4]);
  455. $this->assertTrue($result);
  456. $result = $table->find('all')->toArray();
  457. $this->assertCount(1, $result, 'Only one record should remain');
  458. $this->assertEquals(4, $result[0]['id']);
  459. }
  460. /**
  461. * Test that exceptions from the Query bubble up.
  462. *
  463. * @expectedException Cake\Database\Exception
  464. */
  465. public function testDeleteAllFailure() {
  466. $table = $this->getMock(
  467. 'Cake\ORM\Table',
  468. ['_buildQuery'],
  469. [['table' => 'users', 'connection' => $this->connection]]
  470. );
  471. $query = $this->getMock('Cake\ORM\Query', ['executeStatement'], [$this->connection, null]);
  472. $table->expects($this->once())
  473. ->method('_buildQuery')
  474. ->will($this->returnValue($query));
  475. $query->expects($this->once())
  476. ->method('executeStatement')
  477. ->will($this->throwException(new \Cake\Database\Exception('Not good')));
  478. $table->deleteAll(['id >' => 4]);
  479. }
  480. /**
  481. * Tests that array options are passed to the query object using applyOptions
  482. *
  483. * @return void
  484. */
  485. public function testFindApplyOptions() {
  486. $table = $this->getMock(
  487. 'Cake\ORM\Table',
  488. ['_buildQuery'],
  489. [['table' => 'users', 'connection' => $this->connection]]
  490. );
  491. $query = $this->getMock('Cake\ORM\Query', [], [$this->connection, $table]);
  492. $table->expects($this->once())
  493. ->method('_buildQuery')
  494. ->will($this->returnValue($query));
  495. $options = ['fields' => ['a', 'b'], 'connections' => ['a >' => 1]];
  496. $query->expects($this->any())
  497. ->method('select')
  498. ->will($this->returnSelf());
  499. $query->expects($this->once())
  500. ->method('applyOptions')
  501. ->with($options);
  502. $table->find('all', $options);
  503. }
  504. /**
  505. * Tests find('list')
  506. *
  507. * @return void
  508. */
  509. public function testFindListNoHydration() {
  510. $table = new Table([
  511. 'table' => 'users',
  512. 'connection' => $this->connection,
  513. ]);
  514. $table->displayField('username');
  515. $query = $table->find('list', ['fields' => ['id', 'username']])
  516. ->hydrate(false)
  517. ->order('id');
  518. $expected = [
  519. 1 => 'mariano',
  520. 2 => 'nate',
  521. 3 => 'larry',
  522. 4 => 'garrett'
  523. ];
  524. $this->assertSame($expected, $query->toArray());
  525. $query = $table->find('list', ['groupField' => 'odd'])
  526. ->select(['id', 'username', 'odd' => 'id % 2 = 0'])
  527. ->hydrate(false)
  528. ->order('id');
  529. $expected = [
  530. 0 => [
  531. 1 => 'mariano',
  532. 3 => 'larry'
  533. ],
  534. 1 => [
  535. 2 => 'nate',
  536. 4 => 'garrett'
  537. ]
  538. ];
  539. $this->assertSame($expected, $query->toArray());
  540. }
  541. /**
  542. * Tests find('threaded')
  543. *
  544. * @return void
  545. */
  546. public function testFindThreadedNoHydration() {
  547. $table = new Table([
  548. 'table' => 'categories',
  549. 'connection' => $this->connection,
  550. ]);
  551. $expected = [
  552. [
  553. 'id' => 1,
  554. 'parent_id' => 0,
  555. 'name' => 'Category 1',
  556. 'children' => [
  557. [
  558. 'id' => 2,
  559. 'parent_id' => 1,
  560. 'name' => 'Category 1.1',
  561. 'children' => [
  562. [
  563. 'id' => 7,
  564. 'parent_id' => 2,
  565. 'name' => 'Category 1.1.1',
  566. 'children' => []
  567. ],
  568. [
  569. 'id' => 8,
  570. 'parent_id' => '2',
  571. 'name' => 'Category 1.1.2',
  572. 'children' => []
  573. ]
  574. ],
  575. ],
  576. [
  577. 'id' => 3,
  578. 'parent_id' => '1',
  579. 'name' => 'Category 1.2',
  580. 'children' => []
  581. ],
  582. ]
  583. ],
  584. [
  585. 'id' => 4,
  586. 'parent_id' => 0,
  587. 'name' => 'Category 2',
  588. 'children' => []
  589. ],
  590. [
  591. 'id' => 5,
  592. 'parent_id' => 0,
  593. 'name' => 'Category 3',
  594. 'children' => [
  595. [
  596. 'id' => '6',
  597. 'parent_id' => '5',
  598. 'name' => 'Category 3.1',
  599. 'children' => []
  600. ]
  601. ]
  602. ]
  603. ];
  604. $results = $table->find('all')
  605. ->select(['id', 'parent_id', 'name'])
  606. ->hydrate(false)
  607. ->threaded()
  608. ->toArray();
  609. $this->assertEquals($expected, $results);
  610. }
  611. /**
  612. * Tests that finders can be called directly
  613. *
  614. * @return void
  615. */
  616. public function testCallingFindersDirectly() {
  617. $table = $this->getMock('\Cake\ORM\Table', ['find'], [], '', false);
  618. $query = $this->getMock('\Cake\ORM\Query', [], [$this->connection, $table]);
  619. $table->expects($this->once())
  620. ->method('find')
  621. ->with('list', [])
  622. ->will($this->returnValue($query));
  623. $this->assertSame($query, $table->list());
  624. $table = $this->getMock('\Cake\ORM\Table', ['find'], [], '', false);
  625. $table->expects($this->once())
  626. ->method('find')
  627. ->with('threaded', ['order' => ['name' => 'ASC']])
  628. ->will($this->returnValue($query));
  629. $this->assertSame($query, $table->threaded(['order' => ['name' => 'ASC']]));
  630. }
  631. /**
  632. * Tests that finders can be stacked
  633. *
  634. * @return void
  635. */
  636. public function testStackingFinders() {
  637. $table = $this->getMock('\Cake\ORM\Table', ['find', 'findList'], [], '', false);
  638. $params = [$this->connection, $table];
  639. $query = $this->getMock('\Cake\ORM\Query', ['addDefaultTypes'], $params);
  640. $table->expects($this->once())
  641. ->method('find')
  642. ->with('threaded', ['order' => ['name' => 'ASC']])
  643. ->will($this->returnValue($query));
  644. $table->expects($this->once())
  645. ->method('findList')
  646. ->with($query, ['keyPath' => 'id'])
  647. ->will($this->returnValue($query));
  648. $result = $table
  649. ->threaded(['order' => ['name' => 'ASC']])
  650. ->list(['keyPath' => 'id']);
  651. $this->assertSame($query, $result);
  652. }
  653. /**
  654. * Tests find('threaded') with hydrated results
  655. *
  656. * @return void
  657. */
  658. public function testFindThreadedHydrated() {
  659. $table = new Table([
  660. 'table' => 'categories',
  661. 'connection' => $this->connection,
  662. ]);
  663. $results = $table->find('all')
  664. ->threaded()
  665. ->select(['id', 'parent_id', 'name'])
  666. ->toArray();
  667. $this->assertEquals(1, $results[0]->id);
  668. $expected = [
  669. 'id' => 8,
  670. 'parent_id' => 2,
  671. 'name' => 'Category 1.1.2',
  672. 'children' => []
  673. ];
  674. $this->assertEquals($expected, $results[0]->children[0]->children[1]->toArray());
  675. }
  676. /**
  677. * Tests find('list') with hydrated records
  678. *
  679. * @return void
  680. */
  681. public function testFindListHydrated() {
  682. $table = new Table([
  683. 'table' => 'users',
  684. 'connection' => $this->connection,
  685. ]);
  686. $table->displayField('username');
  687. $query = $table
  688. ->find('list', ['fields' => ['id', 'username']])
  689. ->order('id');
  690. $expected = [
  691. 1 => 'mariano',
  692. 2 => 'nate',
  693. 3 => 'larry',
  694. 4 => 'garrett'
  695. ];
  696. $this->assertSame($expected, $query->toArray());
  697. $query = $table->find('list', ['groupField' => 'odd'])
  698. ->select(['id', 'username', 'odd' => 'id % 2 = 0'])
  699. ->hydrate(true)
  700. ->order('id');
  701. $expected = [
  702. 0 => [
  703. 1 => 'mariano',
  704. 3 => 'larry'
  705. ],
  706. 1 => [
  707. 2 => 'nate',
  708. 4 => 'garrett'
  709. ]
  710. ];
  711. $this->assertSame($expected, $query->toArray());
  712. }
  713. public function testEntityClassDefault() {
  714. $table = new Table();
  715. $this->assertEquals('\Cake\ORM\Entity', $table->entityClass());
  716. }
  717. /**
  718. * Tests that using a simple string for entityClass will try to
  719. * load the class from the App namespace
  720. *
  721. * @return void
  722. */
  723. public function testRepositoryClassInAPP() {
  724. $class = $this->getMockClass('\Cake\ORM\Entity');
  725. class_alias($class, 'TestApp\Model\Entity\TestUser');
  726. $table = new Table();
  727. $this->assertEquals('TestApp\Model\Entity\TestUser', $table->entityClass('TestUser'));
  728. }
  729. /**
  730. * Tests that using a simple string for entityClass will try to
  731. * load the class from the Plugin namespace when using plugin notation
  732. *
  733. * @return void
  734. */
  735. public function testRepositoryClassInPlugin() {
  736. $class = $this->getMockClass('\Cake\ORM\Entity');
  737. class_alias($class, 'MyPlugin\Model\Entity\SuperUser');
  738. $table = new Table();
  739. $this->assertEquals(
  740. 'MyPlugin\Model\Entity\SuperUser',
  741. $table->entityClass('MyPlugin.SuperUser')
  742. );
  743. }
  744. /**
  745. * Tests that using a simple string for entityClass will throw an exception
  746. * when the class does not exist in the namespace
  747. *
  748. * @expectedException Cake\ORM\Error\MissingEntityException
  749. * @expectedExceptionMessage Entity class FooUser could not be found.
  750. * @return void
  751. */
  752. public function testRepositoryClassNonExisting() {
  753. $table = new Table;
  754. $this->assertFalse($table->entityClass('FooUser'));
  755. }
  756. /**
  757. * Tests getting the entityClass based on conventions for the entity
  758. * namespace
  759. *
  760. * @return void
  761. */
  762. public function testRepositoryClassConventionForAPP() {
  763. $table = new \TestApp\Model\Repository\ArticleTable;
  764. $this->assertEquals('TestApp\Model\Entity\Article', $table->entityClass());
  765. }
  766. /**
  767. * Tests setting a entity class object using the setter method
  768. *
  769. * @return void
  770. */
  771. public function testSetEntityClass() {
  772. $table = new Table;
  773. $class = '\\' . $this->getMockClass('\Cake\ORM\Entity');
  774. $table->entityClass($class);
  775. $this->assertEquals($class, $table->entityClass());
  776. }
  777. /**
  778. * Proves that associations, even though they are lazy loaded, will fetch
  779. * records using the correct table class and hydrate with the correct entity
  780. *
  781. * @return void
  782. */
  783. public function testReciprocalBelongsToLoading() {
  784. $table = new \TestApp\Model\Repository\ArticleTable([
  785. 'connection' => $this->connection,
  786. ]);
  787. $result = $table->find('all')->contain(['author'])->first();
  788. $this->assertInstanceOf('TestApp\Model\Entity\Author', $result->author);
  789. }
  790. /**
  791. * Proves that associations, even though they are lazy loaded, will fetch
  792. * records using the correct table class and hydrate with the correct entity
  793. *
  794. * @return void
  795. */
  796. public function testReciprocalHasManyLoading() {
  797. $table = new \TestApp\Model\Repository\ArticleTable([
  798. 'connection' => $this->connection,
  799. ]);
  800. $result = $table->find('all')->contain(['author' => ['article']])->first();
  801. $this->assertCount(2, $result->author->article);
  802. foreach ($result->author->article as $article) {
  803. $this->assertInstanceOf('TestApp\Model\Entity\Article', $article);
  804. }
  805. }
  806. /**
  807. * Tests that the correct table and entity are loaded for the pivot association in
  808. * a belongsToMany setup
  809. *
  810. * @return void
  811. */
  812. public function testReciprocalBelongsToMany() {
  813. $table = new \TestApp\Model\Repository\ArticleTable([
  814. 'connection' => $this->connection,
  815. ]);
  816. $result = $table->find('all')->contain(['tag'])->first();
  817. $this->assertInstanceOf('TestApp\Model\Entity\Tag', $result->tags[0]);
  818. $this->assertInstanceOf('TestApp\Model\Entity\ArticlesTag', $result->tags[0]->extraInfo);
  819. }
  820. /**
  821. * Tests that it is possible to insert a new row using the save method
  822. *
  823. * @return void
  824. */
  825. public function testSaveNewEntity() {
  826. $entity = new \Cake\ORM\Entity([
  827. 'username' => 'superuser',
  828. 'password' => 'root',
  829. 'created' => new \DateTime('2013-10-10 00:00'),
  830. 'updated' => new \DateTime('2013-10-10 00:00')
  831. ]);
  832. $table = TableRegistry::get('user');
  833. $this->assertSame($entity, $table->save($entity));
  834. $this->assertEquals($entity->id, 5);
  835. $row = $table->find('all')->where(['id' => 5])->first();
  836. $this->assertEquals($entity->toArray(), $row->toArray());
  837. }
  838. }