Completed
Push — master ( a332d2...53b748 )
by Matthew
01:45
created

Collection::toJson()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PublishingKit\Utilities\Collections;
6
7
use Countable;
8
use ArrayAccess;
9
use IteratorAggregate;
10
use ArrayIterator;
11
use JsonSerializable;
12
use Serializable;
13
use PublishingKit\Utilities\Contracts\Collectable;
14
use PublishingKit\Utilities\Traits\Macroable;
15
use OutOfBoundsException;
16
17
/**
18
 * Collection class
19
 */
20
class Collection implements Countable, ArrayAccess, IteratorAggregate, JsonSerializable, Collectable, Serializable
21
{
22 1
    use Macroable;
0 ignored issues
show
Bug introduced by
The trait PublishingKit\Utilities\Traits\Macroable requires the property $name which is not provided by PublishingKit\Utilities\Collections\Collection.
Loading history...
23
24
    /**
25
     * Items
26
     *
27
     * @var iterable
28
     */
29
    protected $items;
30
31
    /**
32
     * Position
33
     *
34
     * @var integer
35
     */
36
    protected $position = 0;
37
38
    /**
39
     * Return count of items
40
     *
41
     * @return integer
42
     */
43 12
    public function count()
44
    {
45 12
        if (is_array($this->items)) {
46 9
            return count($this->items);
47
        }
48 3
        $count = 0;
49 3
        foreach ($this->items as $item) {
50 3
            $count++;
51
        }
52 3
        return $count;
53
    }
54
55
    /**
56
     * Constructor
57
     *
58
     * @param iterable $items Items to collect.
59
     * @return void
60
     */
61 159
    public function __construct(iterable $items = [])
62
    {
63 159
        $this->items = $items;
64 159
    }
65
66
    /**
67
     * Create collection
68
     *
69
     * @param iterable $items Items to collect.
70
     * @return Collection
71
     */
72 6
    public static function make(iterable $items)
73
    {
74 6
        return new static($items);
75
    }
76
77
    /**
78
     * Does item exist?
79
     *
80
     * @param mixed $offset The offset.
81
     * @return boolean
82
     */
83 3
    public function offsetExists($offset)
84
    {
85 3
        return isset($this->items[$offset]);
86
    }
87
88
    /**
89
     * Get offset
90
     *
91
     * @param mixed $offset The offset.
92
     * @return mixed
93
     */
94 15
    public function offsetGet($offset)
95
    {
96 15
        return isset($this->items[$offset]) ? $this->items[$offset] : null;
97
    }
98
99
    /**
100
     * Set offset
101
     *
102
     * @param mixed $offset The offset.
103
     * @param mixed $value  The value to set.
104
     * @return void
105
     */
106 6
    public function offsetSet($offset, $value): void
107
    {
108 6
        if (is_null($offset)) {
109 3
            $this->items[] = $value;
110 3
            return;
111
        }
112 3
        $this->items[$offset] = $value;
113 3
    }
114
115
    /**
116
     * Unset offset
117
     *
118
     * @param mixed $offset The offset.
119
     * @return void
120
     */
121 3
    public function offsetUnset($offset)
122
    {
123 3
        unset($this->items[$offset]);
124 3
    }
125
126
    /**
127
     * {@inheritDoc}
128
     */
129 3
    public function getIterator()
130
    {
131 3
        return new ArrayIterator($this->items);
0 ignored issues
show
Bug introduced by
$this->items of type iterable is incompatible with the type array expected by parameter $array of ArrayIterator::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

131
        return new ArrayIterator(/** @scrutinizer ignore-type */ $this->items);
Loading history...
132
    }
133
134
    /**
135
     * Serialize collection to JSON
136
     *
137
     * @return string|false
138
     */
139 6
    public function jsonSerialize()
140
    {
141 6
        return json_encode($this->items);
142
    }
143
144
    /**
145
     * Convert collection to JSON
146
     *
147
     * @return string|false
148
     */
149 3
    public function toJson()
150
    {
151 3
        return $this->jsonSerialize();
152
    }
153
154
    /**
155
     * Convert collection to array
156
     *
157
     * @return iterable
158
     */
159 81
    public function toArray(): iterable
160
    {
161 81
        return $this->items;
162
    }
163
164
    /**
165
     * Map operation
166
     *
167
     * @param callable $callback The callback to use.
168
     * @return Collection
169
     */
170 12
    public function map(callable $callback)
171
    {
172 12
        return new static(array_map($callback, $this->items));
0 ignored issues
show
Bug introduced by
$this->items of type iterable is incompatible with the type array expected by parameter $arr1 of array_map(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

172
        return new static(array_map($callback, /** @scrutinizer ignore-type */ $this->items));
Loading history...
173
    }
174
175
    /**
176
     * Filter operation
177
     *
178
     * @param callable $callback The callback to use.
179
     * @return Collection
180
     */
181 6
    public function filter(callable $callback)
182
    {
183 6
        return new static(array_filter($this->items, $callback));
0 ignored issues
show
Bug introduced by
$this->items of type iterable is incompatible with the type array expected by parameter $input of array_filter(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

183
        return new static(array_filter(/** @scrutinizer ignore-type */ $this->items, $callback));
Loading history...
184
    }
185
186
    /**
187
     * Reverse filter operation
188
     *
189
     * @param callable $callback The callback to use.
190
     * @return Collection
191
     */
192 3
    public function reject(callable $callback)
193
    {
194 2
        return $this->filter(function ($item) use ($callback) {
195 3
            return !$callback($item);
196 3
        });
197
    }
198
199
    /**
200
     * Reduce operation
201
     *
202
     * @param callable $callback The callback to use.
203
     * @param mixed   $initial  The initial value.
204
     * @return mixed
205
     */
206 3
    public function reduce(callable $callback, $initial = 0)
207
    {
208 3
        $accumulator = $initial;
209 3
        foreach ($this->items as $item) {
210 3
            $accumulator = $callback($accumulator, $item);
211
        }
212 3
        return $accumulator;
213
    }
214
215
    /**
216
     * Reduce operation that returns a collection
217
     *
218
     * @param callable $callback The callback to use.
219
     * @param mixed   $initial  The initial value.
220
     * @return Collection
221
     */
222 3
    public function reduceToCollection(callable $callback, $initial = 0): Collection
223
    {
224 3
        $accumulator = $initial;
225 3
        foreach ($this->items as $item) {
226 3
            $accumulator = $callback($accumulator, $item);
227
        }
228 3
        return new static($accumulator);
229
    }
230
231
    /**
232
     * Pluck a single field
233
     *
234
     * @param mixed $name Name of field to pluck.
235
     * @return mixed
236
     */
237 3
    public function pluck($name)
238
    {
239 2
        return $this->map(function (array $item) use ($name) {
240 3
            return $item[$name];
241 3
        });
242
    }
243
244
    /**
245
     * Apply callback to each item in the collection
246
     *
247
     * @param callable $callback The callback to use.
248
     * @return void
249
     */
250 3
    public function each(callable $callback)
251
    {
252 3
        foreach ($this->items as $item) {
253 3
            $callback($item);
254
        }
255 3
    }
256
257
    /**
258
     * Push item to end of collection
259
     *
260
     * @param mixed $item Item to push.
261
     * @return Collection
262
     */
263 3
    public function push($item)
264
    {
265 3
        array_push($this->items, $item);
0 ignored issues
show
Bug introduced by
$this->items of type iterable is incompatible with the type array expected by parameter $array of array_push(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

265
        array_push(/** @scrutinizer ignore-type */ $this->items, $item);
Loading history...
266 3
        return new static($this->items);
267
    }
268
269
    /**
270
     * Pop item from end of collection
271
     *
272
     * @return mixed
273
     */
274 3
    public function pop()
275
    {
276 3
        return array_pop($this->items);
0 ignored issues
show
Bug introduced by
$this->items of type iterable is incompatible with the type array expected by parameter $array of array_pop(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

276
        return array_pop(/** @scrutinizer ignore-type */ $this->items);
Loading history...
277
    }
278
279
    /**
280
     * Push item to start of collection
281
     *
282
     * @param mixed $item Item to push.
283
     * @return Collection
284
     */
285 3
    public function unshift($item)
286
    {
287 3
        array_unshift($this->items, $item);
0 ignored issues
show
Bug introduced by
$this->items of type iterable is incompatible with the type array expected by parameter $array of array_unshift(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

287
        array_unshift(/** @scrutinizer ignore-type */ $this->items, $item);
Loading history...
288 3
        return new static($this->items);
289
    }
290
291
    /**
292
     * Pop item from start of collection
293
     *
294
     * @return mixed
295
     */
296 3
    public function shift()
297
    {
298 3
        return array_shift($this->items);
0 ignored issues
show
Bug introduced by
$this->items of type iterable is incompatible with the type array expected by parameter $array of array_shift(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

298
        return array_shift(/** @scrutinizer ignore-type */ $this->items);
Loading history...
299
    }
300
301
    /**
302
     * Sort collection
303
     *
304
     * @param callable|null $callback The callback to use.
305
     * @return Collection
306
     */
307 6
    public function sort(callable $callback = null)
308
    {
309 6
        if ($callback) {
310 3
            usort($this->items, $callback);
0 ignored issues
show
Bug introduced by
$this->items of type iterable is incompatible with the type array expected by parameter $array of usort(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

310
            usort(/** @scrutinizer ignore-type */ $this->items, $callback);
Loading history...
311
        } else {
312 3
            sort($this->items);
0 ignored issues
show
Bug introduced by
$this->items of type iterable is incompatible with the type array expected by parameter $array of sort(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

312
            sort(/** @scrutinizer ignore-type */ $this->items);
Loading history...
313
        }
314 6
        return new static($this->items);
315
    }
316
317
    /**
318
     * Reverse collection
319
     *
320
     * @return Collection
321
     */
322 3
    public function reverse()
323
    {
324 3
        return new static(array_reverse($this->items));
0 ignored issues
show
Bug introduced by
$this->items of type iterable is incompatible with the type array expected by parameter $array of array_reverse(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

324
        return new static(array_reverse(/** @scrutinizer ignore-type */ $this->items));
Loading history...
325
    }
326
327
    /**
328
     * Return keys
329
     *
330
     * @return Collection
331
     */
332 3
    public function keys()
333
    {
334 3
        return new static(array_keys($this->items));
0 ignored issues
show
Bug introduced by
$this->items of type iterable is incompatible with the type array expected by parameter $input of array_keys(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

334
        return new static(array_keys(/** @scrutinizer ignore-type */ $this->items));
Loading history...
335
    }
336
337
    /**
338
     * Return values
339
     *
340
     * @return Collection
341
     */
342 3
    public function values(): Collection
343
    {
344 3
        return new static(array_values($this->items));
0 ignored issues
show
Bug introduced by
$this->items of type iterable is incompatible with the type array expected by parameter $input of array_values(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

344
        return new static(array_values(/** @scrutinizer ignore-type */ $this->items));
Loading history...
345
    }
346
347
    /**
348
     * Return chunked collection
349
     *
350
     * @param integer $size Chunk size.
351
     * @return Collection
352
     */
353 3
    public function chunk(int $size): Collection
354
    {
355 3
        return new static(array_chunk($this->items, $size));
0 ignored issues
show
Bug introduced by
$this->items of type iterable is incompatible with the type array expected by parameter $input of array_chunk(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

355
        return new static(array_chunk(/** @scrutinizer ignore-type */ $this->items, $size));
Loading history...
356
    }
357
358
    /**
359
     * Merge another array into the collection
360
     *
361
     * @param mixed $merge Array to merge.
362
     * @return Collection
363
     */
364 3
    public function merge($merge): Collection
365
    {
366 3
        return new static(array_merge($this->items, $merge));
0 ignored issues
show
Bug introduced by
$this->items of type iterable is incompatible with the type array expected by parameter $array1 of array_merge(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

366
        return new static(array_merge(/** @scrutinizer ignore-type */ $this->items, $merge));
Loading history...
367
    }
368
369
    /**
370
     * Group by a given key
371
     *
372
     * @param string $key Key to group by.
373
     * @return Collection
374
     */
375 3
    public function groupBy(string $key): Collection
376
    {
377 3
        $items = [];
378 3
        foreach ($this->items as $item) {
379 3
            $items[$item[$key]][] = $item;
380
        }
381 3
        return new static($items);
382
    }
383
384
    /**
385
     * Flatten items
386
     *
387
     * @return Collection
388
     */
389 3
    public function flatten(): Collection
390
    {
391 3
        $return = [];
392 2
        array_walk_recursive($this->items, function ($a) use (&$return) {
0 ignored issues
show
Bug introduced by
$this->items of type iterable is incompatible with the type array expected by parameter $input of array_walk_recursive(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

392
        array_walk_recursive(/** @scrutinizer ignore-type */ $this->items, function ($a) use (&$return) {
Loading history...
393 3
            $return[] = $a;
394 3
        });
395 3
        return new static($return);
396
    }
397
398
    /**
399
     * Paginate items
400
     *
401
     * @return Collection
402
     */
403 3
    public function paginate(int $perPage, int $page): Collection
404
    {
405 3
        $offset = ($page - 1) * $perPage;
406 3
        return new static(array_slice($this->items, $offset, $perPage));
0 ignored issues
show
Bug introduced by
$this->items of type iterable is incompatible with the type array expected by parameter $array of array_slice(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

406
        return new static(array_slice(/** @scrutinizer ignore-type */ $this->items, $offset, $perPage));
Loading history...
407
    }
408
409
    /**
410
     * {@inheritDoc}
411
     */
412 3
    public function serialize()
413
    {
414 3
        return serialize($this->items);
415
    }
416
417
    /**
418
     * {@inheritDoc}
419
     */
420 3
    public function unserialize($serialized)
421
    {
422 3
        $this->items = unserialize($serialized);
423 3
    }
424
425
    /**
426
     * @return mixed
427
     */
428 3
    public function pipe(callable $callback)
429
    {
430 3
        return $callback($this);
431
    }
432
433 3
    public function __debugInfo()
434
    {
435 3
        return $this->toArray();
436
    }
437
438
    /**
439
     * {@inheritDoc}
440
     *
441
     * @return iterable
442
     */
443 3
    public function all(): iterable
444
    {
445 3
        return $this->toArray();
446
    }
447
}
448