Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
95 / 95 |
|
100.00% |
23 / 23 |
CRAP | |
100.00% |
1 / 1 |
Arr | |
100.00% |
95 / 95 |
|
100.00% |
23 / 23 |
60 | |
100.00% |
1 / 1 |
isArray | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
isNumeric | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isAssoc | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
exists | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
key | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
collapse | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
4 | |||
flatten | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
6 | |||
divide | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
slice | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
4 | |||
split | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
4 | |||
join | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
5 | |||
prepend | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
pull | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
sort | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
5 | |||
sortDesc | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
ksort | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
ksortDesc | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
usort | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
uksort | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
map | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
trim | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
filter | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
make | |
100.00% |
1 / 1 |
|
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 | */ |
14 | namespace Pop\Utils; |
15 | |
16 | use 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 | */ |
27 | class 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 | } |