Completed
Push — master ( fa9a11...9c37c7 )
by Jens
13:15
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
Metric Value
dl 0
loc 24
ccs 13
cts 13
cp 1
rs 6.7272
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 960
    public function __construct(array $data = [], $context = null)
29
    {
30 960
        parent::__construct($data, $context);
31 960
    }
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 665
    public function __call($method, $arguments)
49
    {
50 665
        $action = substr($method, 0, 3);
51 665
        $field = lcfirst(substr($method, 3));
52
53 665
        if (!$this->hasField($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 663
            case 'get':
64 382
                return $this->get($field);
65 1
            case 'set':
66 620
                $this->set($field, isset($arguments[0]) ? $arguments[0] : null);
67 618
                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->hasField($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 string $field
85
     * @return bool
86
     * @internal
87
     */
88 665
    protected function hasField($field)
89
    {
90 665
        if (isset($this->fieldDefinitions()[$field])) {
91 663
            return true;
92
        }
93 3
        return false;
94
    }
95
96
    /**
97
     * @param string $field
98
     * @return array
99
     * @internal
100
     */
101 663
    protected function fieldDefinition($field)
102
    {
103 663
        return $this->fieldDefinitions()[$field];
104
    }
105
106
    /**
107
     * @param string $field
108
     * @param string $key
109
     * @param $default
110
     * @return bool|string
111
     * @internal
112
     */
113 663
    protected function fieldDefinitionValue($field, $key, $default = false)
114
    {
115 663
        $field = $this->fieldDefinition($field);
116
117 663
        if (isset($field[$key])) {
118 661
            return $field[$key];
119
        }
120
121 655
        return $default;
122
    }
123
124
    /**
125
     * @param string $field
126
     * @return mixed
127
     * @internal
128
     */
129 383
    public function get($field)
130
    {
131 383
        return $this->getTyped($field);
132
    }
133
134 662
    protected function fieldDefinitionType($field)
135
    {
136 662
        return $this->fieldDefinitionValue($field, static::TYPE);
137
    }
138
    /**
139
     * @param string $field
140
     * @internal
141
     */
142 335
    protected function initialize($field)
143
    {
144 335
        $type = $this->fieldDefinitionType($field);
145 335
        if ($this->isTypeableType($type)) {
146
            /**
147
             * @var TypeableInterface $type
148
             */
149 4
            $value = $type::ofTypeAndData(
150 4
                $this->fieldDefinitionValue($field, static::ELEMENT_TYPE),
151 4
                $this->getRaw($field, []),
152 4
                $this->getContextCallback()
153
            );
154 335
        } elseif ($this->isDeserializableType($type)) {
155
            /**
156
             * @var JsonDeserializeInterface $type
157
             */
158 200
            $value = $this->getRaw($field, null);
159 200
            if (!is_null($value)) {
160 200
                $value = $type::fromArray($value, $this->getContextCallback());
161
            }
162
        } else {
163 323
            $value = $this->getRaw($field);
164
        }
165 335
        if ($value instanceof ObjectTreeInterface) {
166 166
            $value->parentSet($this);
167 166
            $value->rootSet($this->rootGet());
168
        }
169 335
        $this->typeData[$field] = !is_null($value) ? $this->decorateField($field, $value) : null;
170
171 335
        $this->initialized[$field] = true;
172 335
    }
173
174 2
    public function isOptional($field)
175
    {
176 2
        return $this->fieldDefinitionValue($field, static::OPTIONAL, false);
177
    }
178
179 656
    protected function decorateField($field, $value)
180
    {
181 656
        if ($decorator = $this->fieldDefinitionValue($field, static::DECORATOR)) {
182 11
            $value = new $decorator($value);
183
        }
184
185 656
        return $value;
186
    }
187
188
    /**
189
     * @param string $field
190
     * @param mixed $value
191
     * @return $this
192
     * @internal
193
     */
194 620
    public function set($field, $value)
195
    {
196 620
        $type = $this->fieldDefinitionType($field);
197 620
        if (!$this->isValidType($type, $value)) {
198 1
            throw new \InvalidArgumentException(sprintf(Message::WRONG_TYPE, $field, $type));
199
        }
200 619
        if ($value === null && !$this->isOptional($field)) {
201 1
            throw new \InvalidArgumentException(sprintf(Message::EXPECTS_PARAMETER, $field, $type));
202
        }
203 618
        if ($value instanceof ContextAwareInterface) {
204 309
            $value->setContext($this->getContextCallback());
205
        }
206 618
        if ($value instanceof ObjectTreeInterface) {
207 254
            $value->parentSet($this);
208 254
            $value->rootSet($this->rootGet());
209
        }
210 618
        $this->typeData[$field] = $this->decorateField($field, $value);
211
212 618
        $this->initialized[$field] = true;
213
214 618
        return $this;
215
    }
216
}
217