Completed
Push — master ( 1d2d63...5f432b )
by Jens
09:03
created

JsonObject::__call()   C

Complexity

Conditions 7
Paths 5

Size

Total Lines 24
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 7

Importance

Changes 0
Metric Value
dl 0
loc 24
ccs 13
cts 13
cp 1
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 17
nc 5
nop 2
crap 7
1
<?php
2
/**
3
 * @author @jayS-de <[email protected]>
4
 * @created: 27.01.15, 14:54
5
 */
6
7
namespace Commercetools\Core\Model\Common;
8
9
use Commercetools\Core\Error\Message;
10
11
/**
12
 * @package Commercetools\Core\Model\Type
13
 */
14
class JsonObject extends AbstractJsonDeserializeObject implements \JsonSerializable
15
{
16
    use ContextTrait;
17
18
    const TYPE = 'type';
19
    const OPTIONAL = 'optional';
20
    const INITIALIZED = 'initialized';
21
    const DECORATOR = 'decorator';
22
    const ELEMENT_TYPE = 'elementType';
23
24
    /**
25
     * @param array $data
26
     * @param Context|callable $context
27
     */
28 988
    public function __construct(array $data = [], $context = null)
29
    {
30 988
        parent::__construct($data, $context);
31 988
    }
32
33
    /**
34
     * @return array
35
     * @internal
36
     */
37 1
    public function fieldDefinitions()
38
    {
39 1
        return [];
40
    }
41
42
    /**
43
     * @param $method
44
     * @param $arguments
45
     * @return $this|bool|mixed
46
     * @internal
47
     */
48 689
    public function __call($method, $arguments)
49
    {
50 689
        $action = substr($method, 0, 3);
51 689
        $field = lcfirst(substr($method, 3));
52
53 689
        if (!$this->isValidField($field)) {
54 3
            if ($action == 'get' || $action == 'set') {
55 3
                throw new \BadMethodCallException(
56 3
                    sprintf(Message::UNKNOWN_FIELD, $field, $method, implode(', ', $arguments))
57
                );
58
            } else {
59
                throw new \BadMethodCallException(sprintf(Message::UNKNOWN_METHOD, $method, $field));
60
            }
61
        }
62
        switch ($action) {
63 687
            case 'get':
64 406
                return $this->get($field);
65 645
            case 'set':
66 644
                $this->set($field, isset($arguments[0]) ? $arguments[0] : null);
67 642
                return $this;
68
            default:
69 1
                throw new \BadMethodCallException(sprintf(Message::UNKNOWN_METHOD, $method, $field));
70
        }
71
    }
72
73
    public function __get($field)
74
    {
75
        if (!$this->isValidField($field)) {
76
            throw new \BadMethodCallException(
77
                sprintf(Message::UNKNOWN_FIELD, $field, 'get', $field)
78
            );
79
        }
80
        return $this->get($field);
81
    }
82
83
    /**
84
     * @param $field
85
     * @return bool
86
     */
87 3
    public function hasField($field)
88
    {
89 3
        return isset($this->typeData[$field]);
90
    }
91
92
    /**
93
     * @param string $field
94
     * @return bool
95
     * @internal
96
     */
97 689
    protected function isValidField($field)
98
    {
99 689
        if (isset($this->fieldDefinitions()[$field])) {
100 687
            return true;
101
        }
102 3
        return false;
103
    }
104
105
    /**
106
     * @param string $field
107
     * @return array
108
     * @internal
109
     */
110 687
    protected function fieldDefinition($field)
111
    {
112 687
        return $this->fieldDefinitions()[$field];
113
    }
114
115
    /**
116
     * @param string $field
117
     * @param string $key
118
     * @param $default
119
     * @return bool|string
120
     * @internal
121
     */
122 688
    protected function fieldDefinitionValue($field, $key, $default = false)
123
    {
124 688
        $field = $this->fieldDefinition($field);
125
126 688
        if (isset($field[$key])) {
127 685
            return $field[$key];
128
        }
129
130 680
        return $default;
131
    }
132
133
    /**
134
     * @param string $field
135
     * @return mixed
136
     * @internal
137
     */
138 407
    public function get($field)
139
    {
140 407
        return $this->getTyped($field);
141
    }
142
143 687
    protected function fieldDefinitionType($field)
144
    {
145 687
        return $this->fieldDefinitionValue($field, static::TYPE);
146
    }
147
    /**
148
     * @param string $field
149
     * @internal
150
     */
151 358
    protected function initialize($field)
152
    {
153 358
        $type = $this->fieldDefinitionType($field);
154 358
        if ($this->isTypeableType($type)) {
155
            /**
156
             * @var TypeableInterface $type
157
             */
158 4
            $value = $type::ofTypeAndData(
159 4
                $this->fieldDefinitionValue($field, static::ELEMENT_TYPE),
160 4
                $this->getRaw($field, []),
161 4
                $this->getContextCallback()
162
            );
163 358
        } elseif ($this->isDeserializableType($type)) {
164
            /**
165
             * @var JsonDeserializeInterface $type
166
             */
167 220
            $value = $this->getRaw($field, null);
168 220
            if (!is_null($value)) {
169 220
                $value = $type::fromArray($value, $this->getContextCallback());
170
            }
171
        } else {
172 346
            $value = $this->getRaw($field);
173
        }
174 358
        if ($value instanceof ObjectTreeInterface) {
175 186
            $value->parentSet($this);
176 186
            $value->rootSet($this->rootGet());
177
        }
178 358
        $this->typeData[$field] = !is_null($value) ? $this->decorateField($field, $value) : null;
179
180 358
        $this->initialized[$field] = true;
181 358
    }
182
183 2
    public function isOptional($field)
184
    {
185 2
        return $this->fieldDefinitionValue($field, static::OPTIONAL, false);
186
    }
187
188 681
    protected function decorateField($field, $value)
189
    {
190 681
        if ($decorator = $this->fieldDefinitionValue($field, static::DECORATOR)) {
191 11
            $value = new $decorator($value);
192
        }
193
194 681
        return $value;
195
    }
196
197
    /**
198
     * @param string $field
199
     * @param mixed $value
200
     * @return $this
201
     * @internal
202
     */
203 645
    public function set($field, $value)
204
    {
205 645
        $type = $this->fieldDefinitionType($field);
206 645
        if (!$this->isValidType($type, $value)) {
207 1
            throw new \InvalidArgumentException(sprintf(Message::WRONG_TYPE, $field, $type));
208
        }
209 644
        if ($value === null && !$this->isOptional($field)) {
210 1
            throw new \InvalidArgumentException(sprintf(Message::EXPECTS_PARAMETER, $field, $type));
211
        }
212 643
        if ($value instanceof ContextAwareInterface) {
213 330
            $value->setContext($this->getContextCallback());
214
        }
215 643
        if ($value instanceof ObjectTreeInterface) {
216 275
            $value->parentSet($this);
217 275
            $value->rootSet($this->rootGet());
218
        }
219 643
        $this->typeData[$field] = $this->decorateField($field, $value);
220
221 643
        $this->initialized[$field] = true;
222
223 643
        return $this;
224
    }
225
}
226