[TASK] Improve performance of Utility/Arrays::integerExplode
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Tests / Unit / Utility / ArraysTest.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) Extbase Team
6 * All rights reserved
7 *
8 * This class is a backport of the corresponding class of FLOW3.
9 * All credits go to the v5 team.
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27
28 /**
29 * Testcase for the Tx_Extbase_Utility_Arrays class.
30 *
31 * @author Tymoteusz Motylewski <t.motylewski@gmail.com>
32 */
33 class Tx_Extbase_Tests_Unit_Utility_ArraysTest extends Tx_Extbase_Tests_Unit_BaseTestCase {
34
35 /**
36 * @test
37 */
38 public function containsMultipleTypesReturnsFalseOnEmptyArray() {
39 $this->assertFalse(Tx_Extbase_Utility_Arrays::containsMultipleTypes(array()));
40 }
41
42 /**
43 * @test
44 */
45 public function containsMultipleTypesReturnsFalseOnArrayWithIntegers() {
46 $this->assertFalse(Tx_Extbase_Utility_Arrays::containsMultipleTypes(array(1, 2, 3)));
47 }
48
49 /**
50 * @test
51 */
52 public function containsMultipleTypesReturnsFalseOnArrayWithObjects() {
53 $this->assertFalse(Tx_Extbase_Utility_Arrays::containsMultipleTypes(array(new \stdClass(), new \stdClass(), new \stdClass())));
54 }
55
56 /**
57 * @test
58 */
59 public function containsMultipleTypesReturnsTrueOnMixedArray() {
60 $this->assertTrue(Tx_Extbase_Utility_Arrays::containsMultipleTypes(array(1, 'string', 1.25, new \stdClass())));
61 }
62
63 /**
64 * @test
65 */
66 public function getValueByPathReturnsTheValueOfANestedArrayByFollowingTheGivenSimplePath() {
67 $array = array('Foo' => 'the value');
68
69 $this->assertSame('the value', Tx_Extbase_Utility_Arrays::getValueByPath($array, array('Foo')));
70 }
71
72 /**
73 * @test
74 */
75 public function getValueByPathReturnsTheValueOfANestedArrayByFollowingTheGivenPath() {
76 $array = array('Foo' => array('Bar' => array('Baz' => array(2 => 'the value'))));
77
78 $this->assertSame('the value', Tx_Extbase_Utility_Arrays::getValueByPath($array, array('Foo', 'Bar', 'Baz', 2)));
79 }
80
81 /**
82 * @test
83 */
84 public function getValueByPathReturnsTheValueOfANestedArrayByFollowingTheGivenPathIfPathIsString() {
85 $path = 'Foo.Bar.Baz.2';
86 $array = array('Foo' => array('Bar' => array('Baz' => array(2 => 'the value'))));
87 $expectedResult = 'the value';
88 $actualResult = Tx_Extbase_Utility_Arrays::getValueByPath($array, $path);
89
90 $this->assertSame($expectedResult, $actualResult);
91 }
92
93 /**
94 * @test
95 * @expectedException \InvalidArgumentException
96 */
97 public function getValueByPathThrowsExceptionIfPathIsNoArrayOrString() {
98 $array = array('Foo' => array('Bar' => array('Baz' => array(2 => 'the value'))));
99 Tx_Extbase_Utility_Arrays::getValueByPath($array, NULL);
100 }
101
102 /**
103 * @test
104 */
105 public function getValueByPathReturnsNullIfTheSegementsOfThePathDontExist() {
106 $array = array('Foo' => array('Bar' => array('Baz' => array(2 => 'the value'))));
107
108 $this->assertNull(Tx_Extbase_Utility_Arrays::getValueByPath($array, array('Foo', 'Bar', 'Bax', 2)));
109 }
110
111 /**
112 * @test
113 */
114 public function getValueByPathReturnsNullIfThePathHasMoreSegmentsThanTheGivenArray() {
115 $array = array('Foo' => array('Bar' => array('Baz' => 'the value')));
116
117 $this->assertNull(Tx_Extbase_Utility_Arrays::getValueByPath($array, array('Foo', 'Bar', 'Baz', 'Bux')));
118 }
119
120 /**
121 * @test
122 */
123 public function convertObjectToArrayConvertsNestedObjectsToArray() {
124 $object = new \stdClass();
125 $object->a = 'v';
126 $object->b = new \stdClass();
127 $object->b->c = 'w';
128 $object->d = array('i' => 'foo', 'j' => 12, 'k' => TRUE, 'l' => new \stdClass());
129
130 $array = Tx_Extbase_Utility_Arrays::convertObjectToArray($object);
131 $expected = array(
132 'a' => 'v',
133 'b' => array(
134 'c' => 'w'
135 ),
136 'd' => array(
137 'i' => 'foo',
138 'j' => 12,
139 'k' => TRUE,
140 'l' => array()
141 )
142 );
143
144 $this->assertSame($expected, $array);
145 }
146
147 /**
148 * @test
149 */
150 public function setValueByPathSetsValueRecursivelyIfPathIsArray() {
151 $array = array();
152 $path = array('foo', 'bar', 'baz');
153 $expectedValue = array('foo' => array('bar' => array('baz' => 'The Value')));
154 $actualValue = Tx_Extbase_Utility_Arrays::setValueByPath($array, $path, 'The Value');
155
156 $this->assertSame($expectedValue, $actualValue);
157 }
158
159 /**
160 * @test
161 */
162 public function setValueByPathSetsValueRecursivelyIfPathIsString() {
163 $array = array();
164 $path = 'foo.bar.baz';
165 $expectedValue = array('foo' => array('bar' => array('baz' => 'The Value')));
166 $actualValue = Tx_Extbase_Utility_Arrays::setValueByPath($array, $path, 'The Value');
167
168 $this->assertSame($expectedValue, $actualValue);
169 }
170
171 /**
172 * @test
173 */
174 public function setValueByPathRecursivelyMergesAnArray() {
175 $array = array('foo' => array('bar' => 'should be overriden'), 'bar' => 'Baz');
176 $path = array('foo', 'bar', 'baz');
177 $expectedValue = array('foo' => array('bar' => array('baz' => 'The Value')), 'bar' => 'Baz');
178 $actualValue = Tx_Extbase_Utility_Arrays::setValueByPath($array, $path, 'The Value');
179
180 $this->assertSame($expectedValue, $actualValue);
181 }
182
183 /**
184 * @test
185 * @expectedException \InvalidArgumentException
186 */
187 public function setValueByPathThrowsExceptionIfPathIsNoArrayOrString() {
188 $array = array('Foo' => array('Bar' => array('Baz' => array(2 => 'the value'))));
189 Tx_Extbase_Utility_Arrays::setValueByPath($array, NULL, 'Some Value');
190 }
191
192 /**
193 * @test
194 * @expectedException \InvalidArgumentException
195 */
196 public function setValueByPathThrowsExceptionIfSubjectIsNoArray() {
197 $subject = 'foobar';
198 Tx_Extbase_Utility_Arrays::setValueByPath($subject, 'foo', 'bar');
199 }
200
201 /**
202 * @test
203 * @expectedException \InvalidArgumentException
204 */
205 public function setValueByPathThrowsExceptionIfSubjectIsNoArrayAccess() {
206 $subject = new \stdClass();
207 Tx_Extbase_Utility_Arrays::setValueByPath($subject, 'foo', 'bar');
208 }
209
210 /**
211 * @test
212 */
213 public function setValueByLeavesInputArrayUnchanged() {
214 $subject = $subjectBackup = array('foo' => 'bar');
215 Tx_Extbase_Utility_Arrays::setValueByPath($subject, 'foo', 'baz');
216
217 $this->assertSame($subject, $subjectBackup);
218 }
219
220 /**
221 * @test
222 */
223 public function unsetValueByPathDoesNotModifyAnArrayIfThePathWasNotFound() {
224 $array = array('foo' => array('bar' => array('baz' => 'Some Value')), 'bar' => 'Baz');
225 $path = array('foo', 'bar', 'nonExistingKey');
226 $expectedValue = $array;
227 $actualValue = Tx_Extbase_Utility_Arrays::unsetValueByPath($array, $path);
228
229 $this->assertSame($expectedValue, $actualValue);
230 }
231
232 /**
233 * @test
234 */
235 public function unsetValueByPathRemovesSpecifiedKey() {
236 $array = array('foo' => array('bar' => array('baz' => 'Some Value')), 'bar' => 'Baz');
237 $path = array('foo', 'bar', 'baz');
238 $expectedValue = array('foo' => array('bar' => array()), 'bar' => 'Baz');;
239 $actualValue = Tx_Extbase_Utility_Arrays::unsetValueByPath($array, $path);
240
241 $this->assertSame($expectedValue, $actualValue);
242 }
243
244 /**
245 * @test
246 */
247 public function unsetValueByPathRemovesSpecifiedKeyIfPathIsString() {
248 $array = array('foo' => array('bar' => array('baz' => 'Some Value')), 'bar' => 'Baz');
249 $path = 'foo.bar.baz';
250 $expectedValue = array('foo' => array('bar' => array()), 'bar' => 'Baz');;
251 $actualValue = Tx_Extbase_Utility_Arrays::unsetValueByPath($array, $path);
252
253 $this->assertSame($expectedValue, $actualValue);
254 }
255
256 /**
257 * @test
258 */
259 public function unsetValueByPathRemovesSpecifiedBranch() {
260 $array = array('foo' => array('bar' => array('baz' => 'Some Value')), 'bar' => 'Baz');
261 $path = array('foo');
262 $expectedValue = array('bar' => 'Baz');;
263 $actualValue = Tx_Extbase_Utility_Arrays::unsetValueByPath($array, $path);
264
265 $this->assertSame($expectedValue, $actualValue);
266 }
267
268 /**
269 * @test
270 * @expectedException \InvalidArgumentException
271 */
272 public function unsetValueByPathThrowsExceptionIfPathIsNoArrayOrString() {
273 $array = array('Foo' => array('Bar' => array('Baz' => array(2 => 'the value'))));
274 Tx_Extbase_Utility_Arrays::unsetValueByPath($array, NULL);
275 }
276
277 /**
278 * @test
279 */
280 public function removeEmptyElementsRecursivelyRemovesNullValues() {
281 $array = array('EmptyElement' => NULL, 'Foo' => array('Bar' => array('Baz' => array('NotNull' => '', 'AnotherEmptyElement' => NULL))));
282 $expectedResult = array('Foo' => array('Bar' => array('Baz' => array('NotNull' => ''))));
283 $actualResult = Tx_Extbase_Utility_Arrays::removeEmptyElementsRecursively($array);
284
285 $this->assertSame($expectedResult, $actualResult);
286 }
287
288 /**
289 * @test
290 */
291 public function removeEmptyElementsRecursivelyRemovesEmptySubArrays() {
292 $array = array('EmptyElement' => array(), 'Foo' => array('Bar' => array('Baz' => array('AnotherEmptyElement' => NULL))), 'NotNull' => 123);
293 $expectedResult = array('NotNull' => 123);
294 $actualResult = Tx_Extbase_Utility_Arrays::removeEmptyElementsRecursively($array);
295
296 $this->assertSame($expectedResult, $actualResult);
297 }
298
299 public function arrayMergeRecursiveOverruleData() {
300 return array(
301 'simple usage' => array(
302 'inputArray1' => array(
303 'k1' => 'v1',
304 'k2' => 'v2',
305 ),
306 'inputArray2' => array(
307 'k2' => 'v2a',
308 'k3' => 'v3'
309 ),
310 'dontAddNewKeys' => FALSE, // default
311 'emptyValuesOverride' => TRUE, // default
312 'expected' => array(
313 'k1' => 'v1',
314 'k2' => 'v2a',
315 'k3' => 'v3'
316 )
317 ),
318
319 'simple usage with recursion' => array(
320 'inputArray1' => array(
321 'k1' => 'v1',
322 'k2' => array(
323 'k2.1' => 'v2.1',
324 'k2.2' => 'v2.2'
325 ),
326 ),
327 'inputArray2' => array(
328 'k2' => array(
329 'k2.2' => 'v2.2a',
330 'k2.3' => 'v2.3'
331 ),
332 'k3' => 'v3'
333 ),
334 'dontAddNewKeys' => FALSE, // default
335 'emptyValuesOverride' => TRUE, // default
336 'expected' => array(
337 'k1' => 'v1',
338 'k2' => array(
339 'k2.1' => 'v2.1',
340 'k2.2' => 'v2.2a',
341 'k2.3' => 'v2.3'
342 ),
343 'k3' => 'v3'
344 )
345 ),
346
347 'simple type should override array (k2)' => array(
348 'inputArray1' => array(
349 'k1' => 'v1',
350 'k2' => array(
351 'k2.1' => 'v2.1'
352 ),
353 ),
354 'inputArray2' => array(
355 'k2' => 'v2a',
356 'k3' => 'v3'
357 ),
358 'dontAddNewKeys' => FALSE, // default
359 'emptyValuesOverride' => TRUE, // default
360 'expected' => array(
361 'k1' => 'v1',
362 'k2' => 'v2a',
363 'k3' => 'v3'
364 )
365 ),
366
367 'null should override array (k2)' => array(
368 'inputArray1' => array(
369 'k1' => 'v1',
370 'k2' => array(
371 'k2.1' => 'v2.1'
372 ),
373 ),
374 'inputArray2' => array(
375 'k2' => NULL,
376 'k3' => 'v3'
377 ),
378 'dontAddNewKeys' => FALSE, // default
379 'emptyValuesOverride' => TRUE, // default
380 'expected' => array(
381 'k1' => 'v1',
382 'k2' => NULL,
383 'k3' => 'v3'
384 )
385 ),
386 );
387 }
388
389 /**
390 * @test
391 * @param array $inputArray1
392 * @param array $inputArray2
393 * @param boolean $dontAddNewKeys
394 * @param boolean $emptyValuesOverride
395 * @param array $expected
396 * @dataProvider arrayMergeRecursiveOverruleData
397 */
398 public function arrayMergeRecursiveOverruleMergesSimpleArrays(
399 array $inputArray1, array $inputArray2, $dontAddNewKeys, $emptyValuesOverride, array $expected
400 ) {
401 $this->assertSame(
402 $expected,
403 Tx_Extbase_Utility_Arrays::arrayMergeRecursiveOverrule(
404 $inputArray1, $inputArray2, $dontAddNewKeys, $emptyValuesOverride
405 )
406 );
407 }
408
409 /**
410 * @test
411 */
412 public function integerExplodeReturnsArrayOfIntegers() {
413 $inputString = '1,2,3,4,5,6';
414 $expected = array(1,2,3,4,5,6);
415 $this->assertSame(
416 $expected,
417 Tx_Extbase_Utility_Arrays::integerExplode(',', $inputString)
418 );
419 }
420
421 /**
422 * @test
423 */
424 public function integerExplodeReturnsZeroForStringValues() {
425 $inputString = '1,abc,3,,5';
426 $expected = array(1,0,3,0,5);
427 $this->assertSame(
428 $expected,
429 Tx_Extbase_Utility_Arrays::integerExplode(',', $inputString)
430 );
431 }
432
433 }
434 ?>