Skip to content

Commit bc4f308

Browse files
committed
refactor: move code from array_helper.php to ArrayHelper.php
1 parent 514fe62 commit bc4f308

File tree

2 files changed

+147
-126
lines changed

2 files changed

+147
-126
lines changed

system/Helpers/Array/ArrayHelper.php

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,149 @@
1616
*/
1717
final class ArrayHelper
1818
{
19+
/**
20+
* Searches an array through dot syntax. Supports
21+
* wildcard searches, like foo.*.bar
22+
*
23+
* @return array|bool|int|object|string|null
24+
*/
25+
public static function dotArraySearch(string $index, array $array)
26+
{
27+
// See https://regex101.com/r/44Ipql/1
28+
$segments = preg_split(
29+
'/(?<!\\\\)\./',
30+
rtrim($index, '* '),
31+
0,
32+
PREG_SPLIT_NO_EMPTY
33+
);
34+
35+
$segments = array_map(static fn ($key) => str_replace('\.', '.', $key), $segments);
36+
37+
return self::arraySearchDot($segments, $array);
38+
}
39+
40+
/**
41+
* Used by `dotArraySearch()` to recursively search the
42+
* array with wildcards.
43+
*
44+
* @return array|bool|float|int|object|string|null
45+
*/
46+
private static function arraySearchDot(array $indexes, array $array)
47+
{
48+
// If index is empty, returns null.
49+
if ($indexes === []) {
50+
return null;
51+
}
52+
53+
// Grab the current index
54+
$currentIndex = array_shift($indexes);
55+
56+
if (! isset($array[$currentIndex]) && $currentIndex !== '*') {
57+
return null;
58+
}
59+
60+
// Handle Wildcard (*)
61+
if ($currentIndex === '*') {
62+
$answer = [];
63+
64+
foreach ($array as $value) {
65+
if (! is_array($value)) {
66+
return null;
67+
}
68+
69+
$answer[] = self::arraySearchDot($indexes, $value);
70+
}
71+
72+
$answer = array_filter($answer, static fn ($value) => $value !== null);
73+
74+
if ($answer !== []) {
75+
if (count($answer) === 1) {
76+
// If array only has one element, we return that element for BC.
77+
return current($answer);
78+
}
79+
80+
return $answer;
81+
}
82+
83+
return null;
84+
}
85+
86+
// If this is the last index, make sure to return it now,
87+
// and not try to recurse through things.
88+
if (empty($indexes)) {
89+
return $array[$currentIndex];
90+
}
91+
92+
// Do we need to recursively search this value?
93+
if (is_array($array[$currentIndex]) && $array[$currentIndex] !== []) {
94+
return self::arraySearchDot($indexes, $array[$currentIndex]);
95+
}
96+
97+
// Otherwise, not found.
98+
return null;
99+
}
100+
101+
/**
102+
* Groups all rows by their index values. Result's depth equals number of indexes
103+
*
104+
* @param array $array Data array (i.e. from query result)
105+
* @param array $indexes Indexes to group by. Dot syntax used. Returns $array if empty
106+
* @param bool $includeEmpty If true, null and '' are also added as valid keys to group
107+
*
108+
* @return array Result array where rows are grouped together by indexes values.
109+
*/
110+
public static function arrayGroupBy(array $array, array $indexes, bool $includeEmpty = false): array
111+
{
112+
if ($indexes === []) {
113+
return $array;
114+
}
115+
116+
$result = [];
117+
118+
foreach ($array as $row) {
119+
$result = self::arrayAttachIndexedValue($result, $row, $indexes, $includeEmpty);
120+
}
121+
122+
return $result;
123+
}
124+
125+
/**
126+
* Used by `arrayGroupBy()` to recursively attach $row to the $indexes path of values found by
127+
* `dot_array_search()`
128+
*
129+
* @internal This should not be used on its own
130+
*/
131+
private static function arrayAttachIndexedValue(array $result, array $row, array $indexes, bool $includeEmpty): array
132+
{
133+
if (($index = array_shift($indexes)) === null) {
134+
$result[] = $row;
135+
136+
return $result;
137+
}
138+
139+
$value = dot_array_search($index, $row);
140+
141+
if (! is_scalar($value)) {
142+
$value = '';
143+
}
144+
145+
if (is_bool($value)) {
146+
$value = (int) $value;
147+
}
148+
149+
if (! $includeEmpty && $value === '') {
150+
return $result;
151+
}
152+
153+
if (! array_key_exists($value, $result)) {
154+
$result[$value] = [];
155+
}
156+
157+
$result[$value] = self::arrayAttachIndexedValue($result[$value], $row, $indexes, $includeEmpty);
158+
159+
return $result;
160+
}
161+
19162
/**
20163
* Compare recursively two associative arrays and return difference as new array.
21164
* Returns keys that exist in `$original` but not in `$compareWith`.

system/Helpers/array_helper.php

Lines changed: 4 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* the LICENSE file that was distributed with this source code.
1010
*/
1111

12+
use CodeIgniter\Helpers\Array\ArrayHelper;
13+
1214
// CodeIgniter Array Helpers
1315

1416
if (! function_exists('dot_array_search')) {
@@ -20,82 +22,7 @@
2022
*/
2123
function dot_array_search(string $index, array $array)
2224
{
23-
// See https://regex101.com/r/44Ipql/1
24-
$segments = preg_split(
25-
'/(?<!\\\\)\./',
26-
rtrim($index, '* '),
27-
0,
28-
PREG_SPLIT_NO_EMPTY
29-
);
30-
31-
$segments = array_map(static fn ($key) => str_replace('\.', '.', $key), $segments);
32-
33-
return _array_search_dot($segments, $array);
34-
}
35-
}
36-
37-
if (! function_exists('_array_search_dot')) {
38-
/**
39-
* Used by `dot_array_search` to recursively search the
40-
* array with wildcards.
41-
*
42-
* @internal This should not be used on its own.
43-
*
44-
* @return array|bool|float|int|object|string|null
45-
*/
46-
function _array_search_dot(array $indexes, array $array)
47-
{
48-
// If index is empty, returns null.
49-
if ($indexes === []) {
50-
return null;
51-
}
52-
53-
// Grab the current index
54-
$currentIndex = array_shift($indexes);
55-
56-
if (! isset($array[$currentIndex]) && $currentIndex !== '*') {
57-
return null;
58-
}
59-
60-
// Handle Wildcard (*)
61-
if ($currentIndex === '*') {
62-
$answer = [];
63-
64-
foreach ($array as $value) {
65-
if (! is_array($value)) {
66-
return null;
67-
}
68-
69-
$answer[] = _array_search_dot($indexes, $value);
70-
}
71-
72-
$answer = array_filter($answer, static fn ($value) => $value !== null);
73-
74-
if ($answer !== []) {
75-
if (count($answer) === 1) {
76-
// If array only has one element, we return that element for BC.
77-
return current($answer);
78-
}
79-
80-
return $answer;
81-
}
82-
83-
return null;
84-
}
85-
86-
// If this is the last index, make sure to return it now,
87-
// and not try to recurse through things.
88-
if (empty($indexes)) {
89-
return $array[$currentIndex];
90-
}
91-
92-
// Do we need to recursively search this value?
93-
if (is_array($array[$currentIndex]) && $array[$currentIndex] !== []) {
94-
return _array_search_dot($indexes, $array[$currentIndex]);
95-
}
96-
97-
// Otherwise, not found.
98-
return null;
25+
return ArrayHelper::dotArraySearch($index, $array);
9926
}
10027
}
10128

@@ -231,55 +158,6 @@ function array_flatten_with_dots(iterable $array, string $id = ''): array
231158
*/
232159
function array_group_by(array $array, array $indexes, bool $includeEmpty = false): array
233160
{
234-
if ($indexes === []) {
235-
return $array;
236-
}
237-
238-
$result = [];
239-
240-
foreach ($array as $row) {
241-
$result = _array_attach_indexed_value($result, $row, $indexes, $includeEmpty);
242-
}
243-
244-
return $result;
245-
}
246-
}
247-
248-
if (! function_exists('_array_attach_indexed_value')) {
249-
/**
250-
* Used by `array_group_by` to recursively attach $row to the $indexes path of values found by
251-
* `dot_array_search`
252-
*
253-
* @internal This should not be used on its own
254-
*/
255-
function _array_attach_indexed_value(array $result, array $row, array $indexes, bool $includeEmpty): array
256-
{
257-
if (($index = array_shift($indexes)) === null) {
258-
$result[] = $row;
259-
260-
return $result;
261-
}
262-
263-
$value = dot_array_search($index, $row);
264-
265-
if (! is_scalar($value)) {
266-
$value = '';
267-
}
268-
269-
if (is_bool($value)) {
270-
$value = (int) $value;
271-
}
272-
273-
if (! $includeEmpty && $value === '') {
274-
return $result;
275-
}
276-
277-
if (! array_key_exists($value, $result)) {
278-
$result[$value] = [];
279-
}
280-
281-
$result[$value] = _array_attach_indexed_value($result[$value], $row, $indexes, $includeEmpty);
282-
283-
return $result;
161+
return ArrayHelper::arrayGroupBy($array, $indexes, $includeEmpty);
284162
}
285163
}

0 commit comments

Comments
 (0)