Issues (41)

src/Arr.php (1 issue)

Severity
1
<?php
2
3
namespace Nip\Utility;
4
5
use ArrayAccess;
6
use InvalidArgumentException;
7
8
/**
9
 * Class Arr
10
 * @package Nip\Utility
11
 */
12
class Arr
13
{
14
    /**
15
     * Determine whether the given value is array accessible.
16
     *
17
     * @param mixed $value
18
     * @return bool
19
     */
20 1
    public static function accessible($value)
21
    {
22 1
        return is_array($value) || $value instanceof ArrayAccess;
23
    }
24
25
    /**
26
     * Collapse an array of arrays into a single array.
27
     *
28
     * @param array $array
29
     * @return array
30
     */
31
    public static function collapse($array)
32
    {
33
        $results = [];
34
        foreach ($array as $values) {
35
            if (is_object($values) && method_exists($values, 'all')) {
36
                $values = $values->all();
37
            } elseif (!is_array($values)) {
38
                continue;
39
            }
40
            $results[] = $values;
41
        }
42
        return array_merge([], ...$results);
43
    }
44
45
    /**
46
     * Determine if the given key exists in the provided array.
47
     *
48
     * @param \ArrayAccess|array $array
49
     * @param string|int $key
50
     * @return bool
51
     */
52 1
    public static function exists($array, $key)
53
    {
54 1
        if ($array instanceof ArrayAccess) {
55
            return $array->offsetExists($key);
56
        }
57 1
        return array_key_exists($key, $array);
58
    }
59
60
    /**
61
     * Return the first element in an array passing a given truth test.
62
     *
63
     * @param  iterable  $array
64
     * @param  callable|null  $callback
65
     * @param  mixed  $default
66
     * @return mixed
67
     */
68
    public static function first($array, callable $callback = null, $default = null)
69
    {
70
        if (is_null($callback)) {
71
            if (empty($array)) {
72
                return Util::value($default);
73
            }
74
75
            foreach ($array as $item) {
76
                return $item;
77
            }
78
        }
79
80
        foreach ($array as $key => $value) {
81
            if ($callback($value, $key)) {
82
                return $value;
83
            }
84
        }
85
86
        return Util::value($default);
87
    }
88
89
    /**
90
     * Return the last element in an array passing a given truth test.
91
     *
92
     * @param  array  $array
93
     * @param  callable|null  $callback
94
     * @param  mixed  $default
95
     * @return mixed
96
     */
97
    public static function last($array, callable $callback = null, $default = null)
98
    {
99
        if (is_null($callback)) {
100
            return empty($array) ? Util::value($default) : end($array);
101
        }
102
103
        return static::first(array_reverse($array, true), $callback, $default);
104
    }
105
106
    /**
107
     * Remove one or many array items from a given array using "dot" notation.
108
     *
109
     * @param array $array
110
     * @param array|string $keys
111
     * @return void
112
     */
113
    public static function forget(&$array, $keys)
114
    {
115
        $original = &$array;
116
117
        $keys = (array)$keys;
118
119
        if (count($keys) === 0) {
120
            return;
121
        }
122
123
        foreach ($keys as $key) {
124
            // if the exact key exists in the top-level, remove it
125
            if (static::exists($array, $key)) {
126
                unset($array[$key]);
127
128
                continue;
129
            }
130
131
            $parts = explode('.', $key);
132
133
            // clean up before each pass
134
            $array = &$original;
135
136
            while (count($parts) > 1) {
137
                $part = array_shift($parts);
138
139
                if (isset($array[$part]) && is_array($array[$part])) {
140
                    $array = &$array[$part];
141
                } else {
142
                    continue 2;
143
                }
144
            }
145
146
            unset($array[array_shift($parts)]);
147
        }
148
    }
149
150
    /**
151
     * @param $array
152
     * @param mixed ...$values
153
     * @return mixed
154
     */
155 1
    public static function forgetValues(&$array, ...$values)
156
    {
157 1
        if (is_array($values[0])) {
158
            $values = $values[0];
159
        }
160 1
        if ($values) {
161 1
            foreach ($values as $value) {
162 1
                unset($array[array_search($value, $array)]);
163
            }
164
        }
165
166 1
        return $array;
167
    }
168
169
    /**
170
     * Get an item from an array using "dot" notation.
171
     *
172
     * @param \ArrayAccess|array $array
173
     * @param string|int|null $key
174
     * @param mixed $default
175
     * @return mixed
176
     */
177
    public static function get($array, $key, $default = null)
178
    {
179
        if (!static::accessible($array)) {
180
            return value($default);
181
        }
182
183
        if (is_null($key)) {
184
            return $array;
185
        }
186
187
        if (static::exists($array, $key)) {
188
            return $array[$key];
189
        }
190
191
        if (strpos($key, '.') === false) {
192
            return $array[$key] ?? value($default);
193
        }
194
195
        foreach (explode('.', $key) as $segment) {
196
            if (static::accessible($array) && static::exists($array, $segment)) {
197
                $array = $array[$segment];
198
            } else {
199
                return value($default);
200
            }
201
        }
202
203
        return $array;
204
    }
205
206
207
    /**
208
     * Check if an item or items exist in an array using "dot" notation.
209
     *
210
     * @param \ArrayAccess|array $array
211
     * @param string|array $keys
212
     * @return bool
213
     */
214
    public static function has($array, $keys)
215
    {
216
        $keys = (array)$keys;
217
218
        if (!$array || $keys === []) {
219
            return false;
220
        }
221
222
        foreach ($keys as $key) {
223
            $subKeyArray = $array;
224
225
            if (static::exists($array, $key)) {
226
                continue;
227
            }
228
229
            foreach (explode('.', $key) as $segment) {
230
                if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) {
231
                    $subKeyArray = $subKeyArray[$segment];
232
                } else {
233
                    return false;
234
                }
235
            }
236
        }
237
238
        return true;
239
    }
240
241
    /**
242
     * Filter the array using the given callback.
243
     *
244
     * @param array $array
245
     * @param callable $callback
246
     * @return array
247
     */
248
    public static function where($array, callable $callback)
249
    {
250
        return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
251
    }
252
253
    /**
254
     * If the given value is not an array, wrap it in one.
255
     *
256
     * @param mixed $value
257
     * @return array
258
     */
259
    public static function wrap($value)
260
    {
261
        return !is_array($value) ? [$value] : $value;
262
    }
263
264
    /**
265
     * Get a subset of the items from the given array.
266
     *
267
     * @param array $array
268
     * @param array|string $keys
269
     * @return array
270
     */
271
    public static function only($array, $keys)
272
    {
273
        return array_intersect_key($array, array_flip((array)$keys));
274
    }
275
276
    /**
277
     * Pluck an array of values from an array.
278
     *
279
     * @param array $array
280
     * @param string|array $value
281
     * @param string|array|null $key
282
     * @return array
283
     */
284 1
    public static function pluck($array, $value, $key = null)
285
    {
286 1
        $results = [];
287 1
        [$value, $key] = static::explodePluckParameters($value, $key);
288 1
        foreach ($array as $item) {
289 1
            $itemValue = data_get($item, $value);
290
291
            // If the key is "null", we will just append the value to the array and keep
292
            // looping. Otherwise we will key the array using the value of the key we
293
            // received from the developer. Then we'll return the final array form.
294 1
            if (is_null($key)) {
295 1
                $results[] = $itemValue;
296
            } else {
297
                $itemKey = data_get($item, $key);
298
                if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
299
                    $itemKey = (string)$itemKey;
300
                }
301
                $results[$itemKey] = $itemValue;
302
            }
303
        }
304 1
        return $results;
305
    }
306
307
    /**
308
     * Explode the "value" and "key" arguments passed to "pluck".
309
     *
310
     * @param string|array $value
311
     * @param string|array|null $key
312
     * @return array
313
     */
314 1
    protected static function explodePluckParameters($value, $key)
315
    {
316 1
        $value = is_string($value) ? explode('.', $value) : $value;
317 1
        $key = is_null($key) || is_array($key) ? $key : explode('.', $key);
318 1
        return [$value, $key];
319
    }
320
321
    /**
322
     * Push an item onto the beginning of an array.
323
     *
324
     * @param array $array
325
     * @param mixed $value
326
     * @param mixed $key
327
     * @return array
328
     */
329
    public static function prepend($array, $value, $key = null)
330
    {
331
        if (is_null($key)) {
332
            array_unshift($array, $value);
333
        } else {
334
            $array = [$key => $value] + $array;
335
        }
336
337
        return $array;
338
    }
339
340
    /**
341
     * Get a value from the array, and remove it.
342
     *
343
     * @param array $array
344
     * @param string $key
345
     * @param mixed $default
346
     * @return mixed
347
     */
348
    public static function pull(&$array, $key, $default = null)
349
    {
350
        $value = static::get($array, $key, $default);
351
352
        static::forget($array, $key);
353
354
        return $value;
355
    }
356
357
358
    /**
359
     * Get one or a specified number of random values from an array.
360
     *
361
     * @param   array     $array
362
     * @param   int|null  $number
363
     *
364
     * @return mixed
365
     *
366
     * @throws InvalidArgumentException
367
     */
368
    public static function random($array, $number = null)
369
    {
370
        $requested = is_null($number) ? 1 : $number;
371
372
        $count = count($array);
373
374
        if ($requested > $count) {
375
            throw new InvalidArgumentException(
376
                "You requested {$requested} items, but there are only {$count} items available."
377
            );
378
        }
379
380
        if (is_null($number)) {
381
            return $array[array_rand($array)];
382
        }
383
384
        if ((int)$number === 0) {
385
            return [];
386
        }
387
388
        $keys = array_rand($array, $number);
389
390
        $results = [];
391
392
        foreach ((array)$keys as $key) {
393
            $results[] = $array[$key];
394
        }
395
396
        return $results;
397
    }
398
399
    /**
400
     * Set an array item to a given value using "dot" notation.
401
     *
402
     * If no key is given to the method, the entire array will be replaced.
403
     *
404
     * @param array $array
405
     * @param string|null $key
406
     * @param mixed $value
407
     * @return array
408
     */
409
    public static function set(&$array, $key, $value)
410
    {
411
        if (is_null($key)) {
412
            return $array = $value;
413
        }
414
415
        $keys = explode('.', $key);
416
417
        foreach ($keys as $i => $key) {
0 ignored issues
show
$key is overwriting one of the parameters of this function.
Loading history...
418
            if (count($keys) === 1) {
419
                break;
420
            }
421
422
            unset($keys[$i]);
423
424
            // If the key doesn't exist at this depth, we will just create an empty array
425
            // to hold the next value, allowing us to create the arrays to hold final
426
            // values at the correct depth. Then we'll keep digging into the array.
427
            if (!isset($array[$key]) || !is_array($array[$key])) {
428
                $array[$key] = [];
429
            }
430
431
            $array = &$array[$key];
432
        }
433
434
        $array[array_shift($keys)] = $value;
435
436
        return $array;
437
    }
438
439
    /**
440
     * Shuffle the given array and return the result.
441
     *
442
     * @param array $array
443
     * @param int|null $seed
444
     * @return array
445
     */
446
    public static function shuffle($array, $seed = null)
447
    {
448
        if (is_null($seed)) {
449
            shuffle($array);
450
        } else {
451
            mt_srand($seed);
452
            shuffle($array);
453
            mt_srand();
454
        }
455
456
        return $array;
457
    }
458
}
459