Completed
Pull Request — master (#3)
by David
02:00
created

YamlUtils::mergeArrays()   B

Complexity

Conditions 7
Paths 5

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 13
nc 5
nop 3
dl 0
loc 20
rs 8.2222
c 0
b 0
f 0
1
<?php
2
3
4
namespace TheCodingMachine\CMS\StaticRegistry\Loaders;
5
6
7
class YamlUtils
8
{
9
    public const OVERRIDE = 'override';
10
    public const MERGE_ARRAY = 'mergeArray';
11
12
    /**
13
     * @param mixed[] $baseYaml
14
     * @param mixed[] $yaml
15
     * @param string[] $instructions
16
     * @return mixed[]
17
     */
18
    public function mergeArrays(array $baseYaml, array $yaml, array $instructions): array
19
    {
20
        foreach ($instructions as $key => $value) {
21
            switch ($value) {
22
                case self::OVERRIDE:
23
                    if (!isset($yaml[$key]) && isset($baseYaml[$key])) {
24
                        $yaml[$key] = $baseYaml[$key];
25
                    }
26
                    break;
27
                case self::MERGE_ARRAY:
28
                    if (isset($baseYaml[$key])) {
29
                        $yaml[$key] = $this->recursiveMerge($baseYaml[$key], $yaml[$key]);
30
                    }
31
                    break;
32
                default:
33
                    throw new \InvalidArgumentException('Unexpected instruction "'.$value.'" passed. Expecting either "override" or "mergeArray".');
34
            }
35
        }
36
37
        return $yaml;
38
    }
39
40
    private function recursiveMerge(array $base, array $target): array
41
    {
42
        if (!$this->isAssoc($base) && !$this->isAssoc($target)) {
43
            foreach ($target as $value) {
44
                $base[] = $value;
45
            }
46
            return $base;
47
        }
48
49
        foreach ($base as $key => $value) {
50
            if (!isset($target[$key])) {
51
                $target[$key] = $value;
52
                continue;
53
            }
54
            if (is_array($target[$key]) && is_array($value)) {
55
                $target[$key] = $this->recursiveMerge($value, $target[$key]);
56
            }
57
            // Otherwise, target wins, nothing to do
58
        }
59
        return $target;
60
    }
61
62
    /**
63
     * @param mixed[] $arr
64
     * @return bool
65
     */
66
    private function isAssoc(array $arr): bool
67
    {
68
        if (array() === $arr) return false;
69
        return array_keys($arr) !== range(0, count($arr) - 1);
70
    }
71
}
72