Completed
Push — master ( a7bdd4...c7897e )
by Antonio Carlos
03:18
created

Arr::shuffle()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 2
dl 0
loc 14
ccs 2
cts 2
cp 1
crap 2
rs 9.7998
c 0
b 0
f 0
1
<?php
2
3
namespace IlluminateAgnostic\Collection\Support;
4
5
use ArrayAccess;
6
use InvalidArgumentException;
7
use IlluminateAgnostic\Collection\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 4
    public static function collapse($array)
48
    {
49 4
        $results = [];
50
51 4
        foreach ($array as $values) {
52 4
            if ($values instanceof Collection) {
53 2
                $values = $values->all();
54 3
            } elseif (! is_array($values)) {
55
                continue;
56
            }
57
58 4
            $results = array_merge($results, $values);
59
        }
60
61 4
        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 View Code Duplication
        foreach (explode('.', $key) as $segment) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
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
        if (is_null($keys)) {
317
            return false;
318 1
        }
319 1
320
        $keys = (array) $keys;
321
322 1
        if (! $array) {
323 1
            return false;
324
        }
325 1
326 1
        if ($keys === []) {
327
            return false;
328
        }
329 1
330 1
        foreach ($keys as $key) {
331 1
            $subKeyArray = $array;
332
333 1
            if (static::exists($array, $key)) {
334
                continue;
335
            }
336
337 View Code Duplication
            foreach (explode('.', $key) as $segment) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
338 1
                if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) {
339
                    $subKeyArray = $subKeyArray[$segment];
340
                } else {
341
                    return false;
342
                }
343
            }
344
        }
345
346
        return true;
347
    }
348
349 2
    /**
350
     * Determines if an array is associative.
351 2
     *
352
     * An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
353 2
     *
354
     * @param  array  $array
355
     * @return bool
356
     */
357
    public static function isAssoc(array $array)
358
    {
359
        $keys = array_keys($array);
360
361
        return array_keys($keys) !== $keys;
362
    }
363 2
364
    /**
365 2
     * Get a subset of the items from the given array.
366
     *
367
     * @param  array  $array
368
     * @param  array|string  $keys
369
     * @return array
370
     */
371
    public static function only($array, $keys)
372
    {
373
        return array_intersect_key($array, array_flip((array) $keys));
374
    }
375
376 17
    /**
377
     * Pluck an array of values from an array.
378 17
     *
379
     * @param  array  $array
380 17
     * @param  string|array  $value
381
     * @param  string|array|null  $key
382 17
     * @return array
383 17
     */
384
    public static function pluck($array, $value, $key = null)
385
    {
386
        $results = [];
387
388 17
        list($value, $key) = static::explodePluckParameters($value, $key);
389 15
390
        foreach ($array as $item) {
391 7
            $itemValue = data_get($item, $value);
392
393 7
            // If the key is "null", we will just append the value to the array and keep
394 1
            // looping. Otherwise we will key the array using the value of the key we
395
            // received from the developer. Then we'll return the final array form.
396
            if (is_null($key)) {
397 7
                $results[] = $itemValue;
398
            } else {
399
                $itemKey = data_get($item, $key);
400
401 17
                if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
402
                    $itemKey = (string) $itemKey;
403
                }
404
405
                $results[$itemKey] = $itemValue;
406
            }
407
        }
408
409
        return $results;
410
    }
411 17
412
    /**
413 17
     * Explode the "value" and "key" arguments passed to "pluck".
414
     *
415 17
     * @param  string|array  $value
416
     * @param  string|array|null  $key
417 17
     * @return array
418
     */
419
    protected static function explodePluckParameters($value, $key)
420
    {
421
        $value = is_string($value) ? explode('.', $value) : $value;
422
423
        $key = is_null($key) || is_array($key) ? $key : explode('.', $key);
424
425
        return [$value, $key];
426
    }
427
428 2
    /**
429
     * Push an item onto the beginning of an array.
430 2
     *
431 2
     * @param  array  $array
432
     * @param  mixed  $value
433 2
     * @param  mixed  $key
434
     * @return array
435
     */
436 2
    public static function prepend($array, $value, $key = null)
437
    {
438
        if (is_null($key)) {
439
            array_unshift($array, $value);
440
        } else {
441
            $array = [$key => $value] + $array;
442
        }
443
444
        return $array;
445
    }
446
447 4
    /**
448
     * Get a value from the array, and remove it.
449 4
     *
450
     * @param  array   $array
451 4
     * @param  string  $key
452
     * @param  mixed   $default
453 4
     * @return mixed
454
     */
455
    public static function pull(&$array, $key, $default = null)
456
    {
457
        $value = static::get($array, $key, $default);
458
459
        static::forget($array, $key);
460
461
        return $value;
462
    }
463
464
    /**
465 6
     * Get one or a specified number of random values from an array.
466
     *
467 6
     * @param  array  $array
468
     * @param  int|null  $number
469 6
     * @return mixed
470
     *
471 6
     * @throws \InvalidArgumentException
472 2
     */
473 2
    public static function random($array, $number = null)
474
    {
475
        $requested = is_null($number) ? 1 : $number;
476
477 4
        $count = count($array);
478 2
479
        if ($requested > $count) {
480
            throw new InvalidArgumentException(
481 4
                "You requested {$requested} items, but there are only {$count} items available."
482 4
            );
483
        }
484
485 2
        if (is_null($number)) {
486
            return $array[array_rand($array)];
487 2
        }
488
489 2
        if ((int) $number === 0) {
490 2
            return [];
491
        }
492
493 2
        $keys = array_rand($array, $number);
494
495
        $results = [];
496
497
        foreach ((array) $keys as $key) {
498
            $results[] = $array[$key];
499
        }
500
501
        return $results;
502
    }
503
504
    /**
505
     * Set an array item to a given value using "dot" notation.
506 2
     *
507
     * If no key is given to the method, the entire array will be replaced.
508 2
     *
509
     * @param  array   $array
510
     * @param  string  $key
511
     * @param  mixed   $value
512 2
     * @return array
513
     */
514 2
    public static function set(&$array, $key, $value)
515 2
    {
516
        if (is_null($key)) {
517
            return $array = $value;
518
        }
519
520 2
        $keys = explode('.', $key);
521 1
522
        while (count($keys) > 1) {
523
            $key = array_shift($keys);
524 2
525
            // If the key doesn't exist at this depth, we will just create an empty array
526
            // to hold the next value, allowing us to create the arrays to hold final
527 2
            // values at the correct depth. Then we'll keep digging into the array.
528
            if (! isset($array[$key]) || ! is_array($array[$key])) {
529 2
                $array[$key] = [];
530
            }
531
532
            $array = &$array[$key];
533
        }
534
535
        $array[array_shift($keys)] = $value;
536
537
        return $array;
538
    }
539 2
540
    /**
541 2
     * Shuffle the given array and return the result.
542
     *
543
     * @param  array  $array
544 2
     * @param  int|null  $seed
545 2
     * @return array
546 2
     */
547
    public static function shuffle($array, $seed = null)
548
    {
549 2
        if (is_null($seed)) {
550
            shuffle($array);
551
        } else {
552
            srand($seed);
553
554
            usort($array, function () {
555
                return rand(-1, 1);
556
            });
557
        }
558
559 1
        return $array;
560
    }
561 1
562
    /**
563
     * Sort the array using the given callback or "dot" notation.
564
     *
565
     * @param  array  $array
566
     * @param  callable|string|null  $callback
567
     * @return array
568
     */
569
    public static function sort($array, $callback = null)
570 1
    {
571
        return Collection::make($array)->sortBy($callback)->all();
0 ignored issues
show
Bug introduced by
It seems like $callback defined by parameter $callback on line 569 can also be of type null; however, IlluminateAgnostic\Colle...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...
572 1
    }
573 1
574 1
    /**
575
     * Recursively sort an array by keys and values.
576
     *
577
     * @param  array  $array
578 1
     * @return array
579 1
     */
580
    public static function sortRecursive($array)
581 1
    {
582
        foreach ($array as &$value) {
583
            if (is_array($value)) {
584 1
                $value = static::sortRecursive($value);
585
            }
586
        }
587
588
        if (static::isAssoc($array)) {
589
            ksort($array);
590
        } else {
591
            sort($array);
592
        }
593 1
594
        return $array;
595 1
    }
596
597
    /**
598
     * Convert the array into a query string.
599
     *
600
     * @param  array  $array
601
     * @return string
602
     */
603
    public static function query($array)
604
    {
605 34
        return http_build_query($array, null, '&', PHP_QUERY_RFC3986);
606
    }
607 34
608
    /**
609
     * Filter the array using the given callback.
610
     *
611
     * @param  array  $array
612
     * @param  callable  $callback
613
     * @return array
614
     */
615
    public static function where($array, callable $callback)
616 7
    {
617
        return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
618 7
    }
619 1
620
    /**
621
     * If the given value is not an array and not null, wrap it in one.
622 7
     *
623
     * @param  mixed  $value
624
     * @return array
625
     */
626
    public static function wrap($value)
627
    {
628
        if (is_null($value)) {
629
            return [];
630
        }
631
632
        return ! is_array($value) ? [$value] : $value;
633
    }
634
}
635