Closed
Description
The following test (for ViolationMapperTest) should be solved:
<?php
public function testBacktrackIfSeveralSubFormsWithSamePropertyPath()
{
$violation = $this->getConstraintViolation('data.address.street');
$parent = $this->getForm('parent');
$child1 = $this->getForm('subform1', 'address');
$child2 = $this->getForm('subform2', 'address');
$grandChild = $this->getForm('street');
$parent->add($child1);
$parent->add($child2);
$child2->add($grandChild);
$this->mapper->mapViolation($violation, $parent);
// The error occurred on the child of the second form with the same path
$this->assertCount(0, $parent->getErrors(), $parent->getName() . ' should not have an error, but has one');
$this->assertCount(0, $child1->getErrors(), $child1->getName() . ' should not have an error, but has one');
$this->assertCount(0, $child2->getErrors(), $child2->getName() . ' should not have an error, but has one');
$this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChild->getName() . ' should have an error, but has none');
}
In order to do so, a backtracking algorithm needs to be implemented that allows to continue ViolationMapper::matchChild(). The relevant current code is:
<?php
// Test children unless we already found one
if (null === $foundChild) {
foreach ($childIterator as $child) {
/* @var FormInterface $child */
$childPath = (string) $child->getPropertyPath();
// Child found, mark as return value
if ($chunk === $childPath) {
$foundChild = $child;
$foundAtIndex = $it->key();
}
}
}
Here, when a child is found, it is marked for returning. At a later point, if the error could not be mapped, the remaining children should be searched for matches.
See #5578 for reference.