-
Notifications
You must be signed in to change notification settings - Fork 0
/
CollectionFlattener.php
153 lines (133 loc) · 3.45 KB
/
CollectionFlattener.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<?php
declare(strict_types=1);
namespace Peak\Collection;
use Peak\Blueprint\Collection\Collection;
use \Exception;
use function array_merge;
use function is_array;
use function mb_strlen;
use function substr;
class CollectionFlattener
{
/**
* @var Collection
*/
protected $collection;
/**
* @var array
*/
protected $search = [];
/**
* @var string
*/
protected $separator = '.';
/**
* Constructor
* @param Collection $coll
*/
public function __construct(Collection $coll)
{
$this->collection = $coll;
}
/**
* Change keys separators
* @param string $sep
* @return $this
* @throws Exception
*/
public function separator(string $sep): CollectionFlattener
{
if (mb_strlen($sep) != 1 || $sep === '*') {
throw new Exception(__CLASS__.': Separator must be 1 character and cannot be an asterisk (*)');
}
$this->separator = $sep;
return $this;
}
/**
* Simply flat all the collection
* @return array
*/
public function flatAll(): array
{
$this->search = [];
return $this->flatCollection($this->collection->toArray());
}
/**
* @param string $key
* @return array
*/
public function flatKey(string $key): array
{
$this->search = [$key];
return $this->flatCollection($this->collection->toArray());
}
/**
* Flat multiple keys names
* @param array $keys
* @return array
*/
public function flatKeys(array $keys): array
{
$this->search = $keys;
return $this->flatCollection($this->collection->toArray());
}
/**
* Flat collection recursively to one level key,val array
* @param array $data
* @param string|null $prefix
* @param array $flat_data
* @return array
*/
protected function flatCollection(array $data, string $prefix = null, array $flat_data = []): array
{
foreach ($data as $key => $val) {
if ($prefix !== null) {
$key = $prefix.$this->separator.$key;
}
$skip_key = $this->skipKey($key);
if (is_array($val)) {
$flat_data = array_merge(
$flat_data,
$this->flatCollection($val, (string) $key)
);
continue;
}
if ($skip_key) {
continue;
}
$flat_data[$key] = $val;
}
return $flat_data;
}
/**
* Detect if search is finishing by a wildcard (.*)
* @param string $search
* @return bool
*/
protected function hasWildCard(string $search): bool
{
return (substr($search, -2) === $this->separator.'*');
}
/**
* Detect if key must be skipped according to $search
* @param string $key
* @return bool
*/
protected function skipKey(string $key): bool
{
if (!empty($this->search)) {
foreach ($this->search as $search) {
if ($this->hasWildCard($search)) {
$search = substr($search, 0,-2);
if (substr($key, 0, mb_strlen($search)) === $search) {
return false;
}
} elseif ($search === $key) {
return false;
}
}
return true;
}
return false;
}
}