Skip to content

Commit 5bba757

Browse files
authored
[9.x] Patch nested array validation rule regression bug (#43897)
* Remove Arr::flatten * Update tests and remove no-longer relevant tests * Add test for nested validation rules * Rename and move test * Add failing validation run * CS fix
1 parent 2a1a55c commit 5bba757

File tree

3 files changed

+44
-38
lines changed

3 files changed

+44
-38
lines changed

src/Illuminate/Validation/ValidationRuleParser.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ protected function explodeWildcardRules($results, $attribute, $rules)
151151

152152
foreach ($data as $key => $value) {
153153
if (Str::startsWith($key, $attribute) || (bool) preg_match('/^'.$pattern.'\z/', $key)) {
154-
foreach (Arr::flatten((array) $rules) as $rule) {
154+
foreach ((array) $rules as $rule) {
155155
if ($rule instanceof NestedRules) {
156156
$compiled = $rule->compile($key, $value, $data);
157157

tests/Validation/ValidationRuleParserTest.php

Lines changed: 12 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -144,18 +144,6 @@ public function testExplodeFailsParsingRegexWithOtherRulesInSingleString()
144144
$this->assertSame('bar)$/i', $exploded->rules['items.0.type'][2]);
145145
}
146146

147-
public function testExplodeProperlyFlattensRuleArraysOfArrays()
148-
{
149-
$data = ['items' => [['type' => 'foo']]];
150-
151-
$exploded = (new ValidationRuleParser($data))->explode(
152-
['items.*.type' => ['in:foo', [[['regex:/^(foo|bar)$/i']]]]]
153-
);
154-
155-
$this->assertSame('in:foo', $exploded->rules['items.0.type'][0]);
156-
$this->assertSame('regex:/^(foo|bar)$/i', $exploded->rules['items.0.type'][1]);
157-
}
158-
159147
public function testExplodeGeneratesNestedRules()
160148
{
161149
$parser = (new ValidationRuleParser([
@@ -208,28 +196,19 @@ public function testExplodeHandlesArraysOfNestedRules()
208196
]));
209197

210198
$results = $parser->explode([
211-
'users.*.name' => [
212-
Rule::forEach(function ($value, $attribute, $data) {
213-
$this->assertEquals([
214-
'users.0.name' => 'Taylor Otwell',
215-
'users.1.name' => 'Abigail Otwell',
216-
], $data);
217-
218-
return [Rule::requiredIf(true)];
219-
}),
220-
Rule::forEach(function ($value, $attribute, $data) {
199+
'users.*.name' => Rule::forEach(function ($value, $attribute, $data) {
221200
$this->assertEquals([
222201
'users.0.name' => 'Taylor Otwell',
223202
'users.1.name' => 'Abigail Otwell',
224203
], $data);
225204

226205
return [
206+
Rule::requiredIf(true),
227207
$value === 'Taylor Otwell'
228208
? Rule::in('taylor')
229209
: Rule::in('abigail'),
230210
];
231211
}),
232-
],
233212
]);
234213

235214
$this->assertEquals([
@@ -240,8 +219,6 @@ public function testExplodeHandlesArraysOfNestedRules()
240219
$this->assertEquals([
241220
'users.*.name' => [
242221
'users.0.name',
243-
'users.0.name',
244-
'users.1.name',
245222
'users.1.name',
246223
],
247224
], $results->implicitAttributes);
@@ -254,9 +231,13 @@ public function testExplodeHandlesRecursivelyNestedRules()
254231
]));
255232

256233
$results = $parser->explode([
257-
'users.*.name' => [
258-
Rule::forEach(function ($value, $attribute, $data) {
259-
$this->assertSame('Taylor Otwell', $value);
234+
'users.*.name' => Rule::forEach(function ($value, $attribute, $data) {
235+
$this->assertSame('Taylor Otwell', $value);
236+
$this->assertSame('users.0.name', $attribute);
237+
$this->assertEquals(['users.0.name' => 'Taylor Otwell'], $data);
238+
239+
return Rule::forEach(function ($value, $attribute, $data) {
240+
$this->assertNull($value);
260241
$this->assertSame('users.0.name', $attribute);
261242
$this->assertEquals(['users.0.name' => 'Taylor Otwell'], $data);
262243

@@ -265,16 +246,10 @@ public function testExplodeHandlesRecursivelyNestedRules()
265246
$this->assertSame('users.0.name', $attribute);
266247
$this->assertEquals(['users.0.name' => 'Taylor Otwell'], $data);
267248

268-
return Rule::forEach(function ($value, $attribute, $data) {
269-
$this->assertNull($value);
270-
$this->assertSame('users.0.name', $attribute);
271-
$this->assertEquals(['users.0.name' => 'Taylor Otwell'], $data);
272-
273-
return [Rule::requiredIf(true)];
274-
});
249+
return [Rule::requiredIf(true)];
275250
});
276-
}),
277-
],
251+
});
252+
}),
278253
]);
279254

280255
$this->assertEquals(['users.0.name' => ['required']], $results->rules);

tests/Validation/ValidationValidatorTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,37 @@ public function testInValidatableRulesReturnsValid()
173173
$this->assertTrue($v->passes());
174174
}
175175

176+
public function testValidateUsingNestedValidationRulesPasses()
177+
{
178+
$rules = [
179+
'items' => ['array'],
180+
'items.*' => ['array', ['required_array_keys', '|name']],
181+
'items.*.|name' => [['in', '|ABC123']],
182+
];
183+
184+
$data = [
185+
'items' => [
186+
['|name' => '|ABC123'],
187+
],
188+
];
189+
190+
$trans = $this->getIlluminateArrayTranslator();
191+
$v = new Validator($trans, $data, $rules);
192+
193+
$this->assertTrue($v->passes());
194+
195+
$data = [
196+
'items' => [
197+
['|name' => '|1234'],
198+
],
199+
];
200+
201+
$trans = $this->getIlluminateArrayTranslator();
202+
$v = new Validator($trans, $data, $rules);
203+
204+
$this->assertSame('validation.in', $v->messages()->get('items.0.|name')[0]);
205+
}
206+
176207
public function testValidateEmptyStringsAlwaysPasses()
177208
{
178209
$trans = $this->getIlluminateArrayTranslator();

0 commit comments

Comments
 (0)