Skip to content

Commit

Permalink
[TASK] Optimize and cleanup replaceAndAppendScalarValuesRecursive()
Browse files Browse the repository at this point in the history
This optimizes ArrayUtility::replaceAndAppendScalarValuesRecursive() by
moving parts into new method hasStringKeys and removing other
duplicated code.

Resolves: #88674
Releases: master
Change-Id: Ieb0f57c330c400af94fc85bfd9af725cc8a8fe18
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/61215
Reviewed-by: Oliver Klee <typo3-coding@oliverklee.de>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
  • Loading branch information
gilbertsoft authored and NeoBlack committed Aug 23, 2019
1 parent 709a9ee commit 003c5ef
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 20 deletions.
50 changes: 30 additions & 20 deletions typo3/sysext/core/Classes/Utility/ArrayUtility.php
Expand Up @@ -861,44 +861,54 @@ public static function filterRecursive(array $array, callable $callback = null):
return $array;
}

/**
* Check whether the array has non-integer keys. If there is at least one string key, $array will be
* regarded as an associative array.
*
* @param array $array
* @return bool True in case a string key was found.
* @internal
*/
public static function isAssociative(array $array): bool
{
return count(array_filter(array_keys($array), 'is_string')) > 0;
}

/**
* Same as array_replace_recursive except that when in simple arrays (= YAML lists), the entries are
* appended (array_merge). The second array takes precedence in case of equal sub arrays.
*
* @param array $val1
* @param array $val2
* @param array $array1
* @param array $array2
* @return array
* @internal
*/
public static function replaceAndAppendScalarValuesRecursive(array $val1, array $val2): array
public static function replaceAndAppendScalarValuesRecursive(array $array1, array $array2): array
{
// Simple lists get merged / added up
if (count(array_filter(array_keys($val1), 'is_int')) === count($val1)) {
return array_merge($val1, $val2);
if (!self::isAssociative($array1)) {
return array_merge($array1, $array2);
}
foreach ($val1 as $k => $v) {
foreach ($array1 as $k => $v) {
// The key also exists in second array, if it is a simple value
// then $val2 will override the value, where an array is calling mergeYaml() recursively.
if (isset($val2[$k])) {
if (is_array($v) && isset($val2[$k])) {
if (is_array($val2[$k])) {
$val1[$k] = self::replaceAndAppendScalarValuesRecursive($v, $val2[$k]);
} else {
$val1[$k] = $val2[$k];
}
// then $array2 will override the value, where an array is calling
// replaceAndAppendScalarValuesRecursive() recursively.
if (isset($array2[$k])) {
if (is_array($v) && is_array($array2[$k])) {
$array1[$k] = self::replaceAndAppendScalarValuesRecursive($v, $array2[$k]);
} else {
$val1[$k] = $val2[$k];
$array1[$k] = $array2[$k];
}
unset($val2[$k]);
unset($array2[$k]);
}
}
// If there are properties in the second array left, they are added up
if (!empty($val2)) {
foreach ($val2 as $k => $v) {
$val1[$k] = $v;
if (!empty($array2)) {
foreach ($array2 as $k => $v) {
$array1[$k] = $v;
}
}

return $val1;
return $array1;
}
}
45 changes: 45 additions & 0 deletions typo3/sysext/core/Tests/Unit/Utility/ArrayUtilityTest.php
Expand Up @@ -2992,6 +2992,51 @@ public function filterRecursiveSupportsCallableCallback(array $input, array $exp
$this->assertEquals($expectedResult, $result);
}

/**
* Data provider for isAssociativeCorrectlyFindsStringKeys
* @return array
*/
public function isAssociativeCorrectlyFindsStringKeysDataProvider()
{
return [
'array without string keys' => [
[
0 => 'value 0',
1 => 'value 1'
],
false
],
'array with only string keys' => [
[
'key 0' => 'value 0',
'key 1' => 'value 1'
],
true
],
'array with mixed keys' => [
[
0 => 'value 0',
1 => 'value 1',
'key 2' => 'value 2',
'key 3' => 'value 3'
],
true
],
];
}

/**
* @test
* @dataProvider isAssociativeCorrectlyFindsStringKeysDataProvider
* @param array $array
* @param bool $expectedResult
*/
public function isAssociativeCorrectlyFindsStringKeys(array $array, bool $expectedResult)
{
$result = ArrayUtility::isAssociative($array);
$this->assertEquals($expectedResult, $result);
}

/**
* Data provider for replaceAndAppendScalarValuesRecursiveCorrectlyMergesArrays
* @return array
Expand Down

0 comments on commit 003c5ef

Please sign in to comment.