Passed
Pull Request — master (#1)
by Harry
03:00
created

RecursiveArrayMerger::merge()   C

Complexity

Conditions 14
Paths 8

Size

Total Lines 35
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
eloc 22
nc 8
nop 2
dl 0
loc 35
rs 6.2666
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Graze\ArrayMerger;
4
5
use Graze\ArrayMerger\ValueMerger\LastValue;
6
7
/**
8
 * Class RecursiveArrayMerger
9
 *
10
 * array_merge_recursive does indeed merge arrays, but it converts values with duplicate
11
 * keys to arrays rather than overwriting the value in the first array with the duplicate
12
 * value in the second array, as array_merge does. I.e., with array_merge_recursive,
13
 * this happens (documented behavior):
14
 *
15
 * array_merge_recursive(array('key' => 'org value'), array('key' => 'new value'));
16
 *     => array('key' => array('org value', 'new value'));
17
 */
18
class RecursiveArrayMerger implements ArrayMergerInterface
19
{
20
    use StaticMethodsTrait;
21
22
    /** @var callable */
23
    protected $valueMerger;
24
    /** @var int */
25
    private $flags;
26
27
    /**
28
     * @param callable $valueMerger
29
     * @param int      $flags one of ArrayMergerInterface::FLAG_*
30
     */
31
    public function __construct(callable $valueMerger = null, $flags = 0)
32
    {
33
        $this->valueMerger = $valueMerger ?: new LastValue();
34
        $this->flags = $flags;
35
    }
36
37
    /**
38
     * Merge using the supplied Value Merge
39
     *
40
     * @param callable $valueMerger
41
     * @param array    $array1
42
     * @param array    $arrays
43
     *
44
     * @return array
45
     */
46
    public static function mergeUsing(callable $valueMerger, array $array1, array $arrays)
47
    {
48
        $merger = new static($valueMerger);
49
        return call_user_func_array([$merger, 'merge'], array_merge([$array1], array_slice(func_get_args(), 2)));
50
    }
51
52
    /**
53
     * Merge the values from all the array supplied, the first array is treated as the base array to merge into
54
     *
55
     * @param array      $array1
56
     * @param array|null $arrays
57
     *
58
     * @return array
59
     */
60
    public function merge(array $array1, array $arrays = null)
61
    {
62
        $arrays = array_slice(func_get_args(), 1);
63
        if (count($arrays) === 0) {
64
            return $array1;
65
        }
66
67
        // if all arrays are sequential and flag is set, append them all
68
        if ($this->flags & static::FLAG_APPEND_VALUE_ARRAY == static::FLAG_APPEND_VALUE_ARRAY
69
            && array_is_sequential($array1)
70
            && count(array_filter($arrays, 'Graze\ArrayMerger\array_is_sequential')) === count($arrays)) {
71
            return call_user_func_array('array_merge', array_merge([$array1], $arrays));
72
        }
73
74
        $merged = $array1;
75
76
        foreach ($arrays as $toMerge) {
77
            foreach ($toMerge as $key => &$value) {
78
                if (is_array($value) && array_key_exists($key, $merged) && is_array($merged[$key])) {
79
                    if ($this->flags & static::FLAG_APPEND_VALUE_ARRAY == static::FLAG_APPEND_VALUE_ARRAY
80
                        && array_is_sequential($value)
81
                        && array_is_sequential($merged[$key])) {
82
                        $merged[$key] = array_merge($merged[$key], $value);
83
                    } else {
84
                        $merged[$key] = $this->merge($merged[$key], $value);
85
                    }
86
                } elseif (array_key_exists($key, $merged)) {
87
                    $merged[$key] = call_user_func($this->valueMerger, $merged[$key], $value);
88
                } else {
89
                    $merged[$key] = $value;
90
                }
91
            }
92
        }
93
94
        return $merged;
95
    }
96
}
97