These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Innmind\Immutable; |
||
4 | |||
5 | use Innmind\Immutable\Exception\SortException; |
||
6 | use Innmind\Immutable\Exception\OutOfBoundException; |
||
7 | use Innmind\Immutable\Exception\RuntimeException; |
||
8 | use Innmind\Immutable\Exception\InvalidArgumentException; |
||
9 | use Innmind\Immutable\Exception\LogicException; |
||
10 | |||
11 | class Collection implements CollectionInterface |
||
12 | { |
||
13 | private $values; |
||
14 | |||
15 | 16 | public function __construct(array $values) |
|
16 | { |
||
17 | 16 | $this->values = $values; |
|
18 | 16 | } |
|
19 | |||
20 | /** |
||
21 | * {@inheritdoc} |
||
22 | */ |
||
23 | 15 | public function toPrimitive() |
|
24 | { |
||
25 | 15 | return $this->values; |
|
26 | } |
||
27 | |||
28 | /** |
||
29 | * {@inheritdoc} |
||
30 | */ |
||
31 | 1 | public function filter(callable $filter = null) |
|
32 | { |
||
33 | 1 | if ($filter === null) { |
|
34 | 1 | $values = array_filter($this->values); |
|
35 | 1 | } else { |
|
36 | 1 | $values = array_filter( |
|
37 | 1 | $this->values, |
|
38 | 1 | $filter, |
|
39 | ARRAY_FILTER_USE_BOTH |
||
40 | 1 | ); |
|
41 | } |
||
42 | |||
43 | 1 | return new self($values); |
|
44 | } |
||
45 | |||
46 | /** |
||
47 | * {@inheritdoc} |
||
48 | */ |
||
49 | 1 | public function intersect(CollectionInterface $collection) |
|
50 | { |
||
51 | 1 | return new self(array_intersect( |
|
52 | 1 | $this->values, |
|
53 | 1 | $collection->toPrimitive() |
|
54 | 1 | )); |
|
55 | } |
||
56 | |||
57 | /** |
||
58 | * {@inheritdoc} |
||
59 | */ |
||
60 | 1 | public function chunk($size) |
|
61 | { |
||
62 | 1 | return new self(array_chunk($this->values, (int) $size)); |
|
63 | } |
||
64 | |||
65 | /** |
||
66 | * {@inheritdoc} |
||
67 | */ |
||
68 | 1 | public function shift() |
|
69 | { |
||
70 | 1 | $values = $this->values; |
|
71 | 1 | array_shift($values); |
|
72 | |||
73 | 1 | return new self($values); |
|
74 | } |
||
75 | |||
76 | /** |
||
77 | * {@inheritdoc} |
||
78 | */ |
||
79 | 1 | public function reduce(callable $reducer, $initial = null) |
|
80 | { |
||
81 | 1 | return array_reduce($this->values, $reducer, $initial); |
|
82 | } |
||
83 | |||
84 | /** |
||
85 | * {@inheritdoc} |
||
86 | */ |
||
87 | 1 | public function search($needle, $strict = true) |
|
88 | { |
||
89 | 1 | return array_search($needle, $this->values, (bool) $strict); |
|
90 | } |
||
91 | |||
92 | /** |
||
93 | * {@inheritdoc} |
||
94 | */ |
||
95 | 1 | public function uintersect(CollectionInterface $collection, callable $intersecter) |
|
96 | { |
||
97 | 1 | return new self(array_uintersect( |
|
98 | 1 | $this->values, |
|
99 | 1 | $collection->toPrimitive(), |
|
100 | $intersecter |
||
101 | 1 | )); |
|
102 | } |
||
103 | |||
104 | /** |
||
105 | * {@inheritdoc} |
||
106 | */ |
||
107 | 1 | public function keyIntersect(CollectionInterface $collection) |
|
108 | { |
||
109 | 1 | return new self(array_intersect_key( |
|
110 | 1 | $this->values, |
|
111 | 1 | $collection->toPrimitive() |
|
112 | 1 | )); |
|
113 | } |
||
114 | |||
115 | /** |
||
116 | * {@inheritdoc} |
||
117 | */ |
||
118 | 1 | public function map(callable $mapper) |
|
119 | { |
||
120 | 1 | return new self(array_map($mapper, $this->values)); |
|
121 | } |
||
122 | |||
123 | /** |
||
124 | * {@inheritdoc} |
||
125 | */ |
||
126 | 1 | public function pad($size, $value) |
|
127 | { |
||
128 | 1 | return new self(array_pad($this->values, (int) $size, $value)); |
|
129 | } |
||
130 | |||
131 | /** |
||
132 | * {@inheritdoc} |
||
133 | */ |
||
134 | 1 | public function pop() |
|
135 | { |
||
136 | 1 | $values = $this->values; |
|
137 | 1 | array_pop($values); |
|
138 | |||
139 | 1 | return new self($values); |
|
140 | } |
||
141 | |||
142 | /** |
||
143 | * {@inheritdoc} |
||
144 | */ |
||
145 | 1 | public function sum() |
|
146 | { |
||
147 | 1 | return array_sum($this->values); |
|
148 | } |
||
149 | |||
150 | /** |
||
151 | * {@inheritdoc} |
||
152 | */ |
||
153 | 1 | public function diff(CollectionInterface $collection) |
|
154 | { |
||
155 | 1 | return new self(array_diff($this->values, $collection->toPrimitive())); |
|
156 | } |
||
157 | |||
158 | /** |
||
159 | * {@inheritdoc} |
||
160 | */ |
||
161 | 1 | public function flip() |
|
162 | { |
||
163 | 1 | return new self(array_flip($this->values)); |
|
164 | } |
||
165 | |||
166 | /** |
||
167 | * {@inheritdoc} |
||
168 | */ |
||
169 | 1 | public function keys($search = null, $strict = true) |
|
170 | { |
||
171 | 1 | $args = func_get_args(); |
|
172 | |||
173 | 1 | if (count($args) > 0) { |
|
174 | 1 | $keys = array_keys($this->values, $search, (bool) $strict); |
|
175 | 1 | } else { |
|
176 | 1 | $keys = array_keys($this->values); |
|
177 | } |
||
178 | |||
179 | 1 | return new self($keys); |
|
180 | } |
||
181 | |||
182 | /** |
||
183 | * {@inheritdoc} |
||
184 | */ |
||
185 | public function push($value) |
||
186 | { |
||
187 | $values = $this->values; |
||
188 | array_push($values, $value); |
||
189 | |||
190 | return new self($values); |
||
191 | } |
||
192 | |||
193 | /** |
||
194 | * {@inheritdoc} |
||
195 | */ |
||
196 | public function rand($num = 1) |
||
197 | { |
||
198 | if ((int) $num > $this->count()->toPrimitive()) { |
||
0 ignored issues
–
show
|
|||
199 | throw new OutOfBoundException( |
||
200 | 'Trying to return a wider collection than the current one' |
||
201 | ); |
||
202 | } |
||
203 | |||
204 | $keys = (array) array_rand($this->values, $num); |
||
205 | $values = []; |
||
206 | |||
207 | foreach ($keys as $key) { |
||
208 | $values[$key] = $this->values[$key]; |
||
209 | } |
||
210 | |||
211 | return new self($values); |
||
212 | } |
||
213 | |||
214 | /** |
||
215 | * {@inheritdoc} |
||
216 | */ |
||
217 | public function merge(CollectionInterface $collection) |
||
218 | { |
||
219 | return new self(array_merge( |
||
220 | $this->values, |
||
221 | $collection->toPrimitive() |
||
222 | )); |
||
223 | } |
||
224 | |||
225 | /** |
||
226 | * {@inheritdoc} |
||
227 | */ |
||
228 | public function slice($offset, $length = null, $preserveKeys = false) |
||
229 | { |
||
230 | return new self(array_slice( |
||
231 | $this->values, |
||
232 | (int) $offset, |
||
233 | $length === null ? null : (int) $length, |
||
234 | (bool) $preserveKeys |
||
235 | )); |
||
236 | } |
||
237 | |||
238 | /** |
||
239 | * {@inheritdoc} |
||
240 | */ |
||
241 | public function udiff(CollectionInterface $collection, callable $differ) |
||
242 | { |
||
243 | return new self(array_udiff( |
||
244 | $this->values, |
||
245 | $collection->toPrimitive(), |
||
246 | $differ |
||
247 | )); |
||
248 | } |
||
249 | |||
250 | /** |
||
251 | * {@inheritdoc} |
||
252 | */ |
||
253 | public function column($key, $indexKey = null) |
||
254 | { |
||
255 | return new self(array_column( |
||
256 | $this->values, |
||
257 | $key, |
||
258 | $indexKey |
||
259 | )); |
||
260 | } |
||
261 | |||
262 | /** |
||
263 | * {@inheritdoc} |
||
264 | */ |
||
265 | public function splice($offset, $length = 0, $replacement = []) |
||
266 | { |
||
267 | $values = $this->values; |
||
268 | array_splice($values, (int) $offset, (int) $length, $replacement); |
||
269 | |||
270 | return new self($values); |
||
271 | } |
||
272 | |||
273 | /** |
||
274 | * {@inheritdoc} |
||
275 | */ |
||
276 | public function unique($flags = SORT_REGULAR) |
||
277 | { |
||
278 | return new self(array_unique($this->values, (int) $flags)); |
||
279 | } |
||
280 | |||
281 | /** |
||
282 | * {@inheritdoc} |
||
283 | */ |
||
284 | public function values() |
||
285 | { |
||
286 | return new self(array_values($this->values)); |
||
287 | } |
||
288 | |||
289 | /** |
||
290 | * {@inheritdoc} |
||
291 | */ |
||
292 | public function product() |
||
293 | { |
||
294 | return array_product($this->values); |
||
295 | } |
||
296 | |||
297 | /** |
||
298 | * {@inheritdoc} |
||
299 | */ |
||
300 | public function replace(CollectionInterface $collection) |
||
301 | { |
||
302 | return new self(array_replace( |
||
303 | $this->values, |
||
304 | $collection->toPrimitive() |
||
305 | )); |
||
306 | } |
||
307 | |||
308 | /** |
||
309 | * {@inheritdoc} |
||
310 | */ |
||
311 | public function reverse($preserveKeys = false) |
||
312 | { |
||
313 | return new self(array_reverse($this->values, (bool) $preserveKeys)); |
||
314 | } |
||
315 | |||
316 | /** |
||
317 | * {@inheritdoc} |
||
318 | */ |
||
319 | public function unshift($value) |
||
320 | { |
||
321 | $values = $this->values; |
||
322 | array_unshift($values, $value); |
||
323 | |||
324 | return new self($values); |
||
325 | } |
||
326 | |||
327 | /** |
||
328 | * {@inheritdoc} |
||
329 | */ |
||
330 | public function keyDiff(CollectionInterface $collection) |
||
331 | { |
||
332 | return new self(array_diff_key( |
||
333 | $this->values, |
||
334 | $collection->toPrimitive() |
||
335 | )); |
||
336 | } |
||
337 | |||
338 | /** |
||
339 | * {@inheritdoc} |
||
340 | */ |
||
341 | public function ukeyDiff(CollectionInterface $collection, callable $differ) |
||
342 | { |
||
343 | return new self(array_diff_ukey( |
||
344 | $this->values, |
||
345 | $collection->toPrimitive(), |
||
346 | $differ |
||
347 | )); |
||
348 | } |
||
349 | |||
350 | /** |
||
351 | * {@inheritdoc} |
||
352 | */ |
||
353 | public function associativeDiff(CollectionInterface $collection) |
||
354 | { |
||
355 | return new self(array_diff_assoc( |
||
356 | $this->values, |
||
357 | $collection->toPrimitive() |
||
358 | )); |
||
359 | } |
||
360 | |||
361 | /** |
||
362 | * {@inheritdoc} |
||
363 | */ |
||
364 | public function hasKey($key, $strict = true) |
||
365 | { |
||
366 | if ((bool) $strict === true) { |
||
367 | $bool = array_key_exists($key, $this->values); |
||
368 | } else { |
||
369 | $bool = isset($this->values[$key]); |
||
370 | } |
||
371 | |||
372 | return new BooleanPrimitive($bool); |
||
373 | } |
||
374 | |||
375 | /** |
||
376 | * {@inheritdoc} |
||
377 | */ |
||
378 | public function countValues() |
||
379 | { |
||
380 | return new self(array_count_values($this->values)); |
||
381 | } |
||
382 | |||
383 | /** |
||
384 | * {@inheritdoc} |
||
385 | */ |
||
386 | public function ukeyIntersect(CollectionInterface $collection, callable $intersecter) |
||
387 | { |
||
388 | return new self(array_intersect_ukey( |
||
389 | $this->values, |
||
390 | $collection->toPrimitive(), |
||
391 | $intersecter |
||
392 | )); |
||
393 | } |
||
394 | |||
395 | /** |
||
396 | * {@inheritdoc} |
||
397 | */ |
||
398 | public function associativeIntersect(CollectionInterface $collection) |
||
399 | { |
||
400 | return new self(array_intersect_assoc( |
||
401 | $this->values, |
||
402 | $collection->toPrimitive() |
||
403 | )); |
||
404 | } |
||
405 | |||
406 | /** |
||
407 | * {@inheritdoc} |
||
408 | */ |
||
409 | View Code Duplication | public function sort($flags = SORT_REGULAR) |
|
410 | { |
||
411 | $values = $this->values; |
||
412 | $bool = sort($values, (int) $flags); |
||
413 | |||
414 | if ($bool === false) { |
||
415 | throw new SortException('Sort failure'); |
||
416 | } |
||
417 | |||
418 | return new self($values); |
||
419 | } |
||
420 | |||
421 | /** |
||
422 | * {@inheritdoc} |
||
423 | */ |
||
424 | View Code Duplication | public function associativeSort($flags = SORT_REGULAR) |
|
425 | { |
||
426 | $values = $this->values; |
||
427 | $bool = asort($values, (int) $flags); |
||
428 | |||
429 | if ($bool === false) { |
||
430 | throw new SortException('Sort failure'); |
||
431 | } |
||
432 | |||
433 | return new self($values); |
||
434 | } |
||
435 | |||
436 | /** |
||
437 | * {@inheritdoc} |
||
438 | */ |
||
439 | View Code Duplication | public function keySort($flags = SORT_REGULAR) |
|
440 | { |
||
441 | $values = $this->values; |
||
442 | $bool = ksort($values, (int) $flags); |
||
443 | |||
444 | if ($bool === false) { |
||
445 | throw new SortException('Sort failure'); |
||
446 | } |
||
447 | |||
448 | return new self($values); |
||
449 | } |
||
450 | |||
451 | /** |
||
452 | * {@inheritdoc} |
||
453 | */ |
||
454 | View Code Duplication | public function ukeySort(callable $sorter) |
|
455 | { |
||
456 | $values = $this->values; |
||
457 | $bool = uksort($values, $sorter); |
||
458 | |||
459 | if ($bool === false) { |
||
460 | throw new SortException('Sort failure'); |
||
461 | } |
||
462 | |||
463 | return new self($values); |
||
464 | } |
||
465 | |||
466 | /** |
||
467 | * {@inheritdoc} |
||
468 | */ |
||
469 | View Code Duplication | public function reverseSort($flags = SORT_REGULAR) |
|
470 | { |
||
471 | $values = $this->values; |
||
472 | $bool = rsort($values, (int) $flags); |
||
473 | |||
474 | if ($bool === false) { |
||
475 | throw new SortException('Sort failure'); |
||
476 | } |
||
477 | |||
478 | return new self($values); |
||
479 | } |
||
480 | |||
481 | /** |
||
482 | * {@inheritdoc} |
||
483 | */ |
||
484 | View Code Duplication | public function usort(callable $sorter) |
|
485 | { |
||
486 | $values = $this->values; |
||
487 | $bool = usort($values, $sorter); |
||
488 | |||
489 | if ($bool === false) { |
||
490 | throw new SortException('Sort failure'); |
||
491 | } |
||
492 | |||
493 | return new self($values); |
||
494 | } |
||
495 | |||
496 | /** |
||
497 | * {@inheritdoc} |
||
498 | */ |
||
499 | View Code Duplication | public function associativeReverseSort($flags = SORT_REGULAR) |
|
500 | { |
||
501 | $values = $this->values; |
||
502 | $bool = arsort($values, (int) $flags); |
||
503 | |||
504 | if ($bool === false) { |
||
505 | throw new SortException('Sort failure'); |
||
506 | } |
||
507 | |||
508 | return new self($values); |
||
509 | } |
||
510 | |||
511 | /** |
||
512 | * {@inheritdoc} |
||
513 | */ |
||
514 | View Code Duplication | public function keyReverseSort($flags = SORT_REGULAR) |
|
515 | { |
||
516 | $values = $this->values; |
||
517 | $bool = krsort($values, (int) $flags); |
||
518 | |||
519 | if ($bool === false) { |
||
520 | throw new SortException('Sort failure'); |
||
521 | } |
||
522 | |||
523 | return new self($values); |
||
524 | } |
||
525 | |||
526 | /** |
||
527 | * {@inheritdoc} |
||
528 | */ |
||
529 | View Code Duplication | public function uassociativeSort(callable $sorter) |
|
530 | { |
||
531 | $values = $this->values; |
||
532 | $bool = uasort($values, $sorter); |
||
533 | |||
534 | if ($bool === false) { |
||
535 | throw new SortException('Sort failure'); |
||
536 | } |
||
537 | |||
538 | return new self($values); |
||
539 | } |
||
540 | |||
541 | /** |
||
542 | * {@inheritdoc} |
||
543 | */ |
||
544 | public function naturalSort() |
||
545 | { |
||
546 | $values = $this->values; |
||
547 | $bool = natsort($values); |
||
548 | |||
549 | if ($bool === false) { |
||
550 | throw new SortException('Sort failure'); |
||
551 | } |
||
552 | |||
553 | return new self($values); |
||
554 | } |
||
555 | |||
556 | /** |
||
557 | * {@inheritdoc} |
||
558 | */ |
||
559 | View Code Duplication | public function first() |
|
560 | { |
||
561 | if ($this->count() === 0) { |
||
562 | throw new OutOfBoundException('There is no first item'); |
||
563 | } |
||
564 | |||
565 | return array_values($this->values)[0]; |
||
566 | } |
||
567 | |||
568 | /** |
||
569 | * {@inheritdoc} |
||
570 | */ |
||
571 | View Code Duplication | public function last() |
|
572 | { |
||
573 | if ($this->count() === 0) { |
||
574 | throw new OutOfBoundException('There is no last item'); |
||
575 | } |
||
576 | |||
577 | $values = array_values($this->values); |
||
578 | |||
579 | return end($values); |
||
580 | } |
||
581 | |||
582 | /** |
||
583 | * {@inheritdoc} |
||
584 | */ |
||
585 | public function each(callable $callback) |
||
586 | { |
||
587 | foreach ($this->values as $key => $value) { |
||
588 | $callback($key, $value); |
||
589 | } |
||
590 | |||
591 | return $this; |
||
592 | } |
||
593 | |||
594 | /** |
||
595 | * {@inheritdoc} |
||
596 | */ |
||
597 | public function join($separator) |
||
598 | { |
||
599 | return implode((string) $separator, $this->values); |
||
600 | } |
||
601 | |||
602 | /** |
||
603 | * {@inheritdoc} |
||
604 | */ |
||
605 | public function shuffle() |
||
606 | { |
||
607 | $values = $this->values; |
||
608 | $result = shuffle($values); |
||
609 | |||
610 | if ($result === false) { |
||
611 | throw new RuntimeException('Shuffle operation failed'); |
||
612 | } |
||
613 | |||
614 | return new self($values); |
||
615 | } |
||
616 | |||
617 | /** |
||
618 | * {@inheritdoc} |
||
619 | */ |
||
620 | public function take($size, $preserveKeys = false) |
||
621 | { |
||
622 | $took = []; |
||
623 | $keys = array_keys($this->values); |
||
624 | $size = (int) $size; |
||
625 | |||
626 | while (count($took) < $size) { |
||
627 | $random = mt_rand(0, count($keys) - 1); |
||
628 | $key = $keys[$random]; |
||
629 | $took[$key] = $this->values[$key]; |
||
630 | unset($keys[$random]); |
||
631 | } |
||
632 | |||
633 | if ($preserveKeys === false) { |
||
634 | $took = array_values($took); |
||
635 | } |
||
636 | |||
637 | return new self($took); |
||
638 | } |
||
639 | |||
640 | /** |
||
641 | * {@inheritdoc} |
||
642 | */ |
||
643 | public function count() |
||
644 | { |
||
645 | return count($this->values); |
||
646 | } |
||
647 | |||
648 | /** |
||
649 | * {@inheritdoc} |
||
650 | */ |
||
651 | public function current() |
||
652 | { |
||
653 | return current($this->values); |
||
654 | } |
||
655 | |||
656 | /** |
||
657 | * {@inheritdoc} |
||
658 | */ |
||
659 | public function key() |
||
660 | { |
||
661 | return key($this->values); |
||
662 | } |
||
663 | |||
664 | /** |
||
665 | * {@inheritdoc} |
||
666 | */ |
||
667 | public function next() |
||
668 | { |
||
669 | next($this->values); |
||
670 | } |
||
671 | |||
672 | /** |
||
673 | * {@inheritdoc} |
||
674 | */ |
||
675 | public function rewind() |
||
676 | { |
||
677 | reset($this->values); |
||
678 | } |
||
679 | |||
680 | /** |
||
681 | * {@inheritdoc} |
||
682 | */ |
||
683 | public function valid() |
||
684 | { |
||
685 | return $this->key() !== null; |
||
686 | } |
||
687 | |||
688 | /** |
||
689 | * {@inheritdoc} |
||
690 | */ |
||
691 | public function offsetExists($offset) |
||
692 | { |
||
693 | return $this->hasKey($offset); |
||
0 ignored issues
–
show
The return type of
return $this->hasKey($offset); (Innmind\Immutable\BooleanPrimitive ) is incompatible with the return type declared by the interface ArrayAccess::offsetExists of type boolean .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
694 | } |
||
695 | |||
696 | /** |
||
697 | * {@inheritdoc} |
||
698 | */ |
||
699 | public function offsetGet($offset) |
||
700 | { |
||
701 | if (!$this->hasKey($offset)) { |
||
702 | throw new InvalidArgumentException(sprintf( |
||
703 | 'Unknown index %s', |
||
704 | $offset |
||
705 | )); |
||
706 | } |
||
707 | |||
708 | return $this->values[$offset]; |
||
709 | } |
||
710 | |||
711 | /** |
||
712 | * {@inheritdoc} |
||
713 | */ |
||
714 | public function offsetSet($offset, $value) |
||
715 | { |
||
716 | throw new LogicException('You can\'t modify an immutable collection'); |
||
717 | } |
||
718 | |||
719 | /** |
||
720 | * {@inheritdoc} |
||
721 | */ |
||
722 | public function offsetUnset($offset) |
||
723 | { |
||
724 | throw new LogicException('You can\'t modify an immutable collection'); |
||
725 | } |
||
726 | } |
||
727 |
Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.