SortIteratorTest.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  5. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  6. *
  7. * Licensed under The MIT License
  8. * For full copyright and license information, please see the LICENSE.txt
  9. * Redistributions of files must retain the above copyright notice.
  10. *
  11. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  12. * @link https://cakephp.org CakePHP(tm) Project
  13. * @since 3.0.0
  14. * @license https://opensource.org/licenses/mit-license.php MIT License
  15. */
  16. namespace Cake\Test\TestCase\Collection\Iterator;
  17. use ArrayObject;
  18. use Cake\Collection\Iterator\SortIterator;
  19. use Cake\TestSuite\TestCase;
  20. use DateInterval;
  21. use DateTime;
  22. use DateTimeImmutable;
  23. use const SORT_ASC;
  24. use const SORT_DESC;
  25. use const SORT_NUMERIC;
  26. /**
  27. * SortIterator Test
  28. */
  29. class SortIteratorTest extends TestCase
  30. {
  31. /**
  32. * Tests sorting numbers with an identity callbacks
  33. */
  34. public function testSortNumbersIdentity(): void
  35. {
  36. $items = new ArrayObject([3, 5, 1, 2, 4]);
  37. $identity = function ($a) {
  38. return $a;
  39. };
  40. $sorted = new SortIterator($items, $identity);
  41. $expected = range(5, 1);
  42. $this->assertEquals($expected, $sorted->toList());
  43. $sorted = new SortIterator($items, $identity, SORT_ASC);
  44. $expected = range(1, 5);
  45. $this->assertEquals($expected, $sorted->toList());
  46. }
  47. /**
  48. * Tests sorting numbers with custom callback
  49. */
  50. public function testSortNumbersCustom(): void
  51. {
  52. $items = new ArrayObject([3, 5, 1, 2, 4]);
  53. $callback = function ($a) {
  54. return $a * -1;
  55. };
  56. $sorted = new SortIterator($items, $callback);
  57. $expected = range(1, 5);
  58. $this->assertEquals($expected, $sorted->toList());
  59. $sorted = new SortIterator($items, $callback, SORT_ASC);
  60. $expected = range(5, 1);
  61. $this->assertEquals($expected, $sorted->toList());
  62. }
  63. /**
  64. * Tests sorting a complex structure with numeric sort
  65. */
  66. public function testSortComplexNumeric(): void
  67. {
  68. $items = new ArrayObject([
  69. ['foo' => 1, 'bar' => 'a'],
  70. ['foo' => 10, 'bar' => 'a'],
  71. ['foo' => 2, 'bar' => 'a'],
  72. ['foo' => 13, 'bar' => 'a'],
  73. ]);
  74. $callback = function ($a) {
  75. return $a['foo'];
  76. };
  77. $sorted = new SortIterator($items, $callback, SORT_DESC, SORT_NUMERIC);
  78. $expected = [
  79. ['foo' => 13, 'bar' => 'a'],
  80. ['foo' => 10, 'bar' => 'a'],
  81. ['foo' => 2, 'bar' => 'a'],
  82. ['foo' => 1, 'bar' => 'a'],
  83. ];
  84. $this->assertEquals($expected, $sorted->toList());
  85. $sorted = new SortIterator($items, $callback, SORT_ASC, SORT_NUMERIC);
  86. $expected = [
  87. ['foo' => 1, 'bar' => 'a'],
  88. ['foo' => 2, 'bar' => 'a'],
  89. ['foo' => 10, 'bar' => 'a'],
  90. ['foo' => 13, 'bar' => 'a'],
  91. ];
  92. $this->assertEquals($expected, $sorted->toList());
  93. }
  94. /**
  95. * Tests sorting a complex structure with natural sort
  96. */
  97. public function testSortComplexNatural(): void
  98. {
  99. $items = new ArrayObject([
  100. ['foo' => 'foo_1', 'bar' => 'a'],
  101. ['foo' => 'foo_10', 'bar' => 'a'],
  102. ['foo' => 'foo_2', 'bar' => 'a'],
  103. ['foo' => 'foo_13', 'bar' => 'a'],
  104. ]);
  105. $callback = function ($a) {
  106. return $a['foo'];
  107. };
  108. $sorted = new SortIterator($items, $callback, SORT_DESC, SORT_NATURAL);
  109. $expected = [
  110. ['foo' => 'foo_13', 'bar' => 'a'],
  111. ['foo' => 'foo_10', 'bar' => 'a'],
  112. ['foo' => 'foo_2', 'bar' => 'a'],
  113. ['foo' => 'foo_1', 'bar' => 'a'],
  114. ];
  115. $this->assertEquals($expected, $sorted->toList());
  116. $sorted = new SortIterator($items, $callback, SORT_ASC, SORT_NATURAL);
  117. $expected = [
  118. ['foo' => 'foo_1', 'bar' => 'a'],
  119. ['foo' => 'foo_2', 'bar' => 'a'],
  120. ['foo' => 'foo_10', 'bar' => 'a'],
  121. ['foo' => 'foo_13', 'bar' => 'a'],
  122. ];
  123. $this->assertEquals($expected, $sorted->toList());
  124. $this->assertEquals($expected, $sorted->toList(), 'Iterator should rewind');
  125. }
  126. /**
  127. * Tests sorting a complex structure with natural sort with string callback
  128. */
  129. public function testSortComplexNaturalWithPath(): void
  130. {
  131. $items = new ArrayObject([
  132. ['foo' => 'foo_1', 'bar' => 'a'],
  133. ['foo' => 'foo_10', 'bar' => 'a'],
  134. ['foo' => 'foo_2', 'bar' => 'a'],
  135. ['foo' => 'foo_13', 'bar' => 'a'],
  136. ]);
  137. $sorted = new SortIterator($items, 'foo', SORT_DESC, SORT_NATURAL);
  138. $expected = [
  139. ['foo' => 'foo_13', 'bar' => 'a'],
  140. ['foo' => 'foo_10', 'bar' => 'a'],
  141. ['foo' => 'foo_2', 'bar' => 'a'],
  142. ['foo' => 'foo_1', 'bar' => 'a'],
  143. ];
  144. $this->assertEquals($expected, $sorted->toList());
  145. $sorted = new SortIterator($items, 'foo', SORT_ASC, SORT_NATURAL);
  146. $expected = [
  147. ['foo' => 'foo_1', 'bar' => 'a'],
  148. ['foo' => 'foo_2', 'bar' => 'a'],
  149. ['foo' => 'foo_10', 'bar' => 'a'],
  150. ['foo' => 'foo_13', 'bar' => 'a'],
  151. ];
  152. $this->assertEquals($expected, $sorted->toList());
  153. $this->assertEquals($expected, $sorted->toList(), 'Iterator should rewind');
  154. }
  155. /**
  156. * Tests sorting a complex structure with a deep path
  157. */
  158. public function testSortComplexDeepPath(): void
  159. {
  160. $items = new ArrayObject([
  161. ['foo' => ['bar' => 1], 'bar' => 'a'],
  162. ['foo' => ['bar' => 12], 'bar' => 'a'],
  163. ['foo' => ['bar' => 10], 'bar' => 'a'],
  164. ['foo' => ['bar' => 2], 'bar' => 'a'],
  165. ]);
  166. $sorted = new SortIterator($items, 'foo.bar', SORT_ASC, SORT_NUMERIC);
  167. $expected = [
  168. ['foo' => ['bar' => 1], 'bar' => 'a'],
  169. ['foo' => ['bar' => 2], 'bar' => 'a'],
  170. ['foo' => ['bar' => 10], 'bar' => 'a'],
  171. ['foo' => ['bar' => 12], 'bar' => 'a'],
  172. ];
  173. $this->assertEquals($expected, $sorted->toList());
  174. }
  175. /**
  176. * Tests sorting datetime
  177. */
  178. public function testSortDateTime(): void
  179. {
  180. $items = new ArrayObject([
  181. new DateTime('2014-07-21'),
  182. new DateTime('2015-06-30'),
  183. new DateTimeImmutable('2013-08-12'),
  184. ]);
  185. $callback = function ($a) {
  186. return $a->add(new DateInterval('P1Y'));
  187. };
  188. $sorted = new SortIterator($items, $callback);
  189. $expected = [
  190. new DateTime('2016-06-30'),
  191. new DateTime('2015-07-21'),
  192. new DateTimeImmutable('2013-08-12'),
  193. ];
  194. $this->assertEquals($expected, $sorted->toList());
  195. $items = new ArrayObject([
  196. new DateTime('2014-07-21'),
  197. new DateTime('2015-06-30'),
  198. new DateTimeImmutable('2013-08-12'),
  199. ]);
  200. $sorted = new SortIterator($items, $callback, SORT_ASC);
  201. $expected = [
  202. new DateTimeImmutable('2013-08-12'),
  203. new DateTime('2015-07-21'),
  204. new DateTime('2016-06-30'),
  205. ];
  206. $this->assertEquals($expected, $sorted->toList());
  207. }
  208. }