Skip to content

Commit 215b687

Browse files
committed
[Form] Added capability to process "." rules in "error_mapping"
1 parent c9c4900 commit 215b687

File tree

4 files changed

+42
-2
lines changed

4 files changed

+42
-2
lines changed

src/Symfony/Component/Form/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ CHANGELOG
7373
* added option "mapped" which should be used instead of setting "property_path" to false
7474
* "data_class" now *must* be set if a form maps to an object and should be left empty otherwise
7575
* improved error mapping on forms
76+
* dot (".") rules are now allowed to map errors assigned to a form to
77+
one of its children
7678
* errors are not mapped to unsynchronized forms anymore
7779
* changed Form constructor to accept a single `FormConfigInterface` object
7880
* changed argument order in the FormBuilder constructor

src/Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public function isPrefix($propertyPath)
9090
*
9191
* @throws ErrorMappingException
9292
*/
93-
private function getTarget()
93+
public function getTarget()
9494
{
9595
$childNames = explode('.', $this->targetPath);
9696
$target = $this->origin;

src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,15 @@ public function mapViolation(ConstraintViolation $violation, FormInterface $form
9191
}
9292
}
9393

94+
// Follow dot rules until we have the final target
95+
$mapping = $this->scope->getAttribute('error_mapping');
96+
97+
while (isset($mapping['.'])) {
98+
$dotRule = new MappingRule($this->scope, '.', $mapping['.']);
99+
$this->scope = $dotRule->getTarget();
100+
$mapping = $this->scope->getAttribute('error_mapping');
101+
}
102+
94103
// Only add the error if the form is synchronized
95104
// If the form is not synchronized, it already contains an
96105
// error about being invalid. Further errors could be a result
@@ -260,7 +269,10 @@ private function setScope(FormInterface $form)
260269
new VirtualFormAwareIterator($form->getChildren())
261270
);
262271
foreach ($form->getAttribute('error_mapping') as $propertyPath => $targetPath) {
263-
$this->rules[] = new MappingRule($form, $propertyPath, $targetPath);
272+
// Dot rules are considered at the very end
273+
if ('.' !== $propertyPath) {
274+
$this->rules[] = new MappingRule($form, $propertyPath, $targetPath);
275+
}
264276
}
265277
}
266278
}

src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,4 +1354,30 @@ public function testDontMapToUnsynchronizedForms()
13541354
$this->assertFalse($parent->hasErrors(), $parent->getName() . ' should not have an error, but has one');
13551355
$this->assertFalse($child->hasErrors(), $child->getName() . ' should not have an error, but has one');
13561356
}
1357+
1358+
public function testFollowDotRules()
1359+
{
1360+
$violation = $this->getConstraintViolation('data.foo');
1361+
$parent = $this->getForm('parent', null, null, array(
1362+
'foo' => 'address',
1363+
));
1364+
$child = $this->getForm('address', null, null, array(
1365+
'.' => 'street',
1366+
));
1367+
$grandChild = $this->getForm('street', null, null, array(
1368+
'.' => 'name',
1369+
));
1370+
$grandGrandChild = $this->getForm('name');
1371+
1372+
$parent->add($child);
1373+
$child->add($grandChild);
1374+
$grandChild->add($grandGrandChild);
1375+
1376+
$this->mapper->mapViolation($violation, $parent);
1377+
1378+
$this->assertFalse($parent->hasErrors(), $parent->getName() . ' should not have an error, but has one');
1379+
$this->assertFalse($child->hasErrors(), $child->getName() . ' should not have an error, but has one');
1380+
$this->assertFalse($grandChild->hasErrors(), $grandChild->getName() . ' should not have an error, but has one');
1381+
$this->assertEquals(array($this->getFormError()), $grandGrandChild->getErrors(), $grandGrandChild->getName() . ' should have an error, but has none');
1382+
}
13571383
}

0 commit comments

Comments
 (0)