Passed
Push — master ( 12e656...9e9627 )
by Nikolaos
02:33
created

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