Completed
Push — master ( 61eea1...157236 )
by Antonio Carlos
03:35
created

Collection::whereNotInStrict()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace IlluminateAgnostic\Str\Support;
4
5
use stdClass;
6
use Countable;
7
use Exception;
8
use ArrayAccess;
9
use Traversable;
10
use ArrayIterator;
11
use CachingIterator;
12
use JsonSerializable;
13
use IteratorAggregate;
14
use IlluminateAgnostic\Str\Support\Debug\Dumper;
15
use IlluminateAgnostic\Str\Support\Traits\Macroable;
16
use IlluminateAgnostic\Str\Contracts\Support\Jsonable;
17
use IlluminateAgnostic\Str\Contracts\Support\Arrayable;
18
19
/**
20
 * @property-read HigherOrderCollectionProxy $average
21
 * @property-read HigherOrderCollectionProxy $avg
22
 * @property-read HigherOrderCollectionProxy $contains
23
 * @property-read HigherOrderCollectionProxy $each
24
 * @property-read HigherOrderCollectionProxy $every
25
 * @property-read HigherOrderCollectionProxy $filter
26
 * @property-read HigherOrderCollectionProxy $first
27
 * @property-read HigherOrderCollectionProxy $flatMap
28
 * @property-read HigherOrderCollectionProxy $groupBy
29
 * @property-read HigherOrderCollectionProxy $keyBy
30
 * @property-read HigherOrderCollectionProxy $map
31
 * @property-read HigherOrderCollectionProxy $max
32
 * @property-read HigherOrderCollectionProxy $min
33
 * @property-read HigherOrderCollectionProxy $partition
34
 * @property-read HigherOrderCollectionProxy $reject
35
 * @property-read HigherOrderCollectionProxy $sortBy
36
 * @property-read HigherOrderCollectionProxy $sortByDesc
37
 * @property-read HigherOrderCollectionProxy $sum
38
 * @property-read HigherOrderCollectionProxy $unique
39
 *
40
 * Class Collection
41
 */
42
class Collection implements ArrayAccess, Arrayable, Countable, IteratorAggregate, Jsonable, JsonSerializable
43
{
44
    use Macroable;
45
46
    /**
47
     * The items contained in the collection.
48
     *
49
     * @var array
50
     */
51
    protected $items = [];
52
53
    /**
54
     * The methods that can be proxied.
55
     *
56
     * @var array
57
     */
58
    protected static $proxies = [
59
        'average', 'avg', 'contains', 'each', 'every', 'filter', 'first',
60
        'flatMap', 'groupBy', 'keyBy', 'map', 'max', 'min', 'partition',
61
        'reject', 'sortBy', 'sortByDesc', 'sum', 'unique',
62
    ];
63
64
    /**
65
     * Create a new collection.
66
     *
67
     * @param  mixed  $items
68
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
69
     */
70 216
    public function __construct($items = [])
71
    {
72 216
        $this->items = $this->getArrayableItems($items);
73 216
    }
74
75
    /**
76
     * Create a new collection instance if the value isn't one already.
77
     *
78
     * @param  mixed  $items
79
     * @return static
80
     */
81 10
    public static function make($items = [])
82
    {
83 10
        return new static($items);
84
    }
85
86
    /**
87
     * Wrap the given value in a collection if applicable.
88
     *
89
     * @param  mixed  $value
90
     * @return static
91
     */
92 7
    public static function wrap($value)
93
    {
94 7
        return $value instanceof self
95 2
            ? new static($value)
96 7
            : new static(Arr::wrap($value));
97
    }
98
99
    /**
100
     * Get the underlying items from the given collection if applicable.
101
     *
102
     * @param  array|static  $value
103
     * @return array
104
     */
105 3
    public static function unwrap($value)
106
    {
107 3
        return $value instanceof self ? $value->all() : $value;
108
    }
109
110
    /**
111
     * Create a new collection by invoking the callback a given amount of times.
112
     *
113
     * @param  int  $number
114
     * @param  callable  $callback
115
     * @return static
116
     */
117 1
    public static function times($number, callable $callback = null)
118
    {
119 1
        if ($number < 1) {
120 1
            return new static;
121
        }
122
123 1
        if (is_null($callback)) {
124 1
            return new static(range(1, $number));
125
        }
126
127 1
        return (new static(range(1, $number)))->map($callback);
128
    }
129
130
    /**
131
     * Get all of the items in the collection.
132
     *
133
     * @return array
134
     */
135 109
    public function all()
136
    {
137 109
        return $this->items;
138
    }
139
140
    /**
141
     * Get the average value of a given key.
142
     *
143
     * @param  callable|string|null  $callback
144
     * @return mixed
145
     */
146 4
    public function avg($callback = null)
147
    {
148 4
        if ($count = $this->count()) {
149 4
            return $this->sum($callback) / $count;
150
        }
151 1
    }
152
153
    /**
154
     * Alias for the "avg" method.
155
     *
156
     * @param  callable|string|null  $callback
157
     * @return mixed
158
     */
159 3
    public function average($callback = null)
160
    {
161 3
        return $this->avg($callback);
162
    }
163
164
    /**
165
     * Get the median of a given key.
166
     *
167
     * @param  null $key
168
     * @return mixed
169
     */
170 5
    public function median($key = null)
171
    {
172 5
        $count = $this->count();
173
174 5
        if ($count == 0) {
175 1
            return;
176
        }
177
178 4
        $values = (isset($key) ? $this->pluck($key) : $this)
179 4
                    ->sort()->values();
180
181 4
        $middle = (int) ($count / 2);
182
183 4
        if ($count % 2) {
184 1
            return $values->get($middle);
185
        }
186
187 3
        return (new static([
188 3
            $values->get($middle - 1), $values->get($middle),
189 3
        ]))->average();
190
    }
191
192
    /**
193
     * Get the mode of a given key.
194
     *
195
     * @param  mixed  $key
196
     * @return array|null
197
     */
198 4
    public function mode($key = null)
199
    {
200 4
        $count = $this->count();
201
202 4
        if ($count == 0) {
203 1
            return;
204
        }
205
206 3
        $collection = isset($key) ? $this->pluck($key) : $this;
207
208 3
        $counts = new self;
209
210
        $collection->each(function ($value) use ($counts) {
211 3
            $counts[$value] = isset($counts[$value]) ? $counts[$value] + 1 : 1;
212 3
        });
213
214 3
        $sorted = $counts->sort();
215
216 3
        $highestValue = $sorted->last();
217
218
        return $sorted->filter(function ($value) use ($highestValue) {
219 3
            return $value == $highestValue;
220 3
        })->sort()->keys()->all();
221
    }
222
223
    /**
224
     * Collapse the collection of items into a single array.
225
     *
226
     * @return static
227
     */
228 3
    public function collapse()
229
    {
230 3
        return new static(Arr::collapse($this->items));
231
    }
232
233
    /**
234
     * Determine if an item exists in the collection.
235
     *
236
     * @param  mixed  $key
237
     * @param  mixed  $operator
238
     * @param  mixed  $value
239
     * @return bool
240
     */
241 3
    public function contains($key, $operator = null, $value = null)
0 ignored issues
show
Unused Code introduced by
The parameter $operator is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
242
    {
243 3
        if (func_num_args() === 1) {
244 3
            if ($this->useAsCallable($key)) {
245 3
                $placeholder = new stdClass;
246
247 3
                return $this->first($key, $placeholder) !== $placeholder;
248
            }
249
250 1
            return in_array($key, $this->items);
251
        }
252
253 2
        return $this->contains($this->operatorForWhere(...func_get_args()));
0 ignored issues
show
Bug introduced by
The call to operatorForWhere() misses a required argument $operator.

This check looks for function calls that miss required arguments.

Loading history...
Documentation introduced by
func_get_args() is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
254
    }
255
256
    /**
257
     * Determine if an item exists in the collection using strict comparison.
258
     *
259
     * @param  mixed  $key
260
     * @param  mixed  $value
261
     * @return bool
262
     */
263 1
    public function containsStrict($key, $value = null)
264
    {
265 1
        if (func_num_args() === 2) {
266
            return $this->contains(function ($item) use ($key, $value) {
267 1
                return data_get($item, $key) === $value;
268 1
            });
269
        }
270
271 1
        if ($this->useAsCallable($key)) {
272 1
            return ! is_null($this->first($key));
273
        }
274
275 1
        return in_array($key, $this->items, true);
276
    }
277
278
    /**
279
     * Cross join with the given lists, returning all possible permutations.
280
     *
281
     * @param  mixed  ...$lists
282
     * @return static
283
     */
284 1
    public function crossJoin(...$lists)
285
    {
286 1
        return new static(Arr::crossJoin(
287 1
            $this->items, ...array_map([$this, 'getArrayableItems'], $lists)
288
        ));
289
    }
290
291
    /**
292
     * Dump the collection and end the script.
293
     *
294
     * @return void
295
     */
296
    public function dd(...$args)
297
    {
298
        call_user_func_array([$this, 'dump'], $args);
299
300
        die(1);
301
    }
302
303
    /**
304
     * Dump the collection.
305
     *
306
     * @return $this
307
     */
308
    public function dump()
309
    {
310
        (new static(func_get_args()))
311
            ->push($this)
312
            ->each(function ($item) {
313
                (new Dumper)->dump($item);
314
            });
315
316
        return $this;
317
    }
318
319
    /**
320
     * Get the items in the collection that are not present in the given items.
321
     *
322
     * @param  mixed  $items
323
     * @return static
324
     */
325 3
    public function diff($items)
326
    {
327 3
        return new static(array_diff($this->items, $this->getArrayableItems($items)));
328
    }
329
330
    /**
331
     * Get the items in the collection that are not present in the given items.
332
     *
333
     * @param  mixed  $items
334
     * @param  callable  $callback
335
     * @return static
336
     */
337 2
    public function diffUsing($items, callable $callback)
338
    {
339 2
        return new static(array_udiff($this->items, $this->getArrayableItems($items), $callback));
340
    }
341
342
    /**
343
     * Get the items in the collection whose keys and values are not present in the given items.
344
     *
345
     * @param  mixed  $items
346
     * @return static
347
     */
348 2
    public function diffAssoc($items)
349
    {
350 2
        return new static(array_diff_assoc($this->items, $this->getArrayableItems($items)));
351
    }
352
353
    /**
354
     * Get the items in the collection whose keys and values are not present in the given items.
355
     *
356
     * @param  mixed  $items
357
     * @param  callable  $callback
358
     * @return static
359
     */
360 1
    public function diffAssocUsing($items, callable $callback)
361
    {
362 1
        return new static(array_diff_uassoc($this->items, $this->getArrayableItems($items), $callback));
363
    }
364
365
    /**
366
     * Get the items in the collection whose keys are not present in the given items.
367
     *
368
     * @param  mixed  $items
369
     * @return static
370
     */
371 2
    public function diffKeys($items)
372
    {
373 2
        return new static(array_diff_key($this->items, $this->getArrayableItems($items)));
374
    }
375
376
    /**
377
     * Get the items in the collection whose keys are not present in the given items.
378
     *
379
     * @param  mixed   $items
380
     * @param  callable  $callback
381
     * @return static
382
     */
383 1
    public function diffKeysUsing($items, callable $callback)
384
    {
385 1
        return new static(array_diff_ukey($this->items, $this->getArrayableItems($items), $callback));
386
    }
387
388
    /**
389
     * Execute a callback over each item.
390
     *
391
     * @param  callable  $callback
392
     * @return $this
393
     */
394 7
    public function each(callable $callback)
395
    {
396 7
        foreach ($this->items as $key => $item) {
397 7
            if ($callback($item, $key) === false) {
398 7
                break;
399
            }
400
        }
401
402 7
        return $this;
403
    }
404
405
    /**
406
     * Execute a callback over each nested chunk of items.
407
     *
408
     * @param  callable  $callback
409
     * @return static
410
     */
411 1
    public function eachSpread(callable $callback)
412
    {
413
        return $this->each(function ($chunk, $key) use ($callback) {
414 1
            $chunk[] = $key;
415
416 1
            return $callback(...$chunk);
417 1
        });
418
    }
419
420
    /**
421
     * Determine if all items in the collection pass the given test.
422
     *
423
     * @param  string|callable  $key
424
     * @param  mixed  $operator
425
     * @param  mixed  $value
426
     * @return bool
427
     */
428 1
    public function every($key, $operator = null, $value = null)
0 ignored issues
show
Unused Code introduced by
The parameter $operator is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
429
    {
430 1
        if (func_num_args() === 1) {
431 1
            $callback = $this->valueRetriever($key);
0 ignored issues
show
Documentation introduced by
$key is of type callable, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
432
433 1
            foreach ($this->items as $k => $v) {
434 1
                if (! $callback($v, $k)) {
435 1
                    return false;
436
                }
437
            }
438
439 1
            return true;
440
        }
441
442 1
        return $this->every($this->operatorForWhere(...func_get_args()));
0 ignored issues
show
Bug introduced by
The call to operatorForWhere() misses a required argument $operator.

This check looks for function calls that miss required arguments.

Loading history...
Documentation introduced by
func_get_args() is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
443
    }
444
445
    /**
446
     * Get all items except for those with the specified keys.
447
     *
448
     * @param  \IlluminateAgnostic\Str\Support\Collection|mixed  $keys
449
     * @return static
450
     */
451 2
    public function except($keys)
452
    {
453 2
        if ($keys instanceof self) {
454 2
            $keys = $keys->all();
455 1
        } elseif (! is_array($keys)) {
456 1
            $keys = func_get_args();
457
        }
458
459 2
        return new static(Arr::except($this->items, $keys));
460
    }
461
462
    /**
463
     * Run a filter over each of the items.
464
     *
465
     * @param  callable|null  $callback
466
     * @return static
467
     */
468 22
    public function filter(callable $callback = null)
469
    {
470 22
        if ($callback) {
471 22
            return new static(Arr::where($this->items, $callback));
472
        }
473
474 1
        return new static(array_filter($this->items));
475
    }
476
477
    /**
478
     * Apply the callback if the value is truthy.
479
     *
480
     * @param  bool  $value
481
     * @param  callable  $callback
482
     * @param  callable  $default
483
     * @return static|mixed
484
     */
485 4
    public function when($value, callable $callback, callable $default = null)
486
    {
487 4
        if ($value) {
488 2
            return $callback($this, $value);
489 4
        } elseif ($default) {
490 2
            return $default($this, $value);
491
        }
492
493 2
        return $this;
494
    }
495
496
    /**
497
     * Apply the callback if the value is falsy.
498
     *
499
     * @param  bool  $value
500
     * @param  callable  $callback
501
     * @param  callable  $default
502
     * @return static|mixed
503
     */
504 2
    public function unless($value, callable $callback, callable $default = null)
505
    {
506 2
        return $this->when(! $value, $callback, $default);
507
    }
508
509
    /**
510
     * Filter items by the given key value pair.
511
     *
512
     * @param  string  $key
513
     * @param  mixed  $operator
514
     * @param  mixed  $value
515
     * @return static
516
     */
517 2
    public function where($key, $operator, $value = null)
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $operator is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
518
    {
519 2
        return $this->filter($this->operatorForWhere(...func_get_args()));
0 ignored issues
show
Bug introduced by
The call to operatorForWhere() misses a required argument $operator.

This check looks for function calls that miss required arguments.

Loading history...
Documentation introduced by
func_get_args() is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
520
    }
521
522
    /**
523
     * Get an operator checker callback.
524
     *
525
     * @param  string  $key
526
     * @param  string  $operator
527
     * @param  mixed  $value
528
     * @return \Closure
529
     */
530 7
    protected function operatorForWhere($key, $operator, $value = null)
531
    {
532 7
        if (func_num_args() === 2) {
533 5
            $value = $operator;
534
535 5
            $operator = '=';
536
        }
537
538
        return function ($item) use ($key, $operator, $value) {
539 7
            $retrieved = data_get($item, $key);
540
541
            $strings = array_filter([$retrieved, $value], function ($value) {
542 7
                return is_string($value) || (is_object($value) && method_exists($value, '__toString'));
543 7
            });
544
545 7
            if (count($strings) < 2 && count(array_filter([$retrieved, $value], 'is_object')) == 1) {
546 1
                return in_array($operator, ['!=', '<>', '!==']);
547
            }
548
549 7
            switch ($operator) {
550
                default:
551 7
                case '=':
552 7
                case '==':  return $retrieved == $value;
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
553 5
                case '!=':
554 5
                case '<>':  return $retrieved != $value;
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
555 5
                case '<':   return $retrieved < $value;
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
556 5
                case '>':   return $retrieved > $value;
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
557 5
                case '<=':  return $retrieved <= $value;
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
558 5
                case '>=':  return $retrieved >= $value;
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
559 3
                case '===': return $retrieved === $value;
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
560 1
                case '!==': return $retrieved !== $value;
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
561
            }
562 7
        };
563
    }
564
565
    /**
566
     * Filter items by the given key value pair using strict comparison.
567
     *
568
     * @param  string  $key
569
     * @param  mixed  $value
570
     * @return static
571
     */
572 1
    public function whereStrict($key, $value)
573
    {
574 1
        return $this->where($key, '===', $value);
575
    }
576
577
    /**
578
     * Filter items by the given key value pair.
579
     *
580
     * @param  string  $key
581
     * @param  mixed  $values
582
     * @param  bool  $strict
583
     * @return static
584
     */
585 2 View Code Duplication
    public function whereIn($key, $values, $strict = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
586
    {
587 2
        $values = $this->getArrayableItems($values);
588
589
        return $this->filter(function ($item) use ($key, $values, $strict) {
590 2
            return in_array(data_get($item, $key), $values, $strict);
591 2
        });
592
    }
593
594
    /**
595
     * Filter items by the given key value pair using strict comparison.
596
     *
597
     * @param  string  $key
598
     * @param  mixed  $values
599
     * @return static
600
     */
601 1
    public function whereInStrict($key, $values)
602
    {
603 1
        return $this->whereIn($key, $values, true);
604
    }
605
606
    /**
607
     * Filter items by the given key value pair.
608
     *
609
     * @param  string  $key
610
     * @param  mixed  $values
611
     * @param  bool  $strict
612
     * @return static
613
     */
614 2 View Code Duplication
    public function whereNotIn($key, $values, $strict = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
615
    {
616 2
        $values = $this->getArrayableItems($values);
617
618
        return $this->reject(function ($item) use ($key, $values, $strict) {
619 2
            return in_array(data_get($item, $key), $values, $strict);
620 2
        });
621
    }
622
623
    /**
624
     * Filter items by the given key value pair using strict comparison.
625
     *
626
     * @param  string  $key
627
     * @param  mixed  $values
628
     * @return static
629
     */
630 1
    public function whereNotInStrict($key, $values)
631
    {
632 1
        return $this->whereNotIn($key, $values, true);
633
    }
634
635
    /**
636
     * Filter the items, removing any items that don't match the given type.
637
     *
638
     * @param  string  $type
639
     * @return static
640
     */
641 1
    public function whereInstanceOf($type)
642
    {
643
        return $this->filter(function ($value) use ($type) {
644 1
            return $value instanceof $type;
645 1
        });
646
    }
647
648
    /**
649
     * Get the first item from the collection.
650
     *
651
     * @param  callable|null  $callback
652
     * @param  mixed  $default
653
     * @return mixed
654
     */
655 11
    public function first(callable $callback = null, $default = null)
656
    {
657 11
        return Arr::first($this->items, $callback, $default);
658
    }
659
660
    /**
661
     * Get the first item by the given key value pair.
662
     *
663
     * @param  string  $key
664
     * @param  mixed  $operator
665
     * @param  mixed  $value
666
     * @return static
667
     */
668 1
    public function firstWhere($key, $operator, $value = null)
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $operator is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
669
    {
670 1
        return $this->first($this->operatorForWhere(...func_get_args()));
0 ignored issues
show
Bug introduced by
The call to operatorForWhere() misses a required argument $operator.

This check looks for function calls that miss required arguments.

Loading history...
Documentation introduced by
func_get_args() is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
671
    }
672
673
    /**
674
     * Get a flattened array of the items in the collection.
675
     *
676
     * @param  int  $depth
677
     * @return static
678
     */
679 3
    public function flatten($depth = INF)
680
    {
681 3
        return new static(Arr::flatten($this->items, $depth));
682
    }
683
684
    /**
685
     * Flip the items in the collection.
686
     *
687
     * @return static
688
     */
689 1
    public function flip()
690
    {
691 1
        return new static(array_flip($this->items));
692
    }
693
694
    /**
695
     * Remove an item from the collection by key.
696
     *
697
     * @param  string|array  $keys
698
     * @return $this
699
     */
700 2
    public function forget($keys)
701
    {
702 2
        foreach ((array) $keys as $key) {
703 2
            $this->offsetUnset($key);
704
        }
705
706 2
        return $this;
707
    }
708
709
    /**
710
     * Get an item from the collection by key.
711
     *
712
     * @param  mixed  $key
713
     * @param  mixed  $default
714
     * @return mixed
715
     */
716 5
    public function get($key, $default = null)
717
    {
718 5
        if ($this->offsetExists($key)) {
719 4
            return $this->items[$key];
720
        }
721
722 1
        return value($default);
723
    }
724
725
    /**
726
     * Group an associative array by a field or using a callback.
727
     *
728
     * @param  callable|string  $groupBy
729
     * @param  bool  $preserveKeys
730
     * @return static
731
     */
732 8
    public function groupBy($groupBy, $preserveKeys = false)
733
    {
734 8
        if (is_array($groupBy)) {
735 1
            $nextGroups = $groupBy;
736
737 1
            $groupBy = array_shift($nextGroups);
738
        }
739
740 8
        $groupBy = $this->valueRetriever($groupBy);
741
742 8
        $results = [];
743
744 8
        foreach ($this->items as $key => $value) {
745 8
            $groupKeys = $groupBy($value, $key);
746
747 8
            if (! is_array($groupKeys)) {
748 6
                $groupKeys = [$groupKeys];
749
            }
750
751 8
            foreach ($groupKeys as $groupKey) {
752 8
                $groupKey = is_bool($groupKey) ? (int) $groupKey : $groupKey;
753
754 8
                if (! array_key_exists($groupKey, $results)) {
755 8
                    $results[$groupKey] = new static;
756
                }
757
758 8
                $results[$groupKey]->offsetSet($preserveKeys ? $key : null, $value);
759
            }
760
        }
761
762 8
        $result = new static($results);
763
764 8
        if (! empty($nextGroups)) {
765 1
            return $result->map->groupBy($nextGroups, $preserveKeys);
0 ignored issues
show
Documentation Bug introduced by
The method groupBy does not exist on object<IlluminateAgnosti...erOrderCollectionProxy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
766
        }
767
768 8
        return $result;
769
    }
770
771
    /**
772
     * Key an associative array by a field or using a callback.
773
     *
774
     * @param  callable|string  $keyBy
775
     * @return static
776
     */
777 3
    public function keyBy($keyBy)
778
    {
779 3
        $keyBy = $this->valueRetriever($keyBy);
0 ignored issues
show
Documentation introduced by
$keyBy is of type callable, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
780
781 3
        $results = [];
782
783 3
        foreach ($this->items as $key => $item) {
784 3
            $resolvedKey = $keyBy($item, $key);
785
786 3
            if (is_object($resolvedKey)) {
787
                $resolvedKey = (string) $resolvedKey;
788
            }
789
790 3
            $results[$resolvedKey] = $item;
791
        }
792
793 3
        return new static($results);
794
    }
795
796
    /**
797
     * Determine if an item exists in the collection by key.
798
     *
799
     * @param  mixed  $key
800
     * @return bool
801
     */
802 2
    public function has($key)
803
    {
804 2
        $keys = is_array($key) ? $key : func_get_args();
805
806 2
        foreach ($keys as $value) {
807 2
            if (! $this->offsetExists($value)) {
808 2
                return false;
809
            }
810
        }
811
812 2
        return true;
813
    }
814
815
    /**
816
     * Concatenate values of a given key as a string.
817
     *
818
     * @param  string  $value
819
     * @param  string  $glue
820
     * @return string
821
     */
822 1
    public function implode($value, $glue = null)
823
    {
824 1
        $first = $this->first();
825
826 1
        if (is_array($first) || is_object($first)) {
827 1
            return implode($glue, $this->pluck($value)->all());
828
        }
829
830 1
        return implode($value, $this->items);
831
    }
832
833
    /**
834
     * Intersect the collection with the given items.
835
     *
836
     * @param  mixed  $items
837
     * @return static
838
     */
839 2
    public function intersect($items)
840
    {
841 2
        return new static(array_intersect($this->items, $this->getArrayableItems($items)));
842
    }
843
844
    /**
845
     * Intersect the collection with the given items by key.
846
     *
847
     * @param  mixed  $items
848
     * @return static
849
     */
850 2
    public function intersectByKeys($items)
851
    {
852 2
        return new static(array_intersect_key(
853 2
            $this->items, $this->getArrayableItems($items)
854
        ));
855
    }
856
857
    /**
858
     * Determine if the collection is empty or not.
859
     *
860
     * @return bool
861
     */
862 7
    public function isEmpty()
863
    {
864 7
        return empty($this->items);
865
    }
866
867
    /**
868
     * Determine if the collection is not empty.
869
     *
870
     * @return bool
871
     */
872 1
    public function isNotEmpty()
873
    {
874 1
        return ! $this->isEmpty();
875
    }
876
877
    /**
878
     * Determine if the given value is callable, but not a string.
879
     *
880
     * @param  mixed  $value
881
     * @return bool
882
     */
883 41
    protected function useAsCallable($value)
884
    {
885 41
        return ! is_string($value) && is_callable($value);
886
    }
887
888
    /**
889
     * Get the keys of the collection items.
890
     *
891
     * @return static
892
     */
893 6
    public function keys()
894
    {
895 6
        return new static(array_keys($this->items));
896
    }
897
898
    /**
899
     * Get the last item from the collection.
900
     *
901
     * @param  callable|null  $callback
902
     * @param  mixed  $default
903
     * @return mixed
904
     */
905 7
    public function last(callable $callback = null, $default = null)
906
    {
907 7
        return Arr::last($this->items, $callback, $default);
908
    }
909
910
    /**
911
     * Get the values of a given key.
912
     *
913
     * @param  string|array  $value
914
     * @param  string|null  $key
915
     * @return static
916
     */
917 9
    public function pluck($value, $key = null)
918
    {
919 9
        return new static(Arr::pluck($this->items, $value, $key));
920
    }
921
922
    /**
923
     * Run a map over each of the items.
924
     *
925
     * @param  callable  $callback
926
     * @return static
927
     */
928 16
    public function map(callable $callback)
929
    {
930 16
        $keys = array_keys($this->items);
931
932 16
        $items = array_map($callback, $this->items, $keys);
933
934 16
        return new static(array_combine($keys, $items));
935
    }
936
937
    /**
938
     * Run a map over each nested chunk of items.
939
     *
940
     * @param  callable  $callback
941
     * @return static
942
     */
943 1
    public function mapSpread(callable $callback)
944
    {
945
        return $this->map(function ($chunk, $key) use ($callback) {
946 1
            $chunk[] = $key;
947
948 1
            return $callback(...$chunk);
949 1
        });
950
    }
951
952
    /**
953
     * Run a dictionary map over the items.
954
     *
955
     * The callback should return an associative array with a single key/value pair.
956
     *
957
     * @param  callable  $callback
958
     * @return static
959
     */
960 4
    public function mapToDictionary(callable $callback)
961
    {
962 4
        $dictionary = [];
963
964 4
        foreach ($this->items as $key => $item) {
965 4
            $pair = $callback($item, $key);
966
967 4
            $key = key($pair);
968
969 4
            $value = reset($pair);
970
971 4
            if (! isset($dictionary[$key])) {
972 4
                $dictionary[$key] = [];
973
            }
974
975 4
            $dictionary[$key][] = $value;
976
        }
977
978 4
        return new static($dictionary);
979
    }
980
981
    /**
982
     * Run a grouping map over the items.
983
     *
984
     * The callback should return an associative array with a single key/value pair.
985
     *
986
     * @param  callable  $callback
987
     * @return static
988
     */
989 2
    public function mapToGroups(callable $callback)
990
    {
991 2
        $groups = $this->mapToDictionary($callback);
992
993 2
        return $groups->map([$this, 'make']);
994
    }
995
996
    /**
997
     * Run an associative map over each of the items.
998
     *
999
     * The callback should return an associative array with a single key/value pair.
1000
     *
1001
     * @param  callable  $callback
1002
     * @return static
1003
     */
1004 4
    public function mapWithKeys(callable $callback)
1005
    {
1006 4
        $result = [];
1007
1008 4
        foreach ($this->items as $key => $value) {
1009 4
            $assoc = $callback($value, $key);
1010
1011 4
            foreach ($assoc as $mapKey => $mapValue) {
1012 4
                $result[$mapKey] = $mapValue;
1013
            }
1014
        }
1015
1016 4
        return new static($result);
1017
    }
1018
1019
    /**
1020
     * Map a collection and flatten the result by a single level.
1021
     *
1022
     * @param  callable  $callback
1023
     * @return static
1024
     */
1025 1
    public function flatMap(callable $callback)
1026
    {
1027 1
        return $this->map($callback)->collapse();
1028
    }
1029
1030
    /**
1031
     * Map the values into a new class.
1032
     *
1033
     * @param  string  $class
1034
     * @return static
1035
     */
1036 1
    public function mapInto($class)
1037
    {
1038
        return $this->map(function ($value, $key) use ($class) {
1039 1
            return new $class($value, $key);
1040 1
        });
1041
    }
1042
1043
    /**
1044
     * Get the max value of a given key.
1045
     *
1046
     * @param  callable|string|null  $callback
1047
     * @return mixed
1048
     */
1049 1 View Code Duplication
    public function max($callback = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1050
    {
1051 1
        $callback = $this->valueRetriever($callback);
0 ignored issues
show
Documentation introduced by
$callback is of type callable|null, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1052
1053
        return $this->filter(function ($value) {
1054 1
            return ! is_null($value);
1055
        })->reduce(function ($result, $item) use ($callback) {
1056 1
            $value = $callback($item);
1057
1058 1
            return is_null($result) || $value > $result ? $value : $result;
1059 1
        });
1060
    }
1061
1062
    /**
1063
     * Merge the collection with the given items.
1064
     *
1065
     * @param  mixed  $items
1066
     * @return static
1067
     */
1068 3
    public function merge($items)
1069
    {
1070 3
        return new static(array_merge($this->items, $this->getArrayableItems($items)));
1071
    }
1072
1073
    /**
1074
     * Create a collection by using this collection for keys and another for its values.
1075
     *
1076
     * @param  mixed  $values
1077
     * @return static
1078
     */
1079 2
    public function combine($values)
1080
    {
1081 2
        return new static(array_combine($this->all(), $this->getArrayableItems($values)));
1082
    }
1083
1084
    /**
1085
     * Union the collection with the given items.
1086
     *
1087
     * @param  mixed  $items
1088
     * @return static
1089
     */
1090 3
    public function union($items)
1091
    {
1092 3
        return new static($this->items + $this->getArrayableItems($items));
1093
    }
1094
1095
    /**
1096
     * Get the min value of a given key.
1097
     *
1098
     * @param  callable|string|null  $callback
1099
     * @return mixed
1100
     */
1101 1 View Code Duplication
    public function min($callback = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1102
    {
1103 1
        $callback = $this->valueRetriever($callback);
0 ignored issues
show
Documentation introduced by
$callback is of type callable|null, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1104
1105
        return $this->filter(function ($value) {
1106 1
            return ! is_null($value);
1107
        })->reduce(function ($result, $item) use ($callback) {
1108 1
            $value = $callback($item);
1109
1110 1
            return is_null($result) || $value < $result ? $value : $result;
1111 1
        });
1112
    }
1113
1114
    /**
1115
     * Create a new collection consisting of every n-th element.
1116
     *
1117
     * @param  int  $step
1118
     * @param  int  $offset
1119
     * @return static
1120
     */
1121 1
    public function nth($step, $offset = 0)
1122
    {
1123 1
        $new = [];
1124
1125 1
        $position = 0;
1126
1127 1
        foreach ($this->items as $item) {
1128 1
            if ($position % $step === $offset) {
1129 1
                $new[] = $item;
1130
            }
1131
1132 1
            $position++;
1133
        }
1134
1135 1
        return new static($new);
1136
    }
1137
1138
    /**
1139
     * Get the items with the specified keys.
1140
     *
1141
     * @param  mixed  $keys
1142
     * @return static
1143
     */
1144 1
    public function only($keys)
1145
    {
1146 1
        if (is_null($keys)) {
1147 1
            return new static($this->items);
1148
        }
1149
1150 1
        if ($keys instanceof self) {
1151 1
            $keys = $keys->all();
1152
        }
1153
1154 1
        $keys = is_array($keys) ? $keys : func_get_args();
1155
1156 1
        return new static(Arr::only($this->items, $keys));
1157
    }
1158
1159
    /**
1160
     * "Paginate" the collection by slicing it into a smaller collection.
1161
     *
1162
     * @param  int  $page
1163
     * @param  int  $perPage
1164
     * @return static
1165
     */
1166 1
    public function forPage($page, $perPage)
1167
    {
1168 1
        $offset = max(0, ($page - 1) * $perPage);
1169
1170 1
        return $this->slice($offset, $perPage);
1171
    }
1172
1173
    /**
1174
     * Partition the collection into two arrays using the given callback or key.
1175
     *
1176
     * @param  callable|string  $key
1177
     * @param  mixed  $operator
1178
     * @param  mixed  $value
1179
     * @return static
1180
     */
1181 7
    public function partition($key, $operator = null, $value = null)
0 ignored issues
show
Unused Code introduced by
The parameter $operator is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1182
    {
1183 7
        $partitions = [new static, new static];
1184
1185 7
        $callback = func_num_args() === 1
1186 6
                ? $this->valueRetriever($key)
0 ignored issues
show
Documentation introduced by
$key is of type callable, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1187 7
                : $this->operatorForWhere(...func_get_args());
0 ignored issues
show
Bug introduced by
The call to operatorForWhere() misses a required argument $operator.

This check looks for function calls that miss required arguments.

Loading history...
Documentation introduced by
func_get_args() is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1188
1189 7
        foreach ($this->items as $key => $item) {
1190 6
            $partitions[(int) ! $callback($item, $key)][$key] = $item;
1191
        }
1192
1193 7
        return new static($partitions);
1194
    }
1195
1196
    /**
1197
     * Pass the collection to the given callback and return the result.
1198
     *
1199
     * @param  callable $callback
1200
     * @return mixed
1201
     */
1202 1
    public function pipe(callable $callback)
1203
    {
1204 1
        return $callback($this);
1205
    }
1206
1207
    /**
1208
     * Get and remove the last item from the collection.
1209
     *
1210
     * @return mixed
1211
     */
1212 1
    public function pop()
1213
    {
1214 1
        return array_pop($this->items);
1215
    }
1216
1217
    /**
1218
     * Push an item onto the beginning of the collection.
1219
     *
1220
     * @param  mixed  $value
1221
     * @param  mixed  $key
1222
     * @return $this
1223
     */
1224 1
    public function prepend($value, $key = null)
1225
    {
1226 1
        $this->items = Arr::prepend($this->items, $value, $key);
1227
1228 1
        return $this;
1229
    }
1230
1231
    /**
1232
     * Push an item onto the end of the collection.
1233
     *
1234
     * @param  mixed  $value
1235
     * @return $this
1236
     */
1237 7
    public function push($value)
1238
    {
1239 7
        $this->offsetSet(null, $value);
1240
1241 7
        return $this;
1242
    }
1243
1244
    /**
1245
     * Push all of the given items onto the collection.
1246
     *
1247
     * @param  \Traversable|array  $source
1248
     * @return static
1249
     */
1250 2
    public function concat($source)
1251
    {
1252 2
        $result = new static($this);
1253
1254 2
        foreach ($source as $item) {
1255 2
            $result->push($item);
1256
        }
1257
1258 2
        return $result;
1259
    }
1260
1261
    /**
1262
     * Get and remove an item from the collection.
1263
     *
1264
     * @param  mixed  $key
1265
     * @param  mixed  $default
1266
     * @return mixed
1267
     */
1268 3
    public function pull($key, $default = null)
1269
    {
1270 3
        return Arr::pull($this->items, $key, $default);
1271
    }
1272
1273
    /**
1274
     * Put an item in the collection by key.
1275
     *
1276
     * @param  mixed  $key
1277
     * @param  mixed  $value
1278
     * @return $this
1279
     */
1280 3
    public function put($key, $value)
1281
    {
1282 3
        $this->offsetSet($key, $value);
1283
1284 3
        return $this;
1285
    }
1286
1287
    /**
1288
     * Get one or a specified number of items randomly from the collection.
1289
     *
1290
     * @param  int|null  $number
1291
     * @return static|mixed
1292
     *
1293
     * @throws \InvalidArgumentException
1294
     */
1295 3
    public function random($number = null)
1296
    {
1297 3
        if (is_null($number)) {
1298 1
            return Arr::random($this->items);
1299
        }
1300
1301 3
        return new static(Arr::random($this->items, $number));
1302
    }
1303
1304
    /**
1305
     * Reduce the collection to a single value.
1306
     *
1307
     * @param  callable  $callback
1308
     * @param  mixed  $initial
1309
     * @return mixed
1310
     */
1311 6
    public function reduce(callable $callback, $initial = null)
1312
    {
1313 6
        return array_reduce($this->items, $callback, $initial);
1314
    }
1315
1316
    /**
1317
     * Create a collection of all elements that do not pass a given truth test.
1318
     *
1319
     * @param  callable|mixed  $callback
1320
     * @return static
1321
     */
1322 8
    public function reject($callback)
1323
    {
1324 8
        if ($this->useAsCallable($callback)) {
1325
            return $this->filter(function ($value, $key) use ($callback) {
1326 8
                return ! $callback($value, $key);
1327 8
            });
1328
        }
1329
1330
        return $this->filter(function ($item) use ($callback) {
1331 1
            return $item != $callback;
1332 1
        });
1333
    }
1334
1335
    /**
1336
     * Reverse items order.
1337
     *
1338
     * @return static
1339
     */
1340 1
    public function reverse()
1341
    {
1342 1
        return new static(array_reverse($this->items, true));
1343
    }
1344
1345
    /**
1346
     * Search the collection for a given value and return the corresponding key if successful.
1347
     *
1348
     * @param  mixed  $value
1349
     * @param  bool  $strict
1350
     * @return mixed
1351
     */
1352 2
    public function search($value, $strict = false)
1353
    {
1354 2
        if (! $this->useAsCallable($value)) {
1355 2
            return array_search($value, $this->items, $strict);
1356
        }
1357
1358 2
        foreach ($this->items as $key => $item) {
1359 2
            if (call_user_func($value, $item, $key)) {
1360 2
                return $key;
1361
            }
1362
        }
1363
1364 1
        return false;
1365
    }
1366
1367
    /**
1368
     * Get and remove the first item from the collection.
1369
     *
1370
     * @return mixed
1371
     */
1372 1
    public function shift()
1373
    {
1374 1
        return array_shift($this->items);
1375
    }
1376
1377
    /**
1378
     * Shuffle the items in the collection.
1379
     *
1380
     * @param  int  $seed
1381
     * @return static
1382
     */
1383 1
    public function shuffle($seed = null)
1384
    {
1385 1
        return new static(Arr::shuffle($this->items, $seed));
1386
    }
1387
1388
    /**
1389
     * Slice the underlying collection array.
1390
     *
1391
     * @param  int  $offset
1392
     * @param  int  $length
1393
     * @return static
1394
     */
1395 10
    public function slice($offset, $length = null)
1396
    {
1397 10
        return new static(array_slice($this->items, $offset, $length, true));
1398
    }
1399
1400
    /**
1401
     * Split a collection into a certain number of groups.
1402
     *
1403
     * @param  int  $numberOfGroups
1404
     * @return static
1405
     */
1406 4
    public function split($numberOfGroups)
1407
    {
1408 4
        if ($this->isEmpty()) {
1409 1
            return new static;
1410
        }
1411
1412 3
        $groupSize = ceil($this->count() / $numberOfGroups);
1413
1414 3
        return $this->chunk($groupSize);
1415
    }
1416
1417
    /**
1418
     * Chunk the underlying collection array.
1419
     *
1420
     * @param  int  $size
1421
     * @return static
1422
     */
1423 6
    public function chunk($size)
1424
    {
1425 6
        if ($size <= 0) {
1426 2
            return new static;
1427
        }
1428
1429 4
        $chunks = [];
1430
1431 4
        foreach (array_chunk($this->items, $size, true) as $chunk) {
1432 4
            $chunks[] = new static($chunk);
1433
        }
1434
1435 4
        return new static($chunks);
1436
    }
1437
1438
    /**
1439
     * Sort through each item with a callback.
1440
     *
1441
     * @param  callable|null  $callback
1442
     * @return static
1443
     */
1444 9
    public function sort(callable $callback = null)
1445
    {
1446 9
        $items = $this->items;
1447
1448 9
        $callback
1449 1
            ? uasort($items, $callback)
1450 8
            : asort($items);
1451
1452 9
        return new static($items);
1453
    }
1454
1455
    /**
1456
     * Sort the collection using the given callback.
1457
     *
1458
     * @param  callable|string  $callback
1459
     * @param  int  $options
1460
     * @param  bool  $descending
1461
     * @return static
1462
     */
1463 5
    public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
1464
    {
1465 5
        $results = [];
1466
1467 5
        $callback = $this->valueRetriever($callback);
0 ignored issues
show
Documentation introduced by
$callback is of type callable, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1468
1469
        // First we will loop through the items and get the comparator from a callback
1470
        // function which we were given. Then, we will sort the returned values and
1471
        // and grab the corresponding values for the sorted keys from this array.
1472 5
        foreach ($this->items as $key => $value) {
1473 5
            $results[$key] = $callback($value, $key);
1474
        }
1475
1476 5
        $descending ? arsort($results, $options)
1477 5
            : asort($results, $options);
1478
1479
        // Once we have sorted all of the keys in the array, we will loop through them
1480
        // and grab the corresponding model so we can set the underlying items list
1481
        // to the sorted version. Then we'll just return the collection instance.
1482 5
        foreach (array_keys($results) as $key) {
1483 5
            $results[$key] = $this->items[$key];
1484
        }
1485
1486 5
        return new static($results);
1487
    }
1488
1489
    /**
1490
     * Sort the collection in descending order using the given callback.
1491
     *
1492
     * @param  callable|string  $callback
1493
     * @param  int  $options
1494
     * @return static
1495
     */
1496 1
    public function sortByDesc($callback, $options = SORT_REGULAR)
1497
    {
1498 1
        return $this->sortBy($callback, $options, true);
1499
    }
1500
1501
    /**
1502
     * Sort the collection keys.
1503
     *
1504
     * @param  int  $options
1505
     * @param  bool  $descending
1506
     * @return static
1507
     */
1508 2
    public function sortKeys($options = SORT_REGULAR, $descending = false)
1509
    {
1510 2
        $items = $this->items;
1511
1512 2
        $descending ? krsort($items, $options) : ksort($items, $options);
1513
1514 2
        return new static($items);
1515
    }
1516
1517
    /**
1518
     * Sort the collection keys in descending order.
1519
     *
1520
     * @param  int $options
1521
     * @return static
1522
     */
1523
    public function sortKeysDesc($options = SORT_REGULAR)
1524
    {
1525
        return $this->sortKeys($options, true);
1526
    }
1527
1528
    /**
1529
     * Splice a portion of the underlying collection array.
1530
     *
1531
     * @param  int  $offset
1532
     * @param  int|null  $length
1533
     * @param  mixed  $replacement
1534
     * @return static
1535
     */
1536 1
    public function splice($offset, $length = null, $replacement = [])
1537
    {
1538 1
        if (func_num_args() === 1) {
1539 1
            return new static(array_splice($this->items, $offset));
1540
        }
1541
1542 1
        return new static(array_splice($this->items, $offset, $length, $replacement));
1543
    }
1544
1545
    /**
1546
     * Get the sum of the given values.
1547
     *
1548
     * @param  callable|string|null  $callback
1549
     * @return mixed
1550
     */
1551 8
    public function sum($callback = null)
1552
    {
1553 8
        if (is_null($callback)) {
1554 6
            return array_sum($this->items);
1555
        }
1556
1557 3
        $callback = $this->valueRetriever($callback);
0 ignored issues
show
Documentation introduced by
$callback is of type callable, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1558
1559
        return $this->reduce(function ($result, $item) use ($callback) {
1560 2
            return $result + $callback($item);
1561 3
        }, 0);
1562
    }
1563
1564
    /**
1565
     * Take the first or last {$limit} items.
1566
     *
1567
     * @param  int  $limit
1568
     * @return static
1569
     */
1570 2
    public function take($limit)
1571
    {
1572 2
        if ($limit < 0) {
1573 1
            return $this->slice($limit, abs($limit));
1574
        }
1575
1576 1
        return $this->slice(0, $limit);
1577
    }
1578
1579
    /**
1580
     * Pass the collection to the given callback and then return it.
1581
     *
1582
     * @param  callable  $callback
1583
     * @return $this
1584
     */
1585 1
    public function tap(callable $callback)
1586
    {
1587 1
        $callback(new static($this->items));
1588
1589 1
        return $this;
1590
    }
1591
1592
    /**
1593
     * Transform each item in the collection using a callback.
1594
     *
1595
     * @param  callable  $callback
1596
     * @return $this
1597
     */
1598 1
    public function transform(callable $callback)
1599
    {
1600 1
        $this->items = $this->map($callback)->all();
1601
1602 1
        return $this;
1603
    }
1604
1605
    /**
1606
     * Return only unique items from the collection array.
1607
     *
1608
     * @param  string|callable|null  $key
1609
     * @param  bool  $strict
1610
     * @return static
1611
     */
1612 5
    public function unique($key = null, $strict = false)
1613
    {
1614 5
        $callback = $this->valueRetriever($key);
0 ignored issues
show
Documentation introduced by
$key is of type callable|null, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1615
1616 5
        $exists = [];
1617
1618
        return $this->reject(function ($item, $key) use ($callback, $strict, &$exists) {
1619 5
            if (in_array($id = $callback($item, $key), $exists, $strict)) {
1620 5
                return true;
1621
            }
1622
1623 5
            $exists[] = $id;
1624 5
        });
1625
    }
1626
1627
    /**
1628
     * Return only unique items from the collection array using strict comparison.
1629
     *
1630
     * @param  string|callable|null  $key
1631
     * @return static
1632
     */
1633 1
    public function uniqueStrict($key = null)
1634
    {
1635 1
        return $this->unique($key, true);
1636
    }
1637
1638
    /**
1639
     * Reset the keys on the underlying array.
1640
     *
1641
     * @return static
1642
     */
1643 32
    public function values()
1644
    {
1645 32
        return new static(array_values($this->items));
1646
    }
1647
1648
    /**
1649
     * Get a value retrieving callback.
1650
     *
1651
     * @param  string  $value
1652
     * @return callable
1653
     */
1654 33
    protected function valueRetriever($value)
1655
    {
1656 33
        if ($this->useAsCallable($value)) {
1657 23
            return $value;
1658
        }
1659
1660
        return function ($item) use ($value) {
1661 18
            return data_get($item, $value);
1662 19
        };
1663
    }
1664
1665
    /**
1666
     * Zip the collection together with one or more arrays.
1667
     *
1668
     * e.g. new Collection([1, 2, 3])->zip([4, 5, 6]);
1669
     *      => [[1, 4], [2, 5], [3, 6]]
1670
     *
1671
     * @param  mixed ...$items
1672
     * @return static
1673
     */
1674 1
    public function zip($items)
0 ignored issues
show
Unused Code introduced by
The parameter $items is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1675
    {
1676
        $arrayableItems = array_map(function ($items) {
1677 1
            return $this->getArrayableItems($items);
1678 1
        }, func_get_args());
1679
1680
        $params = array_merge([function () {
1681 1
            return new static(func_get_args());
1682 1
        }, $this->items], $arrayableItems);
1683
1684 1
        return new static(call_user_func_array('array_map', $params));
1685
    }
1686
1687
    /**
1688
     * Pad collection to the specified length with a value.
1689
     *
1690
     * @param  int  $size
1691
     * @param  mixed  $value
1692
     * @return static
1693
     */
1694 1
    public function pad($size, $value)
1695
    {
1696 1
        return new static(array_pad($this->items, $size, $value));
1697
    }
1698
1699
    /**
1700
     * Get the collection of items as a plain array.
1701
     *
1702
     * @return array
1703
     */
1704 49
    public function toArray()
1705
    {
1706
        return array_map(function ($value) {
1707 46
            return $value instanceof Arrayable ? $value->toArray() : $value;
1708 49
        }, $this->items);
1709
    }
1710
1711
    /**
1712
     * Convert the object into something JSON serializable.
1713
     *
1714
     * @return array
1715
     */
1716 2
    public function jsonSerialize()
1717
    {
1718
        return array_map(function ($value) {
1719 2
            if ($value instanceof JsonSerializable) {
1720 2
                return $value->jsonSerialize();
1721 2
            } elseif ($value instanceof Jsonable) {
1722 1
                return json_decode($value->toJson(), true);
1723 2
            } elseif ($value instanceof Arrayable) {
1724 2
                return $value->toArray();
1725
            }
1726
1727 1
            return $value;
1728 2
        }, $this->items);
1729
    }
1730
1731
    /**
1732
     * Get the collection of items as JSON.
1733
     *
1734
     * @param  int  $options
1735
     * @return string
1736
     */
1737 2
    public function toJson($options = 0)
1738
    {
1739 2
        return json_encode($this->jsonSerialize(), $options);
1740
    }
1741
1742
    /**
1743
     * Get an iterator for the items.
1744
     *
1745
     * @return \ArrayIterator
1746
     */
1747 5
    public function getIterator()
1748
    {
1749 5
        return new ArrayIterator($this->items);
1750
    }
1751
1752
    /**
1753
     * Get a CachingIterator instance.
1754
     *
1755
     * @param  int  $flags
1756
     * @return \CachingIterator
1757
     */
1758 1
    public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING)
1759
    {
1760 1
        return new CachingIterator($this->getIterator(), $flags);
1761
    }
1762
1763
    /**
1764
     * Count the number of items in the collection.
1765
     *
1766
     * @return int
1767
     */
1768 22
    public function count()
1769
    {
1770 22
        return count($this->items);
1771
    }
1772
1773
    /**
1774
     * Get a base Support collection instance from this collection.
1775
     *
1776
     * @return \IlluminateAgnostic\Str\Support\Collection
1777
     */
1778
    public function toBase()
1779
    {
1780
        return new self($this);
1781
    }
1782
1783
    /**
1784
     * Determine if an item exists at an offset.
1785
     *
1786
     * @param  mixed  $key
1787
     * @return bool
1788
     */
1789 16
    public function offsetExists($key)
1790
    {
1791 16
        return array_key_exists($key, $this->items);
1792
    }
1793
1794
    /**
1795
     * Get an item at a given offset.
1796
     *
1797
     * @param  mixed  $key
1798
     * @return mixed
1799
     */
1800 18
    public function offsetGet($key)
1801
    {
1802 18
        return $this->items[$key];
1803
    }
1804
1805
    /**
1806
     * Set the item at a given offset.
1807
     *
1808
     * @param  mixed  $key
1809
     * @param  mixed  $value
1810
     * @return void
1811
     */
1812 31
    public function offsetSet($key, $value)
1813
    {
1814 31
        if (is_null($key)) {
1815 16
            $this->items[] = $value;
1816
        } else {
1817 17
            $this->items[$key] = $value;
1818
        }
1819 31
    }
1820
1821
    /**
1822
     * Unset the item at a given offset.
1823
     *
1824
     * @param  string  $key
1825
     * @return void
1826
     */
1827 4
    public function offsetUnset($key)
1828
    {
1829 4
        unset($this->items[$key]);
1830 4
    }
1831
1832
    /**
1833
     * Convert the collection to its string representation.
1834
     *
1835
     * @return string
1836
     */
1837 1
    public function __toString()
1838
    {
1839 1
        return $this->toJson();
1840
    }
1841
1842
    /**
1843
     * Results array of items from Collection or Arrayable.
1844
     *
1845
     * @param  mixed  $items
1846
     * @return array
1847
     */
1848 216
    protected function getArrayableItems($items)
1849
    {
1850 216
        if (is_array($items)) {
1851 210
            return $items;
1852 35
        } elseif ($items instanceof self) {
1853 20
            return $items->all();
1854 16
        } elseif ($items instanceof Arrayable) {
1855 1
            return $items->toArray();
1856 16
        } elseif ($items instanceof Jsonable) {
1857 1
            return json_decode($items->toJson(), true);
1858 16
        } elseif ($items instanceof JsonSerializable) {
1859 1
            return $items->jsonSerialize();
1860 15
        } elseif ($items instanceof Traversable) {
1861 2
            return iterator_to_array($items);
1862
        }
1863
1864 13
        return (array) $items;
1865
    }
1866
1867
    /**
1868
     * Add a method to the list of proxied methods.
1869
     *
1870
     * @param  string  $method
1871
     * @return void
1872
     */
1873 1
    public static function proxy($method)
1874
    {
1875 1
        static::$proxies[] = $method;
1876 1
    }
1877
1878
    /**
1879
     * Dynamically access collection proxies.
1880
     *
1881
     * @param  string  $key
1882
     * @return mixed
1883
     *
1884
     * @throws \Exception
1885
     */
1886 15
    public function __get($key)
1887
    {
1888 15
        if (! in_array($key, static::$proxies)) {
1889 1
            throw new Exception("Property [{$key}] does not exist on this collection instance.");
1890
        }
1891
1892 14
        return new HigherOrderCollectionProxy($this, $key);
1893
    }
1894
}
1895