Skip to content

Commit d6aa341

Browse files
committed
fix: validation multiple asterisk
1 parent 118c2c4 commit d6aa341

File tree

2 files changed

+77
-38
lines changed

2 files changed

+77
-38
lines changed

system/Validation/DotArrayFilter.php

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ final class DotArrayFilter
2121
/**
2222
* Creates a new array with only the elements specified in dot array syntax.
2323
*
24-
* This code comes from the dot_array_search() function.
25-
*
2624
* @param array $indexes The dot array syntax pattern to use for filtering.
2725
* @param array $array The array to filter.
2826
*
@@ -33,20 +31,14 @@ public static function run(array $indexes, array $array): array
3331
$result = [];
3432

3533
foreach ($indexes as $index) {
36-
// See https://regex101.com/r/44Ipql/1
37-
$segments = preg_split(
38-
'/(?<!\\\\)\./',
39-
rtrim($index, '* '),
40-
0,
41-
PREG_SPLIT_NO_EMPTY
42-
);
43-
44-
$segments = array_map(
45-
static fn ($key) => str_replace('\.', '.', $key),
46-
$segments
47-
);
48-
49-
$result = array_replace_recursive($result, self::filter($segments, $array));
34+
$segments = preg_split('/(?<!\\\\)\./', $index, -1, PREG_SPLIT_NO_EMPTY);
35+
$segments = array_map(static fn ($key) => str_replace('\.', '.', $key), $segments);
36+
37+
$filteredArray = self::filter($segments, $array);
38+
39+
if ($filteredArray !== []) {
40+
$result = array_replace_recursive($result, $filteredArray);
41+
}
5042
}
5143

5244
return $result;
@@ -62,53 +54,54 @@ public static function run(array $indexes, array $array): array
6254
*/
6355
private static function filter(array $indexes, array $array): array
6456
{
65-
// If index is empty, returns empty array.
57+
// If there are no indexes left, return an empty array
6658
if ($indexes === []) {
6759
return [];
6860
}
6961

70-
// Grab the current index.
62+
// Get the current index
7163
$currentIndex = array_shift($indexes);
7264

65+
// If the current index doesn't exist and is not a wildcard, return an empty array
7366
if (! isset($array[$currentIndex]) && $currentIndex !== '*') {
7467
return [];
7568
}
7669

77-
// Handle Wildcard (*)
70+
// Handle the wildcard '*' at the current level
7871
if ($currentIndex === '*') {
79-
$answer = [];
72+
$result = [];
8073

74+
// Iterate over all keys at this level
8175
foreach ($array as $key => $value) {
82-
if (! is_array($value)) {
83-
continue;
84-
}
85-
86-
$result = self::filter($indexes, $value);
87-
88-
if ($result !== []) {
89-
$answer[$key] = $result;
76+
if ($indexes === []) {
77+
// If no indexes are left, capture the entire value
78+
$result[$key] = $value;
79+
} elseif (is_array($value)) {
80+
// If there are still indexes left, continue filtering recursively
81+
$filtered = self::filter($indexes, $value);
82+
if ($filtered !== []) {
83+
$result[$key] = $filtered;
84+
}
9085
}
9186
}
9287

93-
return $answer;
88+
return $result;
9489
}
9590

96-
// If this is the last index, make sure to return it now,
97-
// and not try to recurse through things.
91+
// If this is the last index, return the value
9892
if ($indexes === []) {
99-
return [$currentIndex => $array[$currentIndex]];
93+
return [$currentIndex => $array[$currentIndex] ?? []];
10094
}
10195

102-
// Do we need to recursively filter this value?
103-
if (is_array($array[$currentIndex]) && $array[$currentIndex] !== []) {
104-
$result = self::filter($indexes, $array[$currentIndex]);
96+
// If the current value is an array, recursively filter it
97+
if (is_array($array[$currentIndex])) {
98+
$filtered = self::filter($indexes, $array[$currentIndex]);
10599

106-
if ($result !== []) {
107-
return [$currentIndex => $result];
100+
if ($filtered !== []) {
101+
return [$currentIndex => $filtered];
108102
}
109103
}
110104

111-
// Otherwise, not found.
112105
return [];
113106
}
114107
}

tests/system/Validation/ValidationTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1826,4 +1826,50 @@ public function testRuleWithAsteriskToMultiDimensionalArray(): void
18261826
$this->validation->getErrors()
18271827
);
18281828
}
1829+
1830+
public function testRuleWithMultipleAsterisk(): void
1831+
{
1832+
$data = [
1833+
'id' => 1,
1834+
'dates' => [
1835+
23 => [
1836+
45 => 'Its Mee!',
1837+
],
1838+
],
1839+
'foo' => [
1840+
'bar' => [
1841+
'data' => [
1842+
'name' => 'John Doe',
1843+
'age' => 29,
1844+
'location' => 'Indonesia',
1845+
],
1846+
],
1847+
],
1848+
];
1849+
1850+
$this->validation->setRules([
1851+
'id' => 'required|numeric',
1852+
'dates.*.*' => 'required',
1853+
'foo.*.*.*' => 'required',
1854+
]);
1855+
1856+
$this->assertTrue($this->validation->run($data));
1857+
$this->assertSame([
1858+
'id' => 1,
1859+
'dates' => [
1860+
23 => [
1861+
45 => 'Its Mee!',
1862+
],
1863+
],
1864+
'foo' => [
1865+
'bar' => [
1866+
'data' => [
1867+
'name' => 'John Doe',
1868+
'age' => 29,
1869+
'location' => 'Indonesia',
1870+
],
1871+
],
1872+
],
1873+
], $this->validation->getValidated());
1874+
}
18291875
}

0 commit comments

Comments
 (0)