Completed
Push — master ( 1a51b8...a7bdd4 )
by Antonio Carlos
01:51
created

Arr::query()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace IlluminateAgnostic\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 48
    public static function accessible($value)
20
    {
21 48
        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 1
                $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 45
    public static function exists($array, $key)
146
    {
147 45
        if ($array instanceof ArrayAccess) {
148 4
            return $array->offsetExists($key);
149
        }
150
151 44
        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 15
    public static function first($array, callable $callback = null, $default = null)
163
    {
164 15
        if (is_null($callback)) {
165 6
            if (empty($array)) {
166 1
                return value($default);
167
            }
168
169 5
            foreach ($array as $item) {
170 5
                return $item;
171
            }
172
        }
173
174 10
        foreach ($array as $key => $value) {
175 10
            if (call_user_func($callback, $value, $key)) {
176 10
                return $value;
177
            }
178
        }
179
180 6
        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 8
    public static function last($array, callable $callback = null, $default = null)
192
    {
193 8
        if (is_null($callback)) {
194 6
            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 5
            $parts = explode('.', $key);
252
253
            // clean up before each pass
254 5
            $array = &$original;
255
256 5
            while (count($parts) > 1) {
257 2
                $part = array_shift($parts);
258
259 2
                if (isset($array[$part]) && is_array($array[$part])) {
260 2
                    $array = &$array[$part];
261
                } else {
262 2
                    continue 2;
263
                }
264
            }
265
266 4
            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 2 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 2
            if (static::accessible($array) && static::exists($array, $segment)) {
298 2
                $array = $array[$segment];
299
            } else {
300 2
                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 1
            return false;
318
        }
319
320 1
        $keys = (array) $keys;
321
322 1
        if (! $array) {
323 1
            return false;
324
        }
325
326 1
        if ($keys === []) {
327 1
            return false;
328
        }
329
330 1
        foreach ($keys as $key) {
331 1
            $subKeyArray = $array;
332
333 1
            if (static::exists($array, $key)) {
334 1
                continue;
335
            }
336
337 1 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 1
                    $subKeyArray = $subKeyArray[$segment];
340
                } else {
341 1
                    return false;
342
                }
343
            }
344
        }
345
346 1
        return true;
347
    }
348
349
    /**
350
     * Determines if an array is associative.
351
     *
352
     * An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
353
     *
354
     * @param  array  $array
355
     * @return bool
356
     */
357 2
    public static function isAssoc(array $array)
358
    {
359 2
        $keys = array_keys($array);
360
361 2
        return array_keys($keys) !== $keys;
362
    }
363
364
    /**
365
     * 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 2
    public static function only($array, $keys)
372
    {
373 2
        return array_intersect_key($array, array_flip((array) $keys));
374
    }
375
376
    /**
377
     * Pluck an array of values from an array.
378
     *
379
     * @param  array  $array
380
     * @param  string|array  $value
381
     * @param  string|array|null  $key
382
     * @return array
383
     */
384 14
    public static function pluck($array, $value, $key = null)
385
    {
386 14
        $results = [];
387
388 14
        list($value, $key) = static::explodePluckParameters($value, $key);
389
390 14
        foreach ($array as $item) {
391 14
            $itemValue = data_get($item, $value);
392
393
            // If the key is "null", we will just append the value to the array and keep
394
            // 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 14
            if (is_null($key)) {
397 12
                $results[] = $itemValue;
398
            } else {
399 4
                $itemKey = data_get($item, $key);
400
401 4
                if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
402 1
                    $itemKey = (string) $itemKey;
403
                }
404
405 14
                $results[$itemKey] = $itemValue;
406
            }
407
        }
408
409 14
        return $results;
410
    }
411
412
    /**
413
     * Explode the "value" and "key" arguments passed to "pluck".
414
     *
415
     * @param  string|array  $value
416
     * @param  string|array|null  $key
417
     * @return array
418
     */
419 14
    protected static function explodePluckParameters($value, $key)
420
    {
421 14
        $value = is_string($value) ? explode('.', $value) : $value;
422
423 14
        $key = is_null($key) || is_array($key) ? $key : explode('.', $key);
424
425 14
        return [$value, $key];
426
    }
427
428
    /**
429
     * Push an item onto the beginning of an array.
430
     *
431
     * @param  array  $array
432
     * @param  mixed  $value
433
     * @param  mixed  $key
434
     * @return array
435
     */
436 2
    public static function prepend($array, $value, $key = null)
437
    {
438 2
        if (is_null($key)) {
439 2
            array_unshift($array, $value);
440
        } else {
441 2
            $array = [$key => $value] + $array;
442
        }
443
444 2
        return $array;
445
    }
446
447
    /**
448
     * Get a value from the array, and remove it.
449
     *
450
     * @param  array   $array
451
     * @param  string  $key
452
     * @param  mixed   $default
453
     * @return mixed
454
     */
455 4
    public static function pull(&$array, $key, $default = null)
456
    {
457 4
        $value = static::get($array, $key, $default);
458
459 4
        static::forget($array, $key);
460
461 4
        return $value;
462
    }
463
464
    /**
465
     * Get one or a specified number of random values from an array.
466
     *
467
     * @param  array  $array
468
     * @param  int|null  $number
469
     * @return mixed
470
     *
471
     * @throws \InvalidArgumentException
472
     */
473 6
    public static function random($array, $number = null)
474
    {
475 6
        $requested = is_null($number) ? 1 : $number;
476
477 6
        $count = count($array);
478
479 6
        if ($requested > $count) {
480 2
            throw new InvalidArgumentException(
481 2
                "You requested {$requested} items, but there are only {$count} items available."
482
            );
483
        }
484
485 4
        if (is_null($number)) {
486 2
            return $array[array_rand($array)];
487
        }
488
489 4
        if ((int) $number === 0) {
490 4
            return [];
491
        }
492
493 2
        $keys = array_rand($array, $number);
494
495 2
        $results = [];
496
497 2
        foreach ((array) $keys as $key) {
498 2
            $results[] = $array[$key];
499
        }
500
501 2
        return $results;
502
    }
503
504
    /**
505
     * Set an array item to a given value using "dot" notation.
506
     *
507
     * If no key is given to the method, the entire array will be replaced.
508
     *
509
     * @param  array   $array
510
     * @param  string  $key
511
     * @param  mixed   $value
512
     * @return array
513
     */
514 2
    public static function set(&$array, $key, $value)
515
    {
516 2
        if (is_null($key)) {
517
            return $array = $value;
518
        }
519
520 2
        $keys = explode('.', $key);
521
522 2
        while (count($keys) > 1) {
523 1
            $key = array_shift($keys);
524
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
            // values at the correct depth. Then we'll keep digging into the array.
528 1
            if (! isset($array[$key]) || ! is_array($array[$key])) {
529
                $array[$key] = [];
530
            }
531
532 1
            $array = &$array[$key];
533
        }
534
535 2
        $array[array_shift($keys)] = $value;
536
537 2
        return $array;
538
    }
539
540
    /**
541
     * Shuffle the given array and return the result.
542
     *
543
     * @param  array  $array
544
     * @param  int|null  $seed
545
     * @return array
546
     */
547 2
    public static function shuffle($array, $seed = null)
548
    {
549 2
        if (is_null($seed)) {
550
            shuffle($array);
551
        } else {
552 2
            srand($seed);
553
554
            usort($array, function () {
555 2
                return rand(-1, 1);
556 2
            });
557
        }
558
559 2
        return $array;
560
    }
561
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 1
    public static function sort($array, $callback = null)
570
    {
571 1
        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
    }
573
574
    /**
575
     * Recursively sort an array by keys and values.
576
     *
577
     * @param  array  $array
578
     * @return array
579
     */
580 1
    public static function sortRecursive($array)
581
    {
582 1
        foreach ($array as &$value) {
583 1
            if (is_array($value)) {
584 1
                $value = static::sortRecursive($value);
585
            }
586
        }
587
588 1
        if (static::isAssoc($array)) {
589 1
            ksort($array);
590
        } else {
591 1
            sort($array);
592
        }
593
594 1
        return $array;
595
    }
596
597
    /**
598
     * Convert the array into a query string.
599
     *
600
     * @param  array  $array
601
     * @return string
602
     */
603 1
    public static function query($array)
604
    {
605 1
        return http_build_query($array, null, '&', PHP_QUERY_RFC3986);
606
    }
607
608
    /**
609
     * Filter the array using the given callback.
610
     *
611
     * @param  array  $array
612
     * @param  callable  $callback
613
     * @return array
614
     */
615 31
    public static function where($array, callable $callback)
616
    {
617 31
        return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
618
    }
619
620
    /**
621
     * If the given value is not an array and not null, wrap it in one.
622
     *
623
     * @param  mixed  $value
624
     * @return array
625
     */
626 7
    public static function wrap($value)
627
    {
628 7
        if (is_null($value)) {
629 1
            return [];
630
        }
631
632 7
        return ! is_array($value) ? [$value] : $value;
633
    }
634
}
635