Passed
Push — develop ( 63f338...8116c8 )
by Jens
18:49
created

JsonObject::fieldDefinition()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 1
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\Common
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 1188
    public function __construct(array $data = [], $context = null)
29
    {
30 1188
        parent::__construct($data, $context);
31 1188
    }
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 883
    public function __call($method, $arguments)
49
    {
50 883
        $action = substr($method, 0, 3);
51 883
        $field = lcfirst(substr($method, 3));
52
53 883
        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 881
            case 'get':
64 602
                return $this->get($field);
65 831
            case 'set':
66 830
                $this->set($field, isset($arguments[0]) ? $arguments[0] : null);
67 828
                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 883
    protected function isValidField($field)
98
    {
99 883
        if (isset($this->fieldDefinitions()[$field])) {
100 881
            return true;
101
        }
102 3
        return false;
103
    }
104
105
    /**
106
     * @param string $field
107
     * @return array
108
     * @internal
109
     */
110 881
    protected function fieldDefinition($field)
111
    {
112 881
        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 882
    protected function fieldDefinitionValue($field, $key, $default = false)
123
    {
124 882
        $field = $this->fieldDefinition($field);
125
126 882
        if (isset($field[$key])) {
127 879
            return $field[$key];
128
        }
129
130 873
        return $default;
131
    }
132
133
    /**
134
     * @param string $field
135
     * @return mixed
136
     * @internal
137
     */
138 603
    public function get($field)
139
    {
140 603
        return $this->getTyped($field);
141
    }
142
143 881
    protected function fieldDefinitionType($field)
144
    {
145 881
        return $this->fieldDefinitionValue($field, static::TYPE);
146
    }
147
    /**
148
     * @param string $field
149
     * @internal
150
     */
151 554
    protected function initialize($field)
152
    {
153 554
        $type = $this->fieldDefinitionType($field);
154 554
        if ($this->isPrimitive($type)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->isPrimitive($type) of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
155 537
            $value = $this->getRaw($field);
156 383
        } elseif ($this->isTypeableType($type)) {
157
            /**
158
             * @var TypeableInterface $type
159
             */
160 4
            $value = $type::ofTypeAndData(
161 4
                $this->fieldDefinitionValue($field, static::ELEMENT_TYPE),
162 4
                $this->getRaw($field, []),
163 4
                $this->getContextCallback()
164
            );
165 381
        } elseif ($this->isDeserializableType($type)) {
166
            /**
167
             * @var JsonDeserializeInterface $type
168
             */
169 371
            $value = $this->getRaw($field, null);
170 371
            if (!is_null($value)) {
171 371
                $value = $type::fromArray($value, $this->getContextCallback());
172
            }
173
        } else {
174 56
            $value = $this->getRaw($field);
175
        }
176 554
        if ($value instanceof ObjectTreeInterface) {
177 332
            $value->parentSet($this);
178 332
            $value->rootSet($this->rootGet());
179
        }
180 554
        $this->typeData[$field] = !is_null($value) ? $this->decorateField($field, $value) : null;
181
182 554
        $this->initialized[$field] = true;
183 554
    }
184
185 2
    public function isOptional($field)
186
    {
187 2
        return $this->fieldDefinitionValue($field, static::OPTIONAL, false);
188
    }
189
190 875
    protected function decorateField($field, $value)
191
    {
192 875
        if ($decorator = $this->fieldDefinitionValue($field, static::DECORATOR)) {
193 12
            $value = new $decorator($value);
194
        }
195
196 875
        return $value;
197
    }
198
199
    /**
200
     * @param string $field
201
     * @param mixed $value
202
     * @return $this
203
     * @internal
204
     */
205 831
    public function set($field, $value)
206
    {
207 831
        $type = $this->fieldDefinitionType($field);
208 831
        if (!$this->isValidType($type, $value)) {
209 1
            throw new \InvalidArgumentException(sprintf(Message::WRONG_TYPE, $field, $type));
210
        }
211 830
        if ($value === null && !$this->isOptional($field)) {
212 1
            throw new \InvalidArgumentException(sprintf(Message::EXPECTS_PARAMETER, $field, $type));
213
        }
214 829
        if ($value instanceof ContextAwareInterface) {
215 471
            $value->setContext($this->getContextCallback());
216
        }
217 829
        if ($value instanceof ObjectTreeInterface) {
218 402
            $value->parentSet($this);
219 402
            $value->rootSet($this->rootGet());
220
        }
221 829
        $this->typeData[$field] = $this->decorateField($field, $value);
222
223 829
        $this->initialized[$field] = true;
224
225 829
        return $this;
226
    }
227
}
228