AssociationCollectionTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  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 http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\ORM;
  16. use Cake\ORM\AssociationCollection;
  17. use Cake\ORM\Association\BelongsTo;
  18. use Cake\ORM\Association\BelongsToMany;
  19. use Cake\ORM\Entity;
  20. use Cake\TestSuite\TestCase;
  21. /**
  22. * AssociationCollection test case.
  23. */
  24. class AssociationCollectionTest extends TestCase
  25. {
  26. /**
  27. * setup
  28. *
  29. * @return void
  30. */
  31. public function setUp()
  32. {
  33. parent::setUp();
  34. $this->associations = new AssociationCollection();
  35. }
  36. /**
  37. * Test the simple add/has and get methods.
  38. *
  39. * @return void
  40. */
  41. public function testAddHasRemoveAndGet()
  42. {
  43. $this->assertFalse($this->associations->has('users'));
  44. $this->assertFalse($this->associations->has('Users'));
  45. $this->assertNull($this->associations->get('users'));
  46. $this->assertNull($this->associations->get('Users'));
  47. $belongsTo = new BelongsTo('');
  48. $this->assertSame($belongsTo, $this->associations->add('Users', $belongsTo));
  49. $this->assertTrue($this->associations->has('users'));
  50. $this->assertTrue($this->associations->has('Users'));
  51. $this->assertSame($belongsTo, $this->associations->get('users'));
  52. $this->assertSame($belongsTo, $this->associations->get('Users'));
  53. $this->assertNull($this->associations->remove('Users'));
  54. $this->assertFalse($this->associations->has('users'));
  55. $this->assertFalse($this->associations->has('Users'));
  56. $this->assertNull($this->associations->get('users'));
  57. $this->assertNull($this->associations->get('Users'));
  58. }
  59. /**
  60. * Test removeAll method
  61. *
  62. * @return void
  63. */
  64. public function testRemoveAll()
  65. {
  66. $this->assertEmpty($this->associations->keys());
  67. $belongsTo = new BelongsTo('');
  68. $this->assertSame($belongsTo, $this->associations->add('Users', $belongsTo));
  69. $belongsToMany = new BelongsToMany('');
  70. $this->assertSame($belongsToMany, $this->associations->add('Cart', $belongsToMany));
  71. $this->associations->removeAll();
  72. $this->assertEmpty($this->associations->keys());
  73. }
  74. /**
  75. * Test getting associations by property.
  76. *
  77. * @return void
  78. */
  79. public function testGetByProperty()
  80. {
  81. $table = $this->getMock('Cake\ORM\Table', ['table'], [[]]);
  82. $table->schema([]);
  83. $belongsTo = new BelongsTo('Users', [
  84. 'sourceTable' => $table
  85. ]);
  86. $this->assertEquals('user', $belongsTo->property());
  87. $this->associations->add('Users', $belongsTo);
  88. $this->assertNull($this->associations->get('user'));
  89. $this->assertSame($belongsTo, $this->associations->getByProperty('user'));
  90. }
  91. /**
  92. * Test associations with plugin names.
  93. *
  94. * @return void
  95. */
  96. public function testAddHasRemoveGetWithPlugin()
  97. {
  98. $this->assertFalse($this->associations->has('Photos.Photos'));
  99. $this->assertFalse($this->associations->has('Photos'));
  100. $belongsTo = new BelongsTo('');
  101. $this->assertSame($belongsTo, $this->associations->add('Photos.Photos', $belongsTo));
  102. $this->assertTrue($this->associations->has('Photos'));
  103. $this->assertFalse($this->associations->has('Photos.Photos'));
  104. }
  105. /**
  106. * Test keys()
  107. *
  108. * @return void
  109. */
  110. public function testKeys()
  111. {
  112. $belongsTo = new BelongsTo('');
  113. $this->associations->add('Users', $belongsTo);
  114. $this->associations->add('Categories', $belongsTo);
  115. $this->assertEquals(['users', 'categories'], $this->associations->keys());
  116. $this->associations->remove('Categories');
  117. $this->assertEquals(['users'], $this->associations->keys());
  118. }
  119. /**
  120. * Test getting association names by type.
  121. *
  122. * @return void
  123. */
  124. public function testType()
  125. {
  126. $belongsTo = new BelongsTo('');
  127. $this->associations->add('Users', $belongsTo);
  128. $belongsToMany = new BelongsToMany('');
  129. $this->associations->add('Tags', $belongsToMany);
  130. $this->assertSame([$belongsTo], $this->associations->type('BelongsTo'));
  131. $this->assertSame([$belongsToMany], $this->associations->type('BelongsToMany'));
  132. $this->assertSame([], $this->associations->type('HasMany'));
  133. $this->assertSame(
  134. [$belongsTo, $belongsToMany],
  135. $this->associations->type(['BelongsTo', 'BelongsToMany'])
  136. );
  137. }
  138. /**
  139. * test cascading deletes.
  140. *
  141. * @return void
  142. */
  143. public function testCascadeDelete()
  144. {
  145. $mockOne = $this->getMock('Cake\ORM\Association\BelongsTo', [], ['']);
  146. $mockTwo = $this->getMock('Cake\ORM\Association\HasMany', [], ['']);
  147. $entity = new Entity();
  148. $options = ['option' => 'value'];
  149. $this->associations->add('One', $mockOne);
  150. $this->associations->add('Two', $mockTwo);
  151. $mockOne->expects($this->once())
  152. ->method('cascadeDelete')
  153. ->with($entity, $options);
  154. $mockTwo->expects($this->once())
  155. ->method('cascadeDelete')
  156. ->with($entity, $options);
  157. $this->assertNull($this->associations->cascadeDelete($entity, $options));
  158. }
  159. /**
  160. * Test saving parent associations
  161. *
  162. * @return void
  163. */
  164. public function testSaveParents()
  165. {
  166. $table = $this->getMock('Cake\ORM\Table', ['table'], [[]]);
  167. $table->schema([]);
  168. $mockOne = $this->getMock(
  169. 'Cake\ORM\Association\BelongsTo',
  170. ['saveAssociated'],
  171. ['Parent', [
  172. 'sourceTable' => $table,
  173. ]]
  174. );
  175. $mockTwo = $this->getMock(
  176. 'Cake\ORM\Association\HasMany',
  177. ['saveAssociated'],
  178. ['Child', [
  179. 'sourceTable' => $table
  180. ]]
  181. );
  182. $this->associations->add('Parent', $mockOne);
  183. $this->associations->add('Child', $mockTwo);
  184. $entity = new Entity();
  185. $entity->set('parent', ['key' => 'value']);
  186. $entity->set('child', ['key' => 'value']);
  187. $options = ['option' => 'value'];
  188. $mockOne->expects($this->once())
  189. ->method('saveAssociated')
  190. ->with($entity, $options)
  191. ->will($this->returnValue(true));
  192. $mockTwo->expects($this->never())
  193. ->method('saveAssociated');
  194. $result = $this->associations->saveParents(
  195. $table,
  196. $entity,
  197. ['Parent', 'Child'],
  198. $options
  199. );
  200. $this->assertTrue($result, 'Save should work.');
  201. }
  202. /**
  203. * Test saving filtered parent associations.
  204. *
  205. * @return void
  206. */
  207. public function testSaveParentsFiltered()
  208. {
  209. $table = $this->getMock('Cake\ORM\Table', ['table'], [[]]);
  210. $table->schema([]);
  211. $mockOne = $this->getMock(
  212. 'Cake\ORM\Association\BelongsTo',
  213. ['saveAssociated'],
  214. ['Parents', [
  215. 'sourceTable' => $table,
  216. ]]
  217. );
  218. $mockTwo = $this->getMock(
  219. 'Cake\ORM\Association\BelongsTo',
  220. ['saveAssociated'],
  221. ['Categories', [
  222. 'sourceTable' => $table
  223. ]]
  224. );
  225. $this->associations->add('Parents', $mockOne);
  226. $this->associations->add('Categories', $mockTwo);
  227. $entity = new Entity();
  228. $entity->set('parent', ['key' => 'value']);
  229. $entity->set('category', ['key' => 'value']);
  230. $options = ['atomic' => true];
  231. $mockOne->expects($this->once())
  232. ->method('saveAssociated')
  233. ->with($entity, ['atomic' => true, 'associated' => ['Others']])
  234. ->will($this->returnValue(true));
  235. $mockTwo->expects($this->never())
  236. ->method('saveAssociated');
  237. $result = $this->associations->saveParents(
  238. $table,
  239. $entity,
  240. ['Parents' => ['associated' => ['Others']]],
  241. $options
  242. );
  243. $this->assertTrue($result, 'Save should work.');
  244. }
  245. /**
  246. * Test saving filtered child associations.
  247. *
  248. * @return void
  249. */
  250. public function testSaveChildrenFiltered()
  251. {
  252. $table = $this->getMock('Cake\ORM\Table', ['table'], [[]]);
  253. $table->schema([]);
  254. $mockOne = $this->getMock(
  255. 'Cake\ORM\Association\HasMany',
  256. ['saveAssociated'],
  257. ['Comments', [
  258. 'sourceTable' => $table,
  259. ]]
  260. );
  261. $mockTwo = $this->getMock(
  262. 'Cake\ORM\Association\HasOne',
  263. ['saveAssociated'],
  264. ['Profiles', [
  265. 'sourceTable' => $table
  266. ]]
  267. );
  268. $this->associations->add('Comments', $mockOne);
  269. $this->associations->add('Profiles', $mockTwo);
  270. $entity = new Entity();
  271. $entity->set('comments', ['key' => 'value']);
  272. $entity->set('profile', ['key' => 'value']);
  273. $options = ['atomic' => true];
  274. $mockOne->expects($this->once())
  275. ->method('saveAssociated')
  276. ->with($entity, $options + ['associated' => ['Other']])
  277. ->will($this->returnValue(true));
  278. $mockTwo->expects($this->never())
  279. ->method('saveAssociated');
  280. $result = $this->associations->saveChildren(
  281. $table,
  282. $entity,
  283. ['Comments' => ['associated' => ['Other']]],
  284. $options
  285. );
  286. $this->assertTrue($result, 'Should succeed.');
  287. }
  288. /**
  289. * Test exceptional case.
  290. *
  291. * @expectedException \InvalidArgumentException
  292. * @expectedExceptionMessage Cannot save Profiles, it is not associated to Users
  293. */
  294. public function testErrorOnUnknownAlias()
  295. {
  296. $table = $this->getMock(
  297. 'Cake\ORM\Table',
  298. ['save'],
  299. [['alias' => 'Users']]
  300. );
  301. $entity = new Entity();
  302. $entity->set('profile', ['key' => 'value']);
  303. $this->associations->saveChildren(
  304. $table,
  305. $entity,
  306. ['Profiles'],
  307. ['atomic' => true]
  308. );
  309. }
  310. /**
  311. * Tests the normalizeKeys method
  312. *
  313. * @return void
  314. */
  315. public function testNormalizeKeys()
  316. {
  317. $this->assertSame([], $this->associations->normalizeKeys([]));
  318. $this->assertSame([], $this->associations->normalizeKeys(false));
  319. $assocs = ['a', 'b', 'd' => ['something']];
  320. $expected = ['a' => [], 'b' => [], 'd' => ['something']];
  321. $this->assertSame($expected, $this->associations->normalizeKeys($assocs));
  322. $belongsTo = new BelongsTo('');
  323. $this->associations->add('users', $belongsTo);
  324. $this->associations->add('categories', $belongsTo);
  325. $expected = ['users' => [], 'categories' => []];
  326. $this->assertSame($expected, $this->associations->normalizeKeys(true));
  327. }
  328. /**
  329. * Ensure that the association collection can be iterated.
  330. *
  331. * @return void
  332. */
  333. public function testAssociationsCanBeIterated()
  334. {
  335. $belongsTo = new BelongsTo('');
  336. $this->associations->add('Users', $belongsTo);
  337. $belongsToMany = new BelongsToMany('');
  338. $this->associations->add('Cart', $belongsToMany);
  339. $expected = ['users' => $belongsTo, 'cart' => $belongsToMany];
  340. $result = iterator_to_array($this->associations, true);
  341. $this->assertSame($expected, $result);
  342. }
  343. }