CollectionTest.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  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\Collection;
  16. use ArrayObject;
  17. use Cake\Collection\Collection;
  18. use Cake\TestSuite\TestCase;
  19. /**
  20. * CollectionTest
  21. *
  22. */
  23. class CollectionTest extends TestCase {
  24. /**
  25. * Tests that it is possible to convert an array into a collection
  26. *
  27. * @return void
  28. */
  29. public function testArrayIsWrapped() {
  30. $items = [1, 2, 3];
  31. $collection = new Collection($items);
  32. $this->assertEquals($items, iterator_to_array($collection));
  33. }
  34. /**
  35. * Tests that it is possible to convert an iterator into a collection
  36. *
  37. * @return void
  38. */
  39. public function testIteratorIsWrapped() {
  40. $items = new \ArrayObject([1, 2, 3]);
  41. $collection = new Collection($items);
  42. $this->assertEquals(iterator_to_array($items), iterator_to_array($collection));
  43. }
  44. /**
  45. * Test running a method over all elements in the collection
  46. *
  47. * @return void
  48. */
  49. public function testEeach() {
  50. $items = ['a' => 1, 'b' => 2, 'c' => 3];
  51. $collection = new Collection($items);
  52. $callable = $this->getMock('stdClass', ['__invoke']);
  53. $callable->expects($this->at(0))
  54. ->method('__invoke')
  55. ->with(1, 'a');
  56. $callable->expects($this->at(1))
  57. ->method('__invoke')
  58. ->with(2, 'b');
  59. $callable->expects($this->at(2))
  60. ->method('__invoke')
  61. ->with(3, 'c');
  62. $collection->each($callable);
  63. }
  64. /**
  65. * Tests that it is possible to chain filter() as it returns a collection object
  66. *
  67. * @return void
  68. */
  69. public function testFilterChaining() {
  70. $this->assertFalse(defined('HHVM_VERSION'), 'Broken on HHVM');
  71. $items = ['a' => 1, 'b' => 2, 'c' => 3];
  72. $collection = new Collection($items);
  73. $callable = $this->getMock('stdClass', ['__invoke']);
  74. $callable->expects($this->once())
  75. ->method('__invoke')
  76. ->with(3, 'c');
  77. $filtered = $collection->filter(function ($value, $key, $iterator) {
  78. return $value > 2;
  79. });
  80. $this->assertInstanceOf('\Cake\Collection\Collection', $filtered);
  81. $filtered->each($callable);
  82. }
  83. /**
  84. * Tests reject
  85. *
  86. * @return void
  87. */
  88. public function testReject() {
  89. $this->assertFalse(defined('HHVM_VERSION'), 'Broken on HHVM');
  90. $items = ['a' => 1, 'b' => 2, 'c' => 3];
  91. $collection = new Collection($items);
  92. $result = $collection->reject(function ($v, $k, $items) use ($collection) {
  93. $this->assertSame($collection, $items);
  94. return $v > 2;
  95. });
  96. $this->assertEquals(['a' => 1, 'b' => 2], iterator_to_array($result));
  97. $this->assertInstanceOf('\Cake\Collection\Collection', $result);
  98. }
  99. /**
  100. * Tests every when the callback returns true for all elements
  101. *
  102. * @return void
  103. */
  104. public function testEveryReturnTrue() {
  105. $items = ['a' => 1, 'b' => 2, 'c' => 3];
  106. $collection = new Collection($items);
  107. $callable = $this->getMock('stdClass', ['__invoke']);
  108. $callable->expects($this->at(0))
  109. ->method('__invoke')
  110. ->with(1, 'a')
  111. ->will($this->returnValue(true));
  112. $callable->expects($this->at(1))
  113. ->method('__invoke')
  114. ->with(2, 'b')
  115. ->will($this->returnValue(true));
  116. $callable->expects($this->at(2))
  117. ->method('__invoke')
  118. ->with(3, 'c')
  119. ->will($this->returnValue(true));
  120. $this->assertTrue($collection->every($callable));
  121. }
  122. /**
  123. * Tests every when the callback returns false for one of the elements
  124. *
  125. * @return void
  126. */
  127. public function testEveryReturnFalse() {
  128. $items = ['a' => 1, 'b' => 2, 'c' => 3];
  129. $collection = new Collection($items);
  130. $callable = $this->getMock('stdClass', ['__invoke']);
  131. $callable->expects($this->at(0))
  132. ->method('__invoke')
  133. ->with(1, 'a')
  134. ->will($this->returnValue(true));
  135. $callable->expects($this->at(1))
  136. ->method('__invoke')
  137. ->with(2, 'b')
  138. ->will($this->returnValue(false));
  139. $callable->expects($this->exactly(2))->method('__invoke');
  140. $this->assertFalse($collection->every($callable));
  141. }
  142. /**
  143. * Tests some() when one of the calls return true
  144. *
  145. * @return void
  146. */
  147. public function testSomeReturnTrue() {
  148. $items = ['a' => 1, 'b' => 2, 'c' => 3];
  149. $collection = new Collection($items);
  150. $callable = $this->getMock('stdClass', ['__invoke']);
  151. $callable->expects($this->at(0))
  152. ->method('__invoke')
  153. ->with(1, 'a')
  154. ->will($this->returnValue(false));
  155. $callable->expects($this->at(1))
  156. ->method('__invoke')
  157. ->with(2, 'b')
  158. ->will($this->returnValue(true));
  159. $callable->expects($this->exactly(2))->method('__invoke');
  160. $this->assertTrue($collection->some($callable));
  161. }
  162. /**
  163. * Tests some() when none of the calls return true
  164. *
  165. * @return void
  166. */
  167. public function testSomeReturnFalse() {
  168. $items = ['a' => 1, 'b' => 2, 'c' => 3];
  169. $collection = new Collection($items);
  170. $callable = $this->getMock('stdClass', ['__invoke']);
  171. $callable->expects($this->at(0))
  172. ->method('__invoke')
  173. ->with(1, 'a')
  174. ->will($this->returnValue(false));
  175. $callable->expects($this->at(1))
  176. ->method('__invoke')
  177. ->with(2, 'b')
  178. ->will($this->returnValue(false));
  179. $callable->expects($this->at(2))
  180. ->method('__invoke')
  181. ->with(3, 'c')
  182. ->will($this->returnValue(false));
  183. $this->assertFalse($collection->some($callable));
  184. }
  185. /**
  186. * Tests contains
  187. *
  188. * @return void
  189. */
  190. public function testContains() {
  191. $items = ['a' => 1, 'b' => 2, 'c' => 3];
  192. $collection = new Collection($items);
  193. $this->assertTrue($collection->contains(2));
  194. $this->assertTrue($collection->contains(1));
  195. $this->assertFalse($collection->contains(10));
  196. $this->assertFalse($collection->contains('2'));
  197. }
  198. /**
  199. * Tests map
  200. *
  201. * @return void
  202. */
  203. public function testMap() {
  204. $items = ['a' => 1, 'b' => 2, 'c' => 3];
  205. $collection = new Collection($items);
  206. $map = $collection->map(function($v, $k, $it) use ($collection) {
  207. $this->assertSame($collection, $it);
  208. return $v * $v;
  209. });
  210. $this->assertInstanceOf('\Cake\Collection\Iterator\ReplaceIterator', $map);
  211. $this->assertEquals(['a' => 1, 'b' => 4, 'c' => 9], iterator_to_array($map));
  212. }
  213. /**
  214. * Tests reduce
  215. *
  216. * @return void
  217. */
  218. public function testReduce() {
  219. $items = ['a' => 1, 'b' => 2, 'c' => 3];
  220. $collection = new Collection($items);
  221. $callable = $this->getMock('stdClass', ['__invoke']);
  222. $callable->expects($this->at(0))
  223. ->method('__invoke')
  224. ->with(10, 1, 'a')
  225. ->will($this->returnValue(11));
  226. $callable->expects($this->at(1))
  227. ->method('__invoke')
  228. ->with(11, 2, 'b')
  229. ->will($this->returnValue(13));
  230. $callable->expects($this->at(2))
  231. ->method('__invoke')
  232. ->with(13, 3, 'c')
  233. ->will($this->returnValue(16));
  234. $this->assertEquals(16, $collection->reduce($callable, 10));
  235. }
  236. /**
  237. * Tests extract
  238. *
  239. * @return void
  240. */
  241. public function testExtract() {
  242. $items = [['a' => ['b' => ['c' => 1]]], 2];
  243. $collection = new Collection($items);
  244. $map = $collection->extract('a.b.c');
  245. $this->assertInstanceOf('\Cake\Collection\Iterator\ExtractIterator', $map);
  246. $this->assertEquals([1, null], iterator_to_array($map));
  247. }
  248. /**
  249. * Tests sort
  250. *
  251. * @return void
  252. */
  253. public function testSortString() {
  254. $items = [
  255. ['a' => ['b' => ['c' => 4]]],
  256. ['a' => ['b' => ['c' => 10]]],
  257. ['a' => ['b' => ['c' => 6]]]
  258. ];
  259. $collection = new Collection($items);
  260. $map = $collection->sortBy('a.b.c');
  261. $this->assertInstanceOf('\Cake\Collection\Collection', $map);
  262. $expected = [
  263. 2 => ['a' => ['b' => ['c' => 10]]],
  264. 1 => ['a' => ['b' => ['c' => 6]]],
  265. 0 => ['a' => ['b' => ['c' => 4]]],
  266. ];
  267. $this->assertEquals($expected, iterator_to_array($map));
  268. }
  269. /**
  270. * Tests max
  271. *
  272. * @return void
  273. */
  274. public function testMax() {
  275. $items = [
  276. ['a' => ['b' => ['c' => 4]]],
  277. ['a' => ['b' => ['c' => 10]]],
  278. ['a' => ['b' => ['c' => 6]]]
  279. ];
  280. $collection = new Collection($items);
  281. $this->assertEquals(['a' => ['b' => ['c' => 10]]], $collection->max('a.b.c'));
  282. $callback = function($e) {
  283. return $e['a']['b']['c'] * - 1;
  284. };
  285. $this->assertEquals(['a' => ['b' => ['c' => 4]]], $collection->max($callback));
  286. }
  287. /**
  288. * Tests min
  289. *
  290. * @return void
  291. */
  292. public function testMin() {
  293. $items = [
  294. ['a' => ['b' => ['c' => 4]]],
  295. ['a' => ['b' => ['c' => 10]]],
  296. ['a' => ['b' => ['c' => 6]]]
  297. ];
  298. $collection = new Collection($items);
  299. $this->assertEquals(['a' => ['b' => ['c' => 4]]], $collection->min('a.b.c'));
  300. }
  301. /**
  302. * Tests groupBy
  303. *
  304. * @return void
  305. */
  306. public function testGroupBy() {
  307. $items = [
  308. ['id' => 1, 'name' => 'foo', 'parent_id' => 10],
  309. ['id' => 2, 'name' => 'bar', 'parent_id' => 11],
  310. ['id' => 3, 'name' => 'baz', 'parent_id' => 10],
  311. ];
  312. $collection = new Collection($items);
  313. $grouped = $collection->groupBy('parent_id');
  314. $expected = [
  315. 10 => [
  316. ['id' => 1, 'name' => 'foo', 'parent_id' => 10],
  317. ['id' => 3, 'name' => 'baz', 'parent_id' => 10],
  318. ],
  319. 11 => [
  320. ['id' => 2, 'name' => 'bar', 'parent_id' => 11],
  321. ]
  322. ];
  323. $this->assertEquals($expected, iterator_to_array($grouped));
  324. $this->assertInstanceOf('\Cake\Collection\Collection', $grouped);
  325. $grouped = $collection->groupBy(function($element) {
  326. return $element['parent_id'];
  327. });
  328. $this->assertEquals($expected, iterator_to_array($grouped));
  329. }
  330. /**
  331. * Tests grouping by a deep key
  332. *
  333. * @return void
  334. */
  335. public function testGroupByDeepKey() {
  336. $items = [
  337. ['id' => 1, 'name' => 'foo', 'thing' => ['parent_id' => 10]],
  338. ['id' => 2, 'name' => 'bar', 'thing' => ['parent_id' => 11]],
  339. ['id' => 3, 'name' => 'baz', 'thing' => ['parent_id' => 10]],
  340. ];
  341. $collection = new Collection($items);
  342. $grouped = $collection->groupBy('thing.parent_id');
  343. $expected = [
  344. 10 => [
  345. ['id' => 1, 'name' => 'foo', 'thing' => ['parent_id' => 10]],
  346. ['id' => 3, 'name' => 'baz', 'thing' => ['parent_id' => 10]],
  347. ],
  348. 11 => [
  349. ['id' => 2, 'name' => 'bar', 'thing' => ['parent_id' => 11]],
  350. ]
  351. ];
  352. $this->assertEquals($expected, iterator_to_array($grouped));
  353. }
  354. /**
  355. * Tests indexBy
  356. *
  357. * @return void
  358. */
  359. public function testIndexBy() {
  360. $items = [
  361. ['id' => 1, 'name' => 'foo', 'parent_id' => 10],
  362. ['id' => 2, 'name' => 'bar', 'parent_id' => 11],
  363. ['id' => 3, 'name' => 'baz', 'parent_id' => 10],
  364. ];
  365. $collection = new Collection($items);
  366. $grouped = $collection->indexBy('id');
  367. $expected = [
  368. 1 => ['id' => 1, 'name' => 'foo', 'parent_id' => 10],
  369. 3 => ['id' => 3, 'name' => 'baz', 'parent_id' => 10],
  370. 2 => ['id' => 2, 'name' => 'bar', 'parent_id' => 11],
  371. ];
  372. $this->assertEquals($expected, iterator_to_array($grouped));
  373. $this->assertInstanceOf('\Cake\Collection\Collection', $grouped);
  374. $grouped = $collection->indexBy(function($element) {
  375. return $element['id'];
  376. });
  377. $this->assertEquals($expected, iterator_to_array($grouped));
  378. }
  379. /**
  380. * Tests indexBy with a deep property
  381. *
  382. * @return void
  383. */
  384. public function testIndexByDeep() {
  385. $items = [
  386. ['id' => 1, 'name' => 'foo', 'thing' => ['parent_id' => 10]],
  387. ['id' => 2, 'name' => 'bar', 'thing' => ['parent_id' => 11]],
  388. ['id' => 3, 'name' => 'baz', 'thing' => ['parent_id' => 10]],
  389. ];
  390. $collection = new Collection($items);
  391. $grouped = $collection->indexBy('thing.parent_id');
  392. $expected = [
  393. 10 => ['id' => 3, 'name' => 'baz', 'thing' => ['parent_id' => 10]],
  394. 11 => ['id' => 2, 'name' => 'bar', 'thing' => ['parent_id' => 11]],
  395. ];
  396. $this->assertEquals($expected, iterator_to_array($grouped));
  397. }
  398. /**
  399. * Tests countBy
  400. *
  401. * @return void
  402. */
  403. public function testCountBy() {
  404. $items = [
  405. ['id' => 1, 'name' => 'foo', 'parent_id' => 10],
  406. ['id' => 2, 'name' => 'bar', 'parent_id' => 11],
  407. ['id' => 3, 'name' => 'baz', 'parent_id' => 10],
  408. ];
  409. $collection = new Collection($items);
  410. $grouped = $collection->countBy('parent_id');
  411. $expected = [
  412. 10 => 2,
  413. 11 => 1
  414. ];
  415. $this->assertEquals($expected, iterator_to_array($grouped));
  416. $this->assertInstanceOf('\Cake\Collection\Collection', $grouped);
  417. $grouped = $collection->countBy(function($element) {
  418. return $element['parent_id'];
  419. });
  420. $this->assertEquals($expected, iterator_to_array($grouped));
  421. }
  422. /**
  423. * Tests shuffle
  424. *
  425. * @return void
  426. */
  427. public function testShuffle() {
  428. $data = [1, 2, 3, 4];
  429. $collection = (new Collection($data))->shuffle();
  430. $this->assertEquals(count($data), count(iterator_to_array($collection)));
  431. foreach ($collection as $value) {
  432. $this->assertContains($value, $data);
  433. }
  434. }
  435. /**
  436. * Tests sample
  437. *
  438. * @return void
  439. */
  440. public function testSample() {
  441. $data = [1, 2, 3, 4];
  442. $collection = (new Collection($data))->sample(2);
  443. $this->assertEquals(2, count(iterator_to_array($collection)));
  444. foreach ($collection as $value) {
  445. $this->assertContains($value, $data);
  446. }
  447. }
  448. /**
  449. * Test toArray method
  450. *
  451. * @return void
  452. */
  453. public function testToArray() {
  454. $data = [1, 2, 3, 4];
  455. $collection = new Collection($data);
  456. $this->assertEquals($data, $collection->toArray());
  457. }
  458. /**
  459. * Test json enconding
  460. *
  461. * @return void
  462. */
  463. public function testToJson() {
  464. $data = [1, 2, 3, 4];
  465. $collection = new Collection($data);
  466. $this->assertEquals(json_encode($data), json_encode($collection));
  467. }
  468. /**
  469. * Tests that only arrays and Traversables are allowed in the constructor
  470. *
  471. * @expectedException \InvalidArgumentException
  472. * @expectedExceptionMessage Only array or \Traversable are allowed for Collection
  473. * @return void
  474. */
  475. public function testInvalidConstructorArgument() {
  476. new Collection('Derp');
  477. }
  478. /**
  479. * Tests take method
  480. *
  481. * @return void
  482. */
  483. public function testTake() {
  484. $data = [1, 2, 3, 4];
  485. $collection = new Collection($data);
  486. $taken = $collection->take(2);
  487. $this->assertEquals([1, 2], $taken->toArray());
  488. $taken = $collection->take(3);
  489. $this->assertEquals([1, 2, 3], $taken->toArray());
  490. $taken = $collection->take(500);
  491. $this->assertEquals([1, 2, 3, 4], $taken->toArray());
  492. $taken = $collection->take(1);
  493. $this->assertEquals([1], $taken->toArray());
  494. $taken = $collection->take();
  495. $this->assertEquals([1], $taken->toArray());
  496. $taken = $collection->take(2, 2);
  497. $this->assertEquals([2 => 3, 3 => 4], $taken->toArray());
  498. }
  499. /**
  500. * Tests match
  501. *
  502. * @return void
  503. */
  504. public function testMatch() {
  505. $this->assertFalse(defined('HHVM_VERSION'), 'Broken on HHVM');
  506. $items = [
  507. ['id' => 1, 'name' => 'foo', 'thing' => ['parent_id' => 10]],
  508. ['id' => 2, 'name' => 'bar', 'thing' => ['parent_id' => 11]],
  509. ['id' => 3, 'name' => 'baz', 'thing' => ['parent_id' => 10]],
  510. ];
  511. $collection = new Collection($items);
  512. $matched = $collection->match(['thing.parent_id' => 10, 'name' => 'baz']);
  513. $this->assertEquals([2 => $items[2]], $matched->toArray());
  514. $matched = $collection->match(['thing.parent_id' => 10]);
  515. $this->assertEquals(
  516. [0 => $items[0], 2 => $items[2]],
  517. $matched->toArray()
  518. );
  519. $matched = $collection->match(['thing.parent_id' => 500]);
  520. $this->assertEquals([], $matched->toArray());
  521. $matched = $collection->match(['parent_id' => 10, 'name' => 'baz']);
  522. $this->assertEquals([], $matched->toArray());
  523. }
  524. /**
  525. * Tests firstMatch
  526. *
  527. * @return void
  528. */
  529. public function testFirstMatch() {
  530. $this->assertFalse(defined('HHVM_VERSION'), 'Broken on HHVM');
  531. $items = [
  532. ['id' => 1, 'name' => 'foo', 'thing' => ['parent_id' => 10]],
  533. ['id' => 2, 'name' => 'bar', 'thing' => ['parent_id' => 11]],
  534. ['id' => 3, 'name' => 'baz', 'thing' => ['parent_id' => 10]],
  535. ];
  536. $collection = new Collection($items);
  537. $matched = $collection->firstMatch(['thing.parent_id' => 10]);
  538. $this->assertEquals(
  539. ['id' => 1, 'name' => 'foo', 'thing' => ['parent_id' => 10]],
  540. $matched
  541. );
  542. $matched = $collection->firstMatch(['thing.parent_id' => 10, 'name' => 'baz']);
  543. $this->assertEquals(
  544. ['id' => 3, 'name' => 'baz', 'thing' => ['parent_id' => 10]],
  545. $matched
  546. );
  547. }
  548. /**
  549. * Tests the append method
  550. *
  551. * @return void
  552. */
  553. public function testAppend() {
  554. $collection = new Collection([1, 2, 3]);
  555. $combined = $collection->append([4, 5, 6]);
  556. $this->assertEquals([1, 2, 3, 4, 5, 6], $combined->toArray(false));
  557. $collection = new Collection(['a' => 1, 'b' => 2]);
  558. $combined = $collection->append(['c' => 3, 'a' => 4]);
  559. $this->assertEquals(['a' => 4, 'b' => 2, 'c' => 3], $combined->toArray());
  560. }
  561. /**
  562. * Tests that by calling compile internal iteration operations are not done
  563. * more than once
  564. *
  565. * @return void
  566. */
  567. public function testCompile() {
  568. $items = ['a' => 1, 'b' => 2, 'c' => 3];
  569. $collection = new Collection($items);
  570. $callable = $this->getMock('stdClass', ['__invoke']);
  571. $callable->expects($this->at(0))
  572. ->method('__invoke')
  573. ->with(1, 'a')
  574. ->will($this->returnValue(4));
  575. $callable->expects($this->at(1))
  576. ->method('__invoke')
  577. ->with(2, 'b')
  578. ->will($this->returnValue(5));
  579. $callable->expects($this->at(2))
  580. ->method('__invoke')
  581. ->with(3, 'c')
  582. ->will($this->returnValue(6));
  583. $compiled = $collection->map($callable)->compile();
  584. $this->assertEquals(['a' => 4, 'b' => 5, 'c' => 6], $compiled->toArray());
  585. $this->assertEquals(['a' => 4, 'b' => 5, 'c' => 6], $compiled->toArray());
  586. }
  587. /**
  588. * Tests the combine method
  589. *
  590. * @return void
  591. */
  592. public function testCombine() {
  593. $items = [
  594. ['id' => 1, 'name' => 'foo', 'parent' => 'a'],
  595. ['id' => 2, 'name' => 'bar', 'parent' => 'b'],
  596. ['id' => 3, 'name' => 'baz', 'parent' => 'a']
  597. ];
  598. $collection = (new Collection($items))->combine('id', 'name');
  599. $expected = [1 => 'foo', 2 => 'bar', 3 => 'baz'];
  600. $this->assertEquals($expected, $collection->toArray());
  601. $expected = ['foo' => 1, 'bar' => 2, 'baz' => 3];
  602. $collection = (new Collection($items))->combine('name', 'id');
  603. $this->assertEquals($expected, $collection->toArray());
  604. $collection = (new Collection($items))->combine('id', 'name', 'parent');
  605. $expected = ['a' => [1 => 'foo', 3 => 'baz'], 'b' => [2 => 'bar']];
  606. $this->assertEquals($expected, $collection->toArray());
  607. $expected = [
  608. '0-1' => ['foo-0-1' => '0-1-foo'],
  609. '1-2' => ['bar-1-2' => '1-2-bar'],
  610. '2-3' => ['baz-2-3' => '2-3-baz']
  611. ];
  612. $collection = (new Collection($items))->combine(
  613. function($value, $key) {
  614. return $value['name'] . '-' . $key;
  615. },
  616. function($value, $key) {
  617. return $key . '-' . $value['name'];
  618. },
  619. function($value, $key) {
  620. return $key . '-' . $value['id'];
  621. }
  622. );
  623. $this->assertEquals($expected, $collection->toArray());
  624. $collection = (new Collection($items))->combine('id', 'crazy');
  625. $this->assertEquals([1 => null, 2 => null, 3 => null], $collection->toArray());
  626. }
  627. /**
  628. * Tests the nest method with only one level
  629. *
  630. * @return void
  631. */
  632. public function testNest() {
  633. $items = [
  634. ['id' => 1, 'parent_id' => null],
  635. ['id' => 2, 'parent_id' => 1],
  636. ['id' => 3, 'parent_id' => 1],
  637. ['id' => 4, 'parent_id' => 1],
  638. ['id' => 5, 'parent_id' => 6],
  639. ['id' => 6, 'parent_id' => null],
  640. ['id' => 7, 'parent_id' => 1],
  641. ['id' => 8, 'parent_id' => 6],
  642. ['id' => 9, 'parent_id' => 6],
  643. ['id' => 10, 'parent_id' => 6]
  644. ];
  645. $collection = (new Collection($items))->nest('id', 'parent_id');
  646. $expected = [
  647. [
  648. 'id' => 1,
  649. 'parent_id' => null,
  650. 'children' => [
  651. ['id' => 2, 'parent_id' => 1, 'children' => []],
  652. ['id' => 3, 'parent_id' => 1, 'children' => []],
  653. ['id' => 4, 'parent_id' => 1, 'children' => []],
  654. ['id' => 7, 'parent_id' => 1, 'children' => []]
  655. ]
  656. ],
  657. [
  658. 'id' => 6,
  659. 'parent_id' => null,
  660. 'children' => [
  661. ['id' => 5, 'parent_id' => 6, 'children' => []],
  662. ['id' => 8, 'parent_id' => 6, 'children' => []],
  663. ['id' => 9, 'parent_id' => 6, 'children' => []],
  664. ['id' => 10, 'parent_id' => 6, 'children' => []]
  665. ]
  666. ]
  667. ];
  668. $this->assertEquals($expected, $collection->toArray());
  669. }
  670. /**
  671. * Tests the nest method with more than one level
  672. *
  673. * @return void
  674. */
  675. public function testNestMultiLevel() {
  676. $items = [
  677. ['id' => 1, 'parent_id' => null],
  678. ['id' => 2, 'parent_id' => 1],
  679. ['id' => 3, 'parent_id' => 2],
  680. ['id' => 4, 'parent_id' => 2],
  681. ['id' => 5, 'parent_id' => 3],
  682. ['id' => 6, 'parent_id' => null],
  683. ['id' => 7, 'parent_id' => 3],
  684. ['id' => 8, 'parent_id' => 4],
  685. ['id' => 9, 'parent_id' => 6],
  686. ['id' => 10, 'parent_id' => 6]
  687. ];
  688. $collection = (new Collection($items))->nest('id', 'parent_id');
  689. $expected = [
  690. [
  691. 'id' => 1,
  692. 'parent_id' => null,
  693. 'children' => [
  694. [
  695. 'id' => 2,
  696. 'parent_id' => 1,
  697. 'children' => [
  698. [
  699. 'id' => 3,
  700. 'parent_id' => 2,
  701. 'children' => [
  702. ['id' => 5, 'parent_id' => 3, 'children' => []],
  703. ['id' => 7, 'parent_id' => 3, 'children' => []]
  704. ]
  705. ],
  706. [
  707. 'id' => 4,
  708. 'parent_id' => 2,
  709. 'children' => [
  710. ['id' => 8, 'parent_id' => 4, 'children' => []]
  711. ]
  712. ]
  713. ]
  714. ]
  715. ]
  716. ],
  717. [
  718. 'id' => 6,
  719. 'parent_id' => null,
  720. 'children' => [
  721. ['id' => 9, 'parent_id' => 6, 'children' => []],
  722. ['id' => 10, 'parent_id' => 6, 'children' => []]
  723. ]
  724. ]
  725. ];
  726. $this->assertEquals($expected, $collection->toArray());
  727. }
  728. /**
  729. * Tests the nest method with more than one level
  730. *
  731. * @return void
  732. */
  733. public function testNestObjects() {
  734. $items = [
  735. new ArrayObject(['id' => 1, 'parent_id' => null]),
  736. new ArrayObject(['id' => 2, 'parent_id' => 1]),
  737. new ArrayObject(['id' => 3, 'parent_id' => 2]),
  738. new ArrayObject(['id' => 4, 'parent_id' => 2]),
  739. new ArrayObject(['id' => 5, 'parent_id' => 3]),
  740. new ArrayObject(['id' => 6, 'parent_id' => null]),
  741. new ArrayObject(['id' => 7, 'parent_id' => 3]),
  742. new ArrayObject(['id' => 8, 'parent_id' => 4]),
  743. new ArrayObject(['id' => 9, 'parent_id' => 6]),
  744. new ArrayObject(['id' => 10, 'parent_id' => 6])
  745. ];
  746. $collection = (new Collection($items))->nest('id', 'parent_id');
  747. $expected = [
  748. new ArrayObject([
  749. 'id' => 1,
  750. 'parent_id' => null,
  751. 'children' => [
  752. new ArrayObject([
  753. 'id' => 2,
  754. 'parent_id' => 1,
  755. 'children' => [
  756. new ArrayObject([
  757. 'id' => 3,
  758. 'parent_id' => 2,
  759. 'children' => [
  760. new ArrayObject(['id' => 5, 'parent_id' => 3, 'children' => []]),
  761. new ArrayObject(['id' => 7, 'parent_id' => 3, 'children' => []])
  762. ]
  763. ]),
  764. new ArrayObject([
  765. 'id' => 4,
  766. 'parent_id' => 2,
  767. 'children' => [
  768. new ArrayObject(['id' => 8, 'parent_id' => 4, 'children' => []])
  769. ]
  770. ])
  771. ]
  772. ])
  773. ]
  774. ]),
  775. new ArrayObject([
  776. 'id' => 6,
  777. 'parent_id' => null,
  778. 'children' => [
  779. new ArrayObject(['id' => 9, 'parent_id' => 6, 'children' => []]),
  780. new ArrayObject(['id' => 10, 'parent_id' => 6, 'children' => []])
  781. ]
  782. ])
  783. ];
  784. $this->assertEquals($expected, $collection->toArray());
  785. }
  786. /**
  787. * Tests insert
  788. *
  789. * @return void
  790. */
  791. public function testInsert() {
  792. $items = [['a' => 1], ['b' => 2]];
  793. $collection = new Collection($items);
  794. $iterator = $collection->insert('c', [3, 4]);
  795. $this->assertInstanceOf('\Cake\Collection\Iterator\InsertIterator', $iterator);
  796. $this->assertEquals(
  797. [['a' => 1, 'c' => 3], ['b' => 2, 'c' => 4]],
  798. iterator_to_array($iterator)
  799. );
  800. }
  801. }