-
Notifications
You must be signed in to change notification settings - Fork 4
/
CollectionUtils.php
135 lines (121 loc) · 3.27 KB
/
CollectionUtils.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<?php declare(strict_types=1);
/**
* This file is part of the Phootwork package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
* @copyright Thomas Gossmann
*/
namespace phootwork\collection;
use Iterator;
use stdClass;
/**
* CollectionUtils help to transform data recursively into collections.
*
* It must be mentioned the API is experimental and may change. Please
* report to the issue tracker.
*/
class CollectionUtils {
/**
* Returns a proper collection for the given array (also transforms nested collections)
* (experimental API)
*
* @param array|Iterator $collection
*
* @return Map|ArrayList the collection
*
* @psalm-suppress MixedReturnStatement `self::toCollection()` returns a collection if the input
* is an array or Iterator
* @psalm-suppress MixedInferredReturnType
*/
public static function fromCollection(array|Iterator $collection): Map|ArrayList {
return self::toCollection($collection);
}
/**
* @param mixed $data
*
* @return mixed
*/
private static function toCollection(mixed $data): mixed {
// prepare normal array
if (!($data instanceof Iterator)) {
/** @var mixed $data */
$data = json_decode(json_encode($data));
}
// check if we can transform it into a collection or just return as is
if (!(is_array($data) || $data instanceof Iterator || $data instanceof stdClass)) {
return $data;
}
// check we have a list
if (is_array($data) || $data instanceof AbstractList) {
return self::toList($data);
}
// everything else must be a map
return self::toMap($data);
}
/**
* Recursively transforms data into a map (on the first level, deeper levels
* transformed to an appropriate collection) (experimental API)
*
* @param array|Iterator|stdClass $collection
*
* @return Map
*/
public static function toMap(Iterator|array|stdClass $collection): Map {
if ($collection instanceof stdClass) {
/** @var array $collection */
$collection = json_decode(json_encode($collection), true);
}
$map = new Map();
/**
* @var string $k
* @var string $v
*/
foreach ($collection as $k => $v) {
$map->set($k, self::toCollection($v));
}
return $map;
}
/**
* Recursively transforms data into a list (on the first level, deeper levels
* transformed to an appropriate collection) (experimental API)
*
* @param array|Iterator $collection
*
* @return ArrayList
*/
public static function toList(Iterator|array $collection): ArrayList {
$list = new ArrayList();
/** @var mixed $v */
foreach ($collection as $v) {
$list->add(self::toCollection($v));
}
return $list;
}
/**
* Recursively exports a collection to an array
*
* @param mixed $collection
*
* @return array
*
* @psalm-suppress MixedAssignment
*/
public static function toArrayRecursive(mixed $collection): array {
$arr = $collection;
if (is_object($collection) && method_exists($collection, 'toArray')) {
$arr = $collection->toArray();
}
/** @var array $arr */
return array_map(
function (mixed $v): mixed {
if (is_object($v) && method_exists($v, 'toArray')) {
return static::toArrayRecursive($v);
}
return $v;
},
$arr
);
}
}