Passed
Push — master ( 70e201...c60b6f )
by Sam
02:31
created

Map::mergeWith()   C

Complexity

Conditions 7
Paths 4

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 7
eloc 13
c 2
b 0
f 0
nc 4
nop 1
dl 0
loc 22
rs 6.9811
1
<?php
2
namespace SamIT\Yii2\Components;
3
4
5
class Map implements \ArrayAccess, \JsonSerializable, \IteratorAggregate
6
{
7
    protected $data = [];
8
9
    public function __construct($data = [])
10
    {
11
        if (is_string($data)) {
12
            $this->data = json_decode($data, true);
13
        } elseif ($data === null || $data instanceof NullObject) {
14
            $this->data = [];
15
        } elseif ($data instanceof self) {
16
            $this->replaceWith($data);
17
        } else {
18
            $this->data = $data;
19
        }
20
21
        if(!is_array($this->data)) {
22
            throw new \DomainException('Data must be array or json encoded array');
23
        }
24
25
    }
26
27
28
    public function __isset($name)
29
    {
30
        return $this->offsetExists($name);
31
    }
32
33
34
35
    public function offsetExists($offset)
36
    {
37
        return isset($this->data[$offset]);
38
    }
39
40
    public function offsetGet($offset)
41
    {
42
        if (array_key_exists($offset, $this->data)) {
43
            if (is_array($this->data[$offset])) {
44
                $this->data[$offset] = new self($this->data[$offset]);
45
            }
46
            $result = $this->data[$offset];
47
        } else {
48
            $result = $this->data[$offset] = new Map();
49
        }
50
        return $result;
51
    }
52
53
    public function offsetSet($offset, $value)
54
    {
55
        if ($value instanceof self) {
56
            $this->data[$offset] = clone $value;
57
        } else {
58
            $this->data[$offset] = $value;
59
        }
60
    }
61
62
    public function offsetUnset($offset)
63
    {
64
        unset($this->data[$offset]);
65
    }
66
67
    public function __toString()
68
    {
69
        return json_encode($this->data, JSON_FORCE_OBJECT);
70
    }
71
72
    public function jsonSerialize()
73
    {
74
        return $this->data;
75
    }
76
77
    public function __get($name)
78
    {
79
        return $this->offsetGet($name);
80
    }
81
82
    public function __set($name, $value)
83
    {
84
        $this->offsetSet($name, $value);
85
    }
86
87
    public function getIterator()
88
    {
89
        return new \ArrayIterator($this->data);
90
    }
91
92
    /**
93
     * Merges some extra data into the current map.
94
     * Supports recursive maps in the new data.
95
     * @param $extraData
96
     * @return mixed
97
     */
98
    public function mergeWith($extraData): void
99
    {
100
        if (is_array($extraData)) {
101
            $this->mergeWith(new self($extraData));
102
            return;
103
        }
104
105
        if ($extraData instanceof self) {
106
            foreach($extraData as $key => $value) {
107
                if (isset($this[$key])
108
                    && $value instanceof self
109
                    && $this[$key] instanceof self
110
                ) {
111
                    $this[$key]->mergeWith($value);
112
                } else {
113
                    $this[$key] = $value;
114
                }
115
            }
116
            return;
117
        }
118
119
        throw new \InvalidArgumentException("Argument must be array or Map");
120
    }
121
122
    public function replaceWith($data) {
123
        if (is_array($data)) {
124
            return $this->replaceWith(new self($data));
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->replaceWith(new self($data)) targeting SamIT\Yii2\Components\Map::replaceWith() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
125
        } elseif ($data instanceof self) {
126
            $cloned = clone $data;
127
            $this->data = $cloned->data;
128
        }
129
    }
130
131
    public function __clone()
132
    {
133
        foreach($this->data as $key => $value) {
134
            if ($value instanceof self) {
135
                $this->data[$key] = clone $value;
136
            }
137
        }
138
    }
139
140
    public function asArray() {
141
        $result = $this->data;
142
        foreach($result as $key => $value) {
143
            if ($value instanceof self) {
144
                $result[$value] = $value->asArray();
145
            }
146
147
        }
148
        return $result;
149
    }
150
}