Completed
Push — master ( 94e338...a71846 )
by Antonio Carlos
02:33
created

Arr::set()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5.0187

Importance

Changes 0
Metric Value
cc 5
nc 4
nop 3
dl 0
loc 25
ccs 10
cts 11
cp 0.9091
crap 5.0187
rs 9.2088
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
        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 2
    public static function set(&$array, $key, $value)
507
    {
508 2
        if (is_null($key)) {
509
            return $array = $value;
510
        }
511
512 2
        $keys = explode('.', $key);
513
514 2
        while (count($keys) > 1) {
515 2
            $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 2
            if (! isset($array[$key]) || ! is_array($array[$key])) {
521 1
                $array[$key] = [];
522
            }
523
524 2
            $array = &$array[$key];
525
        }
526
527 2
        $array[array_shift($keys)] = $value;
528
529 2
        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 2
    public static function shuffle($array, $seed = null)
540
    {
541 2
        if (is_null($seed)) {
542
            shuffle($array);
543
        } else {
544 2
            mt_srand($seed);
545 2
            shuffle($array);
546 2
            mt_srand();
547
        }
548
549 2
        return $array;
550
    }
551
552
    /**
553
     * Sort the array using the given callback or "dot" notation.
554
     *
555
     * @param  array  $array
556
     * @param  callable|string|null  $callback
557
     * @return array
558
     */
559 1
    public static function sort($array, $callback = null)
560
    {
561 1
        return Collection::make($array)->sortBy($callback)->all();
562
    }
563
564
    /**
565
     * Recursively sort an array by keys and values.
566
     *
567
     * @param  array  $array
568
     * @return array
569
     */
570 1
    public static function sortRecursive($array)
571
    {
572 1
        foreach ($array as &$value) {
573 1
            if (is_array($value)) {
574 1
                $value = static::sortRecursive($value);
575
            }
576
        }
577
578 1
        if (static::isAssoc($array)) {
579 1
            ksort($array);
580
        } else {
581 1
            sort($array);
582
        }
583
584 1
        return $array;
585
    }
586
587
    /**
588
     * Convert the array into a query string.
589
     *
590
     * @param  array  $array
591
     * @return string
592
     */
593 1
    public static function query($array)
594
    {
595 1
        return http_build_query($array, null, '&', PHP_QUERY_RFC3986);
596
    }
597
598
    /**
599
     * Filter the array using the given callback.
600
     *
601
     * @param  array  $array
602
     * @param  callable  $callback
603
     * @return array
604
     */
605 34
    public static function where($array, callable $callback)
606
    {
607 34
        return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
608
    }
609
610
    /**
611
     * If the given value is not an array and not null, wrap it in one.
612
     *
613
     * @param  mixed  $value
614
     * @return array
615
     */
616 7
    public static function wrap($value)
617
    {
618 7
        if (is_null($value)) {
619 1
            return [];
620
        }
621
622 7
        return is_array($value) ? $value : [$value];
623
    }
624
}
625