Collection::values()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

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

129
        return new ArrayIterator(/** @scrutinizer ignore-type */ $this->items);
Loading history...
130
    }
131 3
132
    /**
133
     * Serialize collection to JSON
134
     *
135
     * @return string|false
136
     */
137
    public function jsonSerialize()
138
    {
139 6
        return json_encode($this->items);
140
    }
141 6
142
    /**
143
     * Convert collection to JSON
144
     *
145
     * @return string|false
146
     */
147
    public function toJson()
148
    {
149 3
        return $this->jsonSerialize();
150
    }
151 3
152
    /**
153
     * Convert collection to array
154
     *
155
     * @return iterable
156
     */
157
    public function toArray(): iterable
158
    {
159 81
        return $this->items;
160
    }
161 81
162
    /**
163
     * Map operation
164
     *
165
     * @param callable $callback The callback to use.
166
     * @return Collection
167
     */
168
    public function map(callable $callback)
169
    {
170 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 $array 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

170
        return new static(array_map($callback, /** @scrutinizer ignore-type */ $this->items));
Loading history...
171
    }
172 12
173
    /**
174
     * {@inheritDoc}
175
     */
176
    public function filter(callable $callback)
177
    {
178
        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 $array 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

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

257
        array_push(/** @scrutinizer ignore-type */ $this->items, $item);
Loading history...
258
        return new static($this->items);
259
    }
260
261
    /**
262
     * Pop item from end of collection
263 3
     *
264
     * @return mixed
265 3
     */
266 3
    public function pop()
267
    {
268
        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

268
        return array_pop(/** @scrutinizer ignore-type */ $this->items);
Loading history...
269
    }
270
271
    /**
272
     * Push item to start of collection
273
     *
274 3
     * @param mixed $item Item to push.
275
     * @return Collection
276 3
     */
277
    public function unshift($item)
278
    {
279
        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

279
        array_unshift(/** @scrutinizer ignore-type */ $this->items, $item);
Loading history...
280
        return new static($this->items);
281
    }
282
283
    /**
284
     * Pop item from start of collection
285 3
     *
286
     * @return mixed
287 3
     */
288 3
    public function shift()
289
    {
290
        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

290
        return array_shift(/** @scrutinizer ignore-type */ $this->items);
Loading history...
291
    }
292
293
    /**
294
     * Sort collection
295
     *
296 3
     * @param callable|null $callback The callback to use.
297
     * @return Collection
298 3
     */
299
    public function sort(callable $callback = null)
300
    {
301
        if ($callback) {
302
            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

302
            usort(/** @scrutinizer ignore-type */ $this->items, $callback);
Loading history...
303
        } else {
304
            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

304
            sort(/** @scrutinizer ignore-type */ $this->items);
Loading history...
305
        }
306
        return new static($this->items);
307 6
    }
308
309 6
    /**
310 3
     * Reverse collection
311
     *
312 3
     * @return Collection
313
     */
314 6
    public function reverse()
315
    {
316
        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

316
        return new static(array_reverse(/** @scrutinizer ignore-type */ $this->items));
Loading history...
317
    }
318
319
    /**
320
     * Return keys
321
     *
322 3
     * @return Collection
323
     */
324 3
    public function keys()
325
    {
326
        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 $array 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

326
        return new static(array_keys(/** @scrutinizer ignore-type */ $this->items));
Loading history...
327
    }
328
329
    /**
330
     * Return values
331
     *
332 3
     * @return Collection
333
     */
334 3
    public function values(): Collection
335
    {
336
        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 $array 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

336
        return new static(array_values(/** @scrutinizer ignore-type */ $this->items));
Loading history...
337
    }
338
339
    /**
340
     * Return chunked collection
341
     *
342 3
     * @param integer $size Chunk size.
343
     * @return Collection
344 3
     */
345
    public function chunk(int $size): Collection
346
    {
347
        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 $array 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

347
        return new static(array_chunk(/** @scrutinizer ignore-type */ $this->items, $size));
Loading history...
348
    }
349
350
    /**
351
     * Merge another array into the collection
352
     *
353 3
     * @param array<T> $merge Array to merge.
354
     * @return Collection
355 3
     */
356
    public function merge($merge): Collection
357
    {
358
        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 $arrays 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

358
        return new static(array_merge(/** @scrutinizer ignore-type */ $this->items, $merge));
Loading history...
359
    }
360
361
    /**
362
     * Group by a given key
363
     *
364 3
     * @param string $key Key to group by.
365
     * @return Collection
366 3
     */
367
    public function groupBy(string $key): Collection
368
    {
369
        $items = [];
370
        foreach ($this->items as $item) {
371
            $items[$item[$key]][] = $item;
372
        }
373
        return new static($items);
374
    }
375 3
376
    /**
377 3
     * Flatten items
378 3
     *
379 3
     * @return Collection
380
     */
381 3
    public function flatten(): Collection
382
    {
383
        $return = [];
384
        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|object expected by parameter $array 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

384
        array_walk_recursive(/** @scrutinizer ignore-type */ $this->items, function ($a) use (&$return) {
Loading history...
385
            $return[] = $a;
386
        });
387
        /** @var T[] $return **/
388
        return new static($return);
389 3
    }
390
391 3
    /**
392 2
     * Paginate items
393 3
     *
394 3
     * @return Collection
395 3
     */
396
    public function paginate(int $perPage, int $page): Collection
397
    {
398
        $offset = ($page - 1) * $perPage;
399
        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

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