Vous êtes connecté en tant que anonymous Se Deconnecter
Browse code

Application modulaire fonctionnelle !

Emmanuel ROY authored on 12/08/2019 15:10:25
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,2165 +0,0 @@
1
-<?php
2
-
3
-namespace Illuminate\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 Illuminate\Support\Traits\Macroable;
15
-use Illuminate\Contracts\Support\Jsonable;
16
-use Symfony\Component\VarDumper\VarDumper;
17
-use Illuminate\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 implements ArrayAccess, Arrayable, Countable, IteratorAggregate, Jsonable, JsonSerializable
41
-{
42
-    use Macroable;
43
-
44
-    /**
45
-     * The items contained in the collection.
46
-     *
47
-     * @var array
48
-     */
49
-    protected $items = [];
50
-
51
-    /**
52
-     * The methods that can be proxied.
53
-     *
54
-     * @var array
55
-     */
56
-    protected static $proxies = [
57
-        'average', 'avg', 'contains', 'each', 'every', 'filter', 'first',
58
-        'flatMap', 'groupBy', 'keyBy', 'map', 'max', 'min', 'partition',
59
-        'reject', 'some', 'sortBy', 'sortByDesc', 'sum', 'unique',
60
-    ];
61
-
62
-    /**
63
-     * Create a new collection.
64
-     *
65
-     * @param  mixed  $items
66
-     * @return void
67
-     */
68
-    public function __construct($items = [])
69
-    {
70
-        $this->items = $this->getArrayableItems($items);
71
-    }
72
-
73
-    /**
74
-     * Create a new collection instance if the value isn't one already.
75
-     *
76
-     * @param  mixed  $items
77
-     * @return static
78
-     */
79
-    public static function make($items = [])
80
-    {
81
-        return new static($items);
82
-    }
83
-
84
-    /**
85
-     * Wrap the given value in a collection if applicable.
86
-     *
87
-     * @param  mixed  $value
88
-     * @return static
89
-     */
90
-    public static function wrap($value)
91
-    {
92
-        return $value instanceof self
93
-            ? new static($value)
94
-            : new static(Arr::wrap($value));
95
-    }
96
-
97
-    /**
98
-     * Get the underlying items from the given collection if applicable.
99
-     *
100
-     * @param  array|static  $value
101
-     * @return array
102
-     */
103
-    public static function unwrap($value)
104
-    {
105
-        return $value instanceof self ? $value->all() : $value;
106
-    }
107
-
108
-    /**
109
-     * Create a new collection by invoking the callback a given amount of times.
110
-     *
111
-     * @param  int  $number
112
-     * @param  callable  $callback
113
-     * @return static
114
-     */
115
-    public static function times($number, callable $callback = null)
116
-    {
117
-        if ($number < 1) {
118
-            return new static;
119
-        }
120
-
121
-        if (is_null($callback)) {
122
-            return new static(range(1, $number));
123
-        }
124
-
125
-        return (new static(range(1, $number)))->map($callback);
126
-    }
127
-
128
-    /**
129
-     * Get all of the items in the collection.
130
-     *
131
-     * @return array
132
-     */
133
-    public function all()
134
-    {
135
-        return $this->items;
136
-    }
137
-
138
-    /**
139
-     * Get the average value of a given key.
140
-     *
141
-     * @param  callable|string|null  $callback
142
-     * @return mixed
143
-     */
144
-    public function avg($callback = null)
145
-    {
146
-        $callback = $this->valueRetriever($callback);
147
-
148
-        $items = $this->map(function ($value) use ($callback) {
149
-            return $callback($value);
150
-        })->filter(function ($value) {
151
-            return ! is_null($value);
152
-        });
153
-
154
-        if ($count = $items->count()) {
155
-            return $items->sum() / $count;
156
-        }
157
-    }
158
-
159
-    /**
160
-     * Alias for the "avg" method.
161
-     *
162
-     * @param  callable|string|null  $callback
163
-     * @return mixed
164
-     */
165
-    public function average($callback = null)
166
-    {
167
-        return $this->avg($callback);
168
-    }
169
-
170
-    /**
171
-     * Get the median of a given key.
172
-     *
173
-     * @param  string|array|null $key
174
-     * @return mixed
175
-     */
176
-    public function median($key = null)
177
-    {
178
-        $values = (isset($key) ? $this->pluck($key) : $this)
179
-            ->filter(function ($item) {
180
-                return ! is_null($item);
181
-            })->sort()->values();
182
-
183
-        $count = $values->count();
184
-
185
-        if ($count === 0) {
186
-            return;
187
-        }
188
-
189
-        $middle = (int) ($count / 2);
190
-
191
-        if ($count % 2) {
192
-            return $values->get($middle);
193
-        }
194
-
195
-        return (new static([
196
-            $values->get($middle - 1), $values->get($middle),
197
-        ]))->average();
198
-    }
199
-
200
-    /**
201
-     * Get the mode of a given key.
202
-     *
203
-     * @param  string|array|null  $key
204
-     * @return array|null
205
-     */
206
-    public function mode($key = null)
207
-    {
208
-        if ($this->count() === 0) {
209
-            return;
210
-        }
211
-
212
-        $collection = isset($key) ? $this->pluck($key) : $this;
213
-
214
-        $counts = new self;
215
-
216
-        $collection->each(function ($value) use ($counts) {
217
-            $counts[$value] = isset($counts[$value]) ? $counts[$value] + 1 : 1;
218
-        });
219
-
220
-        $sorted = $counts->sort();
221
-
222
-        $highestValue = $sorted->last();
223
-
224
-        return $sorted->filter(function ($value) use ($highestValue) {
225
-            return $value == $highestValue;
226
-        })->sort()->keys()->all();
227
-    }
228
-
229
-    /**
230
-     * Collapse the collection of items into a single array.
231
-     *
232
-     * @return static
233
-     */
234
-    public function collapse()
235
-    {
236
-        return new static(Arr::collapse($this->items));
237
-    }
238
-
239
-    /**
240
-     * Alias for the "contains" method.
241
-     *
242
-     * @param  mixed  $key
243
-     * @param  mixed  $operator
244
-     * @param  mixed  $value
245
-     * @return bool
246
-     */
247
-    public function some($key, $operator = null, $value = null)
248
-    {
249
-        return $this->contains(...func_get_args());
250
-    }
251
-
252
-    /**
253
-     * Determine if an item exists in the collection.
254
-     *
255
-     * @param  mixed  $key
256
-     * @param  mixed  $operator
257
-     * @param  mixed  $value
258
-     * @return bool
259
-     */
260
-    public function contains($key, $operator = null, $value = null)
261
-    {
262
-        if (func_num_args() === 1) {
263
-            if ($this->useAsCallable($key)) {
264
-                $placeholder = new stdClass;
265
-
266
-                return $this->first($key, $placeholder) !== $placeholder;
267
-            }
268
-
269
-            return in_array($key, $this->items);
270
-        }
271
-
272
-        return $this->contains($this->operatorForWhere(...func_get_args()));
273
-    }
274
-
275
-    /**
276
-     * Determine if an item exists in the collection using strict comparison.
277
-     *
278
-     * @param  mixed  $key
279
-     * @param  mixed  $value
280
-     * @return bool
281
-     */
282
-    public function containsStrict($key, $value = null)
283
-    {
284
-        if (func_num_args() === 2) {
285
-            return $this->contains(function ($item) use ($key, $value) {
286
-                return data_get($item, $key) === $value;
287
-            });
288
-        }
289
-
290
-        if ($this->useAsCallable($key)) {
291
-            return ! is_null($this->first($key));
292
-        }
293
-
294
-        return in_array($key, $this->items, true);
295
-    }
296
-
297
-    /**
298
-     * Cross join with the given lists, returning all possible permutations.
299
-     *
300
-     * @param  mixed  ...$lists
301
-     * @return static
302
-     */
303
-    public function crossJoin(...$lists)
304
-    {
305
-        return new static(Arr::crossJoin(
306
-            $this->items, ...array_map([$this, 'getArrayableItems'], $lists)
307
-        ));
308
-    }
309
-
310
-    /**
311
-     * Dump the collection and end the script.
312
-     *
313
-     * @param  mixed  ...$args
314
-     * @return void
315
-     */
316
-    public function dd(...$args)
317
-    {
318
-        call_user_func_array([$this, 'dump'], $args);
319
-
320
-        die(1);
321
-    }
322
-
323
-    /**
324
-     * Dump the collection.
325
-     *
326
-     * @return $this
327
-     */
328
-    public function dump()
329
-    {
330
-        (new static(func_get_args()))
331
-            ->push($this)
332
-            ->each(function ($item) {
333
-                VarDumper::dump($item);
334
-            });
335
-
336
-        return $this;
337
-    }
338
-
339
-    /**
340
-     * Get the items in the collection that are not present in the given items.
341
-     *
342
-     * @param  mixed  $items
343
-     * @return static
344
-     */
345
-    public function diff($items)
346
-    {
347
-        return new static(array_diff($this->items, $this->getArrayableItems($items)));
348
-    }
349
-
350
-    /**
351
-     * Get the items in the collection that are not present in the given items.
352
-     *
353
-     * @param  mixed  $items
354
-     * @param  callable  $callback
355
-     * @return static
356
-     */
357
-    public function diffUsing($items, callable $callback)
358
-    {
359
-        return new static(array_udiff($this->items, $this->getArrayableItems($items), $callback));
360
-    }
361
-
362
-    /**
363
-     * Get the items in the collection whose keys and values are not present in the given items.
364
-     *
365
-     * @param  mixed  $items
366
-     * @return static
367
-     */
368
-    public function diffAssoc($items)
369
-    {
370
-        return new static(array_diff_assoc($this->items, $this->getArrayableItems($items)));
371
-    }
372
-
373
-    /**
374
-     * Get the items in the collection whose keys and values are not present in the given items.
375
-     *
376
-     * @param  mixed  $items
377
-     * @param  callable  $callback
378
-     * @return static
379
-     */
380
-    public function diffAssocUsing($items, callable $callback)
381
-    {
382
-        return new static(array_diff_uassoc($this->items, $this->getArrayableItems($items), $callback));
383
-    }
384
-
385
-    /**
386
-     * Get the items in the collection whose keys are not present in the given items.
387
-     *
388
-     * @param  mixed  $items
389
-     * @return static
390
-     */
391
-    public function diffKeys($items)
392
-    {
393
-        return new static(array_diff_key($this->items, $this->getArrayableItems($items)));
394
-    }
395
-
396
-    /**
397
-     * Get the items in the collection whose keys are not present in the given items.
398
-     *
399
-     * @param  mixed   $items
400
-     * @param  callable  $callback
401
-     * @return static
402
-     */
403
-    public function diffKeysUsing($items, callable $callback)
404
-    {
405
-        return new static(array_diff_ukey($this->items, $this->getArrayableItems($items), $callback));
406
-    }
407
-
408
-    /**
409
-     * Retrieve duplicate items from the collection.
410
-     *
411
-     * @param  callable|null  $callback
412
-     * @param  bool  $strict
413
-     * @return static
414
-     */
415
-    public function duplicates($callback = null, $strict = false)
416
-    {
417
-        $items = $this->map($this->valueRetriever($callback));
418
-
419
-        $uniqueItems = $items->unique(null, $strict);
420
-
421
-        $compare = $this->duplicateComparator($strict);
422
-
423
-        $duplicates = new static;
424
-
425
-        foreach ($items as $key => $value) {
426
-            if ($uniqueItems->isNotEmpty() && $compare($value, $uniqueItems->first())) {
427
-                $uniqueItems->shift();
428
-            } else {
429
-                $duplicates[$key] = $value;
430
-            }
431
-        }
432
-
433
-        return $duplicates;
434
-    }
435
-
436
-    /**
437
-     * Retrieve duplicate items from the collection using strict comparison.
438
-     *
439
-     * @param  callable|null  $callback
440
-     * @return static
441
-     */
442
-    public function duplicatesStrict($callback = null)
443
-    {
444
-        return $this->duplicates($callback, true);
445
-    }
446
-
447
-    /**
448
-     * Get the comparison function to detect duplicates.
449
-     *
450
-     * @param  bool  $strict
451
-     * @return \Closure
452
-     */
453
-    protected function duplicateComparator($strict)
454
-    {
455
-        if ($strict) {
456
-            return function ($a, $b) {
457
-                return $a === $b;
458
-            };
459
-        }
460
-
461
-        return function ($a, $b) {
462
-            return $a == $b;
463
-        };
464
-    }
465
-
466
-    /**
467
-     * Execute a callback over each item.
468
-     *
469
-     * @param  callable  $callback
470
-     * @return $this
471
-     */
472
-    public function each(callable $callback)
473
-    {
474
-        foreach ($this->items as $key => $item) {
475
-            if ($callback($item, $key) === false) {
476
-                break;
477
-            }
478
-        }
479
-
480
-        return $this;
481
-    }
482
-
483
-    /**
484
-     * Execute a callback over each nested chunk of items.
485
-     *
486
-     * @param  callable  $callback
487
-     * @return static
488
-     */
489
-    public function eachSpread(callable $callback)
490
-    {
491
-        return $this->each(function ($chunk, $key) use ($callback) {
492
-            $chunk[] = $key;
493
-
494
-            return $callback(...$chunk);
495
-        });
496
-    }
497
-
498
-    /**
499
-     * Determine if all items in the collection pass the given test.
500
-     *
501
-     * @param  string|callable  $key
502
-     * @param  mixed  $operator
503
-     * @param  mixed  $value
504
-     * @return bool
505
-     */
506
-    public function every($key, $operator = null, $value = null)
507
-    {
508
-        if (func_num_args() === 1) {
509
-            $callback = $this->valueRetriever($key);
510
-
511
-            foreach ($this->items as $k => $v) {
512
-                if (! $callback($v, $k)) {
513
-                    return false;
514
-                }
515
-            }
516
-
517
-            return true;
518
-        }
519
-
520
-        return $this->every($this->operatorForWhere(...func_get_args()));
521
-    }
522
-
523
-    /**
524
-     * Get all items except for those with the specified keys.
525
-     *
526
-     * @param  \Illuminate\Support\Collection|mixed  $keys
527
-     * @return static
528
-     */
529
-    public function except($keys)
530
-    {
531
-        if ($keys instanceof self) {
532
-            $keys = $keys->all();
533
-        } elseif (! is_array($keys)) {
534
-            $keys = func_get_args();
535
-        }
536
-
537
-        return new static(Arr::except($this->items, $keys));
538
-    }
539
-
540
-    /**
541
-     * Run a filter over each of the items.
542
-     *
543
-     * @param  callable|null  $callback
544
-     * @return static
545
-     */
546
-    public function filter(callable $callback = null)
547
-    {
548
-        if ($callback) {
549
-            return new static(Arr::where($this->items, $callback));
550
-        }
551
-
552
-        return new static(array_filter($this->items));
553
-    }
554
-
555
-    /**
556
-     * Apply the callback if the value is truthy.
557
-     *
558
-     * @param  bool  $value
559
-     * @param  callable  $callback
560
-     * @param  callable  $default
561
-     * @return static|mixed
562
-     */
563
-    public function when($value, callable $callback, callable $default = null)
564
-    {
565
-        if ($value) {
566
-            return $callback($this, $value);
567
-        } elseif ($default) {
568
-            return $default($this, $value);
569
-        }
570
-
571
-        return $this;
572
-    }
573
-
574
-    /**
575
-     * Apply the callback if the collection is empty.
576
-     *
577
-     * @param  callable  $callback
578
-     * @param  callable  $default
579
-     * @return static|mixed
580
-     */
581
-    public function whenEmpty(callable $callback, callable $default = null)
582
-    {
583
-        return $this->when($this->isEmpty(), $callback, $default);
584
-    }
585
-
586
-    /**
587
-     * Apply the callback if the collection is not empty.
588
-     *
589
-     * @param  callable  $callback
590
-     * @param  callable  $default
591
-     * @return static|mixed
592
-     */
593
-    public function whenNotEmpty(callable $callback, callable $default = null)
594
-    {
595
-        return $this->when($this->isNotEmpty(), $callback, $default);
596
-    }
597
-
598
-    /**
599
-     * Apply the callback if the value is falsy.
600
-     *
601
-     * @param  bool  $value
602
-     * @param  callable  $callback
603
-     * @param  callable  $default
604
-     * @return static|mixed
605
-     */
606
-    public function unless($value, callable $callback, callable $default = null)
607
-    {
608
-        return $this->when(! $value, $callback, $default);
609
-    }
610
-
611
-    /**
612
-     * Apply the callback unless the collection is empty.
613
-     *
614
-     * @param  callable  $callback
615
-     * @param  callable  $default
616
-     * @return static|mixed
617
-     */
618
-    public function unlessEmpty(callable $callback, callable $default = null)
619
-    {
620
-        return $this->whenNotEmpty($callback, $default);
621
-    }
622
-
623
-    /**
624
-     * Apply the callback unless the collection is not empty.
625
-     *
626
-     * @param  callable  $callback
627
-     * @param  callable  $default
628
-     * @return static|mixed
629
-     */
630
-    public function unlessNotEmpty(callable $callback, callable $default = null)
631
-    {
632
-        return $this->whenEmpty($callback, $default);
633
-    }
634
-
635
-    /**
636
-     * Filter items by the given key value pair.
637
-     *
638
-     * @param  string  $key
639
-     * @param  mixed  $operator
640
-     * @param  mixed  $value
641
-     * @return static
642
-     */
643
-    public function where($key, $operator = null, $value = null)
644
-    {
645
-        return $this->filter($this->operatorForWhere(...func_get_args()));
646
-    }
647
-
648
-    /**
649
-     * Get an operator checker callback.
650
-     *
651
-     * @param  string  $key
652
-     * @param  string  $operator
653
-     * @param  mixed  $value
654
-     * @return \Closure
655
-     */
656
-    protected function operatorForWhere($key, $operator = null, $value = null)
657
-    {
658
-        if (func_num_args() === 1) {
659
-            $value = true;
660
-
661
-            $operator = '=';
662
-        }
663
-
664
-        if (func_num_args() === 2) {
665
-            $value = $operator;
666
-
667
-            $operator = '=';
668
-        }
669
-
670
-        return function ($item) use ($key, $operator, $value) {
671
-            $retrieved = data_get($item, $key);
672
-
673
-            $strings = array_filter([$retrieved, $value], function ($value) {
674
-                return is_string($value) || (is_object($value) && method_exists($value, '__toString'));
675
-            });
676
-
677
-            if (count($strings) < 2 && count(array_filter([$retrieved, $value], 'is_object')) == 1) {
678
-                return in_array($operator, ['!=', '<>', '!==']);
679
-            }
680
-
681
-            switch ($operator) {
682
-                default:
683
-                case '=':
684
-                case '==':  return $retrieved == $value;
685
-                case '!=':
686
-                case '<>':  return $retrieved != $value;
687
-                case '<':   return $retrieved < $value;
688
-                case '>':   return $retrieved > $value;
689
-                case '<=':  return $retrieved <= $value;
690
-                case '>=':  return $retrieved >= $value;
691
-                case '===': return $retrieved === $value;
692
-                case '!==': return $retrieved !== $value;
693
-            }
694
-        };
695
-    }
696
-
697
-    /**
698
-     * Filter items by the given key value pair using strict comparison.
699
-     *
700
-     * @param  string  $key
701
-     * @param  mixed  $value
702
-     * @return static
703
-     */
704
-    public function whereStrict($key, $value)
705
-    {
706
-        return $this->where($key, '===', $value);
707
-    }
708
-
709
-    /**
710
-     * Filter items by the given key value pair.
711
-     *
712
-     * @param  string  $key
713
-     * @param  mixed  $values
714
-     * @param  bool  $strict
715
-     * @return static
716
-     */
717
-    public function whereIn($key, $values, $strict = false)
718
-    {
719
-        $values = $this->getArrayableItems($values);
720
-
721
-        return $this->filter(function ($item) use ($key, $values, $strict) {
722
-            return in_array(data_get($item, $key), $values, $strict);
723
-        });
724
-    }
725
-
726
-    /**
727
-     * Filter items by the given key value pair using strict comparison.
728
-     *
729
-     * @param  string  $key
730
-     * @param  mixed  $values
731
-     * @return static
732
-     */
733
-    public function whereInStrict($key, $values)
734
-    {
735
-        return $this->whereIn($key, $values, true);
736
-    }
737
-
738
-    /**
739
-     * Filter items such that the value of the given key is between the given values.
740
-     *
741
-     * @param  string  $key
742
-     * @param  array  $values
743
-     * @return static
744
-     */
745
-    public function whereBetween($key, $values)
746
-    {
747
-        return $this->where($key, '>=', reset($values))->where($key, '<=', end($values));
748
-    }
749
-
750
-    /**
751
-     * Filter items such that the value of the given key is not between the given values.
752
-     *
753
-     * @param  string  $key
754
-     * @param  array  $values
755
-     * @return static
756
-     */
757
-    public function whereNotBetween($key, $values)
758
-    {
759
-        return $this->filter(function ($item) use ($key, $values) {
760
-            return data_get($item, $key) < reset($values) || data_get($item, $key) > end($values);
761
-        });
762
-    }
763
-
764
-    /**
765
-     * Filter items by the given key value pair.
766
-     *
767
-     * @param  string  $key
768
-     * @param  mixed  $values
769
-     * @param  bool  $strict
770
-     * @return static
771
-     */
772
-    public function whereNotIn($key, $values, $strict = false)
773
-    {
774
-        $values = $this->getArrayableItems($values);
775
-
776
-        return $this->reject(function ($item) use ($key, $values, $strict) {
777
-            return in_array(data_get($item, $key), $values, $strict);
778
-        });
779
-    }
780
-
781
-    /**
782
-     * Filter items by the given key value pair using strict comparison.
783
-     *
784
-     * @param  string  $key
785
-     * @param  mixed  $values
786
-     * @return static
787
-     */
788
-    public function whereNotInStrict($key, $values)
789
-    {
790
-        return $this->whereNotIn($key, $values, true);
791
-    }
792
-
793
-    /**
794
-     * Filter the items, removing any items that don't match the given type.
795
-     *
796
-     * @param  string  $type
797
-     * @return static
798
-     */
799
-    public function whereInstanceOf($type)
800
-    {
801
-        return $this->filter(function ($value) use ($type) {
802
-            return $value instanceof $type;
803
-        });
804
-    }
805
-
806
-    /**
807
-     * Get the first item from the collection passing the given truth test.
808
-     *
809
-     * @param  callable|null  $callback
810
-     * @param  mixed  $default
811
-     * @return mixed
812
-     */
813
-    public function first(callable $callback = null, $default = null)
814
-    {
815
-        return Arr::first($this->items, $callback, $default);
816
-    }
817
-
818
-    /**
819
-     * Get the first item by the given key value pair.
820
-     *
821
-     * @param  string  $key
822
-     * @param  mixed  $operator
823
-     * @param  mixed  $value
824
-     * @return mixed
825
-     */
826
-    public function firstWhere($key, $operator = null, $value = null)
827
-    {
828
-        return $this->first($this->operatorForWhere(...func_get_args()));
829
-    }
830
-
831
-    /**
832
-     * Get a flattened array of the items in the collection.
833
-     *
834
-     * @param  int  $depth
835
-     * @return static
836
-     */
837
-    public function flatten($depth = INF)
838
-    {
839
-        return new static(Arr::flatten($this->items, $depth));
840
-    }
841
-
842
-    /**
843
-     * Flip the items in the collection.
844
-     *
845
-     * @return static
846
-     */
847
-    public function flip()
848
-    {
849
-        return new static(array_flip($this->items));
850
-    }
851
-
852
-    /**
853
-     * Remove an item from the collection by key.
854
-     *
855
-     * @param  string|array  $keys
856
-     * @return $this
857
-     */
858
-    public function forget($keys)
859
-    {
860
-        foreach ((array) $keys as $key) {
861
-            $this->offsetUnset($key);
862
-        }
863
-
864
-        return $this;
865
-    }
866
-
867
-    /**
868
-     * Get an item from the collection by key.
869
-     *
870
-     * @param  mixed  $key
871
-     * @param  mixed  $default
872
-     * @return mixed
873
-     */
874
-    public function get($key, $default = null)
875
-    {
876
-        if ($this->offsetExists($key)) {
877
-            return $this->items[$key];
878
-        }
879
-
880
-        return value($default);
881
-    }
882
-
883
-    /**
884
-     * Group an associative array by a field or using a callback.
885
-     *
886
-     * @param  array|callable|string  $groupBy
887
-     * @param  bool  $preserveKeys
888
-     * @return static
889
-     */
890
-    public function groupBy($groupBy, $preserveKeys = false)
891
-    {
892
-        if (is_array($groupBy)) {
893
-            $nextGroups = $groupBy;
894
-
895
-            $groupBy = array_shift($nextGroups);
896
-        }
897
-
898
-        $groupBy = $this->valueRetriever($groupBy);
899
-
900
-        $results = [];
901
-
902
-        foreach ($this->items as $key => $value) {
903
-            $groupKeys = $groupBy($value, $key);
904
-
905
-            if (! is_array($groupKeys)) {
906
-                $groupKeys = [$groupKeys];
907
-            }
908
-
909
-            foreach ($groupKeys as $groupKey) {
910
-                $groupKey = is_bool($groupKey) ? (int) $groupKey : $groupKey;
911
-
912
-                if (! array_key_exists($groupKey, $results)) {
913
-                    $results[$groupKey] = new static;
914
-                }
915
-
916
-                $results[$groupKey]->offsetSet($preserveKeys ? $key : null, $value);
917
-            }
918
-        }
919
-
920
-        $result = new static($results);
921
-
922
-        if (! empty($nextGroups)) {
923
-            return $result->map->groupBy($nextGroups, $preserveKeys);
924
-        }
925
-
926
-        return $result;
927
-    }
928
-
929
-    /**
930
-     * Key an associative array by a field or using a callback.
931
-     *
932
-     * @param  callable|string  $keyBy
933
-     * @return static
934
-     */
935
-    public function keyBy($keyBy)
936
-    {
937
-        $keyBy = $this->valueRetriever($keyBy);
938
-
939
-        $results = [];
940
-
941
-        foreach ($this->items as $key => $item) {
942
-            $resolvedKey = $keyBy($item, $key);
943
-
944
-            if (is_object($resolvedKey)) {
945
-                $resolvedKey = (string) $resolvedKey;
946
-            }
947
-
948
-            $results[$resolvedKey] = $item;
949
-        }
950
-
951
-        return new static($results);
952
-    }
953
-
954
-    /**
955
-     * Determine if an item exists in the collection by key.
956
-     *
957
-     * @param  mixed  $key
958
-     * @return bool
959
-     */
960
-    public function has($key)
961
-    {
962
-        $keys = is_array($key) ? $key : func_get_args();
963
-
964
-        foreach ($keys as $value) {
965
-            if (! $this->offsetExists($value)) {
966
-                return false;
967
-            }
968
-        }
969
-
970
-        return true;
971
-    }
972
-
973
-    /**
974
-     * Concatenate values of a given key as a string.
975
-     *
976
-     * @param  string  $value
977
-     * @param  string  $glue
978
-     * @return string
979
-     */
980
-    public function implode($value, $glue = null)
981
-    {
982
-        $first = $this->first();
983
-
984
-        if (is_array($first) || is_object($first)) {
985
-            return implode($glue, $this->pluck($value)->all());
986
-        }
987
-
988
-        return implode($value, $this->items);
989
-    }
990
-
991
-    /**
992
-     * Intersect the collection with the given items.
993
-     *
994
-     * @param  mixed  $items
995
-     * @return static
996
-     */
997
-    public function intersect($items)
998
-    {
999
-        return new static(array_intersect($this->items, $this->getArrayableItems($items)));
1000
-    }
1001
-
1002
-    /**
1003
-     * Intersect the collection with the given items by key.
1004
-     *
1005
-     * @param  mixed  $items
1006
-     * @return static
1007
-     */
1008
-    public function intersectByKeys($items)
1009
-    {
1010
-        return new static(array_intersect_key(
1011
-            $this->items, $this->getArrayableItems($items)
1012
-        ));
1013
-    }
1014
-
1015
-    /**
1016
-     * Determine if the collection is empty or not.
1017
-     *
1018
-     * @return bool
1019
-     */
1020
-    public function isEmpty()
1021
-    {
1022
-        return empty($this->items);
1023
-    }
1024
-
1025
-    /**
1026
-     * Determine if the collection is not empty.
1027
-     *
1028
-     * @return bool
1029
-     */
1030
-    public function isNotEmpty()
1031
-    {
1032
-        return ! $this->isEmpty();
1033
-    }
1034
-
1035
-    /**
1036
-     * Determine if the given value is callable, but not a string.
1037
-     *
1038
-     * @param  mixed  $value
1039
-     * @return bool
1040
-     */
1041
-    protected function useAsCallable($value)
1042
-    {
1043
-        return ! is_string($value) && is_callable($value);
1044
-    }
1045
-
1046
-    /**
1047
-     * Join all items from the collection using a string. The final items can use a separate glue string.
1048
-     *
1049
-     * @param  string  $glue
1050
-     * @param  string  $finalGlue
1051
-     * @return string
1052
-     */
1053
-    public function join($glue, $finalGlue = '')
1054
-    {
1055
-        if ($finalGlue === '') {
1056
-            return $this->implode($glue);
1057
-        }
1058
-
1059
-        $count = $this->count();
1060
-
1061
-        if ($count === 0) {
1062
-            return '';
1063
-        }
1064
-
1065
-        if ($count === 1) {
1066
-            return $this->last();
1067
-        }
1068
-
1069
-        $collection = new static($this->items);
1070
-
1071
-        $finalItem = $collection->pop();
1072
-
1073
-        return $collection->implode($glue).$finalGlue.$finalItem;
1074
-    }
1075
-
1076
-    /**
1077
-     * Get the keys of the collection items.
1078
-     *
1079
-     * @return static
1080
-     */
1081
-    public function keys()
1082
-    {
1083
-        return new static(array_keys($this->items));
1084
-    }
1085
-
1086
-    /**
1087
-     * Get the last item from the collection.
1088
-     *
1089
-     * @param  callable|null  $callback
1090
-     * @param  mixed  $default
1091
-     * @return mixed
1092
-     */
1093
-    public function last(callable $callback = null, $default = null)
1094
-    {
1095
-        return Arr::last($this->items, $callback, $default);
1096
-    }
1097
-
1098
-    /**
1099
-     * Get the values of a given key.
1100
-     *
1101
-     * @param  string|array  $value
1102
-     * @param  string|null  $key
1103
-     * @return static
1104
-     */
1105
-    public function pluck($value, $key = null)
1106
-    {
1107
-        return new static(Arr::pluck($this->items, $value, $key));
1108
-    }
1109
-
1110
-    /**
1111
-     * Run a map over each of the items.
1112
-     *
1113
-     * @param  callable  $callback
1114
-     * @return static
1115
-     */
1116
-    public function map(callable $callback)
1117
-    {
1118
-        $keys = array_keys($this->items);
1119
-
1120
-        $items = array_map($callback, $this->items, $keys);
1121
-
1122
-        return new static(array_combine($keys, $items));
1123
-    }
1124
-
1125
-    /**
1126
-     * Run a map over each nested chunk of items.
1127
-     *
1128
-     * @param  callable  $callback
1129
-     * @return static
1130
-     */
1131
-    public function mapSpread(callable $callback)
1132
-    {
1133
-        return $this->map(function ($chunk, $key) use ($callback) {
1134
-            $chunk[] = $key;
1135
-
1136
-            return $callback(...$chunk);
1137
-        });
1138
-    }
1139
-
1140
-    /**
1141
-     * Run a dictionary map over the items.
1142
-     *
1143
-     * The callback should return an associative array with a single key/value pair.
1144
-     *
1145
-     * @param  callable  $callback
1146
-     * @return static
1147
-     */
1148
-    public function mapToDictionary(callable $callback)
1149
-    {
1150
-        $dictionary = [];
1151
-
1152
-        foreach ($this->items as $key => $item) {
1153
-            $pair = $callback($item, $key);
1154
-
1155
-            $key = key($pair);
1156
-
1157
-            $value = reset($pair);
1158
-
1159
-            if (! isset($dictionary[$key])) {
1160
-                $dictionary[$key] = [];
1161
-            }
1162
-
1163
-            $dictionary[$key][] = $value;
1164
-        }
1165
-
1166
-        return new static($dictionary);
1167
-    }
1168
-
1169
-    /**
1170
-     * Run a grouping map over the items.
1171
-     *
1172
-     * The callback should return an associative array with a single key/value pair.
1173
-     *
1174
-     * @param  callable  $callback
1175
-     * @return static
1176
-     */
1177
-    public function mapToGroups(callable $callback)
1178
-    {
1179
-        $groups = $this->mapToDictionary($callback);
1180
-
1181
-        return $groups->map([$this, 'make']);
1182
-    }
1183
-
1184
-    /**
1185
-     * Run an associative map over each of the items.
1186
-     *
1187
-     * The callback should return an associative array with a single key/value pair.
1188
-     *
1189
-     * @param  callable  $callback
1190
-     * @return static
1191
-     */
1192
-    public function mapWithKeys(callable $callback)
1193
-    {
1194
-        $result = [];
1195
-
1196
-        foreach ($this->items as $key => $value) {
1197
-            $assoc = $callback($value, $key);
1198
-
1199
-            foreach ($assoc as $mapKey => $mapValue) {
1200
-                $result[$mapKey] = $mapValue;
1201
-            }
1202
-        }
1203
-
1204
-        return new static($result);
1205
-    }
1206
-
1207
-    /**
1208
-     * Map a collection and flatten the result by a single level.
1209
-     *
1210
-     * @param  callable  $callback
1211
-     * @return static
1212
-     */
1213
-    public function flatMap(callable $callback)
1214
-    {
1215
-        return $this->map($callback)->collapse();
1216
-    }
1217
-
1218
-    /**
1219
-     * Map the values into a new class.
1220
-     *
1221
-     * @param  string  $class
1222
-     * @return static
1223
-     */
1224
-    public function mapInto($class)
1225
-    {
1226
-        return $this->map(function ($value, $key) use ($class) {
1227
-            return new $class($value, $key);
1228
-        });
1229
-    }
1230
-
1231
-    /**
1232
-     * Get the max value of a given key.
1233
-     *
1234
-     * @param  callable|string|null  $callback
1235
-     * @return mixed
1236
-     */
1237
-    public function max($callback = null)
1238
-    {
1239
-        $callback = $this->valueRetriever($callback);
1240
-
1241
-        return $this->filter(function ($value) {
1242
-            return ! is_null($value);
1243
-        })->reduce(function ($result, $item) use ($callback) {
1244
-            $value = $callback($item);
1245
-
1246
-            return is_null($result) || $value > $result ? $value : $result;
1247
-        });
1248
-    }
1249
-
1250
-    /**
1251
-     * Merge the collection with the given items.
1252
-     *
1253
-     * @param  mixed  $items
1254
-     * @return static
1255
-     */
1256
-    public function merge($items)
1257
-    {
1258
-        return new static(array_merge($this->items, $this->getArrayableItems($items)));
1259
-    }
1260
-
1261
-    /**
1262
-     * Recursively merge the collection with the given items.
1263
-     *
1264
-     * @param  mixed  $items
1265
-     * @return static
1266
-     */
1267
-    public function mergeRecursive($items)
1268
-    {
1269
-        return new static(array_merge_recursive($this->items, $this->getArrayableItems($items)));
1270
-    }
1271
-
1272
-    /**
1273
-     * Create a collection by using this collection for keys and another for its values.
1274
-     *
1275
-     * @param  mixed  $values
1276
-     * @return static
1277
-     */
1278
-    public function combine($values)
1279
-    {
1280
-        return new static(array_combine($this->all(), $this->getArrayableItems($values)));
1281
-    }
1282
-
1283
-    /**
1284
-     * Union the collection with the given items.
1285
-     *
1286
-     * @param  mixed  $items
1287
-     * @return static
1288
-     */
1289
-    public function union($items)
1290
-    {
1291
-        return new static($this->items + $this->getArrayableItems($items));
1292
-    }
1293
-
1294
-    /**
1295
-     * Get the min value of a given key.
1296
-     *
1297
-     * @param  callable|string|null  $callback
1298
-     * @return mixed
1299
-     */
1300
-    public function min($callback = null)
1301
-    {
1302
-        $callback = $this->valueRetriever($callback);
1303
-
1304
-        return $this->map(function ($value) use ($callback) {
1305
-            return $callback($value);
1306
-        })->filter(function ($value) {
1307
-            return ! is_null($value);
1308
-        })->reduce(function ($result, $value) {
1309
-            return is_null($result) || $value < $result ? $value : $result;
1310
-        });
1311
-    }
1312
-
1313
-    /**
1314
-     * Create a new collection consisting of every n-th element.
1315
-     *
1316
-     * @param  int  $step
1317
-     * @param  int  $offset
1318
-     * @return static
1319
-     */
1320
-    public function nth($step, $offset = 0)
1321
-    {
1322
-        $new = [];
1323
-
1324
-        $position = 0;
1325
-
1326
-        foreach ($this->items as $item) {
1327
-            if ($position % $step === $offset) {
1328
-                $new[] = $item;
1329
-            }
1330
-
1331
-            $position++;
1332
-        }
1333
-
1334
-        return new static($new);
1335
-    }
1336
-
1337
-    /**
1338
-     * Get the items with the specified keys.
1339
-     *
1340
-     * @param  mixed  $keys
1341
-     * @return static
1342
-     */
1343
-    public function only($keys)
1344
-    {
1345
-        if (is_null($keys)) {
1346
-            return new static($this->items);
1347
-        }
1348
-
1349
-        if ($keys instanceof self) {
1350
-            $keys = $keys->all();
1351
-        }
1352
-
1353
-        $keys = is_array($keys) ? $keys : func_get_args();
1354
-
1355
-        return new static(Arr::only($this->items, $keys));
1356
-    }
1357
-
1358
-    /**
1359
-     * "Paginate" the collection by slicing it into a smaller collection.
1360
-     *
1361
-     * @param  int  $page
1362
-     * @param  int  $perPage
1363
-     * @return static
1364
-     */
1365
-    public function forPage($page, $perPage)
1366
-    {
1367
-        $offset = max(0, ($page - 1) * $perPage);
1368
-
1369
-        return $this->slice($offset, $perPage);
1370
-    }
1371
-
1372
-    /**
1373
-     * Partition the collection into two arrays using the given callback or key.
1374
-     *
1375
-     * @param  callable|string  $key
1376
-     * @param  mixed  $operator
1377
-     * @param  mixed  $value
1378
-     * @return static
1379
-     */
1380
-    public function partition($key, $operator = null, $value = null)
1381
-    {
1382
-        $partitions = [new static, new static];
1383
-
1384
-        $callback = func_num_args() === 1
1385
-                ? $this->valueRetriever($key)
1386
-                : $this->operatorForWhere(...func_get_args());
1387
-
1388
-        foreach ($this->items as $key => $item) {
1389
-            $partitions[(int) ! $callback($item, $key)][$key] = $item;
1390
-        }
1391
-
1392
-        return new static($partitions);
1393
-    }
1394
-
1395
-    /**
1396
-     * Pass the collection to the given callback and return the result.
1397
-     *
1398
-     * @param  callable $callback
1399
-     * @return mixed
1400
-     */
1401
-    public function pipe(callable $callback)
1402
-    {
1403
-        return $callback($this);
1404
-    }
1405
-
1406
-    /**
1407
-     * Get and remove the last item from the collection.
1408
-     *
1409
-     * @return mixed
1410
-     */
1411
-    public function pop()
1412
-    {
1413
-        return array_pop($this->items);
1414
-    }
1415
-
1416
-    /**
1417
-     * Push an item onto the beginning of the collection.
1418
-     *
1419
-     * @param  mixed  $value
1420
-     * @param  mixed  $key
1421
-     * @return $this
1422
-     */
1423
-    public function prepend($value, $key = null)
1424
-    {
1425
-        $this->items = Arr::prepend($this->items, $value, $key);
1426
-
1427
-        return $this;
1428
-    }
1429
-
1430
-    /**
1431
-     * Push an item onto the end of the collection.
1432
-     *
1433
-     * @param  mixed  $value
1434
-     * @return $this
1435
-     */
1436
-    public function push($value)
1437
-    {
1438
-        $this->offsetSet(null, $value);
1439
-
1440
-        return $this;
1441
-    }
1442
-
1443
-    /**
1444
-     * Push all of the given items onto the collection.
1445
-     *
1446
-     * @param  iterable  $source
1447
-     * @return static
1448
-     */
1449
-    public function concat($source)
1450
-    {
1451
-        $result = new static($this);
1452
-
1453
-        foreach ($source as $item) {
1454
-            $result->push($item);
1455
-        }
1456
-
1457
-        return $result;
1458
-    }
1459
-
1460
-    /**
1461
-     * Get and remove an item from the collection.
1462
-     *
1463
-     * @param  mixed  $key
1464
-     * @param  mixed  $default
1465
-     * @return mixed
1466
-     */
1467
-    public function pull($key, $default = null)
1468
-    {
1469
-        return Arr::pull($this->items, $key, $default);
1470
-    }
1471
-
1472
-    /**
1473
-     * Put an item in the collection by key.
1474
-     *
1475
-     * @param  mixed  $key
1476
-     * @param  mixed  $value
1477
-     * @return $this
1478
-     */
1479
-    public function put($key, $value)
1480
-    {
1481
-        $this->offsetSet($key, $value);
1482
-
1483
-        return $this;
1484
-    }
1485
-
1486
-    /**
1487
-     * Get one or a specified number of items randomly from the collection.
1488
-     *
1489
-     * @param  int|null  $number
1490
-     * @return static|mixed
1491
-     *
1492
-     * @throws \InvalidArgumentException
1493
-     */
1494
-    public function random($number = null)
1495
-    {
1496
-        if (is_null($number)) {
1497
-            return Arr::random($this->items);
1498
-        }
1499
-
1500
-        return new static(Arr::random($this->items, $number));
1501
-    }
1502
-
1503
-    /**
1504
-     * Reduce the collection to a single value.
1505
-     *
1506
-     * @param  callable  $callback
1507
-     * @param  mixed  $initial
1508
-     * @return mixed
1509
-     */
1510
-    public function reduce(callable $callback, $initial = null)
1511
-    {
1512
-        return array_reduce($this->items, $callback, $initial);
1513
-    }
1514
-
1515
-    /**
1516
-     * Create a collection of all elements that do not pass a given truth test.
1517
-     *
1518
-     * @param  callable|mixed  $callback
1519
-     * @return static
1520
-     */
1521
-    public function reject($callback = true)
1522
-    {
1523
-        $useAsCallable = $this->useAsCallable($callback);
1524
-
1525
-        return $this->filter(function ($value, $key) use ($callback, $useAsCallable) {
1526
-            return $useAsCallable
1527
-                ? ! $callback($value, $key)
1528
-                : $value != $callback;
1529
-        });
1530
-    }
1531
-
1532
-    /**
1533
-     * Replace the collection items with the given items.
1534
-     *
1535
-     * @param  mixed  $items
1536
-     * @return static
1537
-     */
1538
-    public function replace($items)
1539
-    {
1540
-        return new static(array_replace($this->items, $this->getArrayableItems($items)));
1541
-    }
1542
-
1543
-    /**
1544
-     * Recursively replace the collection items with the given items.
1545
-     *
1546
-     * @param  mixed  $items
1547
-     * @return static
1548
-     */
1549
-    public function replaceRecursive($items)
1550
-    {
1551
-        return new static(array_replace_recursive($this->items, $this->getArrayableItems($items)));
1552
-    }
1553
-
1554
-    /**
1555
-     * Reverse items order.
1556
-     *
1557
-     * @return static
1558
-     */
1559
-    public function reverse()
1560
-    {
1561
-        return new static(array_reverse($this->items, true));
1562
-    }
1563
-
1564
-    /**
1565
-     * Search the collection for a given value and return the corresponding key if successful.
1566
-     *
1567
-     * @param  mixed  $value
1568
-     * @param  bool  $strict
1569
-     * @return mixed
1570
-     */
1571
-    public function search($value, $strict = false)
1572
-    {
1573
-        if (! $this->useAsCallable($value)) {
1574
-            return array_search($value, $this->items, $strict);
1575
-        }
1576
-
1577
-        foreach ($this->items as $key => $item) {
1578
-            if (call_user_func($value, $item, $key)) {
1579
-                return $key;
1580
-            }
1581
-        }
1582
-
1583
-        return false;
1584
-    }
1585
-
1586
-    /**
1587
-     * Get and remove the first item from the collection.
1588
-     *
1589
-     * @return mixed
1590
-     */
1591
-    public function shift()
1592
-    {
1593
-        return array_shift($this->items);
1594
-    }
1595
-
1596
-    /**
1597
-     * Shuffle the items in the collection.
1598
-     *
1599
-     * @param  int  $seed
1600
-     * @return static
1601
-     */
1602
-    public function shuffle($seed = null)
1603
-    {
1604
-        return new static(Arr::shuffle($this->items, $seed));
1605
-    }
1606
-
1607
-    /**
1608
-     * Slice the underlying collection array.
1609
-     *
1610
-     * @param  int  $offset
1611
-     * @param  int  $length
1612
-     * @return static
1613
-     */
1614
-    public function slice($offset, $length = null)
1615
-    {
1616
-        return new static(array_slice($this->items, $offset, $length, true));
1617
-    }
1618
-
1619
-    /**
1620
-     * Split a collection into a certain number of groups.
1621
-     *
1622
-     * @param  int  $numberOfGroups
1623
-     * @return static
1624
-     */
1625
-    public function split($numberOfGroups)
1626
-    {
1627
-        if ($this->isEmpty()) {
1628
-            return new static;
1629
-        }
1630
-
1631
-        $groups = new static;
1632
-
1633
-        $groupSize = floor($this->count() / $numberOfGroups);
1634
-
1635
-        $remain = $this->count() % $numberOfGroups;
1636
-
1637
-        $start = 0;
1638
-
1639
-        for ($i = 0; $i < $numberOfGroups; $i++) {
1640
-            $size = $groupSize;
1641
-
1642
-            if ($i < $remain) {
1643
-                $size++;
1644
-            }
1645
-
1646
-            if ($size) {
1647
-                $groups->push(new static(array_slice($this->items, $start, $size)));
1648
-
1649
-                $start += $size;
1650
-            }
1651
-        }
1652
-
1653
-        return $groups;
1654
-    }
1655
-
1656
-    /**
1657
-     * Chunk the underlying collection array.
1658
-     *
1659
-     * @param  int  $size
1660
-     * @return static
1661
-     */
1662
-    public function chunk($size)
1663
-    {
1664
-        if ($size <= 0) {
1665
-            return new static;
1666
-        }
1667
-
1668
-        $chunks = [];
1669
-
1670
-        foreach (array_chunk($this->items, $size, true) as $chunk) {
1671
-            $chunks[] = new static($chunk);
1672
-        }
1673
-
1674
-        return new static($chunks);
1675
-    }
1676
-
1677
-    /**
1678
-     * Sort through each item with a callback.
1679
-     *
1680
-     * @param  callable|null  $callback
1681
-     * @return static
1682
-     */
1683
-    public function sort(callable $callback = null)
1684
-    {
1685
-        $items = $this->items;
1686
-
1687
-        $callback
1688
-            ? uasort($items, $callback)
1689
-            : asort($items);
1690
-
1691
-        return new static($items);
1692
-    }
1693
-
1694
-    /**
1695
-     * Sort the collection using the given callback.
1696
-     *
1697
-     * @param  callable|string  $callback
1698
-     * @param  int  $options
1699
-     * @param  bool  $descending
1700
-     * @return static
1701
-     */
1702
-    public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
1703
-    {
1704
-        $results = [];
1705
-
1706
-        $callback = $this->valueRetriever($callback);
1707
-
1708
-        // First we will loop through the items and get the comparator from a callback
1709
-        // function which we were given. Then, we will sort the returned values and
1710
-        // and grab the corresponding values for the sorted keys from this array.
1711
-        foreach ($this->items as $key => $value) {
1712
-            $results[$key] = $callback($value, $key);
1713
-        }
1714
-
1715
-        $descending ? arsort($results, $options)
1716
-            : asort($results, $options);
1717
-
1718
-        // Once we have sorted all of the keys in the array, we will loop through them
1719
-        // and grab the corresponding model so we can set the underlying items list
1720
-        // to the sorted version. Then we'll just return the collection instance.
1721
-        foreach (array_keys($results) as $key) {
1722
-            $results[$key] = $this->items[$key];
1723
-        }
1724
-
1725
-        return new static($results);
1726
-    }
1727
-
1728
-    /**
1729
-     * Sort the collection in descending order using the given callback.
1730
-     *
1731
-     * @param  callable|string  $callback
1732
-     * @param  int  $options
1733
-     * @return static
1734
-     */
1735
-    public function sortByDesc($callback, $options = SORT_REGULAR)
1736
-    {
1737
-        return $this->sortBy($callback, $options, true);
1738
-    }
1739
-
1740
-    /**
1741
-     * Sort the collection keys.
1742
-     *
1743
-     * @param  int  $options
1744
-     * @param  bool  $descending
1745
-     * @return static
1746
-     */
1747
-    public function sortKeys($options = SORT_REGULAR, $descending = false)
1748
-    {
1749
-        $items = $this->items;
1750
-
1751
-        $descending ? krsort($items, $options) : ksort($items, $options);
1752
-
1753
-        return new static($items);
1754
-    }
1755
-
1756
-    /**
1757
-     * Sort the collection keys in descending order.
1758
-     *
1759
-     * @param  int $options
1760
-     * @return static
1761
-     */
1762
-    public function sortKeysDesc($options = SORT_REGULAR)
1763
-    {
1764
-        return $this->sortKeys($options, true);
1765
-    }
1766
-
1767
-    /**
1768
-     * Splice a portion of the underlying collection array.
1769
-     *
1770
-     * @param  int  $offset
1771
-     * @param  int|null  $length
1772
-     * @param  mixed  $replacement
1773
-     * @return static
1774
-     */
1775
-    public function splice($offset, $length = null, $replacement = [])
1776
-    {
1777
-        if (func_num_args() === 1) {
1778
-            return new static(array_splice($this->items, $offset));
1779
-        }
1780
-
1781
-        return new static(array_splice($this->items, $offset, $length, $replacement));
1782
-    }
1783
-
1784
-    /**
1785
-     * Get the sum of the given values.
1786
-     *
1787
-     * @param  callable|string|null  $callback
1788
-     * @return mixed
1789
-     */
1790
-    public function sum($callback = null)
1791
-    {
1792
-        if (is_null($callback)) {
1793
-            return array_sum($this->items);
1794
-        }
1795
-
1796
-        $callback = $this->valueRetriever($callback);
1797
-
1798
-        return $this->reduce(function ($result, $item) use ($callback) {
1799
-            return $result + $callback($item);
1800
-        }, 0);
1801
-    }
1802
-
1803
-    /**
1804
-     * Take the first or last {$limit} items.
1805
-     *
1806
-     * @param  int  $limit
1807
-     * @return static
1808
-     */
1809
-    public function take($limit)
1810
-    {
1811
-        if ($limit < 0) {
1812
-            return $this->slice($limit, abs($limit));
1813
-        }
1814
-
1815
-        return $this->slice(0, $limit);
1816
-    }
1817
-
1818
-    /**
1819
-     * Pass the collection to the given callback and then return it.
1820
-     *
1821
-     * @param  callable  $callback
1822
-     * @return $this
1823
-     */
1824
-    public function tap(callable $callback)
1825
-    {
1826
-        $callback(new static($this->items));
1827
-
1828
-        return $this;
1829
-    }
1830
-
1831
-    /**
1832
-     * Transform each item in the collection using a callback.
1833
-     *
1834
-     * @param  callable  $callback
1835
-     * @return $this
1836
-     */
1837
-    public function transform(callable $callback)
1838
-    {
1839
-        $this->items = $this->map($callback)->all();
1840
-
1841
-        return $this;
1842
-    }
1843
-
1844
-    /**
1845
-     * Return only unique items from the collection array.
1846
-     *
1847
-     * @param  string|callable|null  $key
1848
-     * @param  bool  $strict
1849
-     * @return static
1850
-     */
1851
-    public function unique($key = null, $strict = false)
1852
-    {
1853
-        $callback = $this->valueRetriever($key);
1854
-
1855
-        $exists = [];
1856
-
1857
-        return $this->reject(function ($item, $key) use ($callback, $strict, &$exists) {
1858
-            if (in_array($id = $callback($item, $key), $exists, $strict)) {
1859
-                return true;
1860
-            }
1861
-
1862
-            $exists[] = $id;
1863
-        });
1864
-    }
1865
-
1866
-    /**
1867
-     * Return only unique items from the collection array using strict comparison.
1868
-     *
1869
-     * @param  string|callable|null  $key
1870
-     * @return static
1871
-     */
1872
-    public function uniqueStrict($key = null)
1873
-    {
1874
-        return $this->unique($key, true);
1875
-    }
1876
-
1877
-    /**
1878
-     * Reset the keys on the underlying array.
1879
-     *
1880
-     * @return static
1881
-     */
1882
-    public function values()
1883
-    {
1884
-        return new static(array_values($this->items));
1885
-    }
1886
-
1887
-    /**
1888
-     * Get a value retrieving callback.
1889
-     *
1890
-     * @param  callable|string|null  $value
1891
-     * @return callable
1892
-     */
1893
-    protected function valueRetriever($value)
1894
-    {
1895
-        if ($this->useAsCallable($value)) {
1896
-            return $value;
1897
-        }
1898
-
1899
-        return function ($item) use ($value) {
1900
-            return data_get($item, $value);
1901
-        };
1902
-    }
1903
-
1904
-    /**
1905
-     * Zip the collection together with one or more arrays.
1906
-     *
1907
-     * e.g. new Collection([1, 2, 3])->zip([4, 5, 6]);
1908
-     *      => [[1, 4], [2, 5], [3, 6]]
1909
-     *
1910
-     * @param  mixed ...$items
1911
-     * @return static
1912
-     */
1913
-    public function zip($items)
1914
-    {
1915
-        $arrayableItems = array_map(function ($items) {
1916
-            return $this->getArrayableItems($items);
1917
-        }, func_get_args());
1918
-
1919
-        $params = array_merge([function () {
1920
-            return new static(func_get_args());
1921
-        }, $this->items], $arrayableItems);
1922
-
1923
-        return new static(call_user_func_array('array_map', $params));
1924
-    }
1925
-
1926
-    /**
1927
-     * Pad collection to the specified length with a value.
1928
-     *
1929
-     * @param  int  $size
1930
-     * @param  mixed  $value
1931
-     * @return static
1932
-     */
1933
-    public function pad($size, $value)
1934
-    {
1935
-        return new static(array_pad($this->items, $size, $value));
1936
-    }
1937
-
1938
-    /**
1939
-     * Get the collection of items as a plain array.
1940
-     *
1941
-     * @return array
1942
-     */
1943
-    public function toArray()
1944
-    {
1945
-        return array_map(function ($value) {
1946
-            return $value instanceof Arrayable ? $value->toArray() : $value;
1947
-        }, $this->items);
1948
-    }
1949
-
1950
-    /**
1951
-     * Convert the object into something JSON serializable.
1952
-     *
1953
-     * @return array
1954
-     */
1955
-    public function jsonSerialize()
1956
-    {
1957
-        return array_map(function ($value) {
1958
-            if ($value instanceof JsonSerializable) {
1959
-                return $value->jsonSerialize();
1960
-            } elseif ($value instanceof Jsonable) {
1961
-                return json_decode($value->toJson(), true);
1962
-            } elseif ($value instanceof Arrayable) {
1963
-                return $value->toArray();
1964
-            }
1965
-
1966
-            return $value;
1967
-        }, $this->items);
1968
-    }
1969
-
1970
-    /**
1971
-     * Get the collection of items as JSON.
1972
-     *
1973
-     * @param  int  $options
1974
-     * @return string
1975
-     */
1976
-    public function toJson($options = 0)
1977
-    {
1978
-        return json_encode($this->jsonSerialize(), $options);
1979
-    }
1980
-
1981
-    /**
1982
-     * Get an iterator for the items.
1983
-     *
1984
-     * @return \ArrayIterator
1985
-     */
1986
-    public function getIterator()
1987
-    {
1988
-        return new ArrayIterator($this->items);
1989
-    }
1990
-
1991
-    /**
1992
-     * Get a CachingIterator instance.
1993
-     *
1994
-     * @param  int  $flags
1995
-     * @return \CachingIterator
1996
-     */
1997
-    public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING)
1998
-    {
1999
-        return new CachingIterator($this->getIterator(), $flags);
2000
-    }
2001
-
2002
-    /**
2003
-     * Count the number of items in the collection.
2004
-     *
2005
-     * @return int
2006
-     */
2007
-    public function count()
2008
-    {
2009
-        return count($this->items);
2010
-    }
2011
-
2012
-    /**
2013
-     * Count the number of items in the collection using a given truth test.
2014
-     *
2015
-     * @param  callable|null  $callback
2016
-     * @return static
2017
-     */
2018
-    public function countBy($callback = null)
2019
-    {
2020
-        if (is_null($callback)) {
2021
-            $callback = function ($value) {
2022
-                return $value;
2023
-            };
2024
-        }
2025
-
2026
-        return new static($this->groupBy($callback)->map(function ($value) {
2027
-            return $value->count();
2028
-        }));
2029
-    }
2030
-
2031
-    /**
2032
-     * Add an item to the collection.
2033
-     *
2034
-     * @param  mixed  $item
2035
-     * @return $this
2036
-     */
2037
-    public function add($item)
2038
-    {
2039
-        $this->items[] = $item;
2040
-
2041
-        return $this;
2042
-    }
2043
-
2044
-    /**
2045
-     * Get a base Support collection instance from this collection.
2046
-     *
2047
-     * @return \Illuminate\Support\Collection
2048
-     */
2049
-    public function toBase()
2050
-    {
2051
-        return new self($this);
2052
-    }
2053
-
2054
-    /**
2055
-     * Determine if an item exists at an offset.
2056
-     *
2057
-     * @param  mixed  $key
2058
-     * @return bool
2059
-     */
2060
-    public function offsetExists($key)
2061
-    {
2062
-        return array_key_exists($key, $this->items);
2063
-    }
2064
-
2065
-    /**
2066
-     * Get an item at a given offset.
2067
-     *
2068
-     * @param  mixed  $key
2069
-     * @return mixed
2070
-     */
2071
-    public function offsetGet($key)
2072
-    {
2073
-        return $this->items[$key];
2074
-    }
2075
-
2076
-    /**
2077
-     * Set the item at a given offset.
2078
-     *
2079
-     * @param  mixed  $key
2080
-     * @param  mixed  $value
2081
-     * @return void
2082
-     */
2083
-    public function offsetSet($key, $value)
2084
-    {
2085
-        if (is_null($key)) {
2086
-            $this->items[] = $value;
2087
-        } else {
2088
-            $this->items[$key] = $value;
2089
-        }
2090
-    }
2091
-
2092
-    /**
2093
-     * Unset the item at a given offset.
2094
-     *
2095
-     * @param  string  $key
2096
-     * @return void
2097
-     */
2098
-    public function offsetUnset($key)
2099
-    {
2100
-        unset($this->items[$key]);
2101
-    }
2102
-
2103
-    /**
2104
-     * Convert the collection to its string representation.
2105
-     *
2106
-     * @return string
2107
-     */
2108
-    public function __toString()
2109
-    {
2110
-        return $this->toJson();
2111
-    }
2112
-
2113
-    /**
2114
-     * Results array of items from Collection or Arrayable.
2115
-     *
2116
-     * @param  mixed  $items
2117
-     * @return array
2118
-     */
2119
-    protected function getArrayableItems($items)
2120
-    {
2121
-        if (is_array($items)) {
2122
-            return $items;
2123
-        } elseif ($items instanceof self) {
2124
-            return $items->all();
2125
-        } elseif ($items instanceof Arrayable) {
2126
-            return $items->toArray();
2127
-        } elseif ($items instanceof Jsonable) {
2128
-            return json_decode($items->toJson(), true);
2129
-        } elseif ($items instanceof JsonSerializable) {
2130
-            return (array) $items->jsonSerialize();
2131
-        } elseif ($items instanceof Traversable) {
2132
-            return iterator_to_array($items);
2133
-        }
2134
-
2135
-        return (array) $items;
2136
-    }
2137
-
2138
-    /**
2139
-     * Add a method to the list of proxied methods.
2140
-     *
2141
-     * @param  string  $method
2142
-     * @return void
2143
-     */
2144
-    public static function proxy($method)
2145
-    {
2146
-        static::$proxies[] = $method;
2147
-    }
2148
-
2149
-    /**
2150
-     * Dynamically access collection proxies.
2151
-     *
2152
-     * @param  string  $key
2153
-     * @return mixed
2154
-     *
2155
-     * @throws \Exception
2156
-     */
2157
-    public function __get($key)
2158
-    {
2159
-        if (! in_array($key, static::$proxies)) {
2160
-            throw new Exception("Property [{$key}] does not exist on this collection instance.");
2161
-        }
2162
-
2163
-        return new HigherOrderCollectionProxy($this, $key);
2164
-    }
2165
-}
Browse code

initial commit

Emmanuel ROY authored on 09/08/2019 08:39:02
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,2165 @@
1
+<?php
2
+
3
+namespace Illuminate\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 Illuminate\Support\Traits\Macroable;
15
+use Illuminate\Contracts\Support\Jsonable;
16
+use Symfony\Component\VarDumper\VarDumper;
17
+use Illuminate\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 implements ArrayAccess, Arrayable, Countable, IteratorAggregate, Jsonable, JsonSerializable
41
+{
42
+    use Macroable;
43
+
44
+    /**
45
+     * The items contained in the collection.
46
+     *
47
+     * @var array
48
+     */
49
+    protected $items = [];
50
+
51
+    /**
52
+     * The methods that can be proxied.
53
+     *
54
+     * @var array
55
+     */
56
+    protected static $proxies = [
57
+        'average', 'avg', 'contains', 'each', 'every', 'filter', 'first',
58
+        'flatMap', 'groupBy', 'keyBy', 'map', 'max', 'min', 'partition',
59
+        'reject', 'some', 'sortBy', 'sortByDesc', 'sum', 'unique',
60
+    ];
61
+
62
+    /**
63
+     * Create a new collection.
64
+     *
65
+     * @param  mixed  $items
66
+     * @return void
67
+     */
68
+    public function __construct($items = [])
69
+    {
70
+        $this->items = $this->getArrayableItems($items);
71
+    }
72
+
73
+    /**
74
+     * Create a new collection instance if the value isn't one already.
75
+     *
76
+     * @param  mixed  $items
77
+     * @return static
78
+     */
79
+    public static function make($items = [])
80
+    {
81
+        return new static($items);
82
+    }
83
+
84
+    /**
85
+     * Wrap the given value in a collection if applicable.
86
+     *
87
+     * @param  mixed  $value
88
+     * @return static
89
+     */
90
+    public static function wrap($value)
91
+    {
92
+        return $value instanceof self
93
+            ? new static($value)
94
+            : new static(Arr::wrap($value));
95
+    }
96
+
97
+    /**
98
+     * Get the underlying items from the given collection if applicable.
99
+     *
100
+     * @param  array|static  $value
101
+     * @return array
102
+     */
103
+    public static function unwrap($value)
104
+    {
105
+        return $value instanceof self ? $value->all() : $value;
106
+    }
107
+
108
+    /**
109
+     * Create a new collection by invoking the callback a given amount of times.
110
+     *
111
+     * @param  int  $number
112
+     * @param  callable  $callback
113
+     * @return static
114
+     */
115
+    public static function times($number, callable $callback = null)
116
+    {
117
+        if ($number < 1) {
118
+            return new static;
119
+        }
120
+
121
+        if (is_null($callback)) {
122
+            return new static(range(1, $number));
123
+        }
124
+
125
+        return (new static(range(1, $number)))->map($callback);
126
+    }
127
+
128
+    /**
129
+     * Get all of the items in the collection.
130
+     *
131
+     * @return array
132
+     */
133
+    public function all()
134
+    {
135
+        return $this->items;
136
+    }
137
+
138
+    /**
139
+     * Get the average value of a given key.
140
+     *
141
+     * @param  callable|string|null  $callback
142
+     * @return mixed
143
+     */
144
+    public function avg($callback = null)
145
+    {
146
+        $callback = $this->valueRetriever($callback);
147
+
148
+        $items = $this->map(function ($value) use ($callback) {
149
+            return $callback($value);
150
+        })->filter(function ($value) {
151
+            return ! is_null($value);
152
+        });
153
+
154
+        if ($count = $items->count()) {
155
+            return $items->sum() / $count;
156
+        }
157
+    }
158
+
159
+    /**
160
+     * Alias for the "avg" method.
161
+     *
162
+     * @param  callable|string|null  $callback
163
+     * @return mixed
164
+     */
165
+    public function average($callback = null)
166
+    {
167
+        return $this->avg($callback);
168
+    }
169
+
170
+    /**
171
+     * Get the median of a given key.
172
+     *
173
+     * @param  string|array|null $key
174
+     * @return mixed
175
+     */
176
+    public function median($key = null)
177
+    {
178
+        $values = (isset($key) ? $this->pluck($key) : $this)
179
+            ->filter(function ($item) {
180
+                return ! is_null($item);
181
+            })->sort()->values();
182
+
183
+        $count = $values->count();
184
+
185
+        if ($count === 0) {
186
+            return;
187
+        }
188
+
189
+        $middle = (int) ($count / 2);
190
+
191
+        if ($count % 2) {
192
+            return $values->get($middle);
193
+        }
194
+
195
+        return (new static([
196
+            $values->get($middle - 1), $values->get($middle),
197
+        ]))->average();
198
+    }
199
+
200
+    /**
201
+     * Get the mode of a given key.
202
+     *
203
+     * @param  string|array|null  $key
204
+     * @return array|null
205
+     */
206
+    public function mode($key = null)
207
+    {
208
+        if ($this->count() === 0) {
209
+            return;
210
+        }
211
+
212
+        $collection = isset($key) ? $this->pluck($key) : $this;
213
+
214
+        $counts = new self;
215
+
216
+        $collection->each(function ($value) use ($counts) {
217
+            $counts[$value] = isset($counts[$value]) ? $counts[$value] + 1 : 1;
218
+        });
219
+
220
+        $sorted = $counts->sort();
221
+
222
+        $highestValue = $sorted->last();
223
+
224
+        return $sorted->filter(function ($value) use ($highestValue) {
225
+            return $value == $highestValue;
226
+        })->sort()->keys()->all();
227
+    }
228
+
229
+    /**
230
+     * Collapse the collection of items into a single array.
231
+     *
232
+     * @return static
233
+     */
234
+    public function collapse()
235
+    {
236
+        return new static(Arr::collapse($this->items));
237
+    }
238
+
239
+    /**
240
+     * Alias for the "contains" method.
241
+     *
242
+     * @param  mixed  $key
243
+     * @param  mixed  $operator
244
+     * @param  mixed  $value
245
+     * @return bool
246
+     */
247
+    public function some($key, $operator = null, $value = null)
248
+    {
249
+        return $this->contains(...func_get_args());
250
+    }
251
+
252
+    /**
253
+     * Determine if an item exists in the collection.
254
+     *
255
+     * @param  mixed  $key
256
+     * @param  mixed  $operator
257
+     * @param  mixed  $value
258
+     * @return bool
259
+     */
260
+    public function contains($key, $operator = null, $value = null)
261
+    {
262
+        if (func_num_args() === 1) {
263
+            if ($this->useAsCallable($key)) {
264
+                $placeholder = new stdClass;
265
+
266
+                return $this->first($key, $placeholder) !== $placeholder;
267
+            }
268
+
269
+            return in_array($key, $this->items);
270
+        }
271
+
272
+        return $this->contains($this->operatorForWhere(...func_get_args()));
273
+    }
274
+
275
+    /**
276
+     * Determine if an item exists in the collection using strict comparison.
277
+     *
278
+     * @param  mixed  $key
279
+     * @param  mixed  $value
280
+     * @return bool
281
+     */
282
+    public function containsStrict($key, $value = null)
283
+    {
284
+        if (func_num_args() === 2) {
285
+            return $this->contains(function ($item) use ($key, $value) {
286
+                return data_get($item, $key) === $value;
287
+            });
288
+        }
289
+
290
+        if ($this->useAsCallable($key)) {
291
+            return ! is_null($this->first($key));
292
+        }
293
+
294
+        return in_array($key, $this->items, true);
295
+    }
296
+
297
+    /**
298
+     * Cross join with the given lists, returning all possible permutations.
299
+     *
300
+     * @param  mixed  ...$lists
301
+     * @return static
302
+     */
303
+    public function crossJoin(...$lists)
304
+    {
305
+        return new static(Arr::crossJoin(
306
+            $this->items, ...array_map([$this, 'getArrayableItems'], $lists)
307
+        ));
308
+    }
309
+
310
+    /**
311
+     * Dump the collection and end the script.
312
+     *
313
+     * @param  mixed  ...$args
314
+     * @return void
315
+     */
316
+    public function dd(...$args)
317
+    {
318
+        call_user_func_array([$this, 'dump'], $args);
319
+
320
+        die(1);
321
+    }
322
+
323
+    /**
324
+     * Dump the collection.
325
+     *
326
+     * @return $this
327
+     */
328
+    public function dump()
329
+    {
330
+        (new static(func_get_args()))
331
+            ->push($this)
332
+            ->each(function ($item) {
333
+                VarDumper::dump($item);
334
+            });
335
+
336
+        return $this;
337
+    }
338
+
339
+    /**
340
+     * Get the items in the collection that are not present in the given items.
341
+     *
342
+     * @param  mixed  $items
343
+     * @return static
344
+     */
345
+    public function diff($items)
346
+    {
347
+        return new static(array_diff($this->items, $this->getArrayableItems($items)));
348
+    }
349
+
350
+    /**
351
+     * Get the items in the collection that are not present in the given items.
352
+     *
353
+     * @param  mixed  $items
354
+     * @param  callable  $callback
355
+     * @return static
356
+     */
357
+    public function diffUsing($items, callable $callback)
358
+    {
359
+        return new static(array_udiff($this->items, $this->getArrayableItems($items), $callback));
360
+    }
361
+
362
+    /**
363
+     * Get the items in the collection whose keys and values are not present in the given items.
364
+     *
365
+     * @param  mixed  $items
366
+     * @return static
367
+     */
368
+    public function diffAssoc($items)
369
+    {
370
+        return new static(array_diff_assoc($this->items, $this->getArrayableItems($items)));
371
+    }
372
+
373
+    /**
374
+     * Get the items in the collection whose keys and values are not present in the given items.
375
+     *
376
+     * @param  mixed  $items
377
+     * @param  callable  $callback
378
+     * @return static
379
+     */
380
+    public function diffAssocUsing($items, callable $callback)
381
+    {
382
+        return new static(array_diff_uassoc($this->items, $this->getArrayableItems($items), $callback));
383
+    }
384
+
385
+    /**
386
+     * Get the items in the collection whose keys are not present in the given items.
387
+     *
388
+     * @param  mixed  $items
389
+     * @return static
390
+     */
391
+    public function diffKeys($items)
392
+    {
393
+        return new static(array_diff_key($this->items, $this->getArrayableItems($items)));
394
+    }
395
+
396
+    /**
397
+     * Get the items in the collection whose keys are not present in the given items.
398
+     *
399
+     * @param  mixed   $items
400
+     * @param  callable  $callback
401
+     * @return static
402
+     */
403
+    public function diffKeysUsing($items, callable $callback)
404
+    {
405
+        return new static(array_diff_ukey($this->items, $this->getArrayableItems($items), $callback));
406
+    }
407
+
408
+    /**
409
+     * Retrieve duplicate items from the collection.
410
+     *
411
+     * @param  callable|null  $callback
412
+     * @param  bool  $strict
413
+     * @return static
414
+     */
415
+    public function duplicates($callback = null, $strict = false)
416
+    {
417
+        $items = $this->map($this->valueRetriever($callback));
418
+
419
+        $uniqueItems = $items->unique(null, $strict);
420
+
421
+        $compare = $this->duplicateComparator($strict);
422
+
423
+        $duplicates = new static;
424
+
425
+        foreach ($items as $key => $value) {
426
+            if ($uniqueItems->isNotEmpty() && $compare($value, $uniqueItems->first())) {
427
+                $uniqueItems->shift();
428
+            } else {
429
+                $duplicates[$key] = $value;
430
+            }
431
+        }
432
+
433
+        return $duplicates;
434
+    }
435
+
436
+    /**
437
+     * Retrieve duplicate items from the collection using strict comparison.
438
+     *
439
+     * @param  callable|null  $callback
440
+     * @return static
441
+     */
442
+    public function duplicatesStrict($callback = null)
443
+    {
444
+        return $this->duplicates($callback, true);
445
+    }
446
+
447
+    /**
448
+     * Get the comparison function to detect duplicates.
449
+     *
450
+     * @param  bool  $strict
451
+     * @return \Closure
452
+     */
453
+    protected function duplicateComparator($strict)
454
+    {
455
+        if ($strict) {
456
+            return function ($a, $b) {
457
+                return $a === $b;
458
+            };
459
+        }
460
+
461
+        return function ($a, $b) {
462
+            return $a == $b;
463
+        };
464
+    }
465
+
466
+    /**
467
+     * Execute a callback over each item.
468
+     *
469
+     * @param  callable  $callback
470
+     * @return $this
471
+     */
472
+    public function each(callable $callback)
473
+    {
474
+        foreach ($this->items as $key => $item) {
475
+            if ($callback($item, $key) === false) {
476
+                break;
477
+            }
478
+        }
479
+
480
+        return $this;
481
+    }
482
+
483
+    /**
484
+     * Execute a callback over each nested chunk of items.
485
+     *
486
+     * @param  callable  $callback
487
+     * @return static
488
+     */
489
+    public function eachSpread(callable $callback)
490
+    {
491
+        return $this->each(function ($chunk, $key) use ($callback) {
492
+            $chunk[] = $key;
493
+
494
+            return $callback(...$chunk);
495
+        });
496
+    }
497
+
498
+    /**
499
+     * Determine if all items in the collection pass the given test.
500
+     *
501
+     * @param  string|callable  $key
502
+     * @param  mixed  $operator
503
+     * @param  mixed  $value
504
+     * @return bool
505
+     */
506
+    public function every($key, $operator = null, $value = null)
507
+    {
508
+        if (func_num_args() === 1) {
509
+            $callback = $this->valueRetriever($key);
510
+
511
+            foreach ($this->items as $k => $v) {
512
+                if (! $callback($v, $k)) {
513
+                    return false;
514
+                }
515
+            }
516
+
517
+            return true;
518
+        }
519
+
520
+        return $this->every($this->operatorForWhere(...func_get_args()));
521
+    }
522
+
523
+    /**
524
+     * Get all items except for those with the specified keys.
525
+     *
526
+     * @param  \Illuminate\Support\Collection|mixed  $keys
527
+     * @return static
528
+     */
529
+    public function except($keys)
530
+    {
531
+        if ($keys instanceof self) {
532
+            $keys = $keys->all();
533
+        } elseif (! is_array($keys)) {
534
+            $keys = func_get_args();
535
+        }
536
+
537
+        return new static(Arr::except($this->items, $keys));
538
+    }
539
+
540
+    /**
541
+     * Run a filter over each of the items.
542
+     *
543
+     * @param  callable|null  $callback
544
+     * @return static
545
+     */
546
+    public function filter(callable $callback = null)
547
+    {
548
+        if ($callback) {
549
+            return new static(Arr::where($this->items, $callback));
550
+        }
551
+
552
+        return new static(array_filter($this->items));
553
+    }
554
+
555
+    /**
556
+     * Apply the callback if the value is truthy.
557
+     *
558
+     * @param  bool  $value
559
+     * @param  callable  $callback
560
+     * @param  callable  $default
561
+     * @return static|mixed
562
+     */
563
+    public function when($value, callable $callback, callable $default = null)
564
+    {
565
+        if ($value) {
566
+            return $callback($this, $value);
567
+        } elseif ($default) {
568
+            return $default($this, $value);
569
+        }
570
+
571
+        return $this;
572
+    }
573
+
574
+    /**
575
+     * Apply the callback if the collection is empty.
576
+     *
577
+     * @param  callable  $callback
578
+     * @param  callable  $default
579
+     * @return static|mixed
580
+     */
581
+    public function whenEmpty(callable $callback, callable $default = null)
582
+    {
583
+        return $this->when($this->isEmpty(), $callback, $default);
584
+    }
585
+
586
+    /**
587
+     * Apply the callback if the collection is not empty.
588
+     *
589
+     * @param  callable  $callback
590
+     * @param  callable  $default
591
+     * @return static|mixed
592
+     */
593
+    public function whenNotEmpty(callable $callback, callable $default = null)
594
+    {
595
+        return $this->when($this->isNotEmpty(), $callback, $default);
596
+    }
597
+
598
+    /**
599
+     * Apply the callback if the value is falsy.
600
+     *
601
+     * @param  bool  $value
602
+     * @param  callable  $callback
603
+     * @param  callable  $default
604
+     * @return static|mixed
605
+     */
606
+    public function unless($value, callable $callback, callable $default = null)
607
+    {
608
+        return $this->when(! $value, $callback, $default);
609
+    }
610
+
611
+    /**
612
+     * Apply the callback unless the collection is empty.
613
+     *
614
+     * @param  callable  $callback
615
+     * @param  callable  $default
616
+     * @return static|mixed
617
+     */
618
+    public function unlessEmpty(callable $callback, callable $default = null)
619
+    {
620
+        return $this->whenNotEmpty($callback, $default);
621
+    }
622
+
623
+    /**
624
+     * Apply the callback unless the collection is not empty.
625
+     *
626
+     * @param  callable  $callback
627
+     * @param  callable  $default
628
+     * @return static|mixed
629
+     */
630
+    public function unlessNotEmpty(callable $callback, callable $default = null)
631
+    {
632
+        return $this->whenEmpty($callback, $default);
633
+    }
634
+
635
+    /**
636
+     * Filter items by the given key value pair.
637
+     *
638
+     * @param  string  $key
639
+     * @param  mixed  $operator
640
+     * @param  mixed  $value
641
+     * @return static
642
+     */
643
+    public function where($key, $operator = null, $value = null)
644
+    {
645
+        return $this->filter($this->operatorForWhere(...func_get_args()));
646
+    }
647
+
648
+    /**
649
+     * Get an operator checker callback.
650
+     *
651
+     * @param  string  $key
652
+     * @param  string  $operator
653
+     * @param  mixed  $value
654
+     * @return \Closure
655
+     */
656
+    protected function operatorForWhere($key, $operator = null, $value = null)
657
+    {
658
+        if (func_num_args() === 1) {
659
+            $value = true;
660
+
661
+            $operator = '=';
662
+        }
663
+
664
+        if (func_num_args() === 2) {
665
+            $value = $operator;
666
+
667
+            $operator = '=';
668
+        }
669
+
670
+        return function ($item) use ($key, $operator, $value) {
671
+            $retrieved = data_get($item, $key);
672
+
673
+            $strings = array_filter([$retrieved, $value], function ($value) {
674
+                return is_string($value) || (is_object($value) && method_exists($value, '__toString'));
675
+            });
676
+
677
+            if (count($strings) < 2 && count(array_filter([$retrieved, $value], 'is_object')) == 1) {
678
+                return in_array($operator, ['!=', '<>', '!==']);
679
+            }
680
+
681
+            switch ($operator) {
682
+                default:
683
+                case '=':
684
+                case '==':  return $retrieved == $value;
685
+                case '!=':
686
+                case '<>':  return $retrieved != $value;
687
+                case '<':   return $retrieved < $value;
688
+                case '>':   return $retrieved > $value;
689
+                case '<=':  return $retrieved <= $value;
690
+                case '>=':  return $retrieved >= $value;
691
+                case '===': return $retrieved === $value;
692
+                case '!==': return $retrieved !== $value;
693
+            }
694
+        };
695
+    }
696
+
697
+    /**
698
+     * Filter items by the given key value pair using strict comparison.
699
+     *
700
+     * @param  string  $key
701
+     * @param  mixed  $value
702
+     * @return static
703
+     */
704
+    public function whereStrict($key, $value)
705
+    {
706
+        return $this->where($key, '===', $value);
707
+    }
708
+
709
+    /**
710
+     * Filter items by the given key value pair.
711
+     *
712
+     * @param  string  $key
713
+     * @param  mixed  $values
714
+     * @param  bool  $strict
715
+     * @return static
716
+     */
717
+    public function whereIn($key, $values, $strict = false)
718
+    {
719
+        $values = $this->getArrayableItems($values);
720
+
721
+        return $this->filter(function ($item) use ($key, $values, $strict) {
722
+            return in_array(data_get($item, $key), $values, $strict);
723
+        });
724
+    }
725
+
726
+    /**
727
+     * Filter items by the given key value pair using strict comparison.
728
+     *
729
+     * @param  string  $key
730
+     * @param  mixed  $values
731
+     * @return static
732
+     */
733
+    public function whereInStrict($key, $values)
734
+    {
735
+        return $this->whereIn($key, $values, true);
736
+    }
737
+
738
+    /**
739
+     * Filter items such that the value of the given key is between the given values.
740
+     *
741
+     * @param  string  $key
742
+     * @param  array  $values
743
+     * @return static
744
+     */
745
+    public function whereBetween($key, $values)
746
+    {
747
+        return $this->where($key, '>=', reset($values))->where($key, '<=', end($values));
748
+    }
749
+
750
+    /**
751
+     * Filter items such that the value of the given key is not between the given values.
752
+     *
753
+     * @param  string  $key
754
+     * @param  array  $values
755
+     * @return static
756
+     */
757
+    public function whereNotBetween($key, $values)
758
+    {
759
+        return $this->filter(function ($item) use ($key, $values) {
760
+            return data_get($item, $key) < reset($values) || data_get($item, $key) > end($values);
761
+        });
762
+    }
763
+
764
+    /**
765
+     * Filter items by the given key value pair.
766
+     *
767
+     * @param  string  $key
768
+     * @param  mixed  $values
769
+     * @param  bool  $strict
770
+     * @return static
771
+     */
772
+    public function whereNotIn($key, $values, $strict = false)
773
+    {
774
+        $values = $this->getArrayableItems($values);
775
+
776
+        return $this->reject(function ($item) use ($key, $values, $strict) {
777
+            return in_array(data_get($item, $key), $values, $strict);
778
+        });
779
+    }
780
+
781
+    /**
782
+     * Filter items by the given key value pair using strict comparison.
783
+     *
784
+     * @param  string  $key
785
+     * @param  mixed  $values
786
+     * @return static
787
+     */
788
+    public function whereNotInStrict($key, $values)
789
+    {
790
+        return $this->whereNotIn($key, $values, true);
791
+    }
792
+
793
+    /**
794
+     * Filter the items, removing any items that don't match the given type.
795
+     *
796
+     * @param  string  $type
797
+     * @return static
798
+     */
799
+    public function whereInstanceOf($type)
800
+    {
801
+        return $this->filter(function ($value) use ($type) {
802
+            return $value instanceof $type;
803
+        });
804
+    }
805
+
806
+    /**
807
+     * Get the first item from the collection passing the given truth test.
808
+     *
809
+     * @param  callable|null  $callback
810
+     * @param  mixed  $default
811
+     * @return mixed
812
+     */
813
+    public function first(callable $callback = null, $default = null)
814
+    {
815
+        return Arr::first($this->items, $callback, $default);
816
+    }
817
+
818
+    /**
819
+     * Get the first item by the given key value pair.
820
+     *
821
+     * @param  string  $key
822
+     * @param  mixed  $operator
823
+     * @param  mixed  $value
824
+     * @return mixed
825
+     */
826
+    public function firstWhere($key, $operator = null, $value = null)
827
+    {
828
+        return $this->first($this->operatorForWhere(...func_get_args()));
829
+    }
830
+
831
+    /**
832
+     * Get a flattened array of the items in the collection.
833
+     *
834
+     * @param  int  $depth
835
+     * @return static
836
+     */
837
+    public function flatten($depth = INF)
838
+    {
839
+        return new static(Arr::flatten($this->items, $depth));
840
+    }
841
+
842
+    /**
843
+     * Flip the items in the collection.
844
+     *
845
+     * @return static
846
+     */
847
+    public function flip()
848
+    {
849
+        return new static(array_flip($this->items));
850
+    }
851
+
852
+    /**
853
+     * Remove an item from the collection by key.
854
+     *
855
+     * @param  string|array  $keys
856
+     * @return $this
857
+     */
858
+    public function forget($keys)
859
+    {
860
+        foreach ((array) $keys as $key) {
861
+            $this->offsetUnset($key);
862
+        }
863
+
864
+        return $this;
865
+    }
866
+
867
+    /**
868
+     * Get an item from the collection by key.
869
+     *
870
+     * @param  mixed  $key
871
+     * @param  mixed  $default
872
+     * @return mixed
873
+     */
874
+    public function get($key, $default = null)
875
+    {
876
+        if ($this->offsetExists($key)) {
877
+            return $this->items[$key];
878
+        }
879
+
880
+        return value($default);
881
+    }
882
+
883
+    /**
884
+     * Group an associative array by a field or using a callback.
885
+     *
886
+     * @param  array|callable|string  $groupBy
887
+     * @param  bool  $preserveKeys
888
+     * @return static
889
+     */
890
+    public function groupBy($groupBy, $preserveKeys = false)
891
+    {
892
+        if (is_array($groupBy)) {
893
+            $nextGroups = $groupBy;
894
+
895
+            $groupBy = array_shift($nextGroups);
896
+        }
897
+
898
+        $groupBy = $this->valueRetriever($groupBy);
899
+
900
+        $results = [];
901
+
902
+        foreach ($this->items as $key => $value) {
903
+            $groupKeys = $groupBy($value, $key);
904
+
905
+            if (! is_array($groupKeys)) {
906
+                $groupKeys = [$groupKeys];
907
+            }
908
+
909
+            foreach ($groupKeys as $groupKey) {
910
+                $groupKey = is_bool($groupKey) ? (int) $groupKey : $groupKey;
911
+
912
+                if (! array_key_exists($groupKey, $results)) {
913
+                    $results[$groupKey] = new static;
914
+                }
915
+
916
+                $results[$groupKey]->offsetSet($preserveKeys ? $key : null, $value);
917
+            }
918
+        }
919
+
920
+        $result = new static($results);
921
+
922
+        if (! empty($nextGroups)) {
923
+            return $result->map->groupBy($nextGroups, $preserveKeys);
924
+        }
925
+
926
+        return $result;
927
+    }
928
+
929
+    /**
930
+     * Key an associative array by a field or using a callback.
931
+     *
932
+     * @param  callable|string  $keyBy
933
+     * @return static
934
+     */
935
+    public function keyBy($keyBy)
936
+    {
937
+        $keyBy = $this->valueRetriever($keyBy);
938
+
939
+        $results = [];
940
+
941
+        foreach ($this->items as $key => $item) {
942
+            $resolvedKey = $keyBy($item, $key);
943
+
944
+            if (is_object($resolvedKey)) {
945
+                $resolvedKey = (string) $resolvedKey;
946
+            }
947
+
948
+            $results[$resolvedKey] = $item;
949
+        }
950
+
951
+        return new static($results);
952
+    }
953
+
954
+    /**
955
+     * Determine if an item exists in the collection by key.
956
+     *
957
+     * @param  mixed  $key
958
+     * @return bool
959
+     */
960
+    public function has($key)
961
+    {
962
+        $keys = is_array($key) ? $key : func_get_args();
963
+
964
+        foreach ($keys as $value) {
965
+            if (! $this->offsetExists($value)) {
966
+                return false;
967
+            }
968
+        }
969
+
970
+        return true;
971
+    }
972
+
973
+    /**
974
+     * Concatenate values of a given key as a string.
975
+     *
976
+     * @param  string  $value
977
+     * @param  string  $glue
978
+     * @return string
979
+     */
980
+    public function implode($value, $glue = null)
981
+    {
982
+        $first = $this->first();
983
+
984
+        if (is_array($first) || is_object($first)) {
985
+            return implode($glue, $this->pluck($value)->all());
986
+        }
987
+
988
+        return implode($value, $this->items);
989
+    }
990
+
991
+    /**
992
+     * Intersect the collection with the given items.
993
+     *
994
+     * @param  mixed  $items
995
+     * @return static
996
+     */
997
+    public function intersect($items)
998
+    {
999
+        return new static(array_intersect($this->items, $this->getArrayableItems($items)));
1000
+    }
1001
+
1002
+    /**
1003
+     * Intersect the collection with the given items by key.
1004
+     *
1005
+     * @param  mixed  $items
1006
+     * @return static
1007
+     */
1008
+    public function intersectByKeys($items)
1009
+    {
1010
+        return new static(array_intersect_key(
1011
+            $this->items, $this->getArrayableItems($items)
1012
+        ));
1013
+    }
1014
+
1015
+    /**
1016
+     * Determine if the collection is empty or not.
1017
+     *
1018
+     * @return bool
1019
+     */
1020
+    public function isEmpty()
1021
+    {
1022
+        return empty($this->items);
1023
+    }
1024
+
1025
+    /**
1026
+     * Determine if the collection is not empty.
1027
+     *
1028
+     * @return bool
1029
+     */
1030
+    public function isNotEmpty()
1031
+    {
1032
+        return ! $this->isEmpty();
1033
+    }
1034
+
1035
+    /**
1036
+     * Determine if the given value is callable, but not a string.
1037
+     *
1038
+     * @param  mixed  $value
1039
+     * @return bool
1040
+     */
1041
+    protected function useAsCallable($value)
1042
+    {
1043
+        return ! is_string($value) && is_callable($value);
1044
+    }
1045
+
1046
+    /**
1047
+     * Join all items from the collection using a string. The final items can use a separate glue string.
1048
+     *
1049
+     * @param  string  $glue
1050
+     * @param  string  $finalGlue
1051
+     * @return string
1052
+     */
1053
+    public function join($glue, $finalGlue = '')
1054
+    {
1055
+        if ($finalGlue === '') {
1056
+            return $this->implode($glue);
1057
+        }
1058
+
1059
+        $count = $this->count();
1060
+
1061
+        if ($count === 0) {
1062
+            return '';
1063
+        }
1064
+
1065
+        if ($count === 1) {
1066
+            return $this->last();
1067
+        }
1068
+
1069
+        $collection = new static($this->items);
1070
+
1071
+        $finalItem = $collection->pop();
1072
+
1073
+        return $collection->implode($glue).$finalGlue.$finalItem;
1074
+    }
1075
+
1076
+    /**
1077
+     * Get the keys of the collection items.
1078
+     *
1079
+     * @return static
1080
+     */
1081
+    public function keys()
1082
+    {
1083
+        return new static(array_keys($this->items));
1084
+    }
1085
+
1086
+    /**
1087
+     * Get the last item from the collection.
1088
+     *
1089
+     * @param  callable|null  $callback
1090
+     * @param  mixed  $default
1091
+     * @return mixed
1092
+     */
1093
+    public function last(callable $callback = null, $default = null)
1094
+    {
1095
+        return Arr::last($this->items, $callback, $default);
1096
+    }
1097
+
1098
+    /**
1099
+     * Get the values of a given key.
1100
+     *
1101
+     * @param  string|array  $value
1102
+     * @param  string|null  $key
1103
+     * @return static
1104
+     */
1105
+    public function pluck($value, $key = null)
1106
+    {
1107
+        return new static(Arr::pluck($this->items, $value, $key));
1108
+    }
1109
+
1110
+    /**
1111
+     * Run a map over each of the items.
1112
+     *
1113
+     * @param  callable  $callback
1114
+     * @return static
1115
+     */
1116
+    public function map(callable $callback)
1117
+    {
1118
+        $keys = array_keys($this->items);
1119
+
1120
+        $items = array_map($callback, $this->items, $keys);
1121
+
1122
+        return new static(array_combine($keys, $items));
1123
+    }
1124
+
1125
+    /**
1126
+     * Run a map over each nested chunk of items.
1127
+     *
1128
+     * @param  callable  $callback
1129
+     * @return static
1130
+     */
1131
+    public function mapSpread(callable $callback)
1132
+    {
1133
+        return $this->map(function ($chunk, $key) use ($callback) {
1134
+            $chunk[] = $key;
1135
+
1136
+            return $callback(...$chunk);
1137
+        });
1138
+    }
1139
+
1140
+    /**
1141
+     * Run a dictionary map over the items.
1142
+     *
1143
+     * The callback should return an associative array with a single key/value pair.
1144
+     *
1145
+     * @param  callable  $callback
1146
+     * @return static
1147
+     */
1148
+    public function mapToDictionary(callable $callback)
1149
+    {
1150
+        $dictionary = [];
1151
+
1152
+        foreach ($this->items as $key => $item) {
1153
+            $pair = $callback($item, $key);
1154
+
1155
+            $key = key($pair);
1156
+
1157
+            $value = reset($pair);
1158
+
1159
+            if (! isset($dictionary[$key])) {
1160
+                $dictionary[$key] = [];
1161
+            }
1162
+
1163
+            $dictionary[$key][] = $value;
1164
+        }
1165
+
1166
+        return new static($dictionary);
1167
+    }
1168
+
1169
+    /**
1170
+     * Run a grouping map over the items.
1171
+     *
1172
+     * The callback should return an associative array with a single key/value pair.
1173
+     *
1174
+     * @param  callable  $callback
1175
+     * @return static
1176
+     */
1177
+    public function mapToGroups(callable $callback)
1178
+    {
1179
+        $groups = $this->mapToDictionary($callback);
1180
+
1181
+        return $groups->map([$this, 'make']);
1182
+    }
1183
+
1184
+    /**
1185
+     * Run an associative map over each of the items.
1186
+     *
1187
+     * The callback should return an associative array with a single key/value pair.
1188
+     *
1189
+     * @param  callable  $callback
1190
+     * @return static
1191
+     */
1192
+    public function mapWithKeys(callable $callback)
1193
+    {
1194
+        $result = [];
1195
+
1196
+        foreach ($this->items as $key => $value) {
1197
+            $assoc = $callback($value, $key);
1198
+
1199
+            foreach ($assoc as $mapKey => $mapValue) {
1200
+                $result[$mapKey] = $mapValue;
1201
+            }
1202
+        }
1203
+
1204
+        return new static($result);
1205
+    }
1206
+
1207
+    /**
1208
+     * Map a collection and flatten the result by a single level.
1209
+     *
1210
+     * @param  callable  $callback
1211
+     * @return static
1212
+     */
1213
+    public function flatMap(callable $callback)
1214
+    {
1215
+        return $this->map($callback)->collapse();
1216
+    }
1217
+
1218
+    /**
1219
+     * Map the values into a new class.
1220
+     *
1221
+     * @param  string  $class
1222
+     * @return static
1223
+     */
1224
+    public function mapInto($class)
1225
+    {
1226
+        return $this->map(function ($value, $key) use ($class) {
1227
+            return new $class($value, $key);
1228
+        });
1229
+    }
1230
+
1231
+    /**
1232
+     * Get the max value of a given key.
1233
+     *
1234
+     * @param  callable|string|null  $callback
1235
+     * @return mixed
1236
+     */
1237
+    public function max($callback = null)
1238
+    {
1239
+        $callback = $this->valueRetriever($callback);
1240
+
1241
+        return $this->filter(function ($value) {
1242
+            return ! is_null($value);
1243
+        })->reduce(function ($result, $item) use ($callback) {
1244
+            $value = $callback($item);
1245
+
1246
+            return is_null($result) || $value > $result ? $value : $result;
1247
+        });
1248
+    }
1249
+
1250
+    /**
1251
+     * Merge the collection with the given items.
1252
+     *
1253
+     * @param  mixed  $items
1254
+     * @return static
1255
+     */
1256
+    public function merge($items)
1257
+    {
1258
+        return new static(array_merge($this->items, $this->getArrayableItems($items)));
1259
+    }
1260
+
1261
+    /**
1262
+     * Recursively merge the collection with the given items.
1263
+     *
1264
+     * @param  mixed  $items
1265
+     * @return static
1266
+     */
1267
+    public function mergeRecursive($items)
1268
+    {
1269
+        return new static(array_merge_recursive($this->items, $this->getArrayableItems($items)));
1270
+    }
1271
+
1272
+    /**
1273
+     * Create a collection by using this collection for keys and another for its values.
1274
+     *
1275
+     * @param  mixed  $values
1276
+     * @return static
1277
+     */
1278
+    public function combine($values)
1279
+    {
1280
+        return new static(array_combine($this->all(), $this->getArrayableItems($values)));
1281
+    }
1282
+
1283
+    /**
1284
+     * Union the collection with the given items.
1285
+     *
1286
+     * @param  mixed  $items
1287
+     * @return static
1288
+     */
1289
+    public function union($items)
1290
+    {
1291
+        return new static($this->items + $this->getArrayableItems($items));
1292
+    }
1293
+
1294
+    /**
1295
+     * Get the min value of a given key.
1296
+     *
1297
+     * @param  callable|string|null  $callback
1298
+     * @return mixed
1299
+     */
1300
+    public function min($callback = null)
1301
+    {
1302
+        $callback = $this->valueRetriever($callback);
1303
+
1304
+        return $this->map(function ($value) use ($callback) {
1305
+            return $callback($value);
1306
+        })->filter(function ($value) {
1307
+            return ! is_null($value);
1308
+        })->reduce(function ($result, $value) {
1309
+            return is_null($result) || $value < $result ? $value : $result;
1310
+        });
1311
+    }
1312
+
1313
+    /**
1314
+     * Create a new collection consisting of every n-th element.
1315
+     *
1316
+     * @param  int  $step
1317
+     * @param  int  $offset
1318
+     * @return static
1319
+     */
1320
+    public function nth($step, $offset = 0)
1321
+    {
1322
+        $new = [];
1323
+
1324
+        $position = 0;
1325
+
1326
+        foreach ($this->items as $item) {
1327
+            if ($position % $step === $offset) {
1328
+                $new[] = $item;
1329
+            }
1330
+
1331
+            $position++;
1332
+        }
1333
+
1334
+        return new static($new);
1335
+    }
1336
+
1337
+    /**
1338
+     * Get the items with the specified keys.
1339
+     *
1340
+     * @param  mixed  $keys
1341
+     * @return static
1342
+     */
1343
+    public function only($keys)
1344
+    {
1345
+        if (is_null($keys)) {
1346
+            return new static($this->items);
1347
+        }
1348
+
1349
+        if ($keys instanceof self) {
1350
+            $keys = $keys->all();
1351
+        }
1352
+
1353
+        $keys = is_array($keys) ? $keys : func_get_args();
1354
+
1355
+        return new static(Arr::only($this->items, $keys));
1356
+    }
1357
+
1358
+    /**
1359
+     * "Paginate" the collection by slicing it into a smaller collection.
1360
+     *
1361
+     * @param  int  $page
1362
+     * @param  int  $perPage
1363
+     * @return static
1364
+     */
1365
+    public function forPage($page, $perPage)
1366
+    {
1367
+        $offset = max(0, ($page - 1) * $perPage);
1368
+
1369
+        return $this->slice($offset, $perPage);
1370
+    }
1371
+
1372
+    /**
1373
+     * Partition the collection into two arrays using the given callback or key.
1374
+     *
1375
+     * @param  callable|string  $key
1376
+     * @param  mixed  $operator
1377
+     * @param  mixed  $value
1378
+     * @return static
1379
+     */
1380
+    public function partition($key, $operator = null, $value = null)
1381
+    {
1382
+        $partitions = [new static, new static];
1383
+
1384
+        $callback = func_num_args() === 1
1385
+                ? $this->valueRetriever($key)
1386
+                : $this->operatorForWhere(...func_get_args());
1387
+
1388
+        foreach ($this->items as $key => $item) {
1389
+            $partitions[(int) ! $callback($item, $key)][$key] = $item;
1390
+        }
1391
+
1392
+        return new static($partitions);
1393
+    }
1394
+
1395
+    /**
1396
+     * Pass the collection to the given callback and return the result.
1397
+     *
1398
+     * @param  callable $callback
1399
+     * @return mixed
1400
+     */
1401
+    public function pipe(callable $callback)
1402
+    {
1403
+        return $callback($this);
1404
+    }
1405
+
1406
+    /**
1407
+     * Get and remove the last item from the collection.
1408
+     *
1409
+     * @return mixed
1410
+     */
1411
+    public function pop()
1412
+    {
1413
+        return array_pop($this->items);
1414
+    }
1415
+
1416
+    /**
1417
+     * Push an item onto the beginning of the collection.
1418
+     *
1419
+     * @param  mixed  $value
1420
+     * @param  mixed  $key
1421
+     * @return $this
1422
+     */
1423
+    public function prepend($value, $key = null)
1424
+    {
1425
+        $this->items = Arr::prepend($this->items, $value, $key);
1426
+
1427
+        return $this;
1428
+    }
1429
+
1430
+    /**
1431
+     * Push an item onto the end of the collection.
1432
+     *
1433
+     * @param  mixed  $value
1434
+     * @return $this
1435
+     */
1436
+    public function push($value)
1437
+    {
1438
+        $this->offsetSet(null, $value);
1439
+
1440
+        return $this;
1441
+    }
1442
+
1443
+    /**
1444
+     * Push all of the given items onto the collection.
1445
+     *
1446
+     * @param  iterable  $source
1447
+     * @return static
1448
+     */
1449
+    public function concat($source)
1450
+    {
1451
+        $result = new static($this);
1452
+
1453
+        foreach ($source as $item) {
1454
+            $result->push($item);
1455
+        }
1456
+
1457
+        return $result;
1458
+    }
1459
+
1460
+    /**
1461
+     * Get and remove an item from the collection.
1462
+     *
1463
+     * @param  mixed  $key
1464
+     * @param  mixed  $default
1465
+     * @return mixed
1466
+     */
1467
+    public function pull($key, $default = null)
1468
+    {
1469
+        return Arr::pull($this->items, $key, $default);
1470
+    }
1471
+
1472
+    /**
1473
+     * Put an item in the collection by key.
1474
+     *
1475
+     * @param  mixed  $key
1476
+     * @param  mixed  $value
1477
+     * @return $this
1478
+     */
1479
+    public function put($key, $value)
1480
+    {
1481
+        $this->offsetSet($key, $value);
1482
+
1483
+        return $this;
1484
+    }
1485
+
1486
+    /**
1487
+     * Get one or a specified number of items randomly from the collection.
1488
+     *
1489
+     * @param  int|null  $number
1490
+     * @return static|mixed
1491
+     *
1492
+     * @throws \InvalidArgumentException
1493
+     */
1494
+    public function random($number = null)
1495
+    {
1496
+        if (is_null($number)) {
1497
+            return Arr::random($this->items);
1498
+        }
1499
+
1500
+        return new static(Arr::random($this->items, $number));
1501
+    }
1502
+
1503
+    /**
1504
+     * Reduce the collection to a single value.
1505
+     *
1506
+     * @param  callable  $callback
1507
+     * @param  mixed  $initial
1508
+     * @return mixed
1509
+     */
1510
+    public function reduce(callable $callback, $initial = null)
1511
+    {
1512
+        return array_reduce($this->items, $callback, $initial);
1513
+    }
1514
+
1515
+    /**
1516
+     * Create a collection of all elements that do not pass a given truth test.
1517
+     *
1518
+     * @param  callable|mixed  $callback
1519
+     * @return static
1520
+     */
1521
+    public function reject($callback = true)
1522
+    {
1523
+        $useAsCallable = $this->useAsCallable($callback);
1524
+
1525
+        return $this->filter(function ($value, $key) use ($callback, $useAsCallable) {
1526
+            return $useAsCallable
1527
+                ? ! $callback($value, $key)
1528
+                : $value != $callback;
1529
+        });
1530
+    }
1531
+
1532
+    /**
1533
+     * Replace the collection items with the given items.
1534
+     *
1535
+     * @param  mixed  $items
1536
+     * @return static
1537
+     */
1538
+    public function replace($items)
1539
+    {
1540
+        return new static(array_replace($this->items, $this->getArrayableItems($items)));
1541
+    }
1542
+
1543
+    /**
1544
+     * Recursively replace the collection items with the given items.
1545
+     *
1546
+     * @param  mixed  $items
1547
+     * @return static
1548
+     */
1549
+    public function replaceRecursive($items)
1550
+    {
1551
+        return new static(array_replace_recursive($this->items, $this->getArrayableItems($items)));
1552
+    }
1553
+
1554
+    /**
1555
+     * Reverse items order.
1556
+     *
1557
+     * @return static
1558
+     */
1559
+    public function reverse()
1560
+    {
1561
+        return new static(array_reverse($this->items, true));
1562
+    }
1563
+
1564
+    /**
1565
+     * Search the collection for a given value and return the corresponding key if successful.
1566
+     *
1567
+     * @param  mixed  $value
1568
+     * @param  bool  $strict
1569
+     * @return mixed
1570
+     */
1571
+    public function search($value, $strict = false)
1572
+    {
1573
+        if (! $this->useAsCallable($value)) {
1574
+            return array_search($value, $this->items, $strict);
1575
+        }
1576
+
1577
+        foreach ($this->items as $key => $item) {
1578
+            if (call_user_func($value, $item, $key)) {
1579
+                return $key;
1580
+            }
1581
+        }
1582
+
1583
+        return false;
1584
+    }
1585
+
1586
+    /**
1587
+     * Get and remove the first item from the collection.
1588
+     *
1589
+     * @return mixed
1590
+     */
1591
+    public function shift()
1592
+    {
1593
+        return array_shift($this->items);
1594
+    }
1595
+
1596
+    /**
1597
+     * Shuffle the items in the collection.
1598
+     *
1599
+     * @param  int  $seed
1600
+     * @return static
1601
+     */
1602
+    public function shuffle($seed = null)
1603
+    {
1604
+        return new static(Arr::shuffle($this->items, $seed));
1605
+    }
1606
+
1607
+    /**
1608
+     * Slice the underlying collection array.
1609
+     *
1610
+     * @param  int  $offset
1611
+     * @param  int  $length
1612
+     * @return static
1613
+     */
1614
+    public function slice($offset, $length = null)
1615
+    {
1616
+        return new static(array_slice($this->items, $offset, $length, true));
1617
+    }
1618
+
1619
+    /**
1620
+     * Split a collection into a certain number of groups.
1621
+     *
1622
+     * @param  int  $numberOfGroups
1623
+     * @return static
1624
+     */
1625
+    public function split($numberOfGroups)
1626
+    {
1627
+        if ($this->isEmpty()) {
1628
+            return new static;
1629
+        }
1630
+
1631
+        $groups = new static;
1632
+
1633
+        $groupSize = floor($this->count() / $numberOfGroups);
1634
+
1635
+        $remain = $this->count() % $numberOfGroups;
1636
+
1637
+        $start = 0;
1638
+
1639
+        for ($i = 0; $i < $numberOfGroups; $i++) {
1640
+            $size = $groupSize;
1641
+
1642
+            if ($i < $remain) {
1643
+                $size++;
1644
+            }
1645
+
1646
+            if ($size) {
1647
+                $groups->push(new static(array_slice($this->items, $start, $size)));
1648
+
1649
+                $start += $size;
1650
+            }
1651
+        }
1652
+
1653
+        return $groups;
1654
+    }
1655
+
1656
+    /**
1657
+     * Chunk the underlying collection array.
1658
+     *
1659
+     * @param  int  $size
1660
+     * @return static
1661
+     */
1662
+    public function chunk($size)
1663
+    {
1664
+        if ($size <= 0) {
1665
+            return new static;
1666
+        }
1667
+
1668
+        $chunks = [];
1669
+
1670
+        foreach (array_chunk($this->items, $size, true) as $chunk) {
1671
+            $chunks[] = new static($chunk);
1672
+        }
1673
+
1674
+        return new static($chunks);
1675
+    }
1676
+
1677
+    /**
1678
+     * Sort through each item with a callback.
1679
+     *
1680
+     * @param  callable|null  $callback
1681
+     * @return static
1682
+     */
1683
+    public function sort(callable $callback = null)
1684
+    {
1685
+        $items = $this->items;
1686
+
1687
+        $callback
1688
+            ? uasort($items, $callback)
1689
+            : asort($items);
1690
+
1691
+        return new static($items);
1692
+    }
1693
+
1694
+    /**
1695
+     * Sort the collection using the given callback.
1696
+     *
1697
+     * @param  callable|string  $callback
1698
+     * @param  int  $options
1699
+     * @param  bool  $descending
1700
+     * @return static
1701
+     */
1702
+    public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
1703
+    {
1704
+        $results = [];
1705
+
1706
+        $callback = $this->valueRetriever($callback);
1707
+
1708
+        // First we will loop through the items and get the comparator from a callback
1709
+        // function which we were given. Then, we will sort the returned values and
1710
+        // and grab the corresponding values for the sorted keys from this array.
1711
+        foreach ($this->items as $key => $value) {
1712
+            $results[$key] = $callback($value, $key);
1713
+        }
1714
+
1715
+        $descending ? arsort($results, $options)
1716
+            : asort($results, $options);
1717
+
1718
+        // Once we have sorted all of the keys in the array, we will loop through them
1719
+        // and grab the corresponding model so we can set the underlying items list
1720
+        // to the sorted version. Then we'll just return the collection instance.
1721
+        foreach (array_keys($results) as $key) {
1722
+            $results[$key] = $this->items[$key];
1723
+        }
1724
+
1725
+        return new static($results);
1726
+    }
1727
+
1728
+    /**
1729
+     * Sort the collection in descending order using the given callback.
1730
+     *
1731
+     * @param  callable|string  $callback
1732
+     * @param  int  $options
1733
+     * @return static
1734
+     */
1735
+    public function sortByDesc($callback, $options = SORT_REGULAR)
1736
+    {
1737
+        return $this->sortBy($callback, $options, true);
1738
+    }
1739
+
1740
+    /**
1741
+     * Sort the collection keys.
1742
+     *
1743
+     * @param  int  $options
1744
+     * @param  bool  $descending
1745
+     * @return static
1746
+     */
1747
+    public function sortKeys($options = SORT_REGULAR, $descending = false)
1748
+    {
1749
+        $items = $this->items;
1750
+
1751
+        $descending ? krsort($items, $options) : ksort($items, $options);
1752
+
1753
+        return new static($items);
1754
+    }
1755
+
1756
+    /**
1757
+     * Sort the collection keys in descending order.
1758
+     *
1759
+     * @param  int $options
1760
+     * @return static
1761
+     */
1762
+    public function sortKeysDesc($options = SORT_REGULAR)
1763
+    {
1764
+        return $this->sortKeys($options, true);
1765
+    }
1766
+
1767
+    /**
1768
+     * Splice a portion of the underlying collection array.
1769
+     *
1770
+     * @param  int  $offset
1771
+     * @param  int|null  $length
1772
+     * @param  mixed  $replacement
1773
+     * @return static
1774
+     */
1775
+    public function splice($offset, $length = null, $replacement = [])
1776
+    {
1777
+        if (func_num_args() === 1) {
1778
+            return new static(array_splice($this->items, $offset));
1779
+        }
1780
+
1781
+        return new static(array_splice($this->items, $offset, $length, $replacement));
1782
+    }
1783
+
1784
+    /**
1785
+     * Get the sum of the given values.
1786
+     *
1787
+     * @param  callable|string|null  $callback
1788
+     * @return mixed
1789
+     */
1790
+    public function sum($callback = null)
1791
+    {
1792
+        if (is_null($callback)) {
1793
+            return array_sum($this->items);
1794
+        }
1795
+
1796
+        $callback = $this->valueRetriever($callback);
1797
+
1798
+        return $this->reduce(function ($result, $item) use ($callback) {
1799
+            return $result + $callback($item);
1800
+        }, 0);
1801
+    }
1802
+
1803
+    /**
1804
+     * Take the first or last {$limit} items.
1805
+     *
1806
+     * @param  int  $limit
1807
+     * @return static
1808
+     */
1809
+    public function take($limit)
1810
+    {
1811
+        if ($limit < 0) {
1812
+            return $this->slice($limit, abs($limit));
1813
+        }
1814
+
1815
+        return $this->slice(0, $limit);
1816
+    }
1817
+
1818
+    /**
1819
+     * Pass the collection to the given callback and then return it.
1820
+     *
1821
+     * @param  callable  $callback
1822
+     * @return $this
1823
+     */
1824
+    public function tap(callable $callback)
1825
+    {
1826
+        $callback(new static($this->items));
1827
+
1828
+        return $this;
1829
+    }
1830
+
1831
+    /**
1832
+     * Transform each item in the collection using a callback.
1833
+     *
1834
+     * @param  callable  $callback
1835
+     * @return $this
1836
+     */
1837
+    public function transform(callable $callback)
1838
+    {
1839
+        $this->items = $this->map($callback)->all();
1840
+
1841
+        return $this;
1842
+    }
1843
+
1844
+    /**
1845
+     * Return only unique items from the collection array.
1846
+     *
1847
+     * @param  string|callable|null  $key
1848
+     * @param  bool  $strict
1849
+     * @return static
1850
+     */
1851
+    public function unique($key = null, $strict = false)
1852
+    {
1853
+        $callback = $this->valueRetriever($key);
1854
+
1855
+        $exists = [];
1856
+
1857
+        return $this->reject(function ($item, $key) use ($callback, $strict, &$exists) {
1858
+            if (in_array($id = $callback($item, $key), $exists, $strict)) {
1859
+                return true;
1860
+            }
1861
+
1862
+            $exists[] = $id;
1863
+        });
1864
+    }
1865
+
1866
+    /**
1867
+     * Return only unique items from the collection array using strict comparison.
1868
+     *
1869
+     * @param  string|callable|null  $key
1870
+     * @return static
1871
+     */
1872
+    public function uniqueStrict($key = null)
1873
+    {
1874
+        return $this->unique($key, true);
1875
+    }
1876
+
1877
+    /**
1878
+     * Reset the keys on the underlying array.
1879
+     *
1880
+     * @return static
1881
+     */
1882
+    public function values()
1883
+    {
1884
+        return new static(array_values($this->items));
1885
+    }
1886
+
1887
+    /**
1888
+     * Get a value retrieving callback.
1889
+     *
1890
+     * @param  callable|string|null  $value
1891
+     * @return callable
1892
+     */
1893
+    protected function valueRetriever($value)
1894
+    {
1895
+        if ($this->useAsCallable($value)) {
1896
+            return $value;
1897
+        }
1898
+
1899
+        return function ($item) use ($value) {
1900
+            return data_get($item, $value);
1901
+        };
1902
+    }
1903
+
1904
+    /**
1905
+     * Zip the collection together with one or more arrays.
1906
+     *
1907
+     * e.g. new Collection([1, 2, 3])->zip([4, 5, 6]);
1908
+     *      => [[1, 4], [2, 5], [3, 6]]
1909
+     *
1910
+     * @param  mixed ...$items
1911
+     * @return static
1912
+     */
1913
+    public function zip($items)
1914
+    {
1915
+        $arrayableItems = array_map(function ($items) {
1916
+            return $this->getArrayableItems($items);
1917
+        }, func_get_args());
1918
+
1919
+        $params = array_merge([function () {
1920
+            return new static(func_get_args());
1921
+        }, $this->items], $arrayableItems);
1922
+
1923
+        return new static(call_user_func_array('array_map', $params));
1924
+    }
1925
+
1926
+    /**
1927
+     * Pad collection to the specified length with a value.
1928
+     *
1929
+     * @param  int  $size
1930
+     * @param  mixed  $value
1931
+     * @return static
1932
+     */
1933
+    public function pad($size, $value)
1934
+    {
1935
+        return new static(array_pad($this->items, $size, $value));
1936
+    }
1937
+
1938
+    /**
1939
+     * Get the collection of items as a plain array.
1940
+     *
1941
+     * @return array
1942
+     */
1943
+    public function toArray()
1944
+    {
1945
+        return array_map(function ($value) {
1946
+            return $value instanceof Arrayable ? $value->toArray() : $value;
1947
+        }, $this->items);
1948
+    }
1949
+
1950
+    /**
1951
+     * Convert the object into something JSON serializable.
1952
+     *
1953
+     * @return array
1954
+     */
1955
+    public function jsonSerialize()
1956
+    {
1957
+        return array_map(function ($value) {
1958
+            if ($value instanceof JsonSerializable) {
1959
+                return $value->jsonSerialize();
1960
+            } elseif ($value instanceof Jsonable) {
1961
+                return json_decode($value->toJson(), true);
1962
+            } elseif ($value instanceof Arrayable) {
1963
+                return $value->toArray();
1964
+            }
1965
+
1966
+            return $value;
1967
+        }, $this->items);
1968
+    }
1969
+
1970
+    /**
1971
+     * Get the collection of items as JSON.
1972
+     *
1973
+     * @param  int  $options
1974
+     * @return string
1975
+     */
1976
+    public function toJson($options = 0)
1977
+    {
1978
+        return json_encode($this->jsonSerialize(), $options);
1979
+    }
1980
+
1981
+    /**
1982
+     * Get an iterator for the items.
1983
+     *
1984
+     * @return \ArrayIterator
1985
+     */
1986
+    public function getIterator()
1987
+    {
1988
+        return new ArrayIterator($this->items);
1989
+    }
1990
+
1991
+    /**
1992
+     * Get a CachingIterator instance.
1993
+     *
1994
+     * @param  int  $flags
1995
+     * @return \CachingIterator
1996
+     */
1997
+    public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING)
1998
+    {
1999
+        return new CachingIterator($this->getIterator(), $flags);
2000
+    }
2001
+
2002
+    /**
2003
+     * Count the number of items in the collection.
2004
+     *
2005
+     * @return int
2006
+     */
2007
+    public function count()
2008
+    {
2009
+        return count($this->items);
2010
+    }
2011
+
2012
+    /**
2013
+     * Count the number of items in the collection using a given truth test.
2014
+     *
2015
+     * @param  callable|null  $callback
2016
+     * @return static
2017
+     */
2018
+    public function countBy($callback = null)
2019
+    {
2020
+        if (is_null($callback)) {
2021
+            $callback = function ($value) {
2022
+                return $value;
2023
+            };
2024
+        }
2025
+
2026
+        return new static($this->groupBy($callback)->map(function ($value) {
2027
+            return $value->count();
2028
+        }));
2029
+    }
2030
+
2031
+    /**
2032
+     * Add an item to the collection.
2033
+     *
2034
+     * @param  mixed  $item
2035
+     * @return $this
2036
+     */
2037
+    public function add($item)
2038
+    {
2039
+        $this->items[] = $item;
2040
+
2041
+        return $this;
2042
+    }
2043
+
2044
+    /**
2045
+     * Get a base Support collection instance from this collection.
2046
+     *
2047
+     * @return \Illuminate\Support\Collection
2048
+     */
2049
+    public function toBase()
2050
+    {
2051
+        return new self($this);
2052
+    }
2053
+
2054
+    /**
2055
+     * Determine if an item exists at an offset.
2056
+     *
2057
+     * @param  mixed  $key
2058
+     * @return bool
2059
+     */
2060
+    public function offsetExists($key)
2061
+    {
2062
+        return array_key_exists($key, $this->items);
2063
+    }
2064
+
2065
+    /**
2066
+     * Get an item at a given offset.
2067
+     *
2068
+     * @param  mixed  $key
2069
+     * @return mixed
2070
+     */
2071
+    public function offsetGet($key)
2072
+    {
2073
+        return $this->items[$key];
2074
+    }
2075
+
2076
+    /**
2077
+     * Set the item at a given offset.
2078
+     *
2079
+     * @param  mixed  $key
2080
+     * @param  mixed  $value
2081
+     * @return void
2082
+     */
2083
+    public function offsetSet($key, $value)
2084
+    {
2085
+        if (is_null($key)) {
2086
+            $this->items[] = $value;
2087
+        } else {
2088
+            $this->items[$key] = $value;
2089
+        }
2090
+    }
2091
+
2092
+    /**
2093
+     * Unset the item at a given offset.
2094
+     *
2095
+     * @param  string  $key
2096
+     * @return void
2097
+     */
2098
+    public function offsetUnset($key)
2099
+    {
2100
+        unset($this->items[$key]);
2101
+    }
2102
+
2103
+    /**
2104
+     * Convert the collection to its string representation.
2105
+     *
2106
+     * @return string
2107
+     */
2108
+    public function __toString()
2109
+    {
2110
+        return $this->toJson();
2111
+    }
2112
+
2113
+    /**
2114
+     * Results array of items from Collection or Arrayable.
2115
+     *
2116
+     * @param  mixed  $items
2117
+     * @return array
2118
+     */
2119
+    protected function getArrayableItems($items)
2120
+    {
2121
+        if (is_array($items)) {
2122
+            return $items;
2123
+        } elseif ($items instanceof self) {
2124
+            return $items->all();
2125
+        } elseif ($items instanceof Arrayable) {
2126
+            return $items->toArray();
2127
+        } elseif ($items instanceof Jsonable) {
2128
+            return json_decode($items->toJson(), true);
2129
+        } elseif ($items instanceof JsonSerializable) {
2130
+            return (array) $items->jsonSerialize();
2131
+        } elseif ($items instanceof Traversable) {
2132
+            return iterator_to_array($items);
2133
+        }
2134
+
2135
+        return (array) $items;
2136
+    }
2137
+
2138
+    /**
2139
+     * Add a method to the list of proxied methods.
2140
+     *
2141
+     * @param  string  $method
2142
+     * @return void
2143
+     */
2144
+    public static function proxy($method)
2145
+    {
2146
+        static::$proxies[] = $method;
2147
+    }
2148
+
2149
+    /**
2150
+     * Dynamically access collection proxies.
2151
+     *
2152
+     * @param  string  $key
2153
+     * @return mixed
2154
+     *
2155
+     * @throws \Exception
2156
+     */
2157
+    public function __get($key)
2158
+    {
2159
+        if (! in_array($key, static::$proxies)) {
2160
+            throw new Exception("Property [{$key}] does not exist on this collection instance.");
2161
+        }
2162
+
2163
+        return new HigherOrderCollectionProxy($this, $key);
2164
+    }
2165
+}