GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — develop ( e9c41b...f51db1 )
by Baptiste
02:16
created

Collection.php (2 issues)

Upgrade to new PHP Analysis Engine

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
The method toPrimitive cannot be called on $this->count() (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
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
Bug Best Practice introduced by
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 my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
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