115 lines
3.9 KiB
PHP
115 lines
3.9 KiB
PHP
<?php
|
|
/**
|
|
* This file is part of the Composer Merge plugin.
|
|
*
|
|
* Copyright (C) 2015 Bryan Davis, Wikimedia Foundation, and contributors
|
|
*
|
|
* This software may be modified and distributed under the terms of the MIT
|
|
* license. See the LICENSE file for details.
|
|
*/
|
|
|
|
namespace Wikimedia\Composer\Merge\V2;
|
|
|
|
/**
|
|
* Adapted from
|
|
* http://cgit.drupalcode.org/drupal/tree/core/lib/Drupal/Component/Utility/NestedArray.php
|
|
* @ f86a4d650d5af0b82a3981e09977055fa63f6f2e
|
|
*/
|
|
class NestedArray
|
|
{
|
|
|
|
/**
|
|
* Merges multiple arrays, recursively, and returns the merged array.
|
|
*
|
|
* This function is similar to PHP's array_merge_recursive() function, but
|
|
* it handles non-array values differently. When merging values that are
|
|
* not both arrays, the latter value replaces the former rather than
|
|
* merging with it.
|
|
*
|
|
* Example:
|
|
*
|
|
* @code
|
|
* $link_options_1 = ['fragment' => 'x', 'attributes' => ['title' => t('X'), 'class' => ['a', 'b']]];
|
|
* $link_options_2 = ['fragment' => 'y', 'attributes' => ['title' => t('Y'), 'class' => ['c', 'd']]];
|
|
*
|
|
* // This results in ['fragment' => ['x', 'y'], 'attributes' =>
|
|
* // ['title' => [t('X'), t('Y')], 'class' => ['a', 'b',
|
|
* // 'c', 'd']]].
|
|
* $incorrect = array_merge_recursive($link_options_1, $link_options_2);
|
|
*
|
|
* // This results in ['fragment' => 'y', 'attributes' =>
|
|
* // ['title' => t('Y'), 'class' => ['a', 'b', 'c', 'd']]].
|
|
* $correct = NestedArray::mergeDeep($link_options_1, $link_options_2);
|
|
* @endcode
|
|
*
|
|
* @param mixed ...$params Arrays to merge.
|
|
*
|
|
* @return array The merged array.
|
|
*
|
|
* @see NestedArray::mergeDeepArray()
|
|
*/
|
|
public static function mergeDeep(...$params)
|
|
{
|
|
return self::mergeDeepArray($params);
|
|
}
|
|
|
|
/**
|
|
* Merges multiple arrays, recursively, and returns the merged array.
|
|
*
|
|
* This function is equivalent to NestedArray::mergeDeep(), except the
|
|
* input arrays are passed as a single array parameter rather than
|
|
* a variable parameter list.
|
|
*
|
|
* The following are equivalent:
|
|
* - NestedArray::mergeDeep($a, $b);
|
|
* - NestedArray::mergeDeepArray([$a, $b]);
|
|
*
|
|
* The following are also equivalent:
|
|
* - call_user_func_array('NestedArray::mergeDeep', $arrays_to_merge);
|
|
* - NestedArray::mergeDeepArray($arrays_to_merge);
|
|
*
|
|
* @param array $arrays
|
|
* An arrays of arrays to merge.
|
|
* @param bool $preserveIntegerKeys
|
|
* (optional) If given, integer keys will be preserved and merged
|
|
* instead of appended. Defaults to false.
|
|
*
|
|
* @return array
|
|
* The merged array.
|
|
*
|
|
* @see NestedArray::mergeDeep()
|
|
*/
|
|
public static function mergeDeepArray(
|
|
array $arrays,
|
|
$preserveIntegerKeys = false
|
|
) {
|
|
$result = [];
|
|
foreach ($arrays as $array) {
|
|
foreach ($array as $key => $value) {
|
|
// Renumber integer keys as array_merge_recursive() does
|
|
// unless $preserveIntegerKeys is set to TRUE. Note that PHP
|
|
// automatically converts array keys that are integer strings
|
|
// (e.g., '1') to integers.
|
|
if (is_int($key) && !$preserveIntegerKeys) {
|
|
$result[] = $value;
|
|
} elseif (isset($result[$key]) &&
|
|
is_array($result[$key]) &&
|
|
is_array($value)
|
|
) {
|
|
// Recurse when both values are arrays.
|
|
$result[$key] = self::mergeDeepArray(
|
|
[$result[$key], $value],
|
|
$preserveIntegerKeys
|
|
);
|
|
} else {
|
|
// Otherwise, use the latter value, overriding any
|
|
// previous value.
|
|
$result[$key] = $value;
|
|
}
|
|
}
|
|
}
|
|
return $result;
|
|
}
|
|
}
|
|
// vim:sw=4:ts=4:sts=4:et:
|