Passed
Push — master ( 18ff88...32a943 )
by Michael
39s
created

NoKeyConflict::merge()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 41
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 7

Importance

Changes 0
Metric Value
dl 0
loc 41
ccs 19
cts 19
cp 1
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 19
nc 6
nop 2
crap 7
1
<?php
2
3
namespace micmania1\config\MergeStrategy;
4
5
use micmania1\config\Exceptions\KeyConflictException;
6
use micmania1\config\ConfigCollectionInterface;
7
use micmania1\config\ConfigCollection;
8
use Exception;
9
10
class NoKeyConflict
11
{
12 3
    public function merge(ConfigCollectionInterface $mine, ConfigCollectionInterface $theirs)
13
    {
14 3
        foreach ($mine->all() as $key => $item) {
15
16
            // The item doesn exist in theirs, so we can safely set it.
17 3
            if(!$theirs->exists($key)) {
18 3
                $theirs->set($key, $item);
19 3
                continue;
20
            }
21
22 3
            $myValue = $item->getValue();
23 3
            $theirsItem = $theirs->get($key);
24 3
            $theirsValue = $theirsItem->getValue();
25
26
            // If two items are the same, we stil overwrite as to keep a record
27
            // of the hsitory if this is being tracked.
28 3
            if($myValue === $theirsValue) {
29 1
                $theirs->set($key, $item);
30 1
                continue;
31
            }
32
33
            // If the two items aren't an array and they exist then we have a key conflict
34 3
            if(!is_array($myValue) || !is_array($theirsValue)) {
35 2
                throw new KeyConflictException($key, $mine, $theirs);
36
            }
37
38
            // By now we know that both items are arrays - we need to merge them together
39
            // without key conflicts
40
            try {
41 2
                $value = $this->mergeArrays($myValue, $theirsValue);
42 2
            } catch (Exception $e) {
43
                // The array has a key conflict
44 2
                throw new KeyConflictException($key, $mine, $theirs);
45
            }
46
47
            // The item already exists in theirs, so we just update that.
48 1
            $theirsItem->set($value);
49 3
        }
50
51 3
        return $theirs;
52
    }
53
54
    /**
55
     * This (almost) mimics the functionality as above, but works with arrays instead of
56
     * collections.
57
     *
58
     * @param array $mine
59
     * @param array $theirs
60
     *
61
     * @return array
62
     */
63 2
    protected function mergeArrays($mine, $theirs)
64
    {
65 2
        foreach($mine as $key => $value) {
66
            // If they key doesn't exist in theirs, we can safely set it
67 2
            if(!isset($theirs[$key])) {
68 1
                $theirs[$key] = $value;
69 1
                continue;
70
            }
71
72
            // The value is the same so we can skip to the next one.
73 2
            if ($mine[$key] === $theirs[$key]) {
74
                continue;
75
            }
76
77
            // If the values aren't arrays, then we have a key conflict
78 2
            if(!is_array($value) || !is_array($theirs[$key])) {
79 2
                throw new Exception("There is a key conflict in array.");
80
            }
81
82
            $theirs[$key] = $this->mergeArrays($value, $theirs[$key]);
83 1
        }
84
85 1
        return $theirs;
86
    }
87
}
88