TYPO3 CMS  TYPO3_6-2
ArrayUtilityTest.php
Go to the documentation of this file.
1 <?php
3 
17 use \TYPO3\CMS\Core\Utility\ArrayUtility;
18 
26 
28  // Tests concerning filterByValueRecursive
30 
38  public function filterByValueRecursive() {
39  return array(
40  'empty search array' => array(
41  'banana',
42  array(),
43  array()
44  ),
45  'empty string as needle' => array(
46  '',
47  array(
48  '',
49  'apple'
50  ),
51  array(
52  ''
53  )
54  ),
55  'flat array searching for string' => array(
56  'banana',
57  array(
58  'apple',
59  'banana'
60  ),
61  array(
62  1 => 'banana'
63  )
64  ),
65  'flat array searching for string with two matches' => array(
66  'banana',
67  array(
68  'foo' => 'apple',
69  'firstbanana' => 'banana',
70  'secondbanana' => 'banana'
71  ),
72  array(
73  'firstbanana' => 'banana',
74  'secondbanana' => 'banana'
75  )
76  ),
77  'multi dimensional array searching for string with multiple matches' => array(
78  'banana',
79  array(
80  'foo' => 'apple',
81  'firstbanana' => 'banana',
82  'grape' => array(
83  'foo2' => 'apple2',
84  'secondbanana' => 'banana',
85  'foo3' => array()
86  ),
87  'bar' => 'orange'
88  ),
89  array(
90  'firstbanana' => 'banana',
91  'grape' => array(
92  'secondbanana' => 'banana'
93  )
94  )
95  ),
96  'multi dimensional array searching for integer with multiple matches' => array(
97  42,
98  array(
99  'foo' => 23,
100  'bar' => 42,
101  array(
102  'foo' => 23,
103  'bar' => 42
104  )
105  ),
106  array(
107  'bar' => 42,
108  array(
109  'bar' => 42
110  )
111  )
112  ),
113  'flat array searching for boolean TRUE' => array(
114  TRUE,
115  array(
116  23 => FALSE,
117  42 => TRUE
118  ),
119  array(
120  42 => TRUE
121  )
122  ),
123  'multi dimensional array searching for boolean FALSE' => array(
124  FALSE,
125  array(
126  23 => FALSE,
127  42 => TRUE,
128  'foo' => array(
129  23 => FALSE,
130  42 => TRUE
131  )
132  ),
133  array(
134  23 => FALSE,
135  'foo' => array(
136  23 => FALSE
137  )
138  )
139  ),
140  'flat array searching for array' => array(
141  array(
142  'foo' => 'bar'
143  ),
144  array(
145  'foo' => 'bar',
146  'foobar' => array(
147  'foo' => 'bar'
148  )
149  ),
150  array(
151  'foobar' => array(
152  'foo' => 'bar'
153  )
154  )
155  )
156  );
157  }
158 
163  public function filterByValueRecursiveCorrectlyFiltersArray($needle, $haystack, $expectedResult) {
164  $this->assertEquals(
165  $expectedResult,
166  ArrayUtility::filterByValueRecursive($needle, $haystack)
167  );
168  }
169 
174  $instance = new \stdClass();
175  $this->assertEquals(
176  array($instance),
177  ArrayUtility::filterByValueRecursive($instance, array($instance))
178  );
179  }
180 
185  $this->assertEquals(
186  array(),
187  ArrayUtility::filterByValueRecursive(new \stdClass(), array(new \stdClass()))
188  );
189  }
190 
192  // Tests concerning isValidPath
194 
203  $className = $this->getUniqueId('ArrayUtility');
204  eval(
205  'namespace ' . __NAMESPACE__ . ';' .
206  'class ' . $className . ' extends \\TYPO3\\CMS\\Core\\Utility\\ArrayUtility {' .
207  ' public static function getValueByPath() {' .
208  ' return 42;' .
209  ' }' .
210  '}'
211  );
212  $className = __NAMESPACE__ . '\\' . $className;
213  $this->assertTrue($className::isValidPath(array('foo'), 'foo'));
214  }
215 
220  $className = $this->getUniqueId('ArrayUtility');
221  eval(
222  'namespace ' . __NAMESPACE__ . ';' .
223  'class ' . $className . ' extends \\TYPO3\\CMS\\Core\\Utility\\ArrayUtility {' .
224  ' public static function getValueByPath() {' .
225  ' throw new \RuntimeException(\'foo\', 123);' .
226  ' }' .
227  '}'
228  );
229  $className = __NAMESPACE__ . '\\' . $className;
230  $this->assertFalse($className::isValidPath(array('foo'), 'foo'));
231  }
232 
234  // Tests concerning getValueByPath
236 
241  ArrayUtility::getValueByPath(array(), '');
242  }
243 
252  return array(
253  'not existing path 1' => array(
254  array(
255  'foo' => array()
256  ),
257  'foo/bar/baz',
258  FALSE
259  ),
260  'not existing path 2' => array(
261  array(
262  'foo' => array(
263  'baz' => 42
264  ),
265  'bar' => array()
266  ),
267  'foo/bar/baz',
268  FALSE
269  ),
270  // Negative test: This could be improved and the test moved to
271  // the valid data provider if the method supports this
272  'doubletick encapsulated quoted doubletick does not work' => array(
273  array(
274  '"foo"bar"' => array(
275  'baz' => 42
276  ),
277  'bar' => array()
278  ),
279  '"foo\\"bar"/baz',
280  42
281  ),
282  // Negative test: Method could be improved here
283  'path with doubletick does not work' => array(
284  array(
285  'fo"o' => array(
286  'bar' => 42
287  )
288  ),
289  'fo"o/foobar',
290  42
291  )
292  );
293  }
294 
300  public function getValueByPathThrowsExceptionIfPathNotExists(array $array, $path) {
301  ArrayUtility::getValueByPath($array, $path);
302  }
303 
312  $testObject = new \StdClass();
313  $testObject->foo = 'foo';
314  $testObject->bar = 'bar';
315  return array(
316  'integer in multi level array' => array(
317  array(
318  'foo' => array(
319  'bar' => array(
320  'baz' => 42
321  ),
322  'bar2' => array()
323  )
324  ),
325  'foo/bar/baz',
326  42
327  ),
328  'zero integer in multi level array' => array(
329  array(
330  'foo' => array(
331  'bar' => array(
332  'baz' => 0
333  )
334  )
335  ),
336  'foo/bar/baz',
337  0
338  ),
339  'NULL value in multi level array' => array(
340  array(
341  'foo' => array(
342  'baz' => NULL
343  )
344  ),
345  'foo/baz',
346  NULL
347  ),
348  'get string value' => array(
349  array(
350  'foo' => array(
351  'baz' => 'this is a test string'
352  )
353  ),
354  'foo/baz',
355  'this is a test string'
356  ),
357  'get boolean value: FALSE' => array(
358  array(
359  'foo' => array(
360  'baz' => FALSE
361  )
362  ),
363  'foo/baz',
364  FALSE
365  ),
366  'get boolean value: TRUE' => array(
367  array(
368  'foo' => array(
369  'baz' => TRUE
370  )
371  ),
372  'foo/baz',
373  TRUE
374  ),
375  'get object value' => array(
376  array(
377  'foo' => array(
378  'baz' => $testObject
379  )
380  ),
381  'foo/baz',
382  $testObject
383  ),
384  'enclosed path' => array(
385  array(
386  'foo/bar' => array(
387  'foobar' => 42
388  )
389  ),
390  '"foo/bar"/foobar',
391  42
392  )
393  );
394  }
395 
400  public function getValueByPathGetsCorrectValue(array $array, $path, $expectedResult) {
401  $this->assertEquals($expectedResult, ArrayUtility::getValueByPath($array, $path));
402  }
403 
408  $input = array(
409  'foo' => array(
410  'bar' => array(
411  'baz' => 42
412  ),
413  'bar2' => array()
414  )
415  );
416  $searchPath = 'foo%bar%baz';
417  $expected = 42;
418  $delimeter = '%';
419  $this->assertEquals(
420  $expected,
421  ArrayUtility::getValueByPath($input, $searchPath, $delimeter)
422  );
423  }
424 
426  // Tests concerning setValueByPath
428 
433  ArrayUtility::setValueByPath(array(), '', NULL);
434  }
435 
441  ArrayUtility::setValueByPath(array(), array('foo'), NULL);
442  }
443 
454  $testObject = new \StdClass();
455  $testObject->foo = 'foo';
456  $testObject->bar = 'bar';
457  return array(
458  'set integer value: 42' => array(
459  array(
460  'foo' => array(
461  'bar' => array(
462  'baz' => 0
463  )
464  )
465  ),
466  'foo/bar/baz',
467  42,
468  array(
469  'foo' => array(
470  'bar' => array(
471  'baz' => 42
472  )
473  )
474  )
475  ),
476  'set integer value: 0' => array(
477  array(
478  'foo' => array(
479  'bar' => array(
480  'baz' => 42
481  )
482  )
483  ),
484  'foo/bar/baz',
485  0,
486  array(
487  'foo' => array(
488  'bar' => array(
489  'baz' => 0
490  )
491  )
492  )
493  ),
494  'set null value' => array(
495  array(
496  'foo' => array(
497  'bar' => array(
498  'baz' => 42
499  )
500  )
501  ),
502  'foo/bar/baz',
503  NULL,
504  array(
505  'foo' => array(
506  'bar' => array(
507  'baz' => NULL
508  )
509  )
510  )
511  ),
512  'set array value' => array(
513  array(
514  'foo' => array(
515  'bar' => array(
516  'baz' => 42
517  )
518  )
519  ),
520  'foo/bar/baz',
521  array(
522  'foo' => 123
523  ),
524  array(
525  'foo' => array(
526  'bar' => array(
527  'baz' => array(
528  'foo' => 123
529  )
530  )
531  )
532  )
533  ),
534  'set boolean value: FALSE' => array(
535  array(
536  'foo' => array(
537  'bar' => array(
538  'baz' => TRUE
539  )
540  )
541  ),
542  'foo/bar/baz',
543  FALSE,
544  array(
545  'foo' => array(
546  'bar' => array(
547  'baz' => FALSE
548  )
549  )
550  )
551  ),
552  'set boolean value: TRUE' => array(
553  array(
554  'foo' => array(
555  'bar' => array(
556  'baz' => NULL
557  )
558  )
559  ),
560  'foo/bar/baz',
561  TRUE,
562  array(
563  'foo' => array(
564  'bar' => array(
565  'baz' => TRUE
566  )
567  )
568  )
569  ),
570  'set object value' => array(
571  array(
572  'foo' => array(
573  'bar' => array(
574  'baz' => NULL
575  )
576  )
577  ),
578  'foo/bar/baz',
579  $testObject,
580  array(
581  'foo' => array(
582  'bar' => array(
583  'baz' => $testObject
584  )
585  )
586  )
587  ),
588  'multi keys in array' => array(
589  array(
590  'foo' => array(
591  'bar' => array(
592  'baz' => 'value'
593  ),
594  'bar2' => array(
595  'baz' => 'value'
596  )
597  )
598  ),
599  'foo/bar2/baz',
600  'newValue',
601  array(
602  'foo' => array(
603  'bar' => array(
604  'baz' => 'value'
605  ),
606  'bar2' => array(
607  'baz' => 'newValue'
608  )
609  )
610  )
611  )
612  );
613  }
614 
619  public function setValueByPathSetsCorrectValue(array $array, $path, $value, $expectedResult) {
620  $this->assertEquals(
621  $expectedResult,
622  ArrayUtility::setValueByPath($array, $path, $value)
623  );
624  }
625 
626  /**********************
627  /* Tests concerning removeByPath
628  ***********************/
629 
635  ArrayUtility::removeByPath(array(), '');
636  }
637 
643  ArrayUtility::removeByPath(array(), array('foo'));
644  }
645 
651  $inputArray = array(
652  'foo' => array(
653  'bar' => 42,
654  ),
655  );
656  ArrayUtility::removeByPath($inputArray, 'foo//bar');
657  }
658 
664  $inputArray = array(
665  'foo' => array(
666  'bar' => 42,
667  ),
668  );
669  ArrayUtility::removeByPath($inputArray, 'foo/baz');
670  }
671 
676  $inputArray = array(
677  'foo' => array(
678  'toRemove' => 42,
679  'keep' => 23
680  ),
681  );
682  $path = 'foo.toRemove';
683  $expected = array(
684  'foo' => array(
685  'keep' => 23,
686  ),
687  );
688  $this->assertEquals(
689  $expected,
690  ArrayUtility::removeByPath($inputArray, $path, '.')
691  );
692  }
693 
698  return array(
699  'single value' => array(
700  array(
701  'foo' => array(
702  'toRemove' => 42,
703  'keep' => 23
704  ),
705  ),
706  'foo/toRemove',
707  array(
708  'foo' => array(
709  'keep' => 23,
710  ),
711  ),
712  ),
713  'whole array' => array(
714  array(
715  'foo' => array(
716  'bar' => 42
717  ),
718  ),
719  'foo',
720  array(),
721  ),
722  'sub array' => array(
723  array(
724  'foo' => array(
725  'keep' => 23,
726  'toRemove' => array(
727  'foo' => 'bar',
728  ),
729  ),
730  ),
731  'foo/toRemove',
732  array(
733  'foo' => array(
734  'keep' => 23,
735  ),
736  ),
737  ),
738  );
739  }
740 
745  public function removeByPathRemovesCorrectPath(array $array, $path, $expectedResult) {
746  $this->assertEquals(
747  $expectedResult,
748  ArrayUtility::removeByPath($array, $path)
749  );
750  }
751 
753  // Tests concerning sortByKeyRecursive
755 
759  $unsortedArray = array(
760  'z' => NULL,
761  'a' => NULL,
762  'd' => array(
763  'c' => NULL,
764  'b' => NULL,
765  'd' => NULL,
766  'a' => NULL
767  )
768  );
769  $expectedResult = array(
770  'a' => NULL,
771  'd' => array(
772  'a' => NULL,
773  'b' => NULL,
774  'c' => NULL,
775  'd' => NULL
776  ),
777  'z' => NULL
778  );
779  $this->assertSame($expectedResult, ArrayUtility::sortByKeyRecursive($unsortedArray));
780  }
781 
783  // Tests concerning sortArraysByKey
785 
789  return array(
790  'assoc array index' => array(
791  array(
792  '22' => array(
793  'uid' => '22',
794  'title' => 'b',
795  'dummy' => 2
796  ),
797  '24' => array(
798  'uid' => '24',
799  'title' => 'a',
800  'dummy' => 3
801  ),
802  '23' => array(
803  'uid' => '23',
804  'title' => 'a',
805  'dummy' => 4
806  ),
807  ),
808  'title',
809  TRUE,
810  array(
811  '23' => array(
812  'uid' => '23',
813  'title' => 'a',
814  'dummy' => 4
815  ),
816  '24' => array(
817  'uid' => '24',
818  'title' => 'a',
819  'dummy' => 3
820  ),
821  '22' => array(
822  'uid' => '22',
823  'title' => 'b',
824  'dummy' => 2
825  ),
826  ),
827  ),
828  'numeric array index' => array(
829  array(
830  22 => array(
831  'uid' => '22',
832  'title' => 'b',
833  'dummy' => 2
834  ),
835  24 => array(
836  'uid' => '24',
837  'title' => 'a',
838  'dummy' => 3
839  ),
840  23 => array(
841  'uid' => '23',
842  'title' => 'a',
843  'dummy' => 4
844  ),
845  ),
846  'title',
847  TRUE,
848  array(
849  23 => array(
850  'uid' => '23',
851  'title' => 'a',
852  'dummy' => 4
853  ),
854  24 => array(
855  'uid' => '24',
856  'title' => 'a',
857  'dummy' => 3
858  ),
859  22 => array(
860  'uid' => '22',
861  'title' => 'b',
862  'dummy' => 2
863  ),
864  ),
865  ),
866  'numeric array index DESC' => array(
867  array(
868  23 => array(
869  'uid' => '23',
870  'title' => 'a',
871  'dummy' => 4
872  ),
873  22 => array(
874  'uid' => '22',
875  'title' => 'b',
876  'dummy' => 2
877  ),
878  24 => array(
879  'uid' => '24',
880  'title' => 'a',
881  'dummy' => 3
882  ),
883  ),
884  'title',
885  FALSE,
886  array(
887  22 => array(
888  'uid' => '22',
889  'title' => 'b',
890  'dummy' => 2
891  ),
892  24 => array(
893  'uid' => '24',
894  'title' => 'a',
895  'dummy' => 3
896  ),
897  23 => array(
898  'uid' => '23',
899  'title' => 'a',
900  'dummy' => 4
901  ),
902  ),
903  ),
904  );
905  }
906 
911  public function sortArraysByKeyCheckIfSortingIsCorrect(array $array, $key, $ascending, $expectedResult) {
912  $sortedArray = ArrayUtility::sortArraysByKey($array, $key, $ascending);
913  $this->assertSame($sortedArray, $expectedResult);
914  }
915 
921  ArrayUtility::sortArraysByKey(array(array('a'), array('a')), 'dummy');
922  }
923 
925  // Tests concerning arrayExport
927 
931  $array = array(
932  'foo' => array(
933  'bar' => 42,
934  'bar2' => array(
935  'baz' => 'val\'ue',
936  'baz2' => TRUE,
937  'baz3' => FALSE,
938  'baz4' => array()
939  )
940  ),
941  'baz' => 23,
942  'foobar' => NULL,
943  'qux' => 0.1,
944  'qux2' => 0.000000001,
945  );
946  $expected =
947  'array(' . LF .
948  TAB . '\'foo\' => array(' . LF .
949  TAB . TAB . '\'bar\' => 42,' . LF .
950  TAB . TAB . '\'bar2\' => array(' . LF .
951  TAB . TAB . TAB . '\'baz\' => \'val\\\'ue\',' . LF .
952  TAB . TAB . TAB . '\'baz2\' => TRUE,' . LF .
953  TAB . TAB . TAB . '\'baz3\' => FALSE,' . LF .
954  TAB . TAB . TAB . '\'baz4\' => array(),' . LF .
955  TAB . TAB . '),' . LF .
956  TAB . '),' . LF .
957  TAB . '\'baz\' => 23,' . LF .
958  TAB . '\'foobar\' => NULL,' . LF .
959  TAB . '\'qux\' => 0.1,' . LF .
960  TAB . '\'qux2\' => 1.0E-9,' . LF .
961  ')';
962  $this->assertSame($expected, ArrayUtility::arrayExport($array));
963  }
964 
970  $array = array(
971  'foo' => array(
972  'bar' => new \stdClass()
973  )
974  );
976  }
977 
982  $array = array(
983  'foo' => 'string key',
984  23 => 'integer key',
985  '42' => 'string key representing integer'
986  );
987  $expected =
988  'array(' . LF .
989  TAB . '\'foo\' => \'string key\',' . LF .
990  TAB . '23 => \'integer key\',' . LF .
991  TAB . '42 => \'string key representing integer\',' . LF .
992  ')';
993  $this->assertSame($expected, ArrayUtility::arrayExport($array));
994  }
995 
1000  $array = array(
1001  0 => 'zero',
1002  1 => 'one',
1003  2 => 'two'
1004  );
1005  $expected =
1006  'array(' . LF .
1007  TAB . '\'zero\',' . LF .
1008  TAB . '\'one\',' . LF .
1009  TAB . '\'two\',' . LF .
1010  ')';
1011  $this->assertSame($expected, ArrayUtility::arrayExport($array));
1012  }
1013 
1018  $array = array(
1019  0 => 'zero',
1020  1 => 'one',
1021  3 => 'three',
1022  4 => 'four'
1023  );
1024  $expected =
1025  'array(' . LF .
1026  TAB . '0 => \'zero\',' . LF .
1027  TAB . '1 => \'one\',' . LF .
1028  TAB . '3 => \'three\',' . LF .
1029  TAB . '4 => \'four\',' . LF .
1030  ')';
1031  $this->assertSame($expected, ArrayUtility::arrayExport($array));
1032  }
1033 
1034 
1036  // Tests concerning flatten
1038 
1043  return array(
1044  'plain array' => array(
1045  array(
1046  'first' => 1,
1047  'second' => 2
1048  ),
1049  array(
1050  'first' => 1,
1051  'second' => 2
1052  )
1053  ),
1054  'plain array with faulty dots' => array(
1055  array(
1056  'first.' => 1,
1057  'second.' => 2
1058  ),
1059  array(
1060  'first' => 1,
1061  'second' => 2
1062  )
1063  ),
1064  'nested array of 2 levels' => array(
1065  array(
1066  'first.' => array(
1067  'firstSub' => 1
1068  ),
1069  'second.' => array(
1070  'secondSub' => 2
1071  )
1072  ),
1073  array(
1074  'first.firstSub' => 1,
1075  'second.secondSub' => 2
1076  )
1077  ),
1078  'nested array of 2 levels with faulty dots' => array(
1079  array(
1080  'first.' => array(
1081  'firstSub.' => 1
1082  ),
1083  'second.' => array(
1084  'secondSub.' => 2
1085  )
1086  ),
1087  array(
1088  'first.firstSub' => 1,
1089  'second.secondSub' => 2
1090  )
1091  ),
1092  'nested array of 3 levels' => array(
1093  array(
1094  'first.' => array(
1095  'firstSub.' => array(
1096  'firstSubSub' => 1
1097  )
1098  ),
1099  'second.' => array(
1100  'secondSub.' => array(
1101  'secondSubSub' => 2
1102  )
1103  )
1104  ),
1105  array(
1106  'first.firstSub.firstSubSub' => 1,
1107  'second.secondSub.secondSubSub' => 2
1108  )
1109  ),
1110  'nested array of 3 levels with faulty dots' => array(
1111  array(
1112  'first.' => array(
1113  'firstSub.' => array(
1114  'firstSubSub.' => 1
1115  )
1116  ),
1117  'second.' => array(
1118  'secondSub.' => array(
1119  'secondSubSub.' => 2
1120  )
1121  )
1122  ),
1123  array(
1124  'first.firstSub.firstSubSub' => 1,
1125  'second.secondSub.secondSubSub' => 2
1126  )
1127  )
1128  );
1129  }
1130 
1137  public function flattenCalculatesExpectedResult(array $array, array $expected) {
1138  $this->assertEquals($expected, ArrayUtility::flatten($array));
1139  }
1140 
1141 
1143  // Tests concerning intersectRecursive
1145 
1150  $sameObject = new \stdClass();
1151  return array(
1152  // array($source, $mask, $expected)
1153  'empty array is returned if source is empty array' => array(
1154  array(),
1155  array(
1156  'foo' => 'bar',
1157  ),
1158  array(),
1159  ),
1160  'empty array is returned if mask is empty' => array(
1161  array(
1162  'foo' => 'bar',
1163  ),
1164  array(),
1165  array(),
1166  ),
1167  'key is kept on first level if exists in mask' => array(
1168  array(
1169  'foo' => 42,
1170  ),
1171  array(
1172  'foo' => 42,
1173  ),
1174  array(
1175  'foo' => 42,
1176  ),
1177  ),
1178  'value of key in source is kept if mask has different value' => array(
1179  array(
1180  'foo' => 42,
1181  ),
1182  array(
1183  'foo' => new \stdClass(),
1184  ),
1185  array(
1186  'foo' => 42,
1187  ),
1188  ),
1189  'key is kept on first level if according mask value is NULL' => array(
1190  array(
1191  'foo' => 42,
1192  ),
1193  array(
1194  'foo' => NULL,
1195  ),
1196  array(
1197  'foo' => 42,
1198  ),
1199  ),
1200  'null in source value is kept' => array(
1201  array(
1202  'foo' => NULL,
1203  ),
1204  array(
1205  'foo' => 'bar',
1206  ),
1207  array(
1208  'foo' => NULL,
1209  )
1210  ),
1211  'mask does not add new keys' => array(
1212  array(
1213  'foo' => 42,
1214  ),
1215  array(
1216  'foo' => 23,
1217  'bar' => array(
1218  4711
1219  ),
1220  ),
1221  array(
1222  'foo' => 42,
1223  ),
1224  ),
1225  'mask does not overwrite simple values with arrays' => array(
1226  array(
1227  'foo' => 42,
1228  ),
1229  array(
1230  'foo' => array(
1231  'bar' => 23,
1232  ),
1233  ),
1234  array(
1235  'foo' => 42,
1236  ),
1237  ),
1238  'key is kept on first level if according mask value is array' => array(
1239  array(
1240  'foo' => 42,
1241  ),
1242  array(
1243  'foo' => array(
1244  'bar' => 23
1245  ),
1246  ),
1247  array(
1248  'foo' => 42,
1249  ),
1250  ),
1251  'full array is kept if value is array and mask value is simple type' => array(
1252  array(
1253  'foo' => array(
1254  'bar' => 23
1255  ),
1256  ),
1257  array(
1258  'foo' => 42,
1259  ),
1260  array(
1261  'foo' => array(
1262  'bar' => 23
1263  ),
1264  ),
1265  ),
1266  'key handling is type agnostic' => array(
1267  array(
1268  42 => 'foo',
1269  ),
1270  array(
1271  '42' => 'bar',
1272  ),
1273  array(
1274  42 => 'foo',
1275  ),
1276  ),
1277  'value is same if value is object' => array(
1278  array(
1279  'foo' => $sameObject,
1280  ),
1281  array(
1282  'foo' => 'something',
1283  ),
1284  array(
1285  'foo' => $sameObject,
1286  ),
1287  ),
1288  'mask does not add simple value to result if key does not exist in source' => array(
1289  array(
1290  'foo' => '42',
1291  ),
1292  array(
1293  'foo' => '42',
1294  'bar' => 23
1295  ),
1296  array(
1297  'foo' => '42',
1298  ),
1299  ),
1300  'array of source is kept if value of mask key exists but is no array' => array(
1301  array(
1302  'foo' => '42',
1303  'bar' => array(
1304  'baz' => 23
1305  ),
1306  ),
1307  array(
1308  'foo' => 'value is not significant',
1309  'bar' => NULL,
1310  ),
1311  array(
1312  'foo' => '42',
1313  'bar' => array(
1314  'baz' => 23
1315  ),
1316  ),
1317  ),
1318  'sub arrays are kept if mask has according sub array key and is similar array' => array(
1319  array(
1320  'first1' => 42,
1321  'first2' => array(
1322  'second1' => 23,
1323  'second2' => 4711,
1324  ),
1325  ),
1326  array(
1327  'first1' => 42,
1328  'first2' => array(
1329  'second1' => 'exists but different',
1330  ),
1331  ),
1332  array(
1333  'first1' => 42,
1334  'first2' => array(
1335  'second1' => 23,
1336  ),
1337  ),
1338  ),
1339  );
1340  }
1341 
1349  public function intersectRecursiveCalculatesExpectedResult(array $source, array $mask, array $expected) {
1350  $this->assertSame($expected, ArrayUtility::intersectRecursive($source, $mask));
1351  }
1352 
1353 
1355  // Tests concerning renumberKeysToAvoidLeapsIfKeysAreAllNumeric
1357 
1361  return array(
1362  'empty array is returned if source is empty array' => array(
1363  array(),
1364  array()
1365  ),
1366  'returns self if array is already numerically keyed' => array(
1367  array(1,2,3),
1368  array(1,2,3)
1369  ),
1370  'returns correctly if keys are numeric, but contains a leap' => array(
1371  array(0 => 'One', 1 => 'Two', 3 => 'Three'),
1372  array(0 => 'One', 1 => 'Two', 2 => 'Three'),
1373  ),
1374  'returns correctly even though keys are strings but still numeric' => array(
1375  array('0' => 'One', '1' => 'Two', '3' => 'Three'),
1376  array(0 => 'One', 1 => 'Two', 2 => 'Three'),
1377  ),
1378  'returns correctly if just a single keys is not numeric' => array(
1379  array(0 => 'Zero', '1' => 'One', 'Two' => 'Two'),
1380  array(0 => 'Zero', '1' => 'One', 'Two' => 'Two'),
1381  ),
1382  'return self with nested numerically keyed array' => array(
1383  array(
1384  'One',
1385  'Two',
1386  'Three',
1387  array(
1388  'sub.One',
1389  'sub.Two',
1390  )
1391  ),
1392  array(
1393  'One',
1394  'Two',
1395  'Three',
1396  array(
1397  'sub.One',
1398  'sub.Two',
1399  )
1400  )
1401  ),
1402  'returns correctly with nested numerically keyed array with leaps' => array(
1403  array(
1404  'One',
1405  'Two',
1406  'Three',
1407  array(
1408  0 => 'sub.One',
1409  2 => 'sub.Two',
1410  )
1411  ),
1412  array(
1413  'One',
1414  'Two',
1415  'Three',
1416  array(
1417  'sub.One',
1418  'sub.Two',
1419  )
1420  )
1421  ),
1422  'returns correctly with nested string-keyed array' => array(
1423  array(
1424  'One',
1425  'Two',
1426  'Three',
1427  array(
1428  'one' => 'sub.One',
1429  'two' => 'sub.Two',
1430  )
1431  ),
1432  array(
1433  'One',
1434  'Two',
1435  'Three',
1436  array(
1437  'one' => 'sub.One',
1438  'two' => 'sub.Two',
1439  )
1440  )
1441  ),
1442  'returns correctly with deeply nested arrays' => array(
1443  array(
1444  'One',
1445  'Two',
1446  array(
1447  'one' => 1,
1448  'two' => 2,
1449  'three' => array(
1450  2 => 'SubSubOne',
1451  5 => 'SubSubTwo',
1452  9 => array(0,1,2),
1453  array()
1454  )
1455  )
1456  ),
1457  array(
1458  'One',
1459  'Two',
1460  array(
1461  'one' => 1,
1462  'two' => 2,
1463  'three' => array(
1464  'SubSubOne',
1465  'SubSubTwo',
1466  array(0,1,2),
1467  array()
1468  )
1469  )
1470  )
1471  )
1472  );
1473  }
1474 
1481  public function renumberKeysToAvoidLeapsIfKeysAreAllNumeric(array $inputArray, array $expected) {
1482  $this->assertEquals($expected, ArrayUtility::renumberKeysToAvoidLeapsIfKeysAreAllNumeric($inputArray));
1483  }
1484 
1485 
1490  $array1 = array(
1491  'first' => array(
1492  'second' => 'second',
1493  'third' => 'third'
1494  ),
1495  'fifth' => array()
1496  );
1497  $array2 = array(
1498  'first' => array(
1499  'second' => 'overrule',
1500  'third' => '__UNSET',
1501  'fourth' => 'overrile'
1502  ),
1503  'fifth' => '__UNSET'
1504  );
1505  $expected = array(
1506  'first' => array(
1507  'second' => 'overrule',
1508  'fourth' => 'overrile'
1509  )
1510  );
1511  ArrayUtility::mergeRecursiveWithOverrule($array1, $array2);
1512  $this->assertEquals($expected, $array1);
1513  }
1514 }
sortArraysByKeyCheckIfSortingIsCorrect(array $array, $key, $ascending, $expectedResult)
setValueByPathSetsCorrectValue(array $array, $path, $value, $expectedResult)
static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=TRUE, $includeEmptyValues=TRUE, $enableUnsetFeature=TRUE)
static setValueByPath(array $array, $path, $value, $delimiter='/')
static getValueByPath(array $array, $path, $delimiter='/')
intersectRecursiveCalculatesExpectedResult(array $source, array $mask, array $expected)
static flatten(array $array, $prefix='')
static sortArraysByKey(array $arrays, $key, $ascending=TRUE)
removeByPathRemovesCorrectPath(array $array, $path, $expectedResult)
getValueByPathGetsCorrectValue(array $array, $path, $expectedResult)
static removeByPath(array $array, $path, $delimiter='/')
static filterByValueRecursive($needle='', array $haystack=array())
static sortByKeyRecursive(array $array)
static renumberKeysToAvoidLeapsIfKeysAreAllNumeric(array $array=array(), $level=0)
static intersectRecursive(array $source, array $mask=array())
static arrayExport(array $array=array(), $level=0)
flattenCalculatesExpectedResult(array $array, array $expected)
renumberKeysToAvoidLeapsIfKeysAreAllNumeric(array $inputArray, array $expected)
filterByValueRecursiveCorrectlyFiltersArray($needle, $haystack, $expectedResult)