21
21
use SimpleXMLElement ;
22
22
use Traversable ;
23
23
24
- use function array_is_list ;
25
-
26
24
/**
27
25
* Class ArrayHelper.
28
26
*
@@ -242,6 +240,17 @@ public static function mergeRecursive(array ...$arrays): array
242
240
return $ arraySrc ;
243
241
}
244
242
243
+ private static function parseKey (string $ key ): array
244
+ {
245
+ $ normalized = preg_replace ('/\.([^.\[\]]+)/ ' , '[$1] ' , $ key );
246
+ preg_match_all ('/([^\[\]]+)/ ' , $ normalized , $ matches );
247
+ if (substr ($ key , -2 ) == '[] ' ) {
248
+ $ matches [1 ][] = '' ;
249
+ }
250
+
251
+ return $ matches [1 ];
252
+ }
253
+
245
254
/**
246
255
* Traverse array with path and return if path exists.
247
256
*
@@ -252,7 +261,7 @@ public static function mergeRecursive(array ...$arrays): array
252
261
*/
253
262
public static function traverseExists (iterable &$ mixed , string $ path ): bool
254
263
{
255
- $ path = explode ( ' . ' , $ path );
264
+ $ path = self :: parseKey ( $ path );
256
265
257
266
$ temp = &$ mixed ;
258
267
foreach ($ path as $ key ) {
@@ -287,7 +296,7 @@ public static function traverseExists(iterable &$mixed, string $path): bool
287
296
*/
288
297
public static function traverseGet (iterable &$ mixed , string $ path , $ default = null )
289
298
{
290
- $ path = explode ( ' . ' , $ path );
299
+ $ path = self :: parseKey ( $ path );
291
300
292
301
$ temp = &$ mixed ;
293
302
foreach ($ path as $ key ) {
@@ -322,14 +331,21 @@ public static function traverseGet(iterable &$mixed, string $path, $default = nu
322
331
*/
323
332
public static function traverseSet (iterable &$ mixed , string $ path , $ value ): bool
324
333
{
325
- $ path = explode ( ' . ' , $ path );
334
+ $ path = self :: parseKey ( $ path );
326
335
327
336
$ temp = &$ mixed ;
328
337
foreach ($ path as $ key ) {
329
338
if (null !== $ temp && !is_iterable ($ temp )) {
330
339
return false ;
331
340
}
332
341
342
+ if ($ key === '' ) {
343
+ $ temp [] = null ;
344
+ end ($ temp );
345
+ $ temp = &$ temp [key ($ temp )];
346
+ continue ;
347
+ }
348
+
333
349
if (!isset ($ temp [$ key ])) {
334
350
$ temp [$ key ] = null ;
335
351
}
@@ -351,7 +367,7 @@ public static function traverseSet(iterable &$mixed, string $path, $value): bool
351
367
*/
352
368
public static function simpleArray (array $ array , ?string $ prefix = null ): array
353
369
{
354
- $ metaData = [];
370
+ $ output = [];
355
371
356
372
foreach ($ array as $ key => $ value ) {
357
373
// Prefix key if necessary
@@ -360,13 +376,78 @@ public static function simpleArray(array $array, ?string $prefix = null): array
360
376
}
361
377
362
378
if (is_array ($ value )) {
363
- $ metaData = array_merge ($ metaData , self ::simpleArray ($ value , $ key ));
379
+ $ output = array_merge ($ output , self ::simpleArray ($ value , $ key ));
364
380
continue ;
365
381
}
366
382
367
- $ metaData [$ key ] = $ value ;
383
+ $ output [$ key ] = $ value ;
384
+ }
385
+
386
+ return $ output ;
387
+ }
388
+
389
+ /**
390
+ * Transform simple level array to multidimensional.
391
+ *
392
+ * @param array $array
393
+ *
394
+ * @return array
395
+ */
396
+ public static function nestedArray (array $ array ): array
397
+ {
398
+ $ output = [];
399
+
400
+ foreach ($ array as $ key => $ value ) {
401
+ // Normalize dot notation to bracket notation
402
+ $ normalized = preg_replace ('/\.([^.\[\]]+)/ ' , '[$1] ' , $ key );
403
+
404
+ // Extract segments (ex: foo[bar][baz] → ['foo', 'bar', 'baz'])
405
+ preg_match_all ('/([^\[\]]+)/ ' , $ normalized , $ matches );
406
+ $ segments = $ matches [1 ];
407
+
408
+ $ ref = &$ output ;
409
+
410
+ foreach ($ segments as $ i => $ segment ) {
411
+ $ isLast = ($ i === count ($ segments ) - 1 );
412
+
413
+ if ($ isLast ) {
414
+ if ($ segment === '' ) {
415
+ $ ref [] = $ value ;
416
+ continue ;
417
+ }
418
+
419
+ if (is_numeric ($ segment )) {
420
+ $ ref [(int )$ segment ] = $ value ;
421
+ continue ;
422
+ }
423
+
424
+ $ ref [$ segment ] = $ value ;
425
+ continue ;
426
+ }
427
+
428
+ if ($ segment === '' ) {
429
+ $ ref [] = [];
430
+ end ($ ref );
431
+ $ ref = &$ ref [key ($ ref )];
432
+ continue ;
433
+ }
434
+
435
+ if (is_numeric ($ segment )) {
436
+ $ segment = (int )$ segment ;
437
+ if (!isset ($ ref [$ segment ]) || !is_array ($ ref [$ segment ])) {
438
+ $ ref [$ segment ] = [];
439
+ }
440
+ $ ref = &$ ref [$ segment ];
441
+ continue ;
442
+ }
443
+
444
+ if (!isset ($ ref [$ segment ]) || !is_array ($ ref [$ segment ])) {
445
+ $ ref [$ segment ] = [];
446
+ }
447
+ $ ref = &$ ref [$ segment ];
448
+ }
368
449
}
369
450
370
- return $ metaData ;
451
+ return $ output ;
371
452
}
372
453
}
0 commit comments