PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 1.21
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v1.21
2.1.0 2.0.15 2.0.12 2.0.10 2.0.4 2.0.1 2.0.0 1.95.3 1.95.2 1.95 1.91.6 trunk 1.11 1.12 1.13 1.20 1.21 1.22 1.23 1.30 1.31 1.32 1.35 1.40 1.41 All 42 releases
fluent-boards / vendor / wpfluent / framework / src / WPFluent / Support / Arr.php

Arr.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration 1.21, at vendor/wpfluent/framework/src/WPFluent/Support/Arr.php

1,486 lines 37.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentBoards\Framework\Support;
4
5 use Closure;
6 use ArrayAccess;
7 use InvalidArgumentException;
8 use FluentBoards\Framework\Support\Helper;
9 use FluentBoards\Framework\Support\Collection;
10 use FluentBoards\Framework\Support\MacroableTrait;
11
12 class Arr
13 {
14 use MacroableTrait;
15
16 /**
17 * Makes a collection from array
18 *
19 * @param array $array
20 * @return FluentBoards\Framework\Support\Collection
21 */
22 public static function of(array $array)
23 {
24 return Helper::collect($array);
25 }
26
27 /**
28 * Makes a fluent object from iterable|object
29 * An iterable is an array or instanceof Traversable
30 *
31 * @param items iterable|object
32 * @return FluentBoards\Framework\Support\Fluent
33 */
34 public static function make(/*iterable|stdClass*/ $items, $isFluent = true)
35 {
36 if (is_iterable($items) || $items instanceof \stdClass) {
37 return new FluentArray($items, $isFluent);
38 }
39
40 throw new InvalidArgumentException (
41 "The parameter must be an stdClass or stdClass")
42 ;
43 }
44
45 /**
46 * Determine whether the given value is array accessible.
47 *
48 * @param mixed $value
49 * @return bool
50 */
51 public static function accessible($value)
52 {
53 return is_array($value) || $value instanceof ArrayAccess;
54 }
55
56 /**
57 * Add an element to an array using "dot" notation if it doesn't exist.
58 *
59 * @param array $array
60 * @param string $key
61 * @param mixed $value
62 * @return array
63 */
64 public static function add($array, $key, $value)
65 {
66 if (is_null(static::get($array, $key))) {
67 static::set($array, $key, $value);
68 }
69
70 return $array;
71 }
72
73 /**
74 * Collapse an array of arrays into a single array.
75 *
76 * @param iterable $array
77 * @return array
78 */
79 public static function collapse($array)
80 {
81 $results = [];
82
83 foreach ($array as $values) {
84 if ($values instanceof Collection) {
85 $values = $values->all();
86 } elseif (! is_array($values)) {
87 continue;
88 }
89
90 $results[] = $values;
91 }
92
93 return array_merge([], ...$results);
94 }
95
96 /**
97 * Cross join the given arrays, returning all possible permutations.
98 *
99 * @param iterable ...$arrays
100 * @return array
101 */
102 public static function crossJoin(...$arrays)
103 {
104 $results = [[]];
105
106 foreach ($arrays as $index => $array) {
107 $append = [];
108
109 foreach ($results as $product) {
110 foreach ($array as $item) {
111 $product[$index] = $item;
112
113 $append[] = $product;
114 }
115 }
116
117 $results = $append;
118 }
119
120 return $results;
121 }
122
123 /**
124 * Divide an array into two arrays. One with keys and the other with values.
125 *
126 * @param array $array
127 * @return array
128 */
129 public static function divide($array)
130 {
131 return [array_keys($array), array_values($array)];
132 }
133
134 /**
135 * Flatten a multi-dimensional associative array with dots.
136 *
137 * @param iterable $array
138 * @param string $prepend
139 * @return array
140 */
141 public static function dot($array, $prepend = '')
142 {
143 $results = [];
144
145 foreach ($array as $key => $value) {
146 if (is_array($value) && ! empty($value)) {
147 $results = array_merge($results, static::dot($value, $prepend.$key.'.'));
148 } else {
149 $results[$prepend.$key] = $value;
150 }
151 }
152
153 return $results;
154 }
155
156 /**
157 * Convert a flatten "dot" notation array into an expanded array.
158 *
159 * @param iterable $array
160 * @return array
161 */
162 public static function undot($array)
163 {
164 $results = [];
165
166 foreach ($array as $key => $value) {
167 static::set($results, $key, $value);
168 }
169
170 return $results;
171 }
172
173 /**
174 * Get all of the given array except for a specified array of keys.
175 *
176 * @param array $array
177 * @param array|string $keys
178 * @return array
179 */
180 public static function except($array, $keys)
181 {
182 static::forget($array, $keys);
183
184 return $array;
185 }
186
187 /**
188 * Determine if the given key exists in the provided array.
189 *
190 * @param \ArrayAccess|array $array
191 * @param string|int $key
192 * @return bool
193 */
194 public static function exists($array, $key)
195 {
196 if ($array instanceof Enumerable) {
197 return $array->has($key);
198 }
199
200 if ($array instanceof ArrayAccess) {
201 return $array->offsetExists($key);
202 }
203
204 return array_key_exists($key, $array);
205 }
206
207 /**
208 * Alias of exists.
209 * @param \ArrayAccess|array $array
210 * @param string|int $key
211 * @return bool
212 */
213 public static function keyExists($array, $key)
214 {
215 return static::exists($array, $key);
216 }
217
218 /**
219 * Alias of exists.
220 * @param \ArrayAccess|array $array
221 * @param string|int $key
222 * @return bool
223 */
224 public static function arrayKeyExists($array, $key)
225 {
226 return static::exists($array, $key);
227 }
228
229 /**
230 * Return the first element in an array passing a given truth test.
231 *
232 * @param iterable $array
233 * @param callable|null $callback
234 * @param mixed $default
235 * @return mixed
236 */
237 public static function first($array, callable $callback = null, $default = null)
238 {
239 if (is_null($callback)) {
240 if (empty($array)) {
241 return Helper::value($default);
242 }
243
244 foreach ($array as $item) {
245 return $item;
246 }
247 }
248
249 foreach ($array as $key => $value) {
250 if ($callback($value, $key)) {
251 return $value;
252 }
253 }
254
255 return Helper::value($default);
256 }
257
258 /**
259 * Recursively filter an array like array_filter.
260 *
261 * @param array $array
262 * @param callable|null $cb
263 * @param integer $mode (ARRAY_FILTER_USE_BOTH = 1 | ARRAY_FILTER_USE_KEY = 2)
264 * @return array
265 */
266 public static function filterRecursive($array, callable $cb = null, $mode = 0)
267 {
268 $result = [];
269
270 foreach ($array as $key => $value) {
271 if (is_array($value)) {
272 if (is_int($key)) {
273 $result[] = static::filterRecursive($value, $cb, $mode);
274 } else {
275 $result[$key] = static::filterRecursive($value, $cb, $mode);
276 }
277 } else {
278 if (is_null($cb)) {
279 if ($value) {
280 if (is_int($key)) {
281 $result[] = $value;
282 } else {
283 $result[$key] = $value;
284 }
285 }
286 } else {
287 if ($mode && call_user_func($cb, $value, $key)) {
288 if (is_int($key)) {
289 $result[] = $value;
290 } else {
291 $result[$key] = $value;
292 }
293 } elseif (!$mode && call_user_func($cb, $value)) {
294 if (is_int($key)) {
295 $result[] = $value;
296 } else {
297 $result[$key] = $value;
298 }
299 }
300 }
301 }
302 }
303
304 return $result;
305 }
306
307 /**
308 * Recursively search the value and return the path of first match.
309 *
310 * @param array $array
311 * @param mixed $value
312 * @param bool $ci (false for case insensitive search, true otherwise)
313 * @return array|null
314 */
315 public static function findPath($array, $value, $ci = false)
316 {
317 if (!$ci) {
318 $value = strtolower($value);
319 $array = static::map($array, 'strtolower');
320 }
321
322 foreach ($array as $key => $val) {
323 if ($val === $value) {
324 return $key;
325 } elseif (is_array($val) && $path = static::findPath($val, $value, $ci)) {
326 return $key.'.'.$path;
327 }
328 }
329 }
330
331 /**
332 * Return the last element in an array passing a given truth test.
333 *
334 * @param array $array
335 * @param callable|null $callback
336 * @param mixed $default
337 * @return mixed
338 */
339 public static function last($array, callable $callback = null, $default = null)
340 {
341 if (is_null($callback)) {
342 return empty($array) ? Helper::value($default) : end($array);
343 }
344
345 return static::first(array_reverse($array, true), $callback, $default);
346 }
347
348 /**
349 * Flatten a multi-dimensional array into a single level.
350 *
351 * @param iterable $array
352 * @param int $depth
353 * @return array
354 */
355 public static function flatten($array, $depth = INF)
356 {
357 $result = [];
358
359 foreach ($array as $item) {
360 $item = $item instanceof Collection ? $item->all() : $item;
361
362 if (! is_array($item)) {
363 $result[] = $item;
364 } else {
365 $values = $depth === 1
366 ? array_values($item)
367 : static::flatten($item, $depth - 1);
368
369 foreach ($values as $value) {
370 $result[] = $value;
371 }
372 }
373 }
374
375 return $result;
376 }
377
378 /**
379 * Remove one or many array items from a given array using "dot" notation.
380 *
381 * @param array $array
382 * @param array|string $keys
383 * @return void
384 */
385 public static function forget(&$array, $keys)
386 {
387 $original = &$array;
388
389 $keys = (array) $keys;
390
391 if (count($keys) === 0) {
392 return;
393 }
394
395 foreach ($keys as $key) {
396 // if the exact key exists in the top-level, remove it
397 if (static::exists($array, $key)) {
398 unset($array[$key]);
399
400 continue;
401 }
402
403 $parts = explode('.', $key);
404
405 // clean up before each pass
406 $array = &$original;
407
408 while (count($parts) > 1) {
409 $part = array_shift($parts);
410
411 if (isset($array[$part]) && is_array($array[$part])) {
412 $array = &$array[$part];
413 } else {
414 continue 2;
415 }
416 }
417
418 unset($array[array_shift($parts)]);
419 }
420 }
421
422 /**
423 * Get an item from an array using "dot" notation.
424 *
425 * @param \ArrayAccess|array $array
426 * @param string|int|null $key
427 * @param mixed $default
428 * @return mixed
429 */
430 public static function get($array, $key, $default = null)
431 {
432 if (! static::accessible($array)) {
433 return Helper::value($default);
434 }
435
436 if (is_null($key)) {
437 return $array;
438 }
439
440 if (static::exists($array, $key)) {
441 return $array[$key];
442 }
443
444 if (strpos($key, '.') === false) {
445 return $array[$key] ?? Helper::value($default);
446 }
447
448 foreach (explode('.', $key) as $segment) {
449 if (static::accessible($array) && static::exists($array, $segment)) {
450 $array = $array[$segment];
451 } else {
452 return Helper::value($default);
453 }
454 }
455
456 return $array;
457 }
458
459 /**
460 * Check if an item or items (using key) exist in an array using "dot" notation.
461 *
462 * @param \ArrayAccess|array $array
463 * @param string|array $keys
464 * @return bool
465 */
466 public static function has($array, $keys)
467 {
468 $keys = (array) $keys;
469
470 if (! $array || $keys === []) {
471 return false;
472 }
473
474 foreach ($keys as $key) {
475 $subKeyArray = $array;
476
477 if (static::exists($array, $key)) {
478 continue;
479 }
480
481 foreach (explode('.', $key) as $segment) {
482 if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) {
483 $subKeyArray = $subKeyArray[$segment];
484 } else {
485 return false;
486 }
487 }
488 }
489
490 return true;
491 }
492
493 /**
494 * Determine if any of the keys exist in an array using "dot" notation.
495 *
496 * @param \ArrayAccess|array $array
497 * @param string|array $keys
498 * @return bool
499 */
500 public static function hasAny($array, $keys)
501 {
502 if (is_null($keys)) {
503 return false;
504 }
505
506 $keys = (array) $keys;
507
508 if (! $array) {
509 return false;
510 }
511
512 if ($keys === []) {
513 return false;
514 }
515
516 foreach ($keys as $key) {
517 if (static::has($array, $key)) {
518 return true;
519 }
520 }
521
522 return false;
523 }
524
525 /**
526 * Alias of contains.
527 *
528 * @param array $array
529 * @param string|array $values
530 * @return bool
531 */
532 public static function inArray($array, $value)
533 {
534 return static::contains($array, $value);
535 }
536
537 /**
538 * Determines if an array is associative.
539 *
540 * An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
541 *
542 * @param array $array
543 * @return bool
544 */
545 public static function isAssoc(array $array)
546 {
547 $keys = array_keys($array);
548
549 return array_keys($keys) !== $keys;
550 }
551
552 /**
553 * Determines if an array is a list.
554 *
555 * An array is a "list" if all array keys are sequential integers starting from 0 with no gaps in between.
556 *
557 * @param array $array
558 * @return bool
559 */
560 public static function isList($array)
561 {
562 return ! self::isAssoc($array);
563 }
564
565 /**
566 * Determines if the given key contains a boolean value.
567 *
568 * Returns true for true, 1, "1", "true", "on" and "yes"
569 * Returns false for false, "0", "false", "off", "no", and ""
570 * Returns for all non-boolean values.
571 *
572 * @param array $array
573 * @param string $key
574 *
575 * @return bool|null
576 * @see https://www.php.net/manual/en/filter.filters.validate.php
577 */
578 public static function isTrue($array, $key)
579 {
580 return filter_var(
581 static::get($array, $key),
582 FILTER_VALIDATE_BOOLEAN,
583 FILTER_NULL_ON_FAILURE
584 );
585 }
586
587 /**
588 * Get a subset of the items from the given array.
589 *
590 * @param array $array
591 * @param array|string $keys
592 * @return array
593 */
594 public static function only($array, $keys)
595 {
596 return array_intersect_key($array, array_flip((array) $keys));
597 }
598
599 /**
600 * Pluck an array of values from an array.
601 *
602 * @param iterable $array
603 * @param string|array|int|null $value
604 * @param string|array|null $key
605 * @return array
606 */
607 public static function pluck($array, $value, $key = null)
608 {
609 $results = [];
610
611 [$value, $key] = static::explodePluckParameters($value, $key);
612
613 foreach ($array as $item) {
614 $itemValue = Helper::dataGet($item, $value);
615
616 // If the key is "null", we will just append the value to the array and keep
617 // looping. Otherwise we will key the array using the value of the key we
618 // received from the developer. Then we'll return the final array form.
619 if (is_null($key)) {
620 $results[] = $itemValue;
621 } else {
622 $itemKey = Helper::dataGet($item, $key);
623
624 if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
625 $itemKey = (string) $itemKey;
626 }
627
628 $results[$itemKey] = $itemValue;
629 }
630 }
631
632 return $results;
633 }
634
635 /**
636 * Explode the "value" and "key" arguments passed to "pluck".
637 *
638 * @param string|array $value
639 * @param string|array|null $key
640 * @return array
641 */
642 protected static function explodePluckParameters($value, $key)
643 {
644 $value = is_string($value) ? explode('.', $value) : $value;
645
646 $key = is_null($key) || is_array($key) ? $key : explode('.', $key);
647
648 return [$value, $key];
649 }
650
651 /**
652 * Push an item onto the beginning of an array.
653 *
654 * @param array $array
655 * @param mixed $value
656 * @param mixed $key
657 * @return array
658 */
659 public static function prepend($array, $value, $key = null)
660 {
661 if (func_num_args() == 2) {
662 array_unshift($array, $value);
663 } else {
664 $array = [$key => $value] + $array;
665 }
666
667 return $array;
668 }
669
670 /**
671 * Get a value from the array, and remove it.
672 *
673 * @param array $array
674 * @param string|int $key
675 * @param mixed $default
676 * @return mixed
677 */
678 public static function pull(&$array, $key, $default = null)
679 {
680 $value = static::get($array, $key, $default);
681
682 static::forget($array, $key);
683
684 return $value;
685 }
686
687 /**
688 * Convert the array into a query string.
689 *
690 * @param array $array
691 * @return string
692 */
693 public static function query($array)
694 {
695 return http_build_query($array, '', '&', PHP_QUERY_RFC3986);
696 }
697
698 /**
699 * Get one or a specified number of random values from an array.
700 *
701 * @param array $array
702 * @param int|null $number
703 * @param bool|false $preserveKeys
704 * @return mixed
705 *
706 * @throws \InvalidArgumentException
707 */
708 public static function random($array, $number = null, $preserveKeys = false)
709 {
710 $requested = is_null($number) ? 1 : $number;
711
712 $count = count($array);
713
714 if ($requested > $count) {
715 throw new InvalidArgumentException(
716 "You requested {$requested} items, but there are only {$count} items available."
717 );
718 }
719
720 if (is_null($number)) {
721 return $array[array_rand($array)];
722 }
723
724 if ((int) $number === 0) {
725 return [];
726 }
727
728 $keys = array_rand($array, $number);
729
730 $results = [];
731
732 if ($preserveKeys) {
733 foreach ((array) $keys as $key) {
734 $results[$key] = $array[$key];
735 }
736 } else {
737 foreach ((array) $keys as $key) {
738 $results[] = $array[$key];
739 }
740 }
741
742 return $results;
743 }
744
745 /**
746 * Set an array item to a given value using "dot" notation.
747 *
748 * If no key is given to the method, the entire array will be replaced.
749 *
750 * @param array $array
751 * @param string|null $key
752 * @param mixed $value
753 * @return array
754 */
755 public static function set(&$array, $key, $value)
756 {
757 if (is_null($key)) {
758 return $array = $value;
759 }
760
761 $keys = explode('.', $key);
762
763 foreach ($keys as $i => $key) {
764 if (count($keys) === 1) {
765 break;
766 }
767
768 unset($keys[$i]);
769
770 // If the key doesn't exist at this depth, we will just create an empty array
771 // to hold the next value, allowing us to create the arrays to hold final
772 // values at the correct depth. Then we'll keep digging into the array.
773 if (! isset($array[$key]) || ! is_array($array[$key])) {
774 $array[$key] = [];
775 }
776
777 $array = &$array[$key];
778 }
779
780 $array[array_shift($keys)] = $value;
781
782 return $array;
783 }
784
785 /**
786 * Shuffle the given array and return the result.
787 *
788 * @param array $array
789 * @param int|null $seed
790 * @return array
791 */
792 public static function shuffle($array, $seed = null)
793 {
794 if (is_null($seed)) {
795 shuffle($array);
796 } else {
797 mt_srand($seed);
798 shuffle($array);
799 mt_srand();
800 }
801
802 return $array;
803 }
804
805 /**
806 * Sort the array using the given callback or "dot" notation.
807 *
808 * @param array $array
809 * @param callable|array|string|null $callback
810 * @return array
811 */
812 public static function sort($array, $callback = null)
813 {
814 return Collection::make($array)->sortBy($callback)->all();
815 }
816
817 /**
818 * Sort an array in descending order.
819 *
820 * @param array $array
821 * @param Flags
822 * @return array
823 * @see https://www.php.net/manual/en/function.rsort.php
824 */
825 public static function rsort($array, $flags = SORT_REGULAR)
826 {
827 rsort($array, $flags);
828 return $array;
829 }
830
831 /**
832 * Sort an array in ascending order and maintain index association.
833 *
834 * @param array $array
835 * @param Flags
836 * @return array
837 * @see https://www.php.net/manual/en/function.asort.php
838 */
839 public static function asort($array, $flags = SORT_REGULAR)
840 {
841 asort($array, $flags);
842 return $array;
843 }
844
845 /**
846 * Sort an array in descending order and maintain index association.
847 *
848 * @param array $array
849 * @param Flags
850 * @return array
851 * @see https://www.php.net/manual/en/function.arsort.php
852 */
853 public static function arsort($array, $flags = SORT_REGULAR)
854 {
855 arsort($array, $flags);
856 return $array;
857 }
858
859 /**
860 * Sort an array by key in ascending order.
861 *
862 * @param array $array
863 * @param Flags
864 * @return array
865 * @see https://www.php.net/manual/en/function.ksort.php
866 */
867 public static function ksort($array, $flags = SORT_REGULAR)
868 {
869 ksort($array, $flags);
870 return $array;
871 }
872
873 /**
874 * Sort an array by key in descending order.
875 *
876 * @param array $array
877 * @param Flags
878 * @return array
879 * @see https://www.php.net/manual/en/function.krsort.php
880 */
881 public static function krsort($array, $flags = SORT_REGULAR)
882 {
883 krsort($array, $flags);
884 return $array;
885 }
886
887 /**
888 * Sort an array using a "natural order" algorithm.
889 *
890 * @param array $array
891 * @return array
892 * @see https://www.php.net/manual/en/function.natsort.php
893 */
894 public static function natsort($array)
895 {
896 natsort($array);
897 return $array;
898 }
899
900 /**
901 * Sort an array using a case insensitive "natural order" algorithm.
902 *
903 * @param array $array
904 * @return array
905 * @see https://www.php.net/manual/en/function.natcasesort.php
906 */
907 public static function natcasesort($array)
908 {
909 natcasesort($array);
910 return $array;
911 }
912
913 /**
914 * Sort an array by values using a user-defined comparison function.
915 *
916 * @param array $array
917 * @return array
918 * @see https://www.php.net/manual/en/function.usort.php
919 */
920 public static function usort($array, callable $callback)
921 {
922 usort($array, $callback);
923 return $array;
924 }
925
926 /**
927 * Sort an array with a user-defined comparison
928 * function and maintain index association.
929 *
930 * @param array $array
931 * @return array
932 * @see https://www.php.net/manual/en/function.uasort.php
933 */
934 public static function uasort($array, callable $callback)
935 {
936 uasort($array, $callback);
937 return $array;
938 }
939
940 /**
941 * Sort an array by keys using a user-defined comparison function.
942 *
943 * @param array $array
944 * @return array
945 * @see https://www.php.net/manual/en/function.uksort.php
946 */
947 public static function uksort($array, callable $callback)
948 {
949 uksort($array, $callback);
950 return $array;
951 }
952
953 /**
954 * Recursively sort an array by keys and values.
955 *
956 * @param array $array
957 * @param int $options
958 * @param bool $desc
959 * @return array
960 */
961 public static function sortRecursive($array, $options = SORT_REGULAR, $desc = false)
962 {
963 foreach ($array as &$value) {
964 if (is_array($value)) {
965 $value = static::sortRecursive($value, $options, $desc);
966 }
967 }
968
969 if (static::isAssoc($array)) {
970 $desc
971 ? krsort($array, $options)
972 : ksort($array, $options);
973 } else {
974 $desc
975 ? rsort($array, $options)
976 : sort($array, $options);
977 }
978
979 return $array;
980 }
981
982 /**
983 * Conditionally compile classes from an array into a CSS class list.
984 *
985 * @param array $array
986 * @return string
987 */
988 public static function toCssClasses($array)
989 {
990 $classList = static::wrap($array);
991
992 $classes = [];
993
994 foreach ($classList as $class => $constraint) {
995 if (is_numeric($class)) {
996 $classes[] = $constraint;
997 } elseif ($constraint) {
998 $classes[] = $class;
999 }
1000 }
1001
1002 return implode(' ', $classes);
1003 }
1004
1005 /**
1006 * Transforms an array to \stdClass
1007 * @param array $array
1008 * @return \stdClass
1009 */
1010 public static function toObject($array)
1011 {
1012 return StdObject::create($array);
1013 }
1014
1015 /**
1016 * Filter the array using the given callback.
1017 *
1018 * @param array $array
1019 * @param callable $callback
1020 * @return array
1021 */
1022 public static function where($array, callable $callback)
1023 {
1024 return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
1025 }
1026
1027 /**
1028 * Filter items where the value is not null.
1029 *
1030 * @param array $array
1031 * @return array
1032 */
1033 public static function whereNotNull($array)
1034 {
1035 return static::where($array, function ($value) {
1036 return ! is_null($value);
1037 });
1038 }
1039
1040 /**
1041 * Filter items where the value is not null.
1042 *
1043 * @param array $array
1044 * @return array
1045 */
1046 public static function whereNotTrue($array, $strict = false)
1047 {
1048 return static::where($array, function ($value) use ($strict) {
1049 return $strict ? $value === false : !$value;
1050 });
1051 }
1052
1053 /**
1054 * If the given value is not an array and not null, wrap it in one.
1055 *
1056 * @param mixed $value
1057 * @return array
1058 */
1059 public static function wrap($value)
1060 {
1061 if (is_null($value)) {
1062 return [];
1063 }
1064
1065 return is_array($value) ? $value : [$value];
1066 }
1067
1068 /**
1069 * Maps a function to all non-iterable elements of an array or an object.
1070 *
1071 * This is similar to `array_walk_recursive()` but acts upon objects too.
1072 *
1073 * @param mixed $value The array, object, or scalar.
1074 * @param callable $callback The function to map onto $value.
1075 * @see https://developer.wordpress.org/reference/functions/map_deep/
1076 *
1077 * @return mixed The value with the callback applied to all non-arrays and non-objects inside it.
1078 */
1079 public static function map($value, $callback)
1080 {
1081 return map_deep($value, $callback);
1082 }
1083
1084 /**
1085 * Check if the value(s) exist in an array using "dot" notation.
1086 *
1087 * @param array $array
1088 * @param string|array $values
1089 * @return bool
1090 */
1091 public static function contains(array $array, $values)
1092 {
1093 $result = [];
1094
1095 $values = is_array($values) ? $values : [$values];
1096
1097 foreach ($values as $value) {
1098
1099 if (in_array($value, $array)) {
1100 $result[] = $value;
1101 continue;
1102 }
1103
1104 $segments = explode('.', $value);
1105
1106 $value = array_pop($segments);
1107
1108 $nested = (array) static::get($array, implode('.', $segments));
1109
1110 if ($nested && in_array($value, $nested)) {
1111 $result[] = $value;
1112 }
1113 }
1114
1115 return count($result) === count($values);
1116 }
1117
1118 /**
1119 * Check if the any value exist in an array using "dot" notation.
1120 *
1121 * @param array $array
1122 * @param string|array $values
1123 * @return bool
1124 */
1125 public static function containsAny(array $array, $values)
1126 {
1127 $result = [];
1128
1129 $values = is_array($values) ? $values : [$values];
1130
1131 foreach ($values as $value) {
1132
1133 if (in_array($value, $array)) {
1134 return true;
1135 }
1136
1137 $segments = explode('.', $value);
1138
1139 $value = array_pop($segments);
1140
1141 $nested = (array) static::get($array, implode('.', $segments));
1142
1143 if ($nested && in_array($value, $nested)) {
1144 return true;
1145 }
1146 }
1147
1148 return false;
1149 }
1150
1151 /**
1152 * Compare two nested arrays side by side
1153 * @param array $array1
1154 * @param array $array2
1155 * @param array $path
1156 * @return array
1157 */
1158 public static function compare($array1, $array2, $path = [])
1159 {
1160 $differences = [];
1161
1162 foreach ($array1 as $key => $value1) {
1163 // Check if the key exists in the second array
1164 if (!array_key_exists($key, $array2)) {
1165 $differences[implode('.', array_merge($path, [$key]))] = [
1166 'array_1' => $value1,
1167 'array_2' => null,
1168 ];
1169 } else {
1170 // If the value is an array, recursively compare
1171 if (is_array($value1) && is_array($array2[$key])) {
1172 $differences = array_merge($differences, static::compare(
1173 $value1, $array2[$key], array_merge($path, [$key])
1174 ));
1175 } else {
1176 // Compare values
1177 if ($value1 !== $array2[$key]) {
1178 $differences[implode('.', array_merge($path, [$key]))] = [
1179 'array_1' => $value1,
1180 'array_2' => $array2[$key],
1181 ];
1182 }
1183 }
1184 }
1185 }
1186
1187 // Check for keys in the second array that are not in the first array
1188 foreach ($array2 as $key => $value2) {
1189 if (!array_key_exists($key, $array1)) {
1190 $differences[implode('.', array_merge($path, [$key]))] = [
1191 'array_1' => null,
1192 'array_2' => $value2,
1193 ];
1194 }
1195 }
1196
1197 return $differences;
1198 }
1199
1200 /**
1201 * Merge the items from the first array into the
1202 * second array if the second array is missing it.
1203 *
1204 * @param array &$array1
1205 * @param array &$array2
1206 * @return array
1207 */
1208 public static function mergeMissing(&$array1, &$array2)
1209 {
1210 foreach ($array1 as $key => $value1) {
1211 // If the key exists in the second array
1212 if (array_key_exists($key, $array2)) {
1213 // If the value is an array, recursively add missing items
1214 if (is_array($value1) && is_array($array2[$key])) {
1215 static::mergeMissing($value1, $array2[$key]);
1216 }
1217 } else {
1218 // If the key doesn't exist in the second array,
1219 // then add it with the corresponding value
1220 $array2[$key] = $value1;
1221 }
1222 }
1223
1224 return $array2;
1225 }
1226
1227 /**
1228 * Return matching items from array (similar to mysql's %LIKE%)
1229 *
1230 * @param string|regex $pattern
1231 * @param array $array
1232 * @return array|false
1233 */
1234 public static function like($array, $pattern)
1235 {
1236 if (@preg_match($pattern, '') === false) {
1237 $pattern = '~'. preg_quote($pattern, '~') . '~i';
1238 }
1239
1240 return preg_grep($pattern, $array);
1241 }
1242
1243 /**
1244 * Return non-matching items from array (similar to mysql's NOT %LIKE%)
1245 *
1246 * @param string|regex $pattern
1247 * @param array $array
1248 * @return array|false
1249 */
1250 public static function notLike($array, $pattern)
1251 {
1252 if (@preg_match($pattern, '') === false) {
1253 $pattern = '~'. preg_quote($pattern, '~') . '~i';
1254 }
1255
1256 return preg_grep($pattern, $array, PREG_GREP_INVERT);
1257 }
1258
1259 /**
1260 * Return matching starting of items from array (similar to mysql's %LIKE)
1261 *
1262 * @param string|regex $pattern
1263 * @param array $array
1264 * @return array|false
1265 */
1266 public static function startsLike($array, $pattern)
1267 {
1268 if (@preg_match($pattern, '') === false) {
1269 $pattern = '~^'. preg_quote($pattern, '~') . '~i';
1270 }
1271
1272 return preg_grep($pattern, $array);
1273 }
1274
1275 /**
1276 * Return non-matching starting of items from array (similar to mysql's NOT %LIKE)
1277 *
1278 * @param string|regex $pattern
1279 * @param array $array
1280 * @return array|false
1281 */
1282 public static function DoesNotStartLike($array, $pattern)
1283 {
1284 if (@preg_match($pattern, '') === false) {
1285 $pattern = '~^(?!' . preg_quote($pattern, '~') . ')~i';
1286 }
1287
1288 return preg_grep($pattern, $array);
1289 }
1290
1291 /**
1292 * Return matching ending of items from array (similar to mysql's LIKE%)
1293 *
1294 * @param string|regex $pattern
1295 * @param array $array
1296 * @return array|false
1297 */
1298 public static function endsLike($array, $pattern)
1299 {
1300 if (@preg_match($pattern, '') === false) {
1301 $pattern = '~'. preg_quote($pattern, '~') . '$~i';
1302 }
1303
1304 return preg_grep($pattern, $array);
1305 }
1306
1307 /**
1308 * Return non-matching ending of items from array (similar to mysql's NOT LIKE%)
1309 *
1310 * @param string|regex $pattern
1311 * @param array $array
1312 * @return array|false
1313 */
1314 public static function DoesNotEndLike($array, $pattern)
1315 {
1316 if (@preg_match($pattern, '') === false) {
1317 $pattern = '~'. preg_quote($pattern, '~') . '$~i';
1318 }
1319
1320 return preg_grep($pattern, $array, PREG_GREP_INVERT);
1321 }
1322
1323 /**
1324 * Return matching items from array by keys
1325 *
1326 * @param string|regex $pattern
1327 * @param array $array
1328 * @return array|false
1329 */
1330 public static function keysLike($array, $pattern)
1331 {
1332 if (@preg_match($pattern, '') === false) {
1333 $pattern = '~'. preg_quote($pattern, '~') . '~i';
1334 }
1335
1336 $values = [];
1337
1338 $keys = preg_grep($pattern, array_keys($array));
1339
1340 foreach ($keys as $key) {
1341 $values[$key] = $array[$key];
1342 }
1343
1344 return $values;
1345 }
1346
1347 /**
1348 * Return non-matching items from array by keys
1349 *
1350 * @param string|regex $pattern
1351 * @param array $array
1352 * @return array|false
1353 */
1354 public static function keysNotLike($array, $pattern)
1355 {
1356 if (@preg_match($pattern, '') === false) {
1357 $pattern = '~'. preg_quote($pattern, '~') . '~i';
1358 }
1359
1360 $values = [];
1361
1362 $keys = preg_grep($pattern, array_keys($array), 1);
1363
1364 foreach ($keys as $key) {
1365 $values[$key] = $array[$key];
1366 }
1367
1368 return $values;
1369 }
1370
1371 /**
1372 * Return matching starting of items from array by keys
1373 *
1374 * @param string|regex $pattern
1375 * @param array $array
1376 * @return array|false
1377 */
1378 public static function keysStartLike($array, $pattern)
1379 {
1380 if (@preg_match($pattern, '') === false) {
1381 $pattern = '~^'. preg_quote($pattern, '~') . '~i';
1382 }
1383
1384 $values = [];
1385
1386 $keys = preg_grep($pattern, array_keys($array));
1387
1388 foreach ($keys as $key) {
1389 $values[$key] = $array[$key];
1390 }
1391
1392 return $values;
1393 }
1394
1395 /**
1396 * Return non-matching starting of items from array by keys
1397 *
1398 * @param string|regex $pattern
1399 * @param array $array
1400 * @return array|false
1401 */
1402 public static function keysDoesNotStartLike($array, $pattern)
1403 {
1404 if (@preg_match($pattern, '') === false) {
1405 $pattern = '~^(?!' . preg_quote($pattern, '~') . ')~i';
1406 }
1407
1408 $values = [];
1409
1410 $keys = preg_grep($pattern, array_keys($array));
1411
1412 foreach ($keys as $key) {
1413 $values[$key] = $array[$key];
1414 }
1415
1416 return $values;
1417 }
1418
1419 /**
1420 * Return matching ending of items from array by keys
1421 *
1422 * @param string|regex $pattern
1423 * @param array $array
1424 * @return array|false
1425 */
1426 public static function keysEndLike($array, $pattern)
1427 {
1428 if (@preg_match($pattern, '') === false) {
1429 $pattern = '~'. preg_quote($pattern, '~') . '$~i';
1430 }
1431
1432 $values = [];
1433
1434 $keys = preg_grep($pattern, array_keys($array));
1435
1436 foreach ($keys as $key) {
1437 $values[$key] = $array[$key];
1438 }
1439
1440 return $values;
1441 }
1442
1443 /**
1444 * Return non-matching ending of items from array by keys
1445 *
1446 * @param string|regex $pattern
1447 * @param array $array
1448 * @return array|false
1449 */
1450 public static function keysDoesNotEndLike($array, $pattern)
1451 {
1452 if (@preg_match($pattern, '') === false) {
1453 $pattern = '~'. preg_quote($pattern, '~') . '$~i';
1454 }
1455
1456 $values = [];
1457
1458 $keys = preg_grep($pattern, array_keys($array), PREG_GREP_INVERT);
1459
1460 foreach ($keys as $key) {
1461 $values[$key] = $array[$key];
1462 }
1463
1464 return $values;
1465 }
1466
1467 /**
1468 * Insert a new item in the array at the given position.
1469 *
1470 * @param array $array
1471 * @param int $pos
1472 * @param mixed $newItem
1473 * @return array
1474 */
1475 public static function insertAt($array, $pos, $newItem)
1476 {
1477 if (!isset($array[$pos])) {
1478 $array[] = $newItem;
1479 } else {
1480 $array = array_splice($array, $pos, 0, $newItem);
1481 }
1482
1483 return $array;
1484 }
1485 }
1486