Completed
Push — master ( c7b24f...7511ca )
by Antonio Carlos
02:10
created

src/Support/Arr.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace IlluminateAgnostic\Arr\Support;
4
5
use ArrayAccess;
6
use InvalidArgumentException;
7
use IlluminateAgnostic\Arr\Support\Traits\Macroable;
8
9
class Arr
10
{
11
    use Macroable;
12
13
    /**
14
     * Determine whether the given value is array accessible.
15
     *
16
     * @param  mixed  $value
17
     * @return bool
18
     */
19 54
    public static function accessible($value)
20
    {
21 54
        return is_array($value) || $value instanceof ArrayAccess;
22
    }
23
24
    /**
25
     * Add an element to an array using "dot" notation if it doesn't exist.
26
     *
27
     * @param  array   $array
28
     * @param  string  $key
29
     * @param  mixed   $value
30
     * @return array
31
     */
32 1
    public static function add($array, $key, $value)
33
    {
34 1
        if (is_null(static::get($array, $key))) {
35 1
            static::set($array, $key, $value);
36
        }
37
38 1
        return $array;
39
    }
40
41
    /**
42
     * Collapse an array of arrays into a single array.
43
     *
44
     * @param  array  $array
45
     * @return array
46
     */
47 5
    public static function collapse($array)
48
    {
49 5
        $results = [];
50
51 5
        foreach ($array as $values) {
52 5
            if ($values instanceof Collection) {
53 2
                $values = $values->all();
54 4
            } elseif (! is_array($values)) {
55 1
                continue;
56
            }
57
58 5
            $results = array_merge($results, $values);
59
        }
60
61 5
        return $results;
62
    }
63
64
    /**
65
     * Cross join the given arrays, returning all possible permutations.
66
     *
67
     * @param  array  ...$arrays
68
     * @return array
69
     */
70 2
    public static function crossJoin(...$arrays)
71
    {
72 2
        $results = [[]];
73
74 2
        foreach ($arrays as $index => $array) {
75 2
            $append = [];
76
77 2
            foreach ($results as $product) {
78 2
                foreach ($array as $item) {
79 2
                    $product[$index] = $item;
80
81 2
                    $append[] = $product;
82
                }
83
            }
84
85 2
            $results = $append;
86
        }
87
88 2
        return $results;
89
    }
90
91
    /**
92
     * Divide an array into two arrays. One with keys and the other with values.
93
     *
94
     * @param  array  $array
95
     * @return array
96
     */
97 1
    public static function divide($array)
98
    {
99 1
        return [array_keys($array), array_values($array)];
100
    }
101
102
    /**
103
     * Flatten a multi-dimensional associative array with dots.
104
     *
105
     * @param  array   $array
106
     * @param  string  $prepend
107
     * @return array
108
     */
109 1
    public static function dot($array, $prepend = '')
110
    {
111 1
        $results = [];
112
113 1
        foreach ($array as $key => $value) {
114 1
            if (is_array($value) && ! empty($value)) {
115 1
                $results = array_merge($results, static::dot($value, $prepend.$key.'.'));
116
            } else {
117 1
                $results[$prepend.$key] = $value;
118
            }
119
        }
120
121 1
        return $results;
122
    }
123
124
    /**
125
     * Get all of the given array except for a specified array of keys.
126
     *
127
     * @param  array  $array
128
     * @param  array|string  $keys
129
     * @return array
130
     */
131 3
    public static function except($array, $keys)
132
    {
133 3
        static::forget($array, $keys);
134
135 3
        return $array;
136
    }
137
138
    /**
139
     * Determine if the given key exists in the provided array.
140
     *
141
     * @param  \ArrayAccess|array  $array
142
     * @param  string|int  $key
143
     * @return bool
144
     */
145 51
    public static function exists($array, $key)
146
    {
147 51
        if ($array instanceof ArrayAccess) {
148 4
            return $array->offsetExists($key);
149
        }
150
151 50
        return array_key_exists($key, $array);
152
    }
153
154
    /**
155
     * Return the first element in an array passing a given truth test.
156
     *
157
     * @param  array  $array
158
     * @param  callable|null  $callback
159
     * @param  mixed  $default
160
     * @return mixed
161
     */
162 17
    public static function first($array, callable $callback = null, $default = null)
163
    {
164 17
        if (is_null($callback)) {
165 7
            if (empty($array)) {
166 1
                return value($default);
167
            }
168
169 6
            foreach ($array as $item) {
170 6
                return $item;
171
            }
172
        }
173
174 11
        foreach ($array as $key => $value) {
175 11
            if (call_user_func($callback, $value, $key)) {
176 9
                return $value;
177
            }
178
        }
179
180 7
        return value($default);
181
    }
182
183
    /**
184
     * Return the last element in an array passing a given truth test.
185
     *
186
     * @param  array  $array
187
     * @param  callable|null  $callback
188
     * @param  mixed  $default
189
     * @return mixed
190
     */
191 9
    public static function last($array, callable $callback = null, $default = null)
192
    {
193 9
        if (is_null($callback)) {
194 7
            return empty($array) ? value($default) : end($array);
195
        }
196
197 3
        return static::first(array_reverse($array, true), $callback, $default);
198
    }
199
200
    /**
201
     * Flatten a multi-dimensional array into a single level.
202
     *
203
     * @param  array  $array
204
     * @param  int  $depth
205
     * @return array
206
     */
207 5
    public static function flatten($array, $depth = INF)
208
    {
209 5
        $result = [];
210
211 5
        foreach ($array as $item) {
212 5
            $item = $item instanceof Collection ? $item->all() : $item;
213
214 5
            if (! is_array($item)) {
215 5
                $result[] = $item;
216 5
            } elseif ($depth === 1) {
217 3
                $result = array_merge($result, array_values($item));
218
            } else {
219 5
                $result = array_merge($result, static::flatten($item, $depth - 1));
220
            }
221
        }
222
223 5
        return $result;
224
    }
225
226
    /**
227
     * Remove one or many array items from a given array using "dot" notation.
228
     *
229
     * @param  array  $array
230
     * @param  array|string  $keys
231
     * @return void
232
     */
233 8
    public static function forget(&$array, $keys)
234
    {
235 8
        $original = &$array;
236
237 8
        $keys = (array) $keys;
238
239 8
        if (count($keys) === 0) {
240 1
            return;
241
        }
242
243 8
        foreach ($keys as $key) {
244
            // if the exact key exists in the top-level, remove it
245 8
            if (static::exists($array, $key)) {
246 6
                unset($array[$key]);
247
248 6
                continue;
249
            }
250
251 6
            $parts = explode('.', $key);
252
253
            // clean up before each pass
254 6
            $array = &$original;
255
256 6
            while (count($parts) > 1) {
257 3
                $part = array_shift($parts);
258
259 3
                if (isset($array[$part]) && is_array($array[$part])) {
260 3
                    $array = &$array[$part];
261
                } else {
262 2
                    continue 2;
263
                }
264
            }
265
266 5
            unset($array[array_shift($parts)]);
267
        }
268 8
    }
269
270
    /**
271
     * Get an item from an array using "dot" notation.
272
     *
273
     * @param  \ArrayAccess|array  $array
274
     * @param  string  $key
275
     * @param  mixed   $default
276
     * @return mixed
277
     */
278 6
    public static function get($array, $key, $default = null)
279
    {
280 6
        if (! static::accessible($array)) {
281 1
            return value($default);
282
        }
283
284 6
        if (is_null($key)) {
285 1
            return $array;
286
        }
287
288 6
        if (static::exists($array, $key)) {
289 4
            return $array[$key];
290
        }
291
292 4
        if (strpos($key, '.') === false) {
293 2
            return $array[$key] ?? value($default);
294
        }
295
296 3
        foreach (explode('.', $key) as $segment) {
297 3
            if (static::accessible($array) && static::exists($array, $segment)) {
298 2
                $array = $array[$segment];
299
            } else {
300 3
                return value($default);
301
            }
302
        }
303
304 1
        return $array;
305
    }
306
307
    /**
308
     * Check if an item or items exist in an array using "dot" notation.
309
     *
310
     * @param  \ArrayAccess|array  $array
311
     * @param  string|array  $keys
312
     * @return bool
313
     */
314 1
    public static function has($array, $keys)
315
    {
316 1
        $keys = (array) $keys;
317
318 1
        if (! $array || $keys === []) {
319 1
            return false;
320
        }
321
322 1
        foreach ($keys as $key) {
323 1
            $subKeyArray = $array;
324
325 1
            if (static::exists($array, $key)) {
326 1
                continue;
327
            }
328
329 1
            foreach (explode('.', $key) as $segment) {
330 1
                if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) {
331 1
                    $subKeyArray = $subKeyArray[$segment];
332
                } else {
333 1
                    return false;
334
                }
335
            }
336
        }
337
338 1
        return true;
339
    }
340
341
    /**
342
     * Determines if an array is associative.
343
     *
344
     * An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
345
     *
346
     * @param  array  $array
347
     * @return bool
348
     */
349 2
    public static function isAssoc(array $array)
350
    {
351 2
        $keys = array_keys($array);
352
353 2
        return array_keys($keys) !== $keys;
354
    }
355
356
    /**
357
     * Get a subset of the items from the given array.
358
     *
359
     * @param  array  $array
360
     * @param  array|string  $keys
361
     * @return array
362
     */
363 2
    public static function only($array, $keys)
364
    {
365 2
        return array_intersect_key($array, array_flip((array) $keys));
366
    }
367
368
    /**
369
     * Pluck an array of values from an array.
370
     *
371
     * @param  array  $array
372
     * @param  string|array  $value
373
     * @param  string|array|null  $key
374
     * @return array
375
     */
376 17
    public static function pluck($array, $value, $key = null)
377
    {
378 17
        $results = [];
379
380 17
        [$value, $key] = static::explodePluckParameters($value, $key);
381
382 17
        foreach ($array as $item) {
383 17
            $itemValue = data_get($item, $value);
384
385
            // If the key is "null", we will just append the value to the array and keep
386
            // looping. Otherwise we will key the array using the value of the key we
387
            // received from the developer. Then we'll return the final array form.
388 17
            if (is_null($key)) {
389 15
                $results[] = $itemValue;
390
            } else {
391 7
                $itemKey = data_get($item, $key);
392
393 7
                if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
394 1
                    $itemKey = (string) $itemKey;
395
                }
396
397 7
                $results[$itemKey] = $itemValue;
398
            }
399
        }
400
401 17
        return $results;
402
    }
403
404
    /**
405
     * Explode the "value" and "key" arguments passed to "pluck".
406
     *
407
     * @param  string|array  $value
408
     * @param  string|array|null  $key
409
     * @return array
410
     */
411 17
    protected static function explodePluckParameters($value, $key)
412
    {
413 17
        $value = is_string($value) ? explode('.', $value) : $value;
414
415 17
        $key = is_null($key) || is_array($key) ? $key : explode('.', $key);
416
417 17
        return [$value, $key];
418
    }
419
420
    /**
421
     * Push an item onto the beginning of an array.
422
     *
423
     * @param  array  $array
424
     * @param  mixed  $value
425
     * @param  mixed  $key
426
     * @return array
427
     */
428 2
    public static function prepend($array, $value, $key = null)
429
    {
430 2
        if (is_null($key)) {
431 2
            array_unshift($array, $value);
432
        } else {
433 2
            $array = [$key => $value] + $array;
434
        }
435
436 2
        return $array;
437
    }
438
439
    /**
440
     * Get a value from the array, and remove it.
441
     *
442
     * @param  array   $array
443
     * @param  string  $key
444
     * @param  mixed   $default
445
     * @return mixed
446
     */
447 4
    public static function pull(&$array, $key, $default = null)
448
    {
449 4
        $value = static::get($array, $key, $default);
450
451 4
        static::forget($array, $key);
452
453 4
        return $value;
454
    }
455
456
    /**
457
     * Get one or a specified number of random values from an array.
458
     *
459
     * @param  array  $array
460
     * @param  int|null  $number
461
     * @return mixed
462
     *
463
     * @throws \InvalidArgumentException
464
     */
465 6
    public static function random($array, $number = null)
466
    {
467 6
        $requested = is_null($number) ? 1 : $number;
468
469 6
        $count = count($array);
470
471 6
        if ($requested > $count) {
472 2
            throw new InvalidArgumentException(
473 2
                "You requested {$requested} items, but there are only {$count} items available."
474
            );
475
        }
476
477 4
        if (is_null($number)) {
478 2
            return $array[array_rand($array)];
479
        }
480
481 4
        if ((int) $number === 0) {
482 4
            return [];
483
        }
484
485 2
        $keys = array_rand($array, $number);
486
487 2
        $results = [];
488
489 2
        foreach ((array) $keys as $key) {
490 2
            $results[] = $array[$key];
491
        }
492
493 2
        return $results;
494
    }
495
496
    /**
497
     * Set an array item to a given value using "dot" notation.
498
     *
499
     * If no key is given to the method, the entire array will be replaced.
500
     *
501
     * @param  array   $array
502
     * @param  string  $key
503
     * @param  mixed   $value
504
     * @return array
505
     */
506 3
    public static function set(&$array, $key, $value)
507
    {
508 3
        if (is_null($key)) {
509 1
            return $array = $value;
510
        }
511
512 3
        $keys = explode('.', $key);
513
514 3
        while (count($keys) > 1) {
515 3
            $key = array_shift($keys);
516
517
            // If the key doesn't exist at this depth, we will just create an empty array
518
            // to hold the next value, allowing us to create the arrays to hold final
519
            // values at the correct depth. Then we'll keep digging into the array.
520 3
            if (! isset($array[$key]) || ! is_array($array[$key])) {
521 2
                $array[$key] = [];
522
            }
523
524 3
            $array = &$array[$key];
525
        }
526
527 3
        $array[array_shift($keys)] = $value;
528
529 3
        return $array;
530
    }
531
532
    /**
533
     * Shuffle the given array and return the result.
534
     *
535
     * @param  array  $array
536
     * @param  int|null  $seed
537
     * @return array
538
     */
539 3
    public static function shuffle($array, $seed = null)
540
    {
541 3
        if (is_null($seed)) {
542 1
            shuffle($array);
543
        } else {
544 2
            srand($seed);
545 2
546 2
            usort($array, function () {
547
                return rand(-1, 1);
548
            });
549 3
        }
550
551
        return $array;
552
    }
553
554
    /**
555
     * Sort the array using the given callback or "dot" notation.
556
     *
557
     * @param  array  $array
558
     * @param  callable|string|null  $callback
559 1
     * @return array
560
     */
561 1
    public static function sort($array, $callback = null)
562
    {
563
        return Collection::make($array)->sortBy($callback)->all();
0 ignored issues
show
It seems like $callback defined by parameter $callback on line 561 can also be of type null; however, IlluminateAgnostic\Arr\S...rt\Collection::sortBy() does only seem to accept callable, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
564
    }
565
566
    /**
567
     * Recursively sort an array by keys and values.
568
     *
569
     * @param  array  $array
570 1
     * @return array
571
     */
572 1
    public static function sortRecursive($array)
573 1
    {
574 1
        foreach ($array as &$value) {
575
            if (is_array($value)) {
576
                $value = static::sortRecursive($value);
577
            }
578 1
        }
579 1
580
        if (static::isAssoc($array)) {
581 1
            ksort($array);
582
        } else {
583
            sort($array);
584 1
        }
585
586
        return $array;
587
    }
588
589
    /**
590
     * Convert the array into a query string.
591
     *
592
     * @param  array  $array
593 1
     * @return string
594
     */
595 1
    public static function query($array)
596
    {
597
        return http_build_query($array, null, '&', PHP_QUERY_RFC3986);
598
    }
599
600
    /**
601
     * Filter the array using the given callback.
602
     *
603
     * @param  array  $array
604
     * @param  callable  $callback
605 34
     * @return array
606
     */
607 34
    public static function where($array, callable $callback)
608
    {
609
        return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
610
    }
611
612
    /**
613
     * If the given value is not an array and not null, wrap it in one.
614
     *
615
     * @param  mixed  $value
616 6
     * @return array
617
     */
618 6
    public static function wrap($value)
619 1
    {
620
        if (is_null($value)) {
621
            return [];
622 6
        }
623
624
        return is_array($value) ? $value : [$value];
625
    }
626
}
627