Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
95 / 95
100.00% covered (success)
100.00%
23 / 23
CRAP
100.00% covered (success)
100.00%
1 / 1
Arr
100.00% covered (success)
100.00%
95 / 95
100.00% covered (success)
100.00%
23 / 23
60
100.00% covered (success)
100.00%
1 / 1
 isArray
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 isNumeric
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isAssoc
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 exists
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 key
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 collapse
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 flatten
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
6
 divide
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 slice
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
4
 split
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 join
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
5
 prepend
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 pull
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 sort
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
5
 sortDesc
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 ksort
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 ksortDesc
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 usort
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 uksort
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 map
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 trim
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 filter
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 make
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2/**
3 * Pop PHP Framework (http://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@nolainteractive.com>
7 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
8 * @license    http://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Utils;
15
16use ArrayAccess;
17/**
18 * Pop utils array helper class
19 *
20 * @category   Pop
21 * @package    Pop\Utils
22 * @author     Nick Sagona, III <dev@nolainteractive.com>
23 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
24 * @license    http://www.popphp.org/license     New BSD License
25 * @version    2.1.0
26 */
27class Arr
28{
29
30    /**
31     * Check if the value is an array-like (array-accessible) value
32     *
33     * @param  mixed $value
34     * @return bool
35     */
36    public static function isArray(mixed $value): bool
37    {
38        return (is_array($value) || ($value instanceof ArrayAccess));
39    }
40
41    /**
42     * Check if the value is a numeric (non-associative) array
43     *
44     * @param  array $array
45     * @return bool
46     */
47    public static function isNumeric(array $array): bool
48    {
49        return array_is_list($array);
50    }
51
52    /**
53     * Check if the value is an associative (non-numeric) array
54     *
55     * @param  array $array
56     * @return bool
57     */
58    public static function isAssoc(array $array): bool
59    {
60        return !array_is_list($array);
61    }
62
63    /**
64     * Check if the key value exists in the array
65     *
66     * @param  array|ArrayAccess $array
67     * @param  string|int        $key
68     * @return bool
69     */
70    public static function exists(array|ArrayAccess $array, string|int $key): bool
71    {
72        if ($array instanceof ArrayAccess) {
73            return $array->offsetExists($key);
74        } else {
75            return array_key_exists($key, $array);
76        }
77    }
78
79    /**
80     * Return the key in the array based on the first position of the value
81     *
82     * @param  array|AbstractArray $array
83     * @param  mixed               $value
84     * @param  bool                $strict
85     * @return mixed
86     */
87    public static function key(array|AbstractArray $array, string|int $value, bool $strict = false): mixed
88    {
89        if ($array instanceof ArrayAccess) {
90            $array = $array->toArray();
91        }
92
93        return array_search($value, $array, $strict);
94    }
95
96    /**
97     * Collapse an array of arrays
98     *
99     * @param  array|AbstractArray $array
100     * @return array
101     */
102    public static function collapse(array|AbstractArray $array): array
103    {
104        $collapsed = [];
105
106        foreach ($array as $values) {
107            if ($values instanceof AbstractArray) {
108                $values = $values->toArray();
109            } else if (!is_array($values)) {
110                continue;
111            }
112            $collapsed[] = $values;
113        }
114
115        return array_merge([], ...$collapsed);
116    }
117
118    /**
119     * Flatten a multi-dimensional array
120     *
121     * @param  array|AbstractArray $array
122     * @param  int|float           $depth
123     * @return array
124     */
125    public static function flatten(array|AbstractArray $array, int|float $depth = INF): array
126    {
127        $flattened = [];
128
129        foreach ($array as $value) {
130            if ($value instanceof AbstractArray) {
131                $value = $value->toArray();
132            }
133
134            if (!is_array($value)) {
135                $flattened[] = $value;
136            } else {
137                $values = ($depth === 1) ? array_values($value) : static::flatten($value, $depth - 1);
138                foreach ($values as $val) {
139                    $flattened[] = $val;
140                }
141            }
142        }
143
144        return $flattened;
145    }
146
147    /**
148     * Divide the array in an array of keys and values
149     *
150     * @param  array|AbstractArray $array
151     * @return array
152     */
153    public static function divide(array|AbstractArray $array): array
154    {
155        if ($array instanceof AbstractArray) {
156            $array = $array->toArray();
157        }
158        return [array_keys($array), array_values($array)];
159    }
160
161    /**
162     * Return a slice of the array
163     *
164     * @param  array|AbstractArray $array
165     * @param  int                 $limit
166     * @param  int                 $offset
167     * @return array
168     */
169    public static function slice(array|AbstractArray $array, int $limit, int $offset = 0): array
170    {
171        if ($array instanceof AbstractArray) {
172            $array = $array->toArray();
173        }
174
175        return (($limit < 0) && ($offset == 0)) ?
176            array_slice($array, $limit, abs($limit)) : array_slice($array, $offset, $limit);
177    }
178
179    /**
180     * Split a string into an array
181     *
182     * @param  string $string
183     * @param  string $separator
184     * @param  ?int    $limit
185     * @return array
186     */
187    public static function split(string $string, string $separator = '', ?int $limit = null): array
188    {
189        if (empty($separator)) {
190            if ($limit === null) {
191                $limit = 1;
192            }
193            return str_split($string, $limit);
194        } else {
195            if ($limit === null) {
196                $limit = PHP_INT_MAX;
197            }
198            return explode($separator, $string, $limit);
199        }
200    }
201
202    /**
203     * Join the array values into a string
204     *
205     * @param  array|AbstractArray $array
206     * @param  string              $glue
207     * @param  string              $finalGlue
208     * @return string
209     */
210    public static function join(array|AbstractArray $array, string $glue, string $finalGlue = ''): string
211    {
212        if ($array instanceof AbstractArray) {
213            $array = $array->toArray();
214        }
215
216        if ($finalGlue === '') {
217            return implode($glue, $array);
218        }
219
220        if (count($array) == 0) {
221            return '';
222        }
223
224        if (count($array) == 1) {
225            return end($array);
226        }
227
228        $finalItem = array_pop($array);
229
230        return implode($glue, $array) . $finalGlue . $finalItem;
231    }
232
233    /**
234     * Prepend value to the array
235     *
236     * @param  array|AbstractArray $array
237     * @param  mixed               $value
238     * @param  mixed               $key
239     * @return array
240     */
241    public static function prepend(array|AbstractArray $array, mixed $value, mixed $key = null): array
242    {
243        if ($array instanceof AbstractArray) {
244            $array = $array->toArray();
245        }
246
247        if ($key === null) {
248            array_unshift($array, $value);
249        } else {
250            $array = [$key => $value] + $array;
251        }
252
253        return $array;
254    }
255
256    /**
257     * Pull value from the array and remove it
258     *
259     * @param  array $array
260     * @param  mixed $key
261     * @return mixed
262     */
263    public static function pull(array &$array, mixed $key): mixed
264    {
265        $value = $array[$key] ?? null;
266        unset($array[$key]);
267
268        return $value;
269    }
270
271    /**
272     * Sort array
273     *
274     * @param  array|AbstractArray $array
275     * @param  int                 $flags
276     * @param  bool                $assoc
277     * @param  bool                $descending
278     * @return array
279     */
280    public static function sort(
281        array|AbstractArray $array, int $flags = SORT_REGULAR, bool $assoc = true, bool $descending = false
282    ): array
283    {
284        if ($array instanceof AbstractArray) {
285            $array = $array->toArray();
286        }
287        if ($descending) {
288            $func = ($assoc) ? 'arsort' : 'rsort';
289        } else {
290            $func = ($assoc) ? 'asort' : 'sort';
291        }
292
293        $func($array, $flags);
294        return $array;
295    }
296
297    /**
298     * Sort array descending
299     *
300     * @param  array|AbstractArray $array
301     * @param  int                 $flags
302     * @param  bool                $assoc
303     * @return array
304     */
305    public static function sortDesc(array|AbstractArray $array, int $flags = SORT_REGULAR, bool $assoc = true): array
306    {
307        return static::sort($array, $flags, $assoc, true);
308    }
309
310    /**
311     * Sort array by keys
312     *
313     * @param  array|AbstractArray $array
314     * @param  int                 $flags
315     * @param  bool                $descending
316     * @return array
317     */
318    public static function ksort(array|AbstractArray $array, int $flags = SORT_REGULAR, bool $descending = false): array
319    {
320        if ($array instanceof AbstractArray) {
321            $array = $array->toArray();
322        }
323
324        if ($descending) {
325            krsort($array, $flags);
326        } else {
327            ksort($array, $flags);
328        }
329
330        return $array;
331    }
332
333    /**
334     * Sort array by keys, descending
335     *
336     * @param  array|AbstractArray $array
337     * @param  int                 $flags
338     * @return array
339     */
340    public static function ksortDesc(array|AbstractArray $array, int $flags = SORT_REGULAR): array
341    {
342        return static::ksort($array, $flags, true);
343    }
344
345    /**
346     * Sort array by user-defined callback
347     *
348     * @param  array|AbstractArray $array
349     * @param  mixed               $callback
350     * @param  bool                $assoc
351     * @return array
352     */
353    public static function usort(array|AbstractArray $array, mixed $callback, bool $assoc = true): array
354    {
355        if ($array instanceof AbstractArray) {
356            $array = $array->toArray();
357        }
358
359        if ($assoc) {
360            uasort($array, $callback);
361        } else {
362            usort($array, $callback);
363        }
364
365        return $array;
366    }
367
368    /**
369     * Sort array by user-defined callback using keys
370     *
371     * @param  array|AbstractArray $array
372     * @param  mixed               $callback
373     * @return array
374     */
375    public static function uksort(array|AbstractArray $array, mixed $callback): array
376    {
377        if ($array instanceof AbstractArray) {
378            $array = $array->toArray();
379        }
380
381        uksort($array, $callback);
382
383        return $array;
384    }
385
386    /**
387     * Execute a callable over the values of the array
388     *
389     * @param  array|AbstractArray $array
390     * @param  mixed               $callback
391     * @return array
392     */
393    public static function map(array|AbstractArray $array, mixed $callback): array
394    {
395        if ($array instanceof AbstractArray) {
396            $array = $array->toArray();
397        }
398
399        return array_map($callback, $array);
400    }
401
402    /**
403     * Trim extra whitespace in the array values
404     *
405     * @param  array|AbstractArray $array
406     * @return array
407     */
408    public static function trim(array|AbstractArray $array): array
409    {
410        if ($array instanceof AbstractArray) {
411            $array = $array->toArray();
412        }
413
414        return array_map('trim', $array);
415    }
416
417    /**
418     * Execute a filter callback over the values of the array
419     *
420     * @param  array|AbstractArray $array
421     * @param  mixed               $callback
422     * @param  int   $mode
423     * @return array
424     */
425    public static function filter(array|AbstractArray $array, mixed $callback = null, int $mode = ARRAY_FILTER_USE_BOTH): array
426    {
427        if ($array instanceof AbstractArray) {
428            $array = $array->toArray();
429        }
430
431        return array_filter($array, $callback, $mode);
432    }
433
434    /**
435     * Force value to be any array (if it is not one already)
436     *
437     * @param  mixed $value
438     * @return array
439     */
440    public static function make(mixed $value): array
441    {
442        return is_array($value) ? $value : [$value];
443    }
444
445}