Passed
Push — master ( d25cd5...5cf75b )
by Nikolaos
03:08
created

Collection::offsetGet()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of the Phalcon Framework.
5
 *
6
 * (c) Phalcon Team <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE.txt
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Phalcon;
15
16
use ArrayAccess;
17
use Countable;
18
use Generator;
19
use IteratorAggregate;
20
use JsonSerializable;
21
use Phalcon\Helper\Json;
22
use Serializable;
23
24
use function array_key_exists;
25
use function array_keys;
26
use function array_values;
27
use function is_object;
28
use function mb_strtolower;
29
use function method_exists;
30
use function serialize;
31
use function settype;
32
use function strtolower;
33
use function unserialize;
34
35
/**
36
 * `Phalcon\Collection` is a supercharged object oriented array. It implements:
37
 * - [ArrayAccess](https://www.php.net/manual/en/class.arrayaccess.php)
38
 * - [Countable](https://www.php.net/manual/en/class.countable.php)
39
 * -
40
 * [IteratorAggregate](https://www.php.net/manual/en/class.iteratoraggregate.php)
41
 * -
42
 * [JsonSerializable](https://www.php.net/manual/en/class.jsonserializable.php)
43
 * - [Serializable](https://www.php.net/manual/en/class.serializable.php)
44
 *
45
 * It can be used in any part of the application that needs collection of data
46
 * Such implementations are for instance accessing globals `$_GET`, `$_POST`
47
 * etc.
48
 *
49
 * @property array $data
50
 * @property bool  $insensitive
51
 * @property array $lowerKeys
52
 */
53
class Collection implements
54
    ArrayAccess,
55
    Countable,
56
    IteratorAggregate,
57
    JsonSerializable,
58
    Serializable
59
{
60
    /**
61
     * @var array
62
     */
63
    protected $data = [];
64
65
    /**
66
     * @var bool
67
     */
68
    protected $insensitive = true;
69
70
    /**
71
     * @var array
72
     */
73
    protected $lowerKeys = [];
74
75
    /**
76
     * Collection constructor.
77
     *
78
     * @param array $data
79
     * @param bool  $insensitive
80
     */
81 716
    public function __construct(array $data = [], bool $insensitive = true)
82
    {
83 716
        $this->insensitive = $insensitive;
84 716
        $this->init($data);
85 716
    }
86
87
    /**
88
     * Magic getter to get an element from the collection
89
     *
90
     * @param string $element
91
     *
92
     * @return mixed|null
93
     */
94 30
    public function __get(string $element)
95
    {
96 30
        return $this->get($element);
97
    }
98
99
    /**
100
     * Magic isset to check whether an element exists or not
101
     *
102
     * @param string $element
103
     *
104
     * @return bool
105
     */
106 22
    public function __isset(string $element): bool
107
    {
108 22
        return $this->has($element);
109
    }
110
111
    /**
112
     * Magic setter to assign values to an element
113
     *
114
     * @param string $element
115
     * @param mixed  $value
116
     */
117 4
    public function __set(string $element, $value): void
118
    {
119 4
        $this->set($element, $value);
120 2
    }
121
122
    /**
123
     * Magic unset to remove an element from the collection
124
     *
125
     * @param string $element
126
     */
127 4
    public function __unset(string $element): void
128
    {
129 4
        $this->remove($element);
130 2
    }
131
132
    /**
133
     * Clears the internal collection
134
     */
135 64
    public function clear(): void
136
    {
137 64
        $this->data      = [];
138 64
        $this->lowerKeys = [];
139 64
    }
140
141
    /**
142
     * Count elements of an object.
143
     *
144
     * @return int
145
     */
146 42
    public function count(): int
147
    {
148 42
        return count($this->data);
149
    }
150
151
    /**
152
     * Get the element from the collection
153
     *
154
     * @param string      $element
155
     * @param mixed|null  $defaultValue
156
     * @param string|null $cast
157
     *
158
     * @return mixed
159
     */
160 226
    public function get(
161
        string $element,
162
        $defaultValue = null,
163
        string $cast = null
164
    ) {
165 226
        $element = ($this->insensitive) ? strtolower($element) : $element;
166
167 226
        if (!array_key_exists($element, $this->lowerKeys)) {
168 68
            return $defaultValue;
169
        }
170
171 196
        $key   = $this->lowerKeys[$element];
172 196
        $value = $this->data[$key];
173
174 196
        if (null !== $cast) {
175 20
            settype($value, $cast);
176
        }
177
178 196
        return $value;
179
    }
180
181
    /**
182
     * Returns the generator of the class
183
     *
184
     * @return Generator
185
     */
186 28
    public function getIterator(): Generator
187
    {
188 28
        foreach ($this->data as $key => $value) {
189 22
            yield $key => $value;
190
        }
191 28
    }
192
193
    /**
194
     * Returns the keys (insensitive or not) of the collection
195
     *
196
     * @param bool $insensitive
197
     *
198
     * @return array
199
     */
200 6
    public function getKeys(bool $insensitive = true): array
201
    {
202 6
        if ($insensitive) {
203 6
            return array_keys($this->lowerKeys);
204
        } else {
205 2
            return array_keys($this->data);
206
        }
207
    }
208
209
    /**
210
     * Returns the values of the internal array
211
     *
212
     * @return array
213
     */
214 2
    public function getValues(): array
215
    {
216 2
        return array_values($this->data);
217
    }
218
219
    /**
220
     * Get the element from the collection
221
     *
222
     * @param string $element
223
     *
224
     * @return bool
225
     */
226 382
    public function has(string $element): bool
227
    {
228 382
        if ($this->insensitive) {
229 378
            $element = strtolower($element);
230
        }
231
232 382
        return isset($this->lowerKeys[$element]);
233
    }
234
235
    /**
236
     * Initialize internal array
237
     *
238
     * @param array $data
239
     */
240 716
    public function init(array $data = []): void
241
    {
242 716
        foreach ($data as $key => $value) {
243 402
            $this->setData($key, $value);
244
        }
245 716
    }
246
247
    /**
248
     * Specify data which should be serialized to JSON
249
     *
250
     * @link https://php.net/manual/en/jsonserializable.jsonserialize.php
251
     */
252 14
    public function jsonSerialize(): array
253
    {
254 14
        $records = [];
255
256 14
        foreach ($this->data as $key => $value) {
257 14
            if (is_object($value) && method_exists($value, "jsonSerialize")) {
258 4
                $records[$key] = $value->jsonSerialize();
259
            } else {
260 14
                $records[$key] = $value;
261
            }
262
        }
263
264 14
        return $records;
265
    }
266
267
    /**
268
     * Whether a offset exists
269
     *
270
     * @link https://php.net/manual/en/arrayaccess.offsetexists.php
271
     *
272
     * @param mixed $element
273
     *
274
     * @return bool
275
     */
276 32
    public function offsetExists($element): bool
277
    {
278 32
        $element = (string) $element;
279
280 32
        return $this->has($element);
281
    }
282
283
    /**
284
     * Offset to retrieve
285
     *
286
     * @link https://php.net/manual/en/arrayaccess.offsetget.php
287
     *
288
     * @param mixed $element
289
     *
290
     * @return mixed
291
     */
292 34
    public function offsetGet($element)
293
    {
294 34
        $element = (string) $element;
295
296 34
        return $this->get($element);
297
    }
298
299
    /**
300
     * Offset to set
301
     *
302
     * @link https://php.net/manual/en/arrayaccess.offsetset.php
303
     *
304
     * @param mixed $element
305
     * @param mixed $value
306
     */
307 16
    public function offsetSet($element, $value): void
308
    {
309 16
        $element = (string) $element;
310
311 16
        $this->set($element, $value);
312 14
    }
313
314
    /**
315
     * Offset to unset
316
     *
317
     * @link https://php.net/manual/en/arrayaccess.offsetunset.php
318
     *
319
     * @param mixed $element
320
     */
321 16
    public function offsetUnset($element): void
322
    {
323 16
        $element = (string) $element;
324
325 16
        $this->remove($element);
326 14
    }
327
328
    /**
329
     * Delete the element from the collection
330
     *
331
     * @param string $element
332
     */
333 40
    public function remove(string $element): void
334
    {
335 40
        if ($this->has($element)) {
336 36
            if ($this->insensitive) {
337 36
                $element = strtolower($element);
338
            }
339
340 36
            $value = $this->lowerKeys[$element];
341
342 36
            unset($this->lowerKeys[$element]);
343 36
            unset($this->data[$value]);
344
        }
345 40
    }
346
347
    /**
348
     * Set an element in the collection
349
     *
350
     * @param string $element
351
     * @param mixed  $value
352
     */
353 218
    public function set(string $element, $value): void
354
    {
355 218
        $this->setData($element, $value);
356 218
    }
357
358
    /**
359
     * String representation of object
360
     *
361
     * @link https://php.net/manual/en/serializable.serialize.php
362
     */
363 6
    public function serialize(): string
364
    {
365 6
        return serialize($this->toArray());
366
    }
367
368
    /**
369
     * Returns the object in an array format
370
     */
371 246
    public function toArray(): array
372
    {
373 246
        return $this->data;
374
    }
375
376
    /**
377
     * Returns the object in a JSON format
378
     *
379
     * The default string uses the following options for json_encode
380
     *
381
     * JSON_HEX_TAG, JSON_HEX_APOS, JSON_HEX_AMP, JSON_HEX_QUOT,
382
     * JSON_UNESCAPED_SLASHES
383
     *
384
     * @see https://www.ietf.org/rfc/rfc4627.txt
385
     *
386
     * @param int $options
387
     *
388
     * @return string
389
     */
390 6
    public function toJson(int $options = 79): string
391
    {
392 6
        return Json::encode($this->jsonSerialize(), $options);
393
    }
394
395
    /**
396
     * Constructs the object
397
     *
398
     * @link https://php.net/manual/en/serializable.unserialize.php
399
     *
400
     * @param string $serialized
401
     */
402 6
    public function unserialize($serialized): void
403
    {
404 6
        $serialized = (string) $serialized;
405 6
        $data       = unserialize($serialized);
406
407 6
        $this->init($data);
408 6
    }
409
410
    /**
411
     * Internal method to set data
412
     *
413
     * @param mixed $element
414
     * @param mixed $value
415
     */
416 314
    protected function setData($element, $value): void
417
    {
418 314
        $element = (string) $element;
419 314
        $key     = ($this->insensitive) ? mb_strtolower($element) : $element;
420
421 314
        $this->data[$element]  = $value;
422 314
        $this->lowerKeys[$key] = $element;
423 314
    }
424
}
425