CollectionTest.php 22 KB

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