@@ -32,8 +32,22 @@ class Arr
3232 const MAP_ARRAY_VALUE_KEYS_LIST = 2 ;
3333 const MAP_ARRAY_KEYS_ARRAY_VALUE = 4 ;
3434
35+ const UNPACK_ALL = 1 ;
36+ /**
37+ * Preserve arrays with highest nesting level (if they are not assoc) as element values instead of unpacking them
38+ */
39+ const UNPACK_PRESERVE_LIST_ARRAY = 2 ;
40+ /**
41+ * Preserve arrays with highest nesting level (if they are assoc) as element values instead of unpacking them
42+ */
43+ const UNPACK_PRESERVE_ASSOC_ARRAY = 4 ;
44+ /**
45+ * Preserve all arrays with highest nesting level as element values instead of unpacking them
46+ */
47+ const UNPACK_PRESERVE_ARRAY = 8 ;
3548
3649 private const AUTO_INDEX_KEY = '[] ' ;
50+ private const KEY_SEPARATOR = '. ' ;
3751
3852 /*--------------------------------------------------------------------------------------*\
3953 | Common |
@@ -58,7 +72,7 @@ class Arr
5872 public static function getKeysArray ($ keys ): array
5973 {
6074 if (is_string ($ keys )) {
61- return empty ($ keys ) ? [] : explode (' . ' , $ keys );
75+ return empty ($ keys ) ? [] : explode (self :: KEY_SEPARATOR , $ keys );
6276 }
6377 return is_null ($ keys ) ? [] : array_filter (array_values (self ::forceArray ($ keys )), function ($ value ) {
6478 return $ value !== null && $ value !== '' && (is_string ($ value ) || is_int ($ value ));
@@ -153,21 +167,34 @@ public static function setNestedElement(array $array, $keys, $value): array
153167 * Converts multidimensional array to map of keys concatenated by dot and corresponding values
154168 *
155169 * @param array $array
156- * @param array $keys Internal keys storage used for recursive calls
170+ * @param int $mode Modify behaviour of unpack (see description of Arr::UNPACK_ constants)
157171 * @return array
158172 */
159- public static function unpack (array $ array , array $ keys = []): array
173+ public static function unpack (array $ array , int $ mode = self ::UNPACK_ALL ): array
174+ {
175+ return self ::_unpack ($ array , $ mode );
176+ }
177+
178+ private static function _unpack (array $ array , int $ mode = self ::UNPACK_ALL , array $ keys = []): array
160179 {
161180 $ result = [];
162181
163182 foreach ($ array as $ key => $ value ) {
164183
165- if (is_array ($ value )) {
184+ if (is_array ($ value ) && !(
185+ // Check if value IS NOT a subject for preserve mode
186+ !self ::isNested ($ value ) && // Preserve mode only work for highest depth elements
187+ (
188+ ($ mode === self ::UNPACK_PRESERVE_LIST_ARRAY && !self ::isAssoc ($ value , true )) ||
189+ ($ mode === self ::UNPACK_PRESERVE_ASSOC_ARRAY && self ::isAssoc ($ value , true )) ||
190+ $ mode === self ::UNPACK_PRESERVE_ARRAY
191+ )
192+ )) {
166193 $ keys [] = $ key ;
167- $ result += self ::unpack ($ value , $ keys );
194+ $ result += self ::_unpack ($ value, $ mode , $ keys );
168195 array_pop ($ keys );
169196 } else {
170- $ result [implode (' . ' , array_merge ($ keys , [$ key ]))] = $ value ;
197+ $ result [implode (self :: KEY_SEPARATOR , array_merge ($ keys , [$ key ]))] = $ value ;
171198 }
172199 }
173200
@@ -251,7 +278,9 @@ public static function isEmpty($array): bool
251278 *
252279 * @param array $array
253280 * @param bool $strict
254- * If false then this function will match any array that doesn't contain integer keys
281+ * <p>If <i>false</i> then this function will match any array that doesn't contain integer keys.</p>
282+ * <p>If <i>true</i> then this function match only arrays with sequence of integers starting from zero (range from 0 to elements_number - 1) as keys.</p>
283+ *
255284 * @return boolean
256285 */
257286 public static function isAssoc (array $ array , bool $ strict = false ): bool
@@ -772,7 +801,7 @@ public static function createMulti(array $keys, ?array $values = null): array
772801 * Make variable an array (according to flag settings)
773802 *
774803 * @param mixed $var
775- * @param int $flag Set flag(s) to preserve specific values from being converted to array
804+ * @param int $flag Set flag(s) to preserve specific values from being converted to array (see Arr::FORCE_ARRAY_ constants)
776805 * @return array
777806 */
778807 public static function forceArray ($ var , int $ flag = self ::FORCE_ARRAY_ALL )
0 commit comments