‪TYPO3CMS  ‪main
ArrayUtilityTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
23 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
24 
28 final class ‪ArrayUtilityTest extends UnitTestCase
29 {
31  // Tests concerning filterByValueRecursive
33 
41  public static function ‪filterByValueRecursive(): array
42  {
43  return [
44  'empty search array' => [
45  'banana',
46  [],
47  [],
48  ],
49  'empty string as needle' => [
50  '',
51  [
52  '',
53  'apple',
54  ],
55  [
56  '',
57  ],
58  ],
59  'flat array searching for string' => [
60  'banana',
61  [
62  'apple',
63  'banana',
64  ],
65  [
66  1 => 'banana',
67  ],
68  ],
69  'flat array searching for string with two matches' => [
70  'banana',
71  [
72  'foo' => 'apple',
73  'firstbanana' => 'banana',
74  'secondbanana' => 'banana',
75  ],
76  [
77  'firstbanana' => 'banana',
78  'secondbanana' => 'banana',
79  ],
80  ],
81  'multi dimensional array searching for string with multiple matches' => [
82  'banana',
83  [
84  'foo' => 'apple',
85  'firstbanana' => 'banana',
86  'grape' => [
87  'foo2' => 'apple2',
88  'secondbanana' => 'banana',
89  'foo3' => [],
90  ],
91  'bar' => 'orange',
92  ],
93  [
94  'firstbanana' => 'banana',
95  'grape' => [
96  'secondbanana' => 'banana',
97  ],
98  ],
99  ],
100  'multi dimensional array searching for integer with multiple matches' => [
101  42,
102  [
103  'foo' => 23,
104  'bar' => 42,
105  [
106  'foo' => 23,
107  'bar' => 42,
108  ],
109  ],
110  [
111  'bar' => 42,
112  [
113  'bar' => 42,
114  ],
115  ],
116  ],
117  'flat array searching for boolean TRUE' => [
118  true,
119  [
120  23 => false,
121  42 => true,
122  ],
123  [
124  42 => true,
125  ],
126  ],
127  'multi dimensional array searching for boolean FALSE' => [
128  false,
129  [
130  23 => false,
131  42 => true,
132  'foo' => [
133  23 => false,
134  42 => true,
135  ],
136  ],
137  [
138  23 => false,
139  'foo' => [
140  23 => false,
141  ],
142  ],
143  ],
144  'flat array searching for array' => [
145  [
146  'foo' => 'bar',
147  ],
148  [
149  'foo' => 'bar',
150  'foobar' => [
151  'foo' => 'bar',
152  ],
153  ],
154  [
155  'foobar' => [
156  'foo' => 'bar',
157  ],
158  ],
159  ],
160  ];
161  }
162 
170  public function ‪filterByValueRecursiveCorrectlyFiltersArray($needle, $haystack, $expectedResult): void
171  {
172  self::assertEquals(
173  $expectedResult,
174  ‪ArrayUtility::filterByValueRecursive($needle, $haystack)
175  );
176  }
177 
182  {
183  $instance = new \stdClass();
184  self::assertEquals(
185  [$instance],
186  ‪ArrayUtility::filterByValueRecursive($instance, [$instance])
187  );
188  }
189 
194  {
195  self::assertEquals(
196  [],
197  ‪ArrayUtility::filterByValueRecursive(new \stdClass(), [new \stdClass()])
198  );
199  }
200 
202  // Tests concerning isValidPath
204 
208  {
209  self::assertTrue(‪ArrayUtility::isValidPath(['foo' => 'bar'], 'foo'));
210  }
211 
216  {
217  self::assertFalse(‪ArrayUtility::isValidPath(['foo' => 'bar'], 'bar'));
218  }
219 
224  {
225  self::assertTrue(‪ArrayUtility::isValidPath(['foo' => 'bar'], ['foo']));
226  }
227 
232  {
233  self::assertFalse(‪ArrayUtility::isValidPath(['foo' => 'bar'], ['bar']));
234  }
235 
237  // Tests concerning getValueByPath
239 
244  {
245  $this->expectException(\RuntimeException::class);
246  $this->expectExceptionCode(1341397767);
247 
249  }
250 
255  {
256  self::assertSame('foo', ‪ArrayUtility::getValueByPath(['foo'], '0'));
257  }
258 
263  {
264  self::assertSame('bar', ‪ArrayUtility::getValueByPath(['foo' => ['bar']], 'foo/0'));
265  }
266 
274  public static function ‪getValueByPathInvalidPathDataProvider(): array
275  {
276  return [
277  'not existing index' => [
278  [
279  'foo' => ['foo'],
280  ],
281  'foo/1',
282  false,
283  ],
284  'not existing path 1' => [
285  [
286  'foo' => [],
287  ],
288  'foo/bar/baz',
289  false,
290  ],
291  'not existing path 2' => [
292  [
293  'foo' => [
294  'baz' => 42,
295  ],
296  'bar' => [],
297  ],
298  'foo/bar/baz',
299  false,
300  ],
301  'last segment is not an array' => [
302  [
303  'foo' => [
304  'baz' => 42,
305  ],
306  ],
307  'foo/baz/baz',
308  false,
309  ],
310  // Negative test: This could be improved and the test moved to
311  // the valid data provider if the method supports this
312  'doubletick encapsulated quoted doubletick does not work' => [
313  [
314  '"foo"bar"' => [
315  'baz' => 42,
316  ],
317  'bar' => [],
318  ],
319  '"foo\\"bar"/baz',
320  42,
321  ],
322  // Negative test: Method could be improved here
323  'path with doubletick does not work' => [
324  [
325  'fo"o' => [
326  'bar' => 42,
327  ],
328  ],
329  'fo"o/foobar',
330  42,
331  ],
332  ];
333  }
334 
340  public function ‪getValueByPathThrowsExceptionIfPathNotExists(array $array, $path): void
341  {
342  $this->expectException(\RuntimeException::class);
343  $this->expectExceptionCode(1341397869);
344  ‪ArrayUtility::getValueByPath($array, $path);
345  }
346 
351  public function ‪getValueByPathThrowsSpecificExceptionIfPathNotExists(array $array, string $path): void
352  {
353  $this->expectException(MissingArrayPathException::class);
354  $this->expectExceptionCode(1341397869);
355  ‪ArrayUtility::getValueByPath($array, $path);
356  }
357 
365  public static function ‪getValueByPathValidDataProvider(): array
366  {
367  $testObject = new \stdClass();
368  $testObject->foo = 'foo';
369  $testObject->bar = 'bar';
370  return [
371  'integer in multi level array' => [
372  [
373  'foo' => [
374  'bar' => [
375  'baz' => 42,
376  ],
377  'bar2' => [],
378  ],
379  ],
380  'foo/bar/baz',
381  42,
382  ],
383  'zero integer in multi level array' => [
384  [
385  'foo' => [
386  'bar' => [
387  'baz' => 0,
388  ],
389  ],
390  ],
391  'foo/bar/baz',
392  0,
393  ],
394  'NULL value in multi level array' => [
395  [
396  'foo' => [
397  'baz' => null,
398  ],
399  ],
400  'foo/baz',
401  null,
402  ],
403  'get string value' => [
404  [
405  'foo' => [
406  'baz' => 'this is a test string',
407  ],
408  ],
409  'foo/baz',
410  'this is a test string',
411  ],
412  'get boolean value: FALSE' => [
413  [
414  'foo' => [
415  'baz' => false,
416  ],
417  ],
418  'foo/baz',
419  false,
420  ],
421  'get boolean value: TRUE' => [
422  [
423  'foo' => [
424  'baz' => true,
425  ],
426  ],
427  'foo/baz',
428  true,
429  ],
430  'get object value' => [
431  [
432  'foo' => [
433  'baz' => $testObject,
434  ],
435  ],
436  'foo/baz',
437  $testObject,
438  ],
439  'sub array' => [
440  [
441  'foo' => [
442  'bar' => [
443  'baz' => 42,
444  ],
445  ],
446  ],
447  'foo/bar',
448  [
449  'baz' => 42,
450  ],
451  ],
452  'enclosed path' => [
453  [
454  'foo/bar' => [
455  'foobar' => 42,
456  ],
457  ],
458  '"foo/bar"/foobar',
459  42,
460  ],
461  ];
462  }
463 
470  public function ‪getValueByPathGetsCorrectValue(array $array, $path, $expectedResult): void
471  {
472  self::assertEquals($expectedResult, ‪ArrayUtility::getValueByPath($array, $path));
473  }
474 
479  {
480  $input = [
481  'foo' => [
482  'bar' => [
483  'baz' => 42,
484  ],
485  'bar2' => [],
486  ],
487  ];
488  $searchPath = 'foo%bar%baz';
489  $expected = 42;
490  $delimiter = '%';
491  self::assertEquals(
492  $expected,
493  ‪ArrayUtility::getValueByPath($input, $searchPath, $delimiter)
494  );
495  }
496 
498  // Tests concerning setValueByPath
500 
504  {
505  $this->expectException(\RuntimeException::class);
506  $this->expectExceptionCode(1341406194);
507 
508  ‪ArrayUtility::setValueByPath([], '', null);
509  }
510 
515  {
516  $this->expectException(\RuntimeException::class);
517  $this->expectExceptionCode(1341406846);
518 
519  ‪ArrayUtility::setValueByPath(['foo' => 'bar'], '/foo', 'value');
520  }
521 
526  {
527  self::assertSame(['foo' => ['value']], ‪ArrayUtility::setValueByPath(['foo' => []], 'foo/0', 'value'));
528  }
529 
533  public function ‪setValueByPathCanUseZeroAsPath(): void
534  {
535  self::assertSame(['value', 'bar'], ‪ArrayUtility::setValueByPath(['foo', 'bar'], '0', 'value'));
536  }
537 
547  public static function ‪setValueByPathSetsCorrectValueDataProvider(): array
548  {
549  $testObject = new \stdClass();
550  $testObject->foo = 'foo';
551  $testObject->bar = 'bar';
552  return [
553  'set integer value: 42' => [
554  [
555  'foo' => [
556  'bar' => [
557  'baz' => 0,
558  ],
559  ],
560  ],
561  'foo/bar/baz',
562  42,
563  [
564  'foo' => [
565  'bar' => [
566  'baz' => 42,
567  ],
568  ],
569  ],
570  ],
571  'set integer value: 0' => [
572  [
573  'foo' => [
574  'bar' => [
575  'baz' => 42,
576  ],
577  ],
578  ],
579  'foo/bar/baz',
580  0,
581  [
582  'foo' => [
583  'bar' => [
584  'baz' => 0,
585  ],
586  ],
587  ],
588  ],
589  'set null value' => [
590  [
591  'foo' => [
592  'bar' => [
593  'baz' => 42,
594  ],
595  ],
596  ],
597  'foo/bar/baz',
598  null,
599  [
600  'foo' => [
601  'bar' => [
602  'baz' => null,
603  ],
604  ],
605  ],
606  ],
607  'set array value' => [
608  [
609  'foo' => [
610  'bar' => [
611  'baz' => 42,
612  ],
613  ],
614  ],
615  'foo/bar/baz',
616  [
617  'foo' => 123,
618  ],
619  [
620  'foo' => [
621  'bar' => [
622  'baz' => [
623  'foo' => 123,
624  ],
625  ],
626  ],
627  ],
628  ],
629  'set boolean value: FALSE' => [
630  [
631  'foo' => [
632  'bar' => [
633  'baz' => true,
634  ],
635  ],
636  ],
637  'foo/bar/baz',
638  false,
639  [
640  'foo' => [
641  'bar' => [
642  'baz' => false,
643  ],
644  ],
645  ],
646  ],
647  'set boolean value: TRUE' => [
648  [
649  'foo' => [
650  'bar' => [
651  'baz' => null,
652  ],
653  ],
654  ],
655  'foo/bar/baz',
656  true,
657  [
658  'foo' => [
659  'bar' => [
660  'baz' => true,
661  ],
662  ],
663  ],
664  ],
665  'set object value' => [
666  [
667  'foo' => [
668  'bar' => [
669  'baz' => null,
670  ],
671  ],
672  ],
673  'foo/bar/baz',
674  $testObject,
675  [
676  'foo' => [
677  'bar' => [
678  'baz' => $testObject,
679  ],
680  ],
681  ],
682  ],
683  'multi keys in array' => [
684  [
685  'foo' => [
686  'bar' => [
687  'baz' => 'value',
688  ],
689  'bar2' => [
690  'baz' => 'value',
691  ],
692  ],
693  ],
694  'foo/bar2/baz',
695  'newValue',
696  [
697  'foo' => [
698  'bar' => [
699  'baz' => 'value',
700  ],
701  'bar2' => [
702  'baz' => 'newValue',
703  ],
704  ],
705  ],
706  ],
707  'setting longer path' => [
708  [
709  'foo' => [
710  'bar' => 'value',
711  ],
712  ],
713  'foo/bar/baz/foobar',
714  'newValue',
715  [
716  'foo' => [
717  'bar' => [
718  'baz' => [
719  'foobar' => 'newValue',
720  ],
721  ],
722  ],
723  ],
724  ],
725  'setting longer path in existing array' => [
726  [
727  'foo' => [
728  'bar' => [
729  'existingKey' => 'lolli.did.this',
730  ],
731  ],
732  ],
733  'foo/bar/baz/foobar',
734  'newValue',
735  [
736  'foo' => [
737  'bar' => [
738  'existingKey' => 'lolli.did.this',
739  'baz' => [
740  'foobar' => 'newValue',
741  ],
742  ],
743  ],
744  ],
745  ],
746  ];
747  }
748 
756  public function ‪setValueByPathSetsCorrectValue(array $array, $path, $value, $expectedResult): void
757  {
758  self::assertEquals(
759  $expectedResult,
760  ‪ArrayUtility::setValueByPath($array, $path, $value)
761  );
762  }
763 
764  /**********************
765  /* Tests concerning removeByPath
766  ***********************/
767 
772  {
773  $this->expectException(\RuntimeException::class);
774  $this->expectExceptionCode(1371757718);
775 
777  }
778 
783  {
784  $inputArray = [
785  'foo' => [
786  'bar' => 42,
787  ],
788  ];
789 
790  $this->expectException(\RuntimeException::class);
791  $this->expectExceptionCode(1371757720);
792 
793  ‪ArrayUtility::removeByPath($inputArray, 'foo//bar');
794  }
795 
800  {
801  $inputArray = [
802  'foo' => ['bar'],
803  ];
804 
805  self::assertSame(['foo' => []], ‪ArrayUtility::removeByPath($inputArray, 'foo/0'));
806  }
807 
812  {
813  $inputArray = ['bar'];
814 
815  self::assertSame([], ‪ArrayUtility::removeByPath($inputArray, '0'));
816  }
817 
822  {
823  $inputArray = [
824  'foo' => [
825  'bar' => 42,
826  ],
827  ];
828 
829  $this->expectException(\RuntimeException::class);
830  $this->expectExceptionCode(1371758436);
831 
832  ‪ArrayUtility::removeByPath($inputArray, 'foo/baz');
833  }
834 
839  {
840  $inputArray = [
841  'foo' => [
842  'bar' => 42,
843  ],
844  ];
845 
846  $this->expectException(MissingArrayPathException::class);
847  $this->expectExceptionCode(1371758436);
848 
849  ‪ArrayUtility::removeByPath($inputArray, 'foo/baz');
850  }
851 
855  public function ‪removeByPathAcceptsGivenDelimiter(): void
856  {
857  $inputArray = [
858  'foo' => [
859  'toRemove' => 42,
860  'keep' => 23,
861  ],
862  ];
863  $path = 'foo.toRemove';
864  $expected = [
865  'foo' => [
866  'keep' => 23,
867  ],
868  ];
869  self::assertEquals(
870  $expected,
871  ‪ArrayUtility::removeByPath($inputArray, $path, '.')
872  );
873  }
874 
878  public static function ‪removeByPathRemovesCorrectPathDataProvider(): array
879  {
880  return [
881  'single value' => [
882  [
883  'foo' => [
884  'toRemove' => 42,
885  'keep' => 23,
886  ],
887  ],
888  'foo/toRemove',
889  [
890  'foo' => [
891  'keep' => 23,
892  ],
893  ],
894  ],
895  'whole array' => [
896  [
897  'foo' => [
898  'bar' => 42,
899  ],
900  ],
901  'foo',
902  [],
903  ],
904  'sub array' => [
905  [
906  'foo' => [
907  'keep' => 23,
908  'toRemove' => [
909  'foo' => 'bar',
910  ],
911  ],
912  ],
913  'foo/toRemove',
914  [
915  'foo' => [
916  'keep' => 23,
917  ],
918  ],
919  ],
920  ];
921  }
922 
929  public function ‪removeByPathRemovesCorrectPath(array $array, $path, $expectedResult): void
930  {
931  self::assertEquals(
932  $expectedResult,
933  ‪ArrayUtility::removeByPath($array, $path)
934  );
935  }
936 
938  // Tests concerning sortByKeyRecursive
940 
944  {
945  $unsortedArray = [
946  'z' => null,
947  'a' => null,
948  'd' => [
949  'c' => null,
950  'b' => null,
951  'd' => null,
952  'a' => null,
953  ],
954  ];
955  $expectedResult = [
956  'a' => null,
957  'd' => [
958  'a' => null,
959  'b' => null,
960  'c' => null,
961  'd' => null,
962  ],
963  'z' => null,
964  ];
965  self::assertSame($expectedResult, ‪ArrayUtility::sortByKeyRecursive($unsortedArray));
966  }
967 
969  // Tests concerning sortArraysByKey
971 
975  {
976  return [
977  'assoc array index' => [
978  [
979  '22' => [
980  'uid' => '22',
981  'title' => 'c',
982  'dummy' => 2,
983  ],
984  '24' => [
985  'uid' => '24',
986  'title' => 'a',
987  'dummy' => 3,
988  ],
989  '23' => [
990  'uid' => '23',
991  'title' => 'b',
992  'dummy' => 4,
993  ],
994  ],
995  'title',
996  true,
997  [
998  '24' => [
999  'uid' => '24',
1000  'title' => 'a',
1001  'dummy' => 3,
1002  ],
1003  '23' => [
1004  'uid' => '23',
1005  'title' => 'b',
1006  'dummy' => 4,
1007  ],
1008  '22' => [
1009  'uid' => '22',
1010  'title' => 'c',
1011  'dummy' => 2,
1012  ],
1013  ],
1014  ],
1015  'numeric array index' => [
1016  [
1017  22 => [
1018  'uid' => '22',
1019  'title' => 'c',
1020  'dummy' => 2,
1021  ],
1022  24 => [
1023  'uid' => '24',
1024  'title' => 'a',
1025  'dummy' => 3,
1026  ],
1027  23 => [
1028  'uid' => '23',
1029  'title' => 'b',
1030  'dummy' => 4,
1031  ],
1032  ],
1033  'title',
1034  true,
1035  [
1036  24 => [
1037  'uid' => '24',
1038  'title' => 'a',
1039  'dummy' => 3,
1040  ],
1041  23 => [
1042  'uid' => '23',
1043  'title' => 'b',
1044  'dummy' => 4,
1045  ],
1046  22 => [
1047  'uid' => '22',
1048  'title' => 'c',
1049  'dummy' => 2,
1050  ],
1051  ],
1052  ],
1053  'numeric array index DESC' => [
1054  [
1055  23 => [
1056  'uid' => '23',
1057  'title' => 'b',
1058  'dummy' => 4,
1059  ],
1060  22 => [
1061  'uid' => '22',
1062  'title' => 'c',
1063  'dummy' => 2,
1064  ],
1065  24 => [
1066  'uid' => '24',
1067  'title' => 'a',
1068  'dummy' => 3,
1069  ],
1070  ],
1071  'title',
1072  false,
1073  [
1074  22 => [
1075  'uid' => '22',
1076  'title' => 'c',
1077  'dummy' => 2,
1078  ],
1079  23 => [
1080  'uid' => '23',
1081  'title' => 'b',
1082  'dummy' => 4,
1083  ],
1084  24 => [
1085  'uid' => '24',
1086  'title' => 'a',
1087  'dummy' => 3,
1088  ],
1089  ],
1090  ],
1091  ];
1092  }
1093 
1101  public function ‪sortArraysByKeyCheckIfSortingIsCorrect(array $array, $key, $ascending, $expectedResult): void
1102  {
1103  $sortedArray = ‪ArrayUtility::sortArraysByKey($array, $key, $ascending);
1104  self::assertSame($expectedResult, $sortedArray);
1105  }
1106 
1111  {
1112  $this->expectException(\RuntimeException::class);
1113  $this->expectExceptionCode(1373727309);
1114 
1115  ‪ArrayUtility::sortArraysByKey([['a'], ['a']], 'dummy');
1116  }
1117 
1119  // Tests concerning arrayExport
1121 
1125  {
1126  $array = [
1127  'foo' => [
1128  'bar' => 42,
1129  'bar2' => [
1130  'baz' => 'val\'ue',
1131  'baz2' => true,
1132  'baz3' => false,
1133  'baz4' => [],
1134  ],
1135  ],
1136  'baz' => 23,
1137  'foobar' => null,
1138  'qux' => 0.1,
1139  'qux2' => 0.000000001,
1140  ];
1141  $expected =
1142  '[' . LF .
1143  ' \'foo\' => [' . LF .
1144  ' \'bar\' => 42,' . LF .
1145  ' \'bar2\' => [' . LF .
1146  ' \'baz\' => \'val\\\'ue\',' . LF .
1147  ' \'baz2\' => true,' . LF .
1148  ' \'baz3\' => false,' . LF .
1149  ' \'baz4\' => [],' . LF .
1150  ' ],' . LF .
1151  ' ],' . LF .
1152  ' \'baz\' => 23,' . LF .
1153  ' \'foobar\' => null,' . LF .
1154  ' \'qux\' => 0.1,' . LF .
1155  ' \'qux2\' => 1.0E-9,' . LF .
1156  ']';
1157  self::assertSame($expected, ‪ArrayUtility::arrayExport($array));
1158  }
1159 
1164  {
1165  $array = [
1166  'foo' => [
1167  'bar' => new \stdClass(),
1168  ],
1169  ];
1170 
1171  $this->expectException(\RuntimeException::class);
1172  $this->expectExceptionCode(1342294987);
1173 
1175  }
1176 
1181  {
1182  $array = [
1183  'foo' => 'string key',
1184  23 => 'integer key',
1185  '42' => 'string key representing integer',
1186  ];
1187  $expected =
1188  '[' . LF .
1189  ' \'foo\' => \'string key\',' . LF .
1190  ' 23 => \'integer key\',' . LF .
1191  ' 42 => \'string key representing integer\',' . LF .
1192  ']';
1193  self::assertSame($expected, ‪ArrayUtility::arrayExport($array));
1194  }
1195 
1200  {
1201  $array = [
1202  0 => 'zero',
1203  1 => 'one',
1204  2 => 'two',
1205  ];
1206  $expected =
1207  '[' . LF .
1208  ' \'zero\',' . LF .
1209  ' \'one\',' . LF .
1210  ' \'two\',' . LF .
1211  ']';
1212  self::assertSame($expected, ‪ArrayUtility::arrayExport($array));
1213  }
1214 
1219  {
1220  $array = [
1221  0 => 'zero',
1222  1 => 'one',
1223  3 => 'three',
1224  4 => 'four',
1225  ];
1226  $expected =
1227  '[' . LF .
1228  ' 0 => \'zero\',' . LF .
1229  ' 1 => \'one\',' . LF .
1230  ' 3 => \'three\',' . LF .
1231  ' 4 => \'four\',' . LF .
1232  ']';
1233  self::assertSame($expected, ‪ArrayUtility::arrayExport($array));
1234  }
1235 
1236  public static function ‪flattenCalculatesExpectedResultDataProvider(): array
1237  {
1238  return [
1239  'plain array' => [
1240  [
1241  'first' => 1,
1242  'second' => 2,
1243  ],
1244  [
1245  'first' => 1,
1246  'second' => 2,
1247  ],
1248  ],
1249  'plain array with faulty dots' => [
1250  [
1251  'first.' => 1,
1252  'second.' => 2,
1253  ],
1254  [
1255  'first' => 1,
1256  'second' => 2,
1257  ],
1258  ],
1259  'nested array with integer key' => [
1260  [
1261  'templateRootPaths.' => [
1262  10 => '',
1263  ],
1264  ],
1265  [
1266  'templateRootPaths.10' => '',
1267  ],
1268  ],
1269  'nested array of 2 levels' => [
1270  [
1271  'first.' => [
1272  'firstSub' => 1,
1273  ],
1274  'second.' => [
1275  'secondSub' => 2,
1276  ],
1277  ],
1278  [
1279  'first.firstSub' => 1,
1280  'second.secondSub' => 2,
1281  ],
1282  ],
1283  'nested array of 2 levels and values on first level' => [
1284  [
1285  'first' => 'first',
1286  'first.' => [
1287  'firstSub' => 1,
1288  ],
1289  'second' => 'second',
1290  'second.' => [
1291  'secondSub' => 2,
1292  ],
1293  ],
1294  [
1295  'first' => 'first',
1296  'first.firstSub' => 1,
1297  'second' => 'second',
1298  'second.secondSub' => 2,
1299  ],
1300  ],
1301  'nested array of 2 levels with faulty dots' => [
1302  [
1303  'first.' => [
1304  'firstSub.' => 1,
1305  ],
1306  'second.' => [
1307  'secondSub.' => 2,
1308  ],
1309  ],
1310  [
1311  'first.firstSub' => 1,
1312  'second.secondSub' => 2,
1313  ],
1314  ],
1315  'nested array of 3 levels' => [
1316  [
1317  'first.' => [
1318  'firstSub.' => [
1319  'firstSubSub' => 1,
1320  ],
1321  ],
1322  'second.' => [
1323  'secondSub.' => [
1324  'secondSubSub' => 2,
1325  ],
1326  ],
1327  ],
1328  [
1329  'first.firstSub.firstSubSub' => 1,
1330  'second.secondSub.secondSubSub' => 2,
1331  ],
1332  ],
1333  'nested array of 3 levels with faulty dots' => [
1334  [
1335  'first.' => [
1336  'firstSub.' => [
1337  'firstSubSub.' => 1,
1338  ],
1339  ],
1340  'second.' => [
1341  'secondSub.' => [
1342  'secondSubSub.' => 2,
1343  ],
1344  ],
1345  ],
1346  [
1347  'first.firstSub.firstSubSub' => 1,
1348  'second.secondSub.secondSubSub' => 2,
1349  ],
1350  ],
1351  ];
1352  }
1353 
1358  public function ‪flattenCalculatesExpectedResult(array $array, array $expected): void
1359  {
1360  self::assertEquals($expected, ‪ArrayUtility::flatten($array));
1361  }
1362 
1364  {
1365  return [
1366  'plain array' => [
1367  [
1368  'first' => 1,
1369  'second' => 2,
1370  ],
1371  [
1372  'first' => 1,
1373  'second' => 2,
1374  ],
1375  ],
1376  'plain array with trailing dots' => [
1377  [
1378  'first.' => 1,
1379  'second.' => 2,
1380  ],
1381  [
1382  'first\.' => 1,
1383  'second\.' => 2,
1384  ],
1385  ],
1386  'nested array of 2 levels' => [
1387  [
1388  'first' => [
1389  'firstSub' => 1,
1390  ],
1391  'second' => [
1392  'secondSub' => 2,
1393  ],
1394  ],
1395  [
1396  'first.firstSub' => 1,
1397  'second.secondSub' => 2,
1398  ],
1399  ],
1400  'nested array of 2 levels with dots in keys' => [
1401  [
1402  'first.el' => [
1403  'firstSub.' => 1,
1404  ],
1405  'second.el' => [
1406  'secondSub.' => 2,
1407  ],
1408  ],
1409  [
1410  'first\.el.firstSub\.' => 1,
1411  'second\.el.secondSub\.' => 2,
1412  ],
1413  ],
1414  'nested array of 2 levels with dots inside keys' => [
1415  [
1416  'first' => [
1417  'first.sub' => 1,
1418  ],
1419  'second' => [
1420  'second.sub' => 2,
1421  ],
1422  ],
1423  [
1424  'first.first\.sub' => 1,
1425  'second.second\.sub' => 2,
1426  ],
1427  ],
1428  'nested array of 3 levels' => [
1429  [
1430  'first' => [
1431  'firstSub' => [
1432  'firstSubSub' => 1,
1433  ],
1434  ],
1435  'second' => [
1436  'secondSub' => [
1437  'secondSubSub' => 2,
1438  ],
1439  ],
1440  ],
1441  [
1442  'first.firstSub.firstSubSub' => 1,
1443  'second.secondSub.secondSubSub' => 2,
1444  ],
1445  ],
1446  'nested array of 3 levels with dots in keys' => [
1447  [
1448  'first.' => [
1449  'firstSub.' => [
1450  'firstSubSub.' => 1,
1451  ],
1452  ],
1453  'second.' => [
1454  'secondSub.' => [
1455  'secondSubSub.' => 2,
1456  ],
1457  ],
1458  ],
1459  [
1460  'first\..firstSub\..firstSubSub\.' => 1,
1461  'second\..secondSub\..secondSubSub\.' => 2,
1462  ],
1463  ],
1464  'duplicate keys, one with dot, one without' => [
1465  [
1466  'foo' => 'node',
1467  'foo.' => [
1468  'bar' => 'bla',
1469  ],
1470  ],
1471  [
1472  'foo' => 'node',
1473  'foo\..bar' => 'bla',
1474  ],
1475  ],
1476  'duplicate keys, one with dot with scalar value, one without, last wins' => [
1477  [
1478  'foo.' => 'dot',
1479  'foo' => 'node',
1480  ],
1481  [
1482  'foo\.' => 'dot',
1483  'foo' => 'node',
1484  ],
1485  ],
1486  'empty key' => [
1487  [
1488  '' => 'node',
1489  ],
1490  [
1491  '' => 'node',
1492  ],
1493  ],
1494  'dot key' => [
1495  [
1496  '.' => 'node',
1497  ],
1498  [
1499  '\.' => 'node',
1500  ],
1501  ],
1502  'empty array' => [
1503  [],
1504  [],
1505  ],
1506  'nested lists' => [
1507  [
1508  ['foo', 'bar'],
1509  ['bla', 'baz'],
1510  ],
1511  [
1512  '0.0' => 'foo',
1513  '0.1' => 'bar',
1514  '1.0' => 'bla',
1515  '1.1' => 'baz',
1516  ],
1517  ],
1518  ];
1519  }
1520 
1525  public function ‪flattenPlainCalculatesExpectedResult(array $array, array $expected): void
1526  {
1527  self::assertEquals($expected, ‪ArrayUtility::flattenPlain($array));
1528  }
1529 
1531  {
1532  return [
1533  'plain array' => [
1534  [
1535  'first' => 1,
1536  'second' => 2,
1537  ],
1538  [
1539  'first' => 1,
1540  'second' => 2,
1541  ],
1542  ],
1543  'plain array with dots' => [
1544  [
1545  'first.' => 1,
1546  'second.' => 2,
1547  ],
1548  [
1549  'first.' => 1,
1550  'second.' => 2,
1551  ],
1552  ],
1553  'nested array of 2 levels' => [
1554  [
1555  'first.' => [
1556  'firstSub' => 1,
1557  ],
1558  'second.' => [
1559  'secondSub' => 2,
1560  ],
1561  ],
1562  [
1563  'first.firstSub' => 1,
1564  'second.secondSub' => 2,
1565  ],
1566  ],
1567  'nested array of 2 levels with dots' => [
1568  [
1569  'first.' => [
1570  'firstSub.' => 1,
1571  ],
1572  'second.' => [
1573  'secondSub.' => 2,
1574  ],
1575  ],
1576  [
1577  'first.firstSub.' => 1,
1578  'second.secondSub.' => 2,
1579  ],
1580  ],
1581  'nested array of 3 levels' => [
1582  [
1583  'first.' => [
1584  'firstSub.' => [
1585  'firstSubSub' => 1,
1586  ],
1587  ],
1588  'second.' => [
1589  'secondSub.' => [
1590  'secondSubSub' => 2,
1591  ],
1592  ],
1593  ],
1594  [
1595  'first.firstSub.firstSubSub' => 1,
1596  'second.secondSub.secondSubSub' => 2,
1597  ],
1598  ],
1599  'nested array of 3 levels with dots' => [
1600  [
1601  'first.' => [
1602  'firstSub.' => [
1603  'firstSubSub.' => 1,
1604  ],
1605  ],
1606  'second.' => [
1607  'secondSub.' => [
1608  'secondSubSub.' => 2,
1609  ],
1610  ],
1611  ],
1612  [
1613  'first.firstSub.firstSubSub.' => 1,
1614  'second.secondSub.secondSubSub.' => 2,
1615  ],
1616  ],
1617  'nested array of 3 levels with multi dots' => [
1618  [
1619  'first.' => [
1620  'firstSub..' => [
1621  'firstSubSub..' => 1,
1622  ],
1623  ],
1624  'second.' => [
1625  'secondSub..' => [
1626  'secondSubSub.' => 2,
1627  ],
1628  ],
1629  ],
1630  [
1631  'first.firstSub..firstSubSub..' => 1,
1632  'second.secondSub..secondSubSub.' => 2,
1633  ],
1634  ],
1635  ];
1636  }
1637 
1642  public function ‪flattenWithKeepDotsCalculatesExpectedResult(array $array, array $expected): void
1643  {
1644  self::assertEquals($expected, ‪ArrayUtility::flatten($array, '', true));
1645  }
1646 
1648  {
1649  return [
1650  'plain array' => [
1651  [
1652  'first' => 1,
1653  'second' => 2,
1654  ],
1655  [
1656  'first' => 1,
1657  'second' => 2,
1658  ],
1659  ],
1660  'plain array with trailing dots' => [
1661  [
1662  'first\.' => 1,
1663  'second\.' => 2,
1664  ],
1665  [
1666  'first.' => 1,
1667  'second.' => 2,
1668  ],
1669  ],
1670  'nested array of 2 levels' => [
1671  [
1672  'first.firstSub' => 1,
1673  'second.secondSub' => 2,
1674  ],
1675  [
1676  'first' => [
1677  'firstSub' => 1,
1678  ],
1679  'second' => [
1680  'secondSub' => 2,
1681  ],
1682  ],
1683  ],
1684  'nested array of 2 levels with dots in keys' => [
1685  [
1686  'first\.el.firstSub\.' => 1,
1687  'second\.el.secondSub\.' => 2,
1688  ],
1689  [
1690  'first.el' => [
1691  'firstSub.' => 1,
1692  ],
1693  'second.el' => [
1694  'secondSub.' => 2,
1695  ],
1696  ],
1697  ],
1698  'nested array of 2 levels with dots inside keys' => [
1699  [
1700  'first.first\.sub' => 1,
1701  'second.second\.sub' => 2,
1702  ],
1703  [
1704  'first' => [
1705  'first.sub' => 1,
1706  ],
1707  'second' => [
1708  'second.sub' => 2,
1709  ],
1710  ],
1711  ],
1712  'nested array of 3 levels' => [
1713  [
1714  'first.firstSub.firstSubSub' => 1,
1715  'second.secondSub.secondSubSub' => 2,
1716  ],
1717  [
1718  'first' => [
1719  'firstSub' => [
1720  'firstSubSub' => 1,
1721  ],
1722  ],
1723  'second' => [
1724  'secondSub' => [
1725  'secondSubSub' => 2,
1726  ],
1727  ],
1728  ],
1729  ],
1730  'nested array of 3 levels with dots in keys' => [
1731  [
1732  'first\..firstSub\..firstSubSub\.' => 1,
1733  'second\..secondSub\..secondSubSub\.' => 2,
1734  ],
1735  [
1736  'first.' => [
1737  'firstSub.' => [
1738  'firstSubSub.' => 1,
1739  ],
1740  ],
1741  'second.' => [
1742  'secondSub.' => [
1743  'secondSubSub.' => 2,
1744  ],
1745  ],
1746  ],
1747  ],
1748  'duplicate keys, one with dot, one without' => [
1749  [
1750  'foo' => 'node',
1751  'foo\..bar' => 'bla',
1752  ],
1753  [
1754  'foo' => 'node',
1755  'foo.' => [
1756  'bar' => 'bla',
1757  ],
1758  ],
1759  ],
1760  'duplicate keys, one with dot with scalar value, one without, last wins' => [
1761  [
1762  'foo\.' => 'dot',
1763  'foo' => 'node',
1764  ],
1765  [
1766  'foo.' => 'dot',
1767  'foo' => 'node',
1768  ],
1769  ],
1770  'empty key' => [
1771  [
1772  '' => 'node',
1773  ],
1774  [
1775  '' => 'node',
1776  ],
1777  ],
1778  'dot key' => [
1779  [
1780  '\.' => 'node',
1781  ],
1782  [
1783  '.' => 'node',
1784  ],
1785  ],
1786  'empty array' => [
1787  [],
1788  [],
1789  ],
1790  'nested lists' => [
1791  [
1792  '0.0' => 'foo',
1793  '0.1' => 'bar',
1794  '1.0' => 'bla',
1795  '1.1' => 'baz',
1796  ],
1797  [
1798  ['foo', 'bar'],
1799  ['bla', 'baz'],
1800  ],
1801  ],
1802  ];
1803  }
1804 
1809  public function ‪unflattenCalculatesExpectedResult(array $array, array $expected): void
1810  {
1811  self::assertEquals($expected, ArrayUtility::unflatten($array));
1812  }
1813 
1815  {
1816  $sameObject = new \stdClass();
1817  return [
1818  // array($source, $mask, $expected)
1819  'empty array is returned if source is empty array' => [
1820  [],
1821  [
1822  'foo' => 'bar',
1823  ],
1824  [],
1825  ],
1826  'empty array is returned if mask is empty' => [
1827  [
1828  'foo' => 'bar',
1829  ],
1830  [],
1831  [],
1832  ],
1833  'key is kept on first level if exists in mask' => [
1834  [
1835  'foo' => 42,
1836  ],
1837  [
1838  'foo' => 42,
1839  ],
1840  [
1841  'foo' => 42,
1842  ],
1843  ],
1844  'value of key in source is kept if mask has different value' => [
1845  [
1846  'foo' => 42,
1847  ],
1848  [
1849  'foo' => new \stdClass(),
1850  ],
1851  [
1852  'foo' => 42,
1853  ],
1854  ],
1855  'key is kept on first level if according mask value is NULL' => [
1856  [
1857  'foo' => 42,
1858  ],
1859  [
1860  'foo' => null,
1861  ],
1862  [
1863  'foo' => 42,
1864  ],
1865  ],
1866  'null in source value is kept' => [
1867  [
1868  'foo' => null,
1869  ],
1870  [
1871  'foo' => 'bar',
1872  ],
1873  [
1874  'foo' => null,
1875  ],
1876  ],
1877  'mask does not add new keys' => [
1878  [
1879  'foo' => 42,
1880  ],
1881  [
1882  'foo' => 23,
1883  'bar' => [
1884  4711,
1885  ],
1886  ],
1887  [
1888  'foo' => 42,
1889  ],
1890  ],
1891  'mask does not overwrite simple values with arrays' => [
1892  [
1893  'foo' => 42,
1894  ],
1895  [
1896  'foo' => [
1897  'bar' => 23,
1898  ],
1899  ],
1900  [
1901  'foo' => 42,
1902  ],
1903  ],
1904  'key is kept on first level if according mask value is array' => [
1905  [
1906  'foo' => 42,
1907  ],
1908  [
1909  'foo' => [
1910  'bar' => 23,
1911  ],
1912  ],
1913  [
1914  'foo' => 42,
1915  ],
1916  ],
1917  'full array is kept if value is array and mask value is simple type' => [
1918  [
1919  'foo' => [
1920  'bar' => 23,
1921  ],
1922  ],
1923  [
1924  'foo' => 42,
1925  ],
1926  [
1927  'foo' => [
1928  'bar' => 23,
1929  ],
1930  ],
1931  ],
1932  'key handling is type agnostic' => [
1933  [
1934  42 => 'foo',
1935  ],
1936  [
1937  '42' => 'bar',
1938  ],
1939  [
1940  42 => 'foo',
1941  ],
1942  ],
1943  'value is same if value is object' => [
1944  [
1945  'foo' => $sameObject,
1946  ],
1947  [
1948  'foo' => 'something',
1949  ],
1950  [
1951  'foo' => $sameObject,
1952  ],
1953  ],
1954  'mask does not add simple value to result if key does not exist in source' => [
1955  [
1956  'foo' => '42',
1957  ],
1958  [
1959  'foo' => '42',
1960  'bar' => 23,
1961  ],
1962  [
1963  'foo' => '42',
1964  ],
1965  ],
1966  'array of source is kept if value of mask key exists but is no array' => [
1967  [
1968  'foo' => '42',
1969  'bar' => [
1970  'baz' => 23,
1971  ],
1972  ],
1973  [
1974  'foo' => 'value is not significant',
1975  'bar' => null,
1976  ],
1977  [
1978  'foo' => '42',
1979  'bar' => [
1980  'baz' => 23,
1981  ],
1982  ],
1983  ],
1984  'sub arrays are kept if mask has according sub array key and is similar array' => [
1985  [
1986  'first1' => 42,
1987  'first2' => [
1988  'second1' => 23,
1989  'second2' => 4711,
1990  ],
1991  ],
1992  [
1993  'first1' => 42,
1994  'first2' => [
1995  'second1' => 'exists but different',
1996  ],
1997  ],
1998  [
1999  'first1' => 42,
2000  'first2' => [
2001  'second1' => 23,
2002  ],
2003  ],
2004  ],
2005  ];
2006  }
2007 
2012  public function ‪intersectRecursiveCalculatesExpectedResult(array $source, array $mask, array $expected): void
2013  {
2014  self::assertSame($expected, ArrayUtility::intersectRecursive($source, $mask));
2015  }
2016 
2018  {
2019  return [
2020  'empty array is returned if source is empty array' => [
2021  [],
2022  [],
2023  ],
2024  'returns self if array is already numerically keyed' => [
2025  [1, 2, 3],
2026  [1, 2, 3],
2027  ],
2028  'returns correctly if keys are numeric, but contains a leap' => [
2029  [0 => 'One', 1 => 'Two', 3 => 'Three'],
2030  [0 => 'One', 1 => 'Two', 2 => 'Three'],
2031  ],
2032  'returns correctly even though keys are strings but still numeric' => [
2033  ['0' => 'One', '1' => 'Two', '3' => 'Three'],
2034  [0 => 'One', 1 => 'Two', 2 => 'Three'],
2035  ],
2036  'returns correctly if just a single keys is not numeric' => [
2037  [0 => 'Zero', '1' => 'One', 'Two' => 'Two'],
2038  [0 => 'Zero', '1' => 'One', 'Two' => 'Two'],
2039  ],
2040  'returns unchanged if keys end with a dot' => [
2041  ['2.' => 'Two', '1.' => 'One', '0.' => 'Zero'],
2042  ['2.' => 'Two', '1.' => 'One', '0.' => 'Zero'],
2043  ],
2044  'return self with nested numerically keyed array' => [
2045  [
2046  'One',
2047  'Two',
2048  'Three',
2049  [
2050  'sub.One',
2051  'sub.Two',
2052  ],
2053  ],
2054  [
2055  'One',
2056  'Two',
2057  'Three',
2058  [
2059  'sub.One',
2060  'sub.Two',
2061  ],
2062  ],
2063  ],
2064  'returns correctly with nested numerically keyed array with leaps' => [
2065  [
2066  'One',
2067  'Two',
2068  'Three',
2069  [
2070  0 => 'sub.One',
2071  2 => 'sub.Two',
2072  ],
2073  ],
2074  [
2075  'One',
2076  'Two',
2077  'Three',
2078  [
2079  'sub.One',
2080  'sub.Two',
2081  ],
2082  ],
2083  ],
2084  'returns correctly with nested string-keyed array' => [
2085  [
2086  'One',
2087  'Two',
2088  'Three',
2089  [
2090  'one' => 'sub.One',
2091  'two' => 'sub.Two',
2092  ],
2093  ],
2094  [
2095  'One',
2096  'Two',
2097  'Three',
2098  [
2099  'one' => 'sub.One',
2100  'two' => 'sub.Two',
2101  ],
2102  ],
2103  ],
2104  'returns correctly with deeply nested arrays' => [
2105  [
2106  'One',
2107  'Two',
2108  [
2109  'one' => 1,
2110  'two' => 2,
2111  'three' => [
2112  2 => 'SubSubOne',
2113  5 => 'SubSubTwo',
2114  9 => [0, 1, 2],
2115  [],
2116  ],
2117  ],
2118  ],
2119  [
2120  'One',
2121  'Two',
2122  [
2123  'one' => 1,
2124  'two' => 2,
2125  'three' => [
2126  'SubSubOne',
2127  'SubSubTwo',
2128  [0, 1, 2],
2129  [],
2130  ],
2131  ],
2132  ],
2133  ],
2134  ];
2135  }
2136 
2141  public function ‪renumberKeysToAvoidLeapsIfKeysAreAllNumericReturnsExpectedOrder(array $inputArray, array $expected): void
2142  {
2143  self::assertEquals($expected, ArrayUtility::renumberKeysToAvoidLeapsIfKeysAreAllNumeric($inputArray));
2144  }
2145 
2147  {
2148  return [
2149  'Override array can reset string to array' => [
2150  [
2151  'first' => [
2152  'second' => 'foo',
2153  ],
2154  ],
2155  [
2156  'first' => [
2157  'second' => ['third' => 'bar'],
2158  ],
2159  ],
2160  true,
2161  true,
2162  true,
2163  [
2164  'first' => [
2165  'second' => ['third' => 'bar'],
2166  ],
2167  ],
2168  ],
2169  'Override array does not reset array to string (weird!)' => [
2170  [
2171  'first' => [],
2172  ],
2173  [
2174  'first' => 'foo',
2175  ],
2176  true,
2177  true,
2178  true,
2179  [
2180  'first' => [], // This is rather unexpected, naive expectation: first => 'foo'
2181  ],
2182  ],
2183  'Override array does override string with null' => [
2184  [
2185  'first' => 'foo',
2186  ],
2187  [
2188  'first' => null,
2189  ],
2190  true,
2191  true,
2192  true,
2193  [
2194  'first' => null,
2195  ],
2196  ],
2197  'Override array does override null with string' => [
2198  [
2199  'first' => null,
2200  ],
2201  [
2202  'first' => 'foo',
2203  ],
2204  true,
2205  true,
2206  true,
2207  [
2208  'first' => 'foo',
2209  ],
2210  ],
2211  'Override array does override null with empty string' => [
2212  [
2213  'first' => null,
2214  ],
2215  [
2216  'first' => '',
2217  ],
2218  true,
2219  true,
2220  true,
2221  [
2222  'first' => '',
2223  ],
2224  ],
2225  'Override array does not override string with NULL if requested' => [
2226  [
2227  'first' => 'foo',
2228  ],
2229  [
2230  'first' => null,
2231  ],
2232  true,
2233  false, // no include empty values
2234  true,
2235  [
2236  'first' => 'foo',
2237  ],
2238  ],
2239  'Override array does override null with null' => [
2240  [
2241  'first' => null,
2242  ],
2243  [
2244  'first' => null,
2245  ],
2246  true,
2247  true,
2248  true,
2249  [
2250  'first' => '',
2251  ],
2252  ],
2253  'Override array can __UNSET values' => [
2254  [
2255  'first' => [
2256  'second' => 'second',
2257  'third' => 'third',
2258  ],
2259  'fifth' => [],
2260  ],
2261  [
2262  'first' => [
2263  'second' => 'overrule',
2264  'third' => '__UNSET',
2265  'fourth' => 'overrile',
2266  ],
2267  'fifth' => '__UNSET',
2268  ],
2269  true,
2270  true,
2271  true,
2272  [
2273  'first' => [
2274  'second' => 'overrule',
2275  'fourth' => 'overrile',
2276  ],
2277  ],
2278  ],
2279  'Override can add keys' => [
2280  [
2281  'first' => 'foo',
2282  ],
2283  [
2284  'second' => 'bar',
2285  ],
2286  true,
2287  true,
2288  true,
2289  [
2290  'first' => 'foo',
2291  'second' => 'bar',
2292  ],
2293  ],
2294  'Override does not add key if __UNSET' => [
2295  [
2296  'first' => 'foo',
2297  ],
2298  [
2299  'second' => '__UNSET',
2300  ],
2301  true,
2302  true,
2303  true,
2304  [
2305  'first' => 'foo',
2306  ],
2307  ],
2308  'Override does not add key if not requested' => [
2309  [
2310  'first' => 'foo',
2311  ],
2312  [
2313  'second' => 'bar',
2314  ],
2315  false, // no add keys
2316  true,
2317  true,
2318  [
2319  'first' => 'foo',
2320  ],
2321  ],
2322  'Override does not add key if not requested with add include empty values' => [
2323  [
2324  'first' => 'foo',
2325  ],
2326  [
2327  'second' => 'bar',
2328  ],
2329  false, // no add keys
2330  false, // no include empty values
2331  true,
2332  [
2333  'first' => 'foo',
2334  ],
2335  ],
2336  'Override does not override string with empty string if requested' => [
2337  [
2338  'first' => 'foo',
2339  ],
2340  [
2341  'first' => '',
2342  ],
2343  true,
2344  false, // no include empty values
2345  true,
2346  [
2347  'first' => 'foo',
2348  ],
2349  ],
2350  'Override array does merge instead of __UNSET if requested (weird!)' => [
2351  [
2352  'first' => [
2353  'second' => 'second',
2354  'third' => 'third',
2355  ],
2356  'fifth' => [],
2357  ],
2358  [
2359  'first' => [
2360  'second' => 'overrule',
2361  'third' => '__UNSET',
2362  'fourth' => 'overrile',
2363  ],
2364  'fifth' => '__UNSET',
2365  ],
2366  true,
2367  true,
2368  false,
2369  [
2370  'first' => [
2371  'second' => 'overrule',
2372  'third' => '__UNSET', // overruled
2373  'fourth' => 'overrile',
2374  ],
2375  'fifth' => [], // not overruled with string here, naive expectation: 'fifth' => '__UNSET'
2376  ],
2377  ],
2378  ];
2379  }
2380 
2391  public function ‪mergeRecursiveWithOverruleCalculatesExpectedResult($input1, $input2, $addKeys, $includeEmptyValues, $enableUnsetFeature, $expected): void
2392  {
2393  ArrayUtility::mergeRecursiveWithOverrule($input1, $input2, $addKeys, $includeEmptyValues, $enableUnsetFeature);
2394  self::assertEquals($expected, $input1);
2395  }
2396 
2398  // Tests concerning removeArrayEntryByValue
2400 
2404  {
2405  $inputArray = [
2406  '0' => 'test1',
2407  '1' => 'test2',
2408  '2' => 'test3',
2409  '3' => 'test2',
2410  ];
2411  $compareValue = 'test2';
2412  $expectedResult = [
2413  '0' => 'test1',
2414  '2' => 'test3',
2415  ];
2416  $actualResult = ArrayUtility::removeArrayEntryByValue($inputArray, $compareValue);
2417  self::assertEquals($expectedResult, $actualResult);
2418  }
2419 
2424  {
2425  $inputArray = [
2426  '0' => 'foo',
2427  '1' => [
2428  '10' => 'bar',
2429  ],
2430  '2' => 'bar',
2431  ];
2432  $compareValue = 'bar';
2433  $expectedResult = [
2434  '0' => 'foo',
2435  '1' => [],
2436  ];
2437  $actualResult = ArrayUtility::removeArrayEntryByValue($inputArray, $compareValue);
2438  self::assertEquals($expectedResult, $actualResult);
2439  }
2440 
2445  {
2446  $inputArray = [
2447  '0' => 'foo',
2448  '1' => '',
2449  '2' => 'bar',
2450  ];
2451  $compareValue = '';
2452  $expectedResult = [
2453  '0' => 'foo',
2454  '2' => 'bar',
2455  ];
2456  $actualResult = ArrayUtility::removeArrayEntryByValue($inputArray, $compareValue);
2457  self::assertEquals($expectedResult, $actualResult);
2458  }
2459 
2461  // Tests concerning keepItemsInArray
2463 
2470  public function ‪keepItemsInArrayWorksWithOneArgument($search, $array, $expected): void
2471  {
2472  self::assertEquals($expected, ArrayUtility::keepItemsInArray($array, $search));
2473  }
2474 
2479  {
2480  $array = [
2481  0 => 0,
2482  'one' => 'one',
2483  'two' => 'two',
2484  'three' => 'three',
2485  ];
2486  return [
2487  'Empty argument will match "all" elements' => [null, $array, $array],
2488  'No match' => ['four', $array, []],
2489  'One match' => ['two', $array, ['two' => 'two']],
2490  'Multiple matches' => ['two,one', $array, ['one' => 'one', 'two' => 'two']],
2491  'Argument can be an array' => [['three'], $array, ['three' => 'three']],
2492  ];
2493  }
2494 
2502  public function ‪keepItemsInArrayCanUseClosure(): void
2503  {
2504  $array = [
2505  'aa' => ['first', 'second'],
2506  'bb' => ['third', 'fourth'],
2507  'cc' => ['fifth', 'sixth'],
2508  ];
2509  $expected = ['bb' => ['third', 'fourth']];
2510  $keepItems = 'third';
2511  $match = ArrayUtility::keepItemsInArray(
2512  $array,
2513  $keepItems,
2514  static function ($value) {
2515  return $value[0];
2516  }
2517  );
2518  self::assertEquals($expected, $match);
2519  }
2520 
2522  // Tests concerning remapArrayKeys
2524 
2528  {
2529  $array = [
2530  'one' => 'one',
2531  'two' => 'two',
2532  'three' => 'three',
2533  ];
2534  $keyMapping = [
2535  'one' => '1',
2536  'two' => '2',
2537  ];
2538  $expected = [
2539  '1' => 'one',
2540  '2' => 'two',
2541  'three' => 'three',
2542  ];
2543  ArrayUtility::remapArrayKeys($array, $keyMapping);
2544  self::assertEquals($expected, $array);
2545  }
2546 
2548  // Tests concerning arrayDiffKeyRecursive
2550 
2554  {
2555  $array1 = [
2556  'key1' => 'value1',
2557  'key2' => 'value2',
2558  'key3' => 'value3',
2559  ];
2560  $array2 = [
2561  'key1' => 'value1',
2562  'key3' => 'value3',
2563  ];
2564  $expectedResult = [
2565  'key2' => 'value2',
2566  ];
2567  $actualResult = ArrayUtility::arrayDiffKeyRecursive($array1, $array2);
2568  self::assertEquals($expectedResult, $actualResult);
2569  }
2570 
2575  {
2576  $array1 = [
2577  'key1' => 'value1',
2578  'key2' => [
2579  'key21' => 'value21',
2580  'key22' => 'value22',
2581  'key23' => [
2582  'key231' => 'value231',
2583  'key232' => 'value232',
2584  ],
2585  ],
2586  ];
2587  $array2 = [
2588  'key1' => 'valueDoesNotMatter',
2589  'key2' => [
2590  'key21' => 'value21',
2591  'key23' => [
2592  'key231' => 'value231',
2593  ],
2594  ],
2595  ];
2596  $expectedResult = [
2597  'key2' => [
2598  'key22' => 'value22',
2599  'key23' => [
2600  'key232' => 'value232',
2601  ],
2602  ],
2603  ];
2604  $actualResult = ArrayUtility::arrayDiffKeyRecursive($array1, $array2);
2605  self::assertEquals($expectedResult, $actualResult);
2606  }
2607 
2612  {
2613  $array1 = [
2614  'key1' => [
2615  'key11' => 'value11',
2616  'key12' => 'value12',
2617  ],
2618  'key2' => 'value2',
2619  'key3' => 'value3',
2620  ];
2621  $array2 = [
2622  'key1' => 'value1',
2623  'key2' => [
2624  'key21' => 'valueDoesNotMatter',
2625  ],
2626  ];
2627  $expectedResult = [
2628  'key3' => 'value3',
2629  ];
2630  $actualResult = ArrayUtility::arrayDiffKeyRecursive($array1, $array2);
2631  self::assertEquals($expectedResult, $actualResult);
2632  }
2633 
2638  {
2639  $array1 = [
2640  'key1' => [
2641  'key11' => 'value11',
2642  'key12' => 'value12',
2643  ],
2644  'key2' => 'value2',
2645  'key3' => 'value3',
2646  ];
2647  $array2 = [
2648  'key1' => [
2649  'key11' => 'valueDoesNotMatter',
2650  'key12' => 'value12',
2651  ],
2652  'key2' => 'value2',
2653  'key3' => 'value3',
2654  ];
2655  $expectedResult = [];
2656  $actualResult = ArrayUtility::arrayDiffKeyRecursive($array1, $array2);
2657  self::assertEquals($expectedResult, $actualResult);
2658  }
2659 
2661  // Tests concerning arrayDiffAssocRecursive
2663 
2667  {
2668  $array1 = [
2669  'key1' => 'value1',
2670  'key2' => 'value2',
2671  'key3' => 'value3',
2672  ];
2673  $array2 = [
2674  'key1' => 'value1',
2675  'key3' => 'value3',
2676  ];
2677  $expectedResult = [
2678  'key2' => 'value2',
2679  ];
2680  $actualResult = ArrayUtility::arrayDiffAssocRecursive($array1, $array2);
2681  self::assertEquals($expectedResult, $actualResult);
2682  }
2683 
2688  {
2689  $array1 = [
2690  'key1' => 'value1',
2691  'key2' => [
2692  'key21' => 'value21',
2693  'key22' => 'value22',
2694  'key23' => [
2695  'key231' => 'value231',
2696  'key232' => 'value232',
2697  ],
2698  ],
2699  ];
2700  $array2 = [
2701  'key1' => 'value2',
2702  'key2' => [
2703  'key21' => 'value21',
2704  'key23' => [
2705  'key231' => 'value231',
2706  ],
2707  ],
2708  ];
2709  $expectedResult = [
2710  'key1' => 'value1',
2711  'key2' => [
2712  'key22' => 'value22',
2713  'key23' => [
2714  'key232' => 'value232',
2715  ],
2716  ],
2717  ];
2718  $actualResult = ArrayUtility::arrayDiffAssocRecursive($array1, $array2);
2719  self::assertEquals($expectedResult, $actualResult);
2720  }
2721 
2726  {
2727  $array1 = [
2728  'key1' => [
2729  'key11' => 'value11',
2730  'key12' => 'value12',
2731  ],
2732  'key2' => 'value2',
2733  'key3' => 'value3',
2734  ];
2735  $array2 = [
2736  'key1' => 'value1',
2737  'key2' => [
2738  'key21' => 'valueDoesNotMatter',
2739  ],
2740  ];
2741  $expectedResult = [
2742  'key2' => 'value2',
2743  'key3' => 'value3',
2744  ];
2745  $actualResult = ArrayUtility::arrayDiffAssocRecursive($array1, $array2);
2746  self::assertEquals($expectedResult, $actualResult);
2747  }
2748 
2753  {
2754  $array1 = [
2755  'key1' => [
2756  'key11' => 'value11',
2757  'key12' => 'value12',
2758  ],
2759  'key2' => 'value2',
2760  'key3' => 'value3',
2761  ];
2762  $array2 = [
2763  'key1' => [
2764  'key11' => 'value11',
2765  'key12' => 'value12',
2766  ],
2767  'key2' => 'value2',
2768  'key3' => 'value3',
2769  ];
2770  $expectedResult = [];
2771  $actualResult = ArrayUtility::arrayDiffAssocRecursive($array1, $array2);
2772  self::assertEquals($expectedResult, $actualResult);
2773  }
2774 
2776  // Tests concerning naturalKeySortRecursive
2778 
2783  {
2784  $testArray = [
2785  'bb' => 'bb',
2786  'ab' => 'ab',
2787  '123' => '123',
2788  'aaa' => 'aaa',
2789  'abc' => 'abc',
2790  '23' => '23',
2791  'ba' => 'ba',
2792  'bad' => 'bad',
2793  '2' => '2',
2794  'zap' => 'zap',
2795  '210' => '210',
2796  ];
2797  $expectedResult = [
2798  '2',
2799  '23',
2800  '123',
2801  '210',
2802  'aaa',
2803  'ab',
2804  'abc',
2805  'ba',
2806  'bad',
2807  'bb',
2808  'zap',
2809  ];
2810  ArrayUtility::naturalKeySortRecursive($testArray);
2811  self::assertEquals($expectedResult, array_values($testArray));
2812  }
2813 
2818  {
2819  $testArray = [
2820  '2' => '2',
2821  'bb' => 'bb',
2822  'ab' => 'ab',
2823  '23' => '23',
2824  'aaa' => [
2825  'bb' => 'bb',
2826  'ab' => 'ab',
2827  '123' => '123',
2828  'aaa' => 'aaa',
2829  '2' => '2',
2830  'abc' => 'abc',
2831  'ba' => 'ba',
2832  '23' => '23',
2833  'bad' => [
2834  'bb' => 'bb',
2835  'ab' => 'ab',
2836  '123' => '123',
2837  'aaa' => 'aaa',
2838  'abc' => 'abc',
2839  '23' => '23',
2840  'ba' => 'ba',
2841  'bad' => 'bad',
2842  '2' => '2',
2843  'zap' => 'zap',
2844  '210' => '210',
2845  ],
2846  '210' => '210',
2847  'zap' => 'zap',
2848  ],
2849  'abc' => 'abc',
2850  'ba' => 'ba',
2851  '210' => '210',
2852  'bad' => 'bad',
2853  '123' => '123',
2854  'zap' => 'zap',
2855  ];
2856  $expectedResult = [
2857  '2',
2858  '23',
2859  '123',
2860  '210',
2861  'aaa',
2862  'ab',
2863  'abc',
2864  'ba',
2865  'bad',
2866  'bb',
2867  'zap',
2868  ];
2869  ArrayUtility::naturalKeySortRecursive($testArray);
2870  self::assertEquals($expectedResult, array_values(array_keys($testArray['aaa']['bad'])));
2871  self::assertEquals($expectedResult, array_values(array_keys($testArray['aaa'])));
2872  self::assertEquals($expectedResult, array_values(array_keys($testArray)));
2873  }
2874 
2878  public static function ‪filterAndSortByNumericKeysWithAcceptAnyKey(): array
2879  {
2880  return [
2881  'ordered list of plain numeric keys' => [
2882  'input' => [
2883  '10' => 'foo',
2884  '20' => 'bar',
2885  ],
2886  'expected' => [
2887  10,
2888  20,
2889  ],
2890  ],
2891  'unordered list of plain numeric keys' => [
2892  'input' => [
2893  '20' => 'bar',
2894  '10' => 'foo',
2895  ],
2896  'expected' => [
2897  10,
2898  20,
2899  ],
2900  ],
2901  'list of string keys' => [
2902  'input' => [
2903  '10.' => [
2904  'wrap' => 'foo',
2905  ],
2906  '20.' => [
2907  'wrap' => 'bar',
2908  ],
2909  ],
2910  'expected' => [
2911  10,
2912  20,
2913  ],
2914  ],
2915  'list of mixed keys' => [
2916  'input' => [
2917  '10' => 'foo',
2918  '20.' => [
2919  'wrap' => 'bar',
2920  ],
2921  ],
2922  'expected' => [
2923  10,
2924  20,
2925  ],
2926  ],
2927  'list of mixed keys with one not interpreted as integer' => [
2928  'input' => [
2929  '10' => 'foo',
2930  'bla20.' => [
2931  'wrap' => 'bar',
2932  ],
2933  ],
2934  'expected' => [
2935  0,
2936  10,
2937  ],
2938  ],
2939  'list of mixed keys with more than one not interpreted as integer' => [
2940  'input' => [
2941  '10' => 'foo',
2942  'bla20.' => [
2943  'wrap' => 'bar',
2944  ],
2945  'bla21.' => [
2946  'wrap' => 'foobar',
2947  ],
2948  ],
2949  'expected' => [
2950  0,
2951  10,
2952  ],
2953  ],
2954  ];
2955  }
2956 
2965  {
2966  $result = ArrayUtility::filterAndSortByNumericKeys($input, true);
2967  self::assertEquals($result, $expected);
2968  }
2969 
2974  {
2975  return [
2976  'ordered list of plain numeric keys' => [
2977  'input' => [
2978  '10' => 'foo',
2979  '20' => 'bar',
2980  ],
2981  'expected' => [
2982  10,
2983  20,
2984  ],
2985  ],
2986  'unordered list of plain numeric keys' => [
2987  'input' => [
2988  '20' => 'bar',
2989  '10' => 'foo',
2990  ],
2991  'expected' => [
2992  10,
2993  20,
2994  ],
2995  ],
2996  'list of string keys' => [
2997  'input' => [
2998  '10.' => [
2999  'wrap' => 'foo',
3000  ],
3001  '20.' => [
3002  'wrap' => 'bar',
3003  ],
3004  ],
3005  'expected' => [],
3006  ],
3007  'list of mixed keys' => [
3008  'input' => [
3009  '10' => 'foo',
3010  '20.' => [
3011  'wrap' => 'bar',
3012  ],
3013  ],
3014  'expected' => [
3015  10,
3016  ],
3017  ],
3018  ];
3019  }
3020 
3029  {
3030  $result = ArrayUtility::filterAndSortByNumericKeys($input);
3031  self::assertEquals($result, $expected);
3032  }
3033 
3037  public static function ‪sortArrayWithIntegerKeysDataProvider(): array
3038  {
3039  return [
3040  [
3041  [
3042  '20' => 'test1',
3043  '11' => 'test2',
3044  '16' => 'test3',
3045  ],
3046  [
3047  '11' => 'test2',
3048  '16' => 'test3',
3049  '20' => 'test1',
3050  ],
3051  ],
3052  [
3053  [
3054  '20' => 'test1',
3055  '16.5' => 'test2',
3056  '16' => 'test3',
3057  ],
3058  [
3059  '20' => 'test1',
3060  '16.5' => 'test2',
3061  '16' => 'test3',
3062  ],
3063  ],
3064  [
3065  [
3066  '20' => 'test20',
3067  'somestring' => 'teststring',
3068  '16' => 'test16',
3069  ],
3070  [
3071  '20' => 'test20',
3072  'somestring' => 'teststring',
3073  '16' => 'test16',
3074  ],
3075  ],
3076  ];
3077  }
3078 
3085  public function ‪sortArrayWithIntegerKeysSortsNumericArrays(array $arrayToSort, array $expectedArray): void
3086  {
3087  $sortedArray = ArrayUtility::sortArrayWithIntegerKeys($arrayToSort);
3088  self::assertSame($sortedArray, $expectedArray);
3089  }
3090 
3095  {
3096  $this->expectException(\InvalidArgumentException::class);
3097  $this->expectExceptionCode(1325697085);
3098 
3099  $arrayToTest = [
3100  'roger' => '',
3101  'francine' => '',
3102  'stan' => '',
3103  ];
3104 
3105  $allowedArrayKeys = [
3106  'roger',
3107  'francine',
3108  ];
3109 
3110  ‪ArrayUtility::assertAllArrayKeysAreValid($arrayToTest, $allowedArrayKeys);
3111  }
3112 
3117  {
3118  $arrayToTest = [
3119  'roger' => '',
3120  'francine' => '',
3121  'stan' => '',
3122  ];
3123 
3124  $allowedArrayKeys = [
3125  'roger',
3126  'francine',
3127  'stan',
3128  ];
3129 
3130  ‪ArrayUtility::assertAllArrayKeysAreValid($arrayToTest, $allowedArrayKeys);
3131  }
3132 
3137  {
3138  $input = [
3139  20 => 'b',
3140  10 => 'a',
3141  40 => 'd',
3142  30 => 'c',
3143  50 => [
3144  20 => 'a',
3145  10 => 'b',
3146  ],
3147  ];
3148 
3149  $expected = [
3150  10 => 'a',
3151  20 => 'b',
3152  30 => 'c',
3153  40 => 'd',
3154  50 => [
3155  10 => 'b',
3156  20 => 'a',
3157  ],
3158  ];
3159 
3160  self::assertSame($expected, ArrayUtility::sortArrayWithIntegerKeysRecursive($input));
3161  }
3162 
3167  {
3168  $input = [
3169  'b' => 'b',
3170  10 => 'a',
3171  40 => 'd',
3172  30 => 'c',
3173  ];
3174 
3175  $expected = [
3176  'b' => 'b',
3177  10 => 'a',
3178  40 => 'd',
3179  30 => 'c',
3180  ];
3181 
3182  self::assertSame($expected, ArrayUtility::sortArrayWithIntegerKeysRecursive($input));
3183  }
3184 
3189  {
3190  $input = [
3191  20 => 'b',
3192  10 => 'a',
3193  40 => 'd',
3194  30 => 'c',
3195  50 => [
3196  20 => 'a',
3197  10 => 'b',
3198  ],
3199  ];
3200 
3201  $expected = [
3202  0 => 'b',
3203  1 => 'a',
3204  2 => 'd',
3205  3 => 'c',
3206  4 => [
3207  0 => 'a',
3208  1 => 'b',
3209  ],
3210  ];
3211 
3212  self::assertSame($expected, ‪ArrayUtility::reIndexNumericArrayKeysRecursive($input));
3213  }
3214 
3219  {
3220  $input = [
3221  'a' => 'b',
3222  10 => 'a',
3223  40 => 'd',
3224  30 => 'c',
3225  50 => [
3226  20 => 'a',
3227  10 => 'b',
3228  ],
3229  ];
3230 
3231  $expected = [
3232  'a' => 'b',
3233  10 => 'a',
3234  40 => 'd',
3235  30 => 'c',
3236  50 => [
3237  0 => 'a',
3238  1 => 'b',
3239  ],
3240  ];
3241 
3242  self::assertSame($expected, ‪ArrayUtility::reIndexNumericArrayKeysRecursive($input));
3243  }
3244 
3249  {
3250  $input = [
3251  'a' => 'a',
3252  'b' => [
3253  'c' => null,
3254  'd' => 'd',
3255  ],
3256  ];
3257 
3258  $expected = [
3259  'a' => 'a',
3260  'b' => [
3261  'd' => 'd',
3262  ],
3263  ];
3264 
3265  self::assertSame($expected, ‪ArrayUtility::removeNullValuesRecursive($input));
3266  }
3267 
3272  {
3273  $input = [
3274  'a' => 'a',
3275  'b' => [
3276  'c' => '<b>i am evil</b>',
3277  'd' => 'd',
3278  ],
3279  ];
3280 
3281  $expected = [
3282  'a' => 'a',
3283  'b' => [
3284  'c' => 'i am evil',
3285  'd' => 'd',
3286  ],
3287  ];
3288 
3289  self::assertSame($expected, ArrayUtility::stripTagsFromValuesRecursive($input));
3290  }
3291 
3296  {
3297  $testObject = new \stdClass();
3298 
3299  $input = [
3300  'stringWithTags' => '<b>i am evil</b>',
3301  'boolean' => true,
3302  'integer' => 1,
3303  'float' => 1.9,
3304  'object' => $testObject,
3305  'objectWithStringConversion' => new class () {
3309  public function __toString()
3310  {
3311  return 'i am evil <b>too</b>';
3312  }
3313  },
3314  ];
3315 
3316  $expected = [
3317  'stringWithTags' => 'i am evil',
3318  'boolean' => true,
3319  'integer' => 1,
3320  'float' => 1.9,
3321  'object' => $testObject,
3322  'objectWithStringConversion' => 'i am evil too',
3323  ];
3324 
3325  self::assertSame($expected, ArrayUtility::stripTagsFromValuesRecursive($input));
3326  }
3327 
3332  {
3333  $input = [
3334  'a' => 'a',
3335  'b' => [
3336  'c' => 'true',
3337  'd' => 'd',
3338  ],
3339  ];
3340 
3341  $expected = [
3342  'a' => 'a',
3343  'b' => [
3344  'c' => true,
3345  'd' => 'd',
3346  ],
3347  ];
3348 
3349  self::assertSame($expected, ‪ArrayUtility::convertBooleanStringsToBooleanRecursive($input));
3350  }
3351 
3356  {
3357  return [
3358  'filter all values which will be false when converted to boolean' => [
3359  // input
3360  [
3361  true,
3362  false,
3363  'foo1' => [
3364  'bar' => [
3365  'baz' => [
3366  '1',
3367  null,
3368  '',
3369  ],
3370  '' => 1,
3371  'bbd' => 0,
3372  ],
3373  ],
3374  'foo2' => 'foo',
3375  'foo3' => '',
3376  'foo4' => [
3377  'z' => 'bar',
3378  'bar' => 0,
3379  'baz' => [
3380  'foo' => [
3381  'bar' => '',
3382  'boo' => [],
3383  'bamboo' => 5,
3384  'fooAndBoo' => [0],
3385  ],
3386  ],
3387  ],
3388  ],
3389  // expected
3390  [
3391  true,
3392  'foo1' => [
3393  'bar' => [
3394  'baz' => [
3395  '1',
3396  ],
3397  '' => 1,
3398  ],
3399  ],
3400  'foo2' => 'foo',
3401  'foo4' => [
3402  'z' => 'bar',
3403  'baz' => [
3404  'foo' => [
3405  'bamboo' => 5,
3406  ],
3407  ],
3408  ],
3409  ],
3410  ],
3411  ];
3412  }
3413 
3418  public function ‪filterRecursiveFiltersFalseElements(array $input, array $expectedResult): void
3419  {
3420  // If no callback is supplied, all entries of array equal to FALSE (see converting to boolean) will be removed.
3421  $result = ArrayUtility::filterRecursive($input);
3422  self::assertEquals($expectedResult, $result);
3423  }
3424 
3429  {
3430  return [
3431  'filter empty values, keep zero integers' => [
3432  // input
3433  [
3434  true,
3435  false,
3436  'foo1' => [
3437  'bar' => [
3438  'baz' => [
3439  '1',
3440  null,
3441  '',
3442  ],
3443  '' => 1,
3444  'bbd' => 0,
3445  ],
3446  ],
3447  'foo2' => 'foo',
3448  'foo3' => '',
3449  'foo4' => [
3450  'z' => 'bar',
3451  'bar' => 0,
3452  'baz' => [
3453  'foo' => [
3454  'bar' => '',
3455  'boo' => [],
3456  'bamboo' => 5,
3457  'fooAndBoo' => [0],
3458  ],
3459  ],
3460  ],
3461  ],
3462  // expected
3463  [
3464  true,
3465  false,
3466  'foo1' => [
3467  'bar' => [
3468  'baz' => [
3469  '1',
3470  ],
3471  '' => 1,
3472  'bbd' => 0,
3473  ],
3474  ],
3475  'foo2' => 'foo',
3476  'foo4' => [
3477  'z' => 'bar',
3478  'bar' => 0,
3479  'baz' => [
3480  'foo' => [
3481  'bamboo' => 5,
3482  'fooAndBoo' => [0],
3483  ],
3484  ],
3485  ],
3486  ],
3487  ],
3488  ];
3489  }
3490 
3495  public function ‪filterRecursiveCallbackFiltersEmptyElementsWithoutIntegerByCallback(array $input, array $expectedResult): void
3496  {
3497  // callback filters empty strings, array and null but keeps zero integers
3498  $result = ArrayUtility::filterRecursive(
3499  $input,
3500  static function ($item) {
3501  return $item !== '' && $item !== [] && $item !== null;
3502  }
3503  );
3504  self::assertEquals($expectedResult, $result);
3505  }
3506 
3511  {
3512  $input = [
3513  'foo' => 'remove',
3514  'bar' => [
3515  'baz' => 'remove',
3516  'keep1' => 'keep',
3517  ],
3518  'keep2' => 'keep',
3519  ];
3520  $expectedResult = [
3521  'bar' => [
3522  'keep1' => 'keep',
3523  ],
3524  'keep2' => 'keep',
3525  ];
3526 
3527  return [
3528  'filter using a closure' => [
3529  $input,
3530  $expectedResult,
3531  static function ($value): bool {
3532  return is_array($value) || $value === 'keep';
3533  },
3534  ],
3535  'filter using a callable "static class-method call" as string' => [
3536  $input,
3537  $expectedResult,
3538  ArrayUtilityFilterRecursiveCallbackFixture::class . '::callbackViaStaticMethod',
3539  ],
3540  'filter using a callable "static class-method call" as array' => [
3541  $input,
3542  $expectedResult,
3543  [ArrayUtilityFilterRecursiveCallbackFixture::class, 'callbackViaStaticMethod'],
3544  ],
3545  'filter using a callable "instance-method call" as array' => [
3546  $input,
3547  $expectedResult,
3548  [new ‪ArrayUtilityFilterRecursiveCallbackFixture(), 'callbackViaInstanceMethod'],
3549  ],
3550  'only keep2 key is kept' => [
3551  $input,
3552  ['keep2' => 'keep'],
3553  static fn($key): bool => $key === 'keep2',
3554  ARRAY_FILTER_USE_KEY,
3555  ],
3556  'keys baz, keep1 and empty arrays are removed' => [
3557  $input,
3558  ['foo' => 'remove', 'keep2' => 'keep'],
3559  static fn($value, $key): bool => $value !== [] && !in_array($key, ['baz', 'keep1'], true),
3560  ARRAY_FILTER_USE_BOTH,
3561  ],
3562  ];
3563  }
3564 
3572  public function ‪filterRecursiveSupportsCallableCallback(array $input, array $expectedResult, callable $callback, int $mode = 0): void
3573  {
3574  $result = ArrayUtility::filterRecursive($input, $callback, $mode);
3575  self::assertEquals($expectedResult, $result);
3576  }
3577 
3582  {
3583  return [
3584  'array without string keys' => [
3585  [
3586  0 => 'value 0',
3587  1 => 'value 1',
3588  ],
3589  false,
3590  ],
3591  'array with only string keys' => [
3592  [
3593  'key 0' => 'value 0',
3594  'key 1' => 'value 1',
3595  ],
3596  true,
3597  ],
3598  'array with mixed keys' => [
3599  [
3600  0 => 'value 0',
3601  1 => 'value 1',
3602  'key 2' => 'value 2',
3603  'key 3' => 'value 3',
3604  ],
3605  true,
3606  ],
3607  ];
3608  }
3609 
3614  public function ‪isAssociativeCorrectlyFindsStringKeys(array $array, bool $expectedResult): void
3615  {
3616  $result = ‪ArrayUtility::isAssociative($array);
3617  self::assertEquals($expectedResult, $result);
3618  }
3619 
3624  {
3625  return [
3626  'merge simple lists' => [
3627  [
3628  0 => 'keep',
3629  ],
3630  [
3631  0 => 'keep',
3632  ],
3633  [
3634  0 => 'keep',
3635  1 => 'keep',
3636  ],
3637  ],
3638  'merge simple list arrays' => [
3639  [
3640  'foo' => [
3641  0 => 'keep',
3642  ],
3643  ],
3644  [
3645  'foo' => [
3646  0 => 'keep',
3647  ],
3648  ],
3649  [
3650  'foo' => [
3651  0 => 'keep',
3652  1 => 'keep',
3653  ],
3654  ],
3655  ],
3656  'merge array and simple value' => [
3657  [
3658  'foo' => [
3659  0 => 'override',
3660  ],
3661  ],
3662  [
3663  'foo' => 'keep',
3664  ],
3665  [
3666  'foo' => 'keep',
3667  ],
3668  ],
3669  'merge simple values' => [
3670  [
3671  'foo' => 'override',
3672  ],
3673  [
3674  'foo' => 'keep',
3675  ],
3676  [
3677  'foo' => 'keep',
3678  ],
3679  ],
3680  'merge new keys' => [
3681  [
3682  'foo' => 'keep',
3683  ],
3684  [
3685  'bar' => 'keep',
3686  ],
3687  [
3688  'foo' => 'keep',
3689  'bar' => 'keep',
3690  ],
3691  ],
3692  ];
3693  }
3694 
3699  public function ‪replaceAndAppendScalarValuesRecursiveCorrectlyMergesArrays(array $array1, array $array2, array $expectedResult): void
3700  {
3701  $result = ‪ArrayUtility::replaceAndAppendScalarValuesRecursive($array1, $array2);
3702  self::assertEquals($expectedResult, $result);
3703  }
3704 }
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\arrayExportReturnsNoKeyIndexForConsecutiveCountedArrays
‪arrayExportReturnsNoKeyIndexForConsecutiveCountedArrays()
Definition: ArrayUtilityTest.php:1199
‪TYPO3\CMS\Core\Utility\ArrayUtility\isAssociative
‪static bool isAssociative(array $array)
Definition: ArrayUtility.php:960
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\filterRecursiveFiltersFalseElementsDataProvider
‪static filterRecursiveFiltersFalseElementsDataProvider()
Definition: ArrayUtilityTest.php:3355
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\removeNullValuesRecursiveExpectRemoval
‪removeNullValuesRecursiveExpectRemoval()
Definition: ArrayUtilityTest.php:3248
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\mergeRecursiveWithOverruleCalculatesExpectedResultDataProvider
‪static mergeRecursiveWithOverruleCalculatesExpectedResultDataProvider()
Definition: ArrayUtilityTest.php:2146
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\arrayExportReturnsNumericArrayKeys
‪arrayExportReturnsNumericArrayKeys()
Definition: ArrayUtilityTest.php:1180
‪TYPO3\CMS\Core\Utility\ArrayUtility\flattenPlain
‪static flattenPlain(array $array)
Definition: ArrayUtility.php:496
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\assertAllArrayKeysAreValidThrowsExceptionOnNotAllowedArrayKeys
‪assertAllArrayKeysAreValidThrowsExceptionOnNotAllowedArrayKeys()
Definition: ArrayUtilityTest.php:3094
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\getValueByPathThrowsExceptionIfPathIsEmpty
‪getValueByPathThrowsExceptionIfPathIsEmpty()
Definition: ArrayUtilityTest.php:243
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\getValueByPathGetsCorrectValue
‪getValueByPathGetsCorrectValue(array $array, $path, $expectedResult)
Definition: ArrayUtilityTest.php:470
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\setValueByPathThrowsExceptionIfPathSegmentIsEmpty
‪setValueByPathThrowsExceptionIfPathSegmentIsEmpty()
Definition: ArrayUtilityTest.php:514
‪TYPO3\CMS\Core\Utility\ArrayUtility\removeByPath
‪static array removeByPath(array $array, string $path, string $delimiter='/')
Definition: ArrayUtility.php:303
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\getValueByPathAcceptsDifferentDelimiter
‪getValueByPathAcceptsDifferentDelimiter()
Definition: ArrayUtilityTest.php:478
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\sortArrayWithIntegerKeysDataProvider
‪static sortArrayWithIntegerKeysDataProvider()
Definition: ArrayUtilityTest.php:3037
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\filterByValueRecursiveMatchesReferencesToSameObject
‪filterByValueRecursiveMatchesReferencesToSameObject()
Definition: ArrayUtilityTest.php:181
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\filterRecursiveSupportsCallableCallback
‪filterRecursiveSupportsCallableCallback(array $input, array $expectedResult, callable $callback, int $mode=0)
Definition: ArrayUtilityTest.php:3572
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\keepItemsInArrayWorksWithOneArgumentDataProvider
‪static keepItemsInArrayWorksWithOneArgumentDataProvider()
Definition: ArrayUtilityTest.php:2478
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\filterRecursiveSupportsCallableCallbackDataProvider
‪static filterRecursiveSupportsCallableCallbackDataProvider()
Definition: ArrayUtilityTest.php:3510
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\reIndexNumericArrayKeysRecursiveExpectNoReindexing
‪reIndexNumericArrayKeysRecursiveExpectNoReindexing()
Definition: ArrayUtilityTest.php:3218
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\sortByKeyRecursiveCheckIfSortingIsCorrect
‪sortByKeyRecursiveCheckIfSortingIsCorrect()
Definition: ArrayUtilityTest.php:943
‪TYPO3\CMS\Core\Utility\Exception\MissingArrayPathException
Definition: MissingArrayPathException.php:27
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\removeByPathRemovesFirstIndexWithZeroAsPathSegment
‪removeByPathRemovesFirstIndexWithZeroAsPathSegment()
Definition: ArrayUtilityTest.php:799
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\sortArraysByKeyCheckIfSortingIsCorrect
‪sortArraysByKeyCheckIfSortingIsCorrect(array $array, $key, $ascending, $expectedResult)
Definition: ArrayUtilityTest.php:1101
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\removeByPathRemovesCorrectPathDataProvider
‪static removeByPathRemovesCorrectPathDataProvider()
Definition: ArrayUtilityTest.php:878
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\filterByValueRecursiveCorrectlyFiltersArray
‪filterByValueRecursiveCorrectlyFiltersArray($needle, $haystack, $expectedResult)
Definition: ArrayUtilityTest.php:170
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\filterAndSortByNumericKeysWithoutAcceptAnyKey
‪static filterAndSortByNumericKeysWithoutAcceptAnyKey()
Definition: ArrayUtilityTest.php:2973
‪TYPO3\CMS\Core\Tests\Unit\Utility
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\keepItemsInArrayWorksWithOneArgument
‪keepItemsInArrayWorksWithOneArgument($search, $array, $expected)
Definition: ArrayUtilityTest.php:2470
‪TYPO3\CMS\Core\Utility\ArrayUtility\sortByKeyRecursive
‪static array sortByKeyRecursive(array $array)
Definition: ArrayUtility.php:338
‪TYPO3\CMS\Core\Utility\ArrayUtility\replaceAndAppendScalarValuesRecursive
‪static replaceAndAppendScalarValuesRecursive(array $array1, array $array2)
Definition: ArrayUtility.php:971
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\getValueByPathThrowsExceptionIfPathNotExists
‪getValueByPathThrowsExceptionIfPathNotExists(array $array, $path)
Definition: ArrayUtilityTest.php:340
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\setValueByPathCanUseZeroAsPath
‪setValueByPathCanUseZeroAsPath()
Definition: ArrayUtilityTest.php:533
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\mergeRecursiveWithOverruleCalculatesExpectedResult
‪mergeRecursiveWithOverruleCalculatesExpectedResult($input1, $input2, $addKeys, $includeEmptyValues, $enableUnsetFeature, $expected)
Definition: ArrayUtilityTest.php:2391
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\removeByPathRemovesCorrectPath
‪removeByPathRemovesCorrectPath(array $array, $path, $expectedResult)
Definition: ArrayUtilityTest.php:929
‪TYPO3\CMS\Core\Utility\ArrayUtility\arrayExport
‪static string arrayExport(array $array=[], int $level=0)
Definition: ArrayUtility.php:386
‪TYPO3\CMS\Core\Utility\ArrayUtility\isValidPath
‪static bool isValidPath(array $array, array|string $path, string $delimiter='/')
Definition: ArrayUtility.php:141
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\removeByPathThrowsExceptionIfPathDoesNotExistInArray
‪removeByPathThrowsExceptionIfPathDoesNotExistInArray()
Definition: ArrayUtilityTest.php:821
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\arrayDiffKeyRecursiveReturnsEmptyIfEqual
‪arrayDiffKeyRecursiveReturnsEmptyIfEqual()
Definition: ArrayUtilityTest.php:2637
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest
Definition: ArrayUtilityTest.php:29
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\naturalKeySortRecursiveSortsMultiDimensionalArrayByNaturalOrder
‪naturalKeySortRecursiveSortsMultiDimensionalArrayByNaturalOrder()
Definition: ArrayUtilityTest.php:2817
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\sortArrayWithIntegerKeysSortsNumericArrays
‪sortArrayWithIntegerKeysSortsNumericArrays(array $arrayToSort, array $expectedArray)
Definition: ArrayUtilityTest.php:3085
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\arrayExportReturnsKeyIndexForNonConsecutiveCountedArrays
‪arrayExportReturnsKeyIndexForNonConsecutiveCountedArrays()
Definition: ArrayUtilityTest.php:1218
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\arrayDiffKeyRecursiveHandlesOneDimensionalArrays
‪arrayDiffKeyRecursiveHandlesOneDimensionalArrays()
Definition: ArrayUtilityTest.php:2553
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\removeByPathAcceptsGivenDelimiter
‪removeByPathAcceptsGivenDelimiter()
Definition: ArrayUtilityTest.php:855
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\unflattenCalculatesExpectedResult
‪unflattenCalculatesExpectedResult(array $array, array $expected)
Definition: ArrayUtilityTest.php:1809
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\flattenWithKeepDotsCalculatesExpectedResult
‪flattenWithKeepDotsCalculatesExpectedResult(array $array, array $expected)
Definition: ArrayUtilityTest.php:1642
‪TYPO3\CMS\Core\Utility\ArrayUtility\getValueByPath
‪static getValueByPath(array $array, array|string $path, string $delimiter='/')
Definition: ArrayUtility.php:176
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\sortArrayWithIntegerKeysRecursiveExpectSorting
‪sortArrayWithIntegerKeysRecursiveExpectSorting()
Definition: ArrayUtilityTest.php:3136
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\isValidPathReturnsTrueIfPathExistsStringVersion
‪isValidPathReturnsTrueIfPathExistsStringVersion()
Definition: ArrayUtilityTest.php:207
‪TYPO3\CMS\Core\Utility\ArrayUtility\flatten
‪static flatten(array $array, string $prefix='', bool $keepDots=false)
Definition: ArrayUtility.php:469
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\stripTagsFromValuesRecursiveExpectRemoval
‪stripTagsFromValuesRecursiveExpectRemoval()
Definition: ArrayUtilityTest.php:3271
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\sortArraysByKeyCheckIfSortingIsCorrectDataProvider
‪static sortArraysByKeyCheckIfSortingIsCorrectDataProvider()
Definition: ArrayUtilityTest.php:974
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\reIndexNumericArrayKeysRecursiveExpectReindexing
‪reIndexNumericArrayKeysRecursiveExpectReindexing()
Definition: ArrayUtilityTest.php:3188
‪TYPO3\CMS\Core\Tests\Unit\Utility\Fixtures\ArrayUtilityFilterRecursiveCallbackFixture
Definition: ArrayUtilityFilterRecursiveCallbackFixture.php:24
‪TYPO3\CMS\Core\Utility\ArrayUtility\removeNullValuesRecursive
‪static removeNullValuesRecursive(array $array)
Definition: ArrayUtility.php:222
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\filterAndSortByNumericKeysBehavesCorrectlyForAcceptAnyKeysIsTrue
‪filterAndSortByNumericKeysBehavesCorrectlyForAcceptAnyKeysIsTrue($input, $expected)
Definition: ArrayUtilityTest.php:2964
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\removeByPathThrowsExceptionWithEmptyPathSegment
‪removeByPathThrowsExceptionWithEmptyPathSegment()
Definition: ArrayUtilityTest.php:782
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\intersectRecursiveCalculatesExpectedResult
‪intersectRecursiveCalculatesExpectedResult(array $source, array $mask, array $expected)
Definition: ArrayUtilityTest.php:2012
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\sortArraysByKeyThrowsExceptionForNonExistingKey
‪sortArraysByKeyThrowsExceptionForNonExistingKey()
Definition: ArrayUtilityTest.php:1110
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\flattenCalculatesExpectedResult
‪flattenCalculatesExpectedResult(array $array, array $expected)
Definition: ArrayUtilityTest.php:1358
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\filterAndSortByNumericKeysWithAcceptAnyKey
‪static filterAndSortByNumericKeysWithAcceptAnyKey()
Definition: ArrayUtilityTest.php:2878
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\removeByPathRemovesFirstIndexWithZeroAsPath
‪removeByPathRemovesFirstIndexWithZeroAsPath()
Definition: ArrayUtilityTest.php:811
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\getValueByPathThrowsSpecificExceptionIfPathNotExists
‪getValueByPathThrowsSpecificExceptionIfPathNotExists(array $array, string $path)
Definition: ArrayUtilityTest.php:351
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\getValueByPathReturnsFirstIndexIfPathSegmentIsZero
‪getValueByPathReturnsFirstIndexIfPathSegmentIsZero()
Definition: ArrayUtilityTest.php:262
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\flattenPlainCalculatesExpectedResultDataProvider
‪static flattenPlainCalculatesExpectedResultDataProvider()
Definition: ArrayUtilityTest.php:1363
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\stripTagsFromValuesRecursiveExpectNoTypeCast
‪stripTagsFromValuesRecursiveExpectNoTypeCast()
Definition: ArrayUtilityTest.php:3295
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\setValueByPathThrowsExceptionIfPathIsEmpty
‪setValueByPathThrowsExceptionIfPathIsEmpty()
Definition: ArrayUtilityTest.php:503
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\isAssociativeCorrectlyFindsStringKeys
‪isAssociativeCorrectlyFindsStringKeys(array $array, bool $expectedResult)
Definition: ArrayUtilityTest.php:3614
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\arrayDiffAssocRecursiveHandlesOneDimensionalArrays
‪arrayDiffAssocRecursiveHandlesOneDimensionalArrays()
Definition: ArrayUtilityTest.php:2666
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\convertBooleanStringsToBooleanRecursiveExpectConverting
‪convertBooleanStringsToBooleanRecursiveExpectConverting()
Definition: ArrayUtilityTest.php:3331
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\flattenWithKeepDotsCalculatesExpectedResultDataProvider
‪static flattenWithKeepDotsCalculatesExpectedResultDataProvider()
Definition: ArrayUtilityTest.php:1530
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\filterRecursiveCallbackFiltersEmptyElementsWithoutIntegerZeroByCallbackDataProvider
‪static filterRecursiveCallbackFiltersEmptyElementsWithoutIntegerZeroByCallbackDataProvider()
Definition: ArrayUtilityTest.php:3428
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\setValueByPathCanUseZeroAsPathSegment
‪setValueByPathCanUseZeroAsPathSegment()
Definition: ArrayUtilityTest.php:525
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\assertAllArrayKeysAreValidReturnsNullOnAllowedArrayKeys
‪assertAllArrayKeysAreValidReturnsNullOnAllowedArrayKeys()
Definition: ArrayUtilityTest.php:3116
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\checkRemoveArrayEntryByValueRemovesEntryWithEmptyString
‪checkRemoveArrayEntryByValueRemovesEntryWithEmptyString()
Definition: ArrayUtilityTest.php:2444
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\unflattenCalculatesExpectedResultDataProvider
‪static unflattenCalculatesExpectedResultDataProvider()
Definition: ArrayUtilityTest.php:1647
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\flattenPlainCalculatesExpectedResult
‪flattenPlainCalculatesExpectedResult(array $array, array $expected)
Definition: ArrayUtilityTest.php:1525
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\removeByPathThrowsExceptionIfPathIsEmpty
‪removeByPathThrowsExceptionIfPathIsEmpty()
Definition: ArrayUtilityTest.php:771
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\intersectRecursiveCalculatesExpectedResultDataProvider
‪static intersectRecursiveCalculatesExpectedResultDataProvider()
Definition: ArrayUtilityTest.php:1814
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\arrayExportReturnsFormattedMultidimensionalArray
‪arrayExportReturnsFormattedMultidimensionalArray()
Definition: ArrayUtilityTest.php:1124
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\filterByValueRecursiveDoesNotMatchDifferentInstancesOfSameClass
‪filterByValueRecursiveDoesNotMatchDifferentInstancesOfSameClass()
Definition: ArrayUtilityTest.php:193
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\remapArrayKeysExchangesKeysWithGivenMapping
‪remapArrayKeysExchangesKeysWithGivenMapping()
Definition: ArrayUtilityTest.php:2527
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\isValidPathReturnsTrueIfPathExistsArrayVersion
‪isValidPathReturnsTrueIfPathExistsArrayVersion()
Definition: ArrayUtilityTest.php:223
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\getValueByPathInvalidPathDataProvider
‪static getValueByPathInvalidPathDataProvider()
Definition: ArrayUtilityTest.php:274
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\filterByValueRecursive
‪static filterByValueRecursive()
Definition: ArrayUtilityTest.php:41
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\checkRemoveArrayEntryByValueRemovesEntriesFromOneDimensionalArray
‪checkRemoveArrayEntryByValueRemovesEntriesFromOneDimensionalArray()
Definition: ArrayUtilityTest.php:2403
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\checkRemoveArrayEntryByValueRemovesEntriesFromMultiDimensionalArray
‪checkRemoveArrayEntryByValueRemovesEntriesFromMultiDimensionalArray()
Definition: ArrayUtilityTest.php:2423
‪TYPO3\CMS\Core\Utility\ArrayUtility\filterByValueRecursive
‪static array filterByValueRecursive(mixed $needle='', array $haystack=[])
Definition: ArrayUtility.php:101
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:26
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\setValueByPathSetsCorrectValue
‪setValueByPathSetsCorrectValue(array $array, $path, $value, $expectedResult)
Definition: ArrayUtilityTest.php:756
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\getValueByPathValidDataProvider
‪static getValueByPathValidDataProvider()
Definition: ArrayUtilityTest.php:365
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\isValidPathReturnsFalseIfPathDoesNotExistArrayVersion
‪isValidPathReturnsFalseIfPathDoesNotExistArrayVersion()
Definition: ArrayUtilityTest.php:231
‪TYPO3\CMS\Core\Utility\ArrayUtility\reIndexNumericArrayKeysRecursive
‪static reIndexNumericArrayKeysRecursive(array $array)
Definition: ArrayUtility.php:204
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\sortArrayWithIntegerKeysRecursiveExpectNoSorting
‪sortArrayWithIntegerKeysRecursiveExpectNoSorting()
Definition: ArrayUtilityTest.php:3166
‪TYPO3\CMS\Core\Utility\ArrayUtility\assertAllArrayKeysAreValid
‪static assertAllArrayKeysAreValid(array $arrayToTest, array $allowedArrayKeys)
Definition: ArrayUtility.php:33
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\isValidPathReturnsFalseIfPathDoesNotExistStringVersion
‪isValidPathReturnsFalseIfPathDoesNotExistStringVersion()
Definition: ArrayUtilityTest.php:215
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\removeByPathThrowsSpecificExceptionIfPathDoesNotExistInArray
‪removeByPathThrowsSpecificExceptionIfPathDoesNotExistInArray()
Definition: ArrayUtilityTest.php:838
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\filterRecursiveFiltersFalseElements
‪filterRecursiveFiltersFalseElements(array $input, array $expectedResult)
Definition: ArrayUtilityTest.php:3418
‪TYPO3\CMS\Core\Utility\ArrayUtility\sortArraysByKey
‪static array sortArraysByKey(array $arrays, string $key, bool $ascending=true)
Definition: ArrayUtility.php:358
‪TYPO3\CMS\Core\Utility\ArrayUtility\setValueByPath
‪static array setValueByPath(array $array, string|array|\ArrayAccess $path, mixed $value, string $delimiter='/')
Definition: ArrayUtility.php:261
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\arrayDiffKeyRecursiveHandlesMixedArrays
‪arrayDiffKeyRecursiveHandlesMixedArrays()
Definition: ArrayUtilityTest.php:2611
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\keepItemsInArrayCanUseClosure
‪keepItemsInArrayCanUseClosure()
Definition: ArrayUtilityTest.php:2502
‪TYPO3\CMS\Core\Utility\ArrayUtility\convertBooleanStringsToBooleanRecursive
‪static convertBooleanStringsToBooleanRecursive(array $array)
Definition: ArrayUtility.php:51
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\arrayDiffAssocRecursiveReturnsEmptyIfEqual
‪arrayDiffAssocRecursiveReturnsEmptyIfEqual()
Definition: ArrayUtilityTest.php:2752
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\arrayDiffAssocRecursiveHandlesMixedArrays
‪arrayDiffAssocRecursiveHandlesMixedArrays()
Definition: ArrayUtilityTest.php:2725
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\renumberKeysToAvoidLeapsIfKeysAreAllNumericReturnsExpectedOrder
‪renumberKeysToAvoidLeapsIfKeysAreAllNumericReturnsExpectedOrder(array $inputArray, array $expected)
Definition: ArrayUtilityTest.php:2141
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\naturalKeySortRecursiveSortsOneDimensionalArrayByNaturalOrder
‪naturalKeySortRecursiveSortsOneDimensionalArrayByNaturalOrder()
Definition: ArrayUtilityTest.php:2782
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\isAssociativeCorrectlyFindsStringKeysDataProvider
‪static isAssociativeCorrectlyFindsStringKeysDataProvider()
Definition: ArrayUtilityTest.php:3581
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\flattenCalculatesExpectedResultDataProvider
‪static flattenCalculatesExpectedResultDataProvider()
Definition: ArrayUtilityTest.php:1236
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\getValueByPathReturnsFirstIndexIfPathIsZero
‪getValueByPathReturnsFirstIndexIfPathIsZero()
Definition: ArrayUtilityTest.php:254
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\setValueByPathSetsCorrectValueDataProvider
‪static setValueByPathSetsCorrectValueDataProvider()
Definition: ArrayUtilityTest.php:547
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\arrayDiffAssocRecursiveHandlesMultiDimensionalArrays
‪arrayDiffAssocRecursiveHandlesMultiDimensionalArrays()
Definition: ArrayUtilityTest.php:2687
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\arrayDiffKeyRecursiveHandlesMultiDimensionalArrays
‪arrayDiffKeyRecursiveHandlesMultiDimensionalArrays()
Definition: ArrayUtilityTest.php:2574
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\replaceAndAppendScalarValuesRecursiveCorrectlyMergesArraysDataProvider
‪static replaceAndAppendScalarValuesRecursiveCorrectlyMergesArraysDataProvider()
Definition: ArrayUtilityTest.php:3623
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\renumberKeysToAvoidLeapsIfKeysAreAllNumericDataProvider
‪static renumberKeysToAvoidLeapsIfKeysAreAllNumericDataProvider()
Definition: ArrayUtilityTest.php:2017
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\filterRecursiveCallbackFiltersEmptyElementsWithoutIntegerByCallback
‪filterRecursiveCallbackFiltersEmptyElementsWithoutIntegerByCallback(array $input, array $expectedResult)
Definition: ArrayUtilityTest.php:3495
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\replaceAndAppendScalarValuesRecursiveCorrectlyMergesArrays
‪replaceAndAppendScalarValuesRecursiveCorrectlyMergesArrays(array $array1, array $array2, array $expectedResult)
Definition: ArrayUtilityTest.php:3699
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\filterAndSortByNumericKeysBehavesCorrectlyForAcceptAnyKeysIsFalse
‪filterAndSortByNumericKeysBehavesCorrectlyForAcceptAnyKeysIsFalse($input, $expected)
Definition: ArrayUtilityTest.php:3028
‪TYPO3\CMS\Core\Tests\Unit\Utility\ArrayUtilityTest\arrayExportThrowsExceptionIfObjectShouldBeExported
‪arrayExportThrowsExceptionIfObjectShouldBeExported()
Definition: ArrayUtilityTest.php:1163