Completed
Push — master ( 4b89b9...dd9abc )
by Jens
10:35
created

Collection::add()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * @author @jayS-de <[email protected]>
4
 */
5
6
namespace Commercetools\Core\Model\Common;
7
8
use Commercetools\Core\Error\Message;
9
10
/**
11
 * @package Commercetools\Core\Model\Common
12
 */
13
class Collection extends AbstractJsonDeserializeObject implements \Iterator, \JsonSerializable, \Countable, \ArrayAccess
14
{
15
    const ID = 'id';
16
    use ContextTrait;
17
18
    /**
19
     * @var string
20
     */
21
    protected $type;
22
23
    protected $pos = 0;
24
25
    protected $keys = [];
26
27
    protected $index = [];
28
29
    /**
30
     * @param array $data
31
     * @param Context|callable $context
32
     */
33 296
    final public function __construct(array $data = [], $context = null)
34
    {
35 296
        parent::__construct($data, $context);
36 296
        $this->indexData();
37 296
    }
38
39
    /**
40
     * @return string
41
     */
42 230
    public function getType()
43
    {
44 230
        return $this->type;
45
    }
46
47
    /**
48
     * @param string $type
49
     * @internal
50
     * @return $this
51
     */
52 18
    public function setType($type)
53
    {
54 18
        $this->type = $type;
55
56 18
        return $this;
57
    }
58
59 296
    protected function indexData()
60
    {
61 296
        $this->keys = array_keys($this->rawData);
62 296
        foreach ($this->rawData as $offset => $row) {
63 175
            $this->indexRow($offset, $row);
64
        }
65 296
    }
66
67
    /**
68
     * @param array $rawData
69
     * @internal
70
     * @return $this
71
     */
72 6
    public function setRawData(array $rawData)
73
    {
74 6
        parent::setRawData($rawData);
75 6
        $this->indexData();
76
77 6
        return $this;
78
    }
79
80
    /**
81
     * @param string $indexName
82
     * @param int $offset
83
     * @param $key
84
     */
85 259
    protected function addToIndex($indexName, $offset, $key)
86
    {
87 259
        if (!is_null($key)) {
88 156
            $this->index[$indexName][$key] = $offset;
89
        }
90 259
    }
91
92 156
    protected function indexRow($offset, $row)
93
    {
94 156
        $id = null;
95 156
        if ($row instanceof Resource) {
96 1
            $id = $row->getId();
97 155
        } elseif (is_array($row)) {
98 82
            $id = isset($row[static::ID]) ? $row[static::ID] : null;
99
        }
100 156
        $this->addToIndex(static::ID, $offset, $id);
101 156
    }
102
103
    /**
104
     * @param $id
105
     * @return static
106
     */
107 24
    public function getById($id)
108
    {
109 24
        return $this->getBy(static::ID, $id);
110
    }
111
112
    /**
113
     * @param $indexName
114
     * @param $key
115
     * @return mixed|null
116
     */
117 45
    public function getBy($indexName, $key)
118
    {
119 45
        if (isset($this->index[$indexName][$key])) {
120 43
            $key = $this->index[$indexName][$key];
121
122 43
            return $this->getAt($key);
123
        }
124 4
        return null;
125
    }
126
127 154
    public function add($object)
128
    {
129 154
        $this->setAt(null, $object);
130
131 153
        return $this;
132
    }
133
134
    /**
135
     * @param $offset
136
     * @internal
137
     */
138 139
    protected function initialize($offset)
139
    {
140 139
        $type = $this->getType();
141 139
        if ($this->isDeserializableType($type)) {
142
            /**
143
             * @var JsonDeserializeInterface $type
144
             */
145 138
            $value = $type::fromArray($this->getRaw($offset), $this->getContextCallback());
146 138
            if ($value instanceof ObjectTreeInterface) {
147 138
                $value->parentSet($this);
148 138
                $value->rootSet($this->rootGet());
149
            }
150 138
            $this->typeData[$offset] = $value;
151
        }
152 139
        $this->initialized[$offset] = true;
153 139
    }
154
155
    /**
156
     * @return array
157
     */
158
    public function toArray()
159
    {
160
        $values = [];
161
        foreach ($this->typeData as $key => $value) {
162
            if ($value instanceof JsonDeserializeInterface) {
163
                $values[$key] = $value->toArray();
164
            } else {
165
                $values[$key] = $value;
166
            }
167
        }
168
169
        return $values;
170
    }
171
172
    /**
173
     * @param $offset
174
     * @return mixed
175
     */
176 154
    public function getAt($offset)
177
    {
178 154
        return $this->getTyped($offset);
179
    }
180
181
    /**
182
     * @param $offset
183
     * @param mixed $default
184
     * @return array
185
     */
186 138
    protected function getRaw($offset, $default = [])
187
    {
188 138
        return parent::getRaw($offset, $default);
189
    }
190
191
    /**
192
     * @param $offset
193
     * @param $object
194
     * @return $this
195
     */
196 158
    public function setAt($offset, $object)
197
    {
198 158
        $type = $this->getType();
199 158
        if (!$this->isValidType($type, $object)) {
200 1
            throw new \InvalidArgumentException(sprintf(Message::WRONG_TYPE, $offset, $type));
201
        }
202
203 157
        if ($object instanceof ContextAwareInterface) {
204 152
            $object->setContext($this->getContextCallback());
205
        }
206 157
        if ($object instanceof ObjectTreeInterface) {
207 152
            $object->parentSet($this);
208 152
            $object->rootSet($this->rootGet());
209
        }
210 157
        if (is_null($offset)) {
211 155
            $this->typeData[] = $object;
212 155
            $offset = count($this->typeData) - 1;
213
        } else {
214 3
            $this->typeData[$offset] = $object;
215
        }
216 157
        $this->initialized[$offset] = true;
217 157
        if (!in_array($offset, $this->keys)) {
218 157
            $this->keys[] = $offset;
219
        }
220 157
        $this->indexRow($offset, $object);
221
222 157
        return $this;
223
    }
224
225
    /**
226
     * (PHP 5 &gt;= 5.1.0)<br/>
227
     * Count elements of an object
228
     * @link http://php.net/manual/en/countable.count.php
229
     * @return int The custom count as an integer.
230
     * </p>
231
     * <p>
232
     * The return value is cast to an integer.
233
     */
234 81
    public function count()
235
    {
236 81
        $rawKeys = array_keys($this->rawData);
237 81
        $typeKeys = array_keys($this->typeData);
238 81
        $keys = array_merge($rawKeys, $typeKeys);
239 81
        $uniqueKeys = array_unique($keys);
240 81
        return count($uniqueKeys);
241
    }
242
243
244
    /**
245
     * (PHP 5 &gt;= 5.0.0)<br/>
246
     * Return the current element
247
     * @link http://php.net/manual/en/iterator.current.php
248
     * @return mixed Can return any type.
249
     */
250 80
    public function current()
251
    {
252 80
        if (isset($this->keys[$this->pos])) {
253 80
            return $this->getAt($this->keys[$this->pos]);
254
        }
255
        return null;
256
    }
257
258
    /**
259
     * (PHP 5 &gt;= 5.0.0)<br/>
260
     * Move forward to next element
261
     * @link http://php.net/manual/en/iterator.next.php
262
     * @return void Any returned value is ignored.
263
     */
264 18
    public function next()
265
    {
266 18
        $this->pos++;
267 18
    }
268
269
    /**
270
     * (PHP 5 &gt;= 5.0.0)<br/>
271
     * Return the key of the current element
272
     * @link http://php.net/manual/en/iterator.key.php
273
     * @return mixed scalar on success, or null on failure.
274
     */
275 4
    public function key()
276
    {
277 4
        if (isset($this->keys[$this->pos])) {
278 4
            return $this->keys[$this->pos];
279
        }
280
        return null;
281
    }
282
283
    /**
284
     * (PHP 5 &gt;= 5.0.0)<br/>
285
     * Checks if current position is valid
286
     * @link http://php.net/manual/en/iterator.valid.php
287
     * @return boolean The return value will be casted to boolean and then evaluated.
288
     * Returns true on success or false on failure.
289
     */
290 20
    public function valid()
291
    {
292 20
        if (isset($this->keys[$this->pos])) {
293 18
            return $this->offsetExists($this->keys[$this->pos]);
294
        }
295 20
        return false;
296
    }
297
298
    /**
299
     * (PHP 5 &gt;= 5.0.0)<br/>
300
     * Rewind the Iterator to the first element
301
     * @link http://php.net/manual/en/iterator.rewind.php
302
     * @return void Any returned value is ignored.
303
     */
304 20
    public function rewind()
305
    {
306 20
        $this->pos = 0;
307 20
    }
308
309
    /**
310
     * (PHP 5 &gt;= 5.0.0)<br/>
311
     * Whether a offset exists
312
     * @link http://php.net/manual/en/arrayaccess.offsetexists.php
313
     * @param mixed $offset <p>
314
     * An offset to check for.
315
     * </p>
316
     * @return boolean true on success or false on failure.
317
     * </p>
318
     * <p>
319
     * The return value will be casted to boolean if non-boolean was returned.
320
     */
321 23
    public function offsetExists($offset)
322
    {
323 23
        return isset($this->rawData[$offset]) || isset($this->typeData[$offset]);
324
    }
325
326
    /**
327
     * (PHP 5 &gt;= 5.0.0)<br/>
328
     * Offset to retrieve
329
     * @link http://php.net/manual/en/arrayaccess.offsetget.php
330
     * @param mixed $offset <p>
331
     * The offset to retrieve.
332
     * </p>
333
     * @return mixed Can return all value types.
334
     */
335 5
    public function offsetGet($offset)
336
    {
337 5
        return $this->getAt($offset);
338
    }
339
340
    /**
341
     * (PHP 5 &gt;= 5.0.0)<br/>
342
     * Offset to set
343
     * @link http://php.net/manual/en/arrayaccess.offsetset.php
344
     * @param mixed $offset <p>
345
     * The offset to assign the value to.
346
     * </p>
347
     * @param mixed $value <p>
348
     * The value to set.
349
     * </p>
350
     * @return void
351
     */
352 3
    public function offsetSet($offset, $value)
353
    {
354 3
        $this->setAt($offset, $value);
355 3
    }
356
357
    /**
358
     * (PHP 5 &gt;= 5.0.0)<br/>
359
     * Offset to unset
360
     * @link http://php.net/manual/en/arrayaccess.offsetunset.php
361
     * @param mixed $offset <p>
362
     * The offset to unset.
363
     * </p>
364
     * @return void
365
     */
366 1
    public function offsetUnset($offset)
367
    {
368 1
        unset($this->rawData[$offset]);
369 1
        unset($this->typeData[$offset]);
370 1
    }
371
}
372