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