Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit f005c80

Browse filesBrowse files
alekittofabpot
authored andcommitted
[Form] Fixed violation mapping if multiple forms are using the same (or part of the same) property path
1 parent a89fe42 commit f005c80
Copy full SHA for f005c80

File tree

2 files changed

+41
-35
lines changed
Filter options

2 files changed

+41
-35
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php
+20-35Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,9 @@ public function mapViolation(ConstraintViolation $violation, FormInterface $form
147147
*/
148148
private function matchChild(FormInterface $form, PropertyPathIteratorInterface $it)
149149
{
150-
// Remember at what property path underneath "data"
151-
// we are looking. Check if there is a child with that
152-
// path, otherwise increase path by one more piece
150+
$target = null;
153151
$chunk = '';
154-
$foundChild = null;
155-
$foundAtIndex = 0;
152+
$foundAtIndex = null;
156153

157154
// Construct mapping rules for the given form
158155
$rules = array();
@@ -164,17 +161,11 @@ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $
164161
}
165162
}
166163

167-
// Skip forms inheriting their parent data when iterating the children
168-
$childIterator = new \RecursiveIteratorIterator(
164+
$children = iterator_to_array(new \RecursiveIteratorIterator(
169165
new InheritDataAwareIterator($form)
170-
);
171-
172-
// Make the path longer until we find a matching child
173-
while (true) {
174-
if (!$it->valid()) {
175-
return;
176-
}
166+
));
177167

168+
while ($it->valid()) {
178169
if ($it->isIndex()) {
179170
$chunk .= '['.$it->current().']';
180171
} else {
@@ -196,33 +187,27 @@ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $
196187
}
197188
}
198189

199-
// Test children unless we already found one
200-
if (null === $foundChild) {
201-
foreach ($childIterator as $child) {
202-
/* @var FormInterface $child */
203-
$childPath = (string) $child->getPropertyPath();
204-
205-
// Child found, mark as return value
206-
if ($chunk === $childPath) {
207-
$foundChild = $child;
208-
$foundAtIndex = $it->key();
209-
}
190+
/** @var FormInterface $child */
191+
foreach ($children as $key => $child) {
192+
$childPath = (string) $child->getPropertyPath();
193+
if ($childPath === $chunk) {
194+
$target = $child;
195+
$foundAtIndex = $it->key();
196+
} elseif (0 === strpos($childPath, $chunk)) {
197+
continue;
210198
}
199+
200+
unset($children[$key]);
211201
}
212202

213-
// Add element to the chunk
214203
$it->next();
204+
}
215205

216-
// If we reached the end of the path or if there are no
217-
// more matching mapping rules, return the found child
218-
if (null !== $foundChild && (!$it->valid() || count($rules) === 0)) {
219-
// Reset index in case we tried to find mapping
220-
// rules further down the path
221-
$it->seek($foundAtIndex);
222-
223-
return $foundChild;
224-
}
206+
if (null !== $foundAtIndex) {
207+
$it->seek($foundAtIndex);
225208
}
209+
210+
return $target;
226211
}
227212

228213
/**

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php
+21Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,4 +1474,25 @@ public function testErrorMappingForFormInheritingParentData($target, $childName,
14741474
$this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none');
14751475
}
14761476
}
1477+
1478+
public function testBacktrackIfSeveralSubFormsWithSamePropertyPath()
1479+
{
1480+
$violation = $this->getConstraintViolation('data.address[street]');
1481+
$parent = $this->getForm('parent');
1482+
$child1 = $this->getForm('subform1', 'address');
1483+
$child2 = $this->getForm('subform2', 'address');
1484+
$grandChild = $this->getForm('street');
1485+
1486+
$parent->add($child1);
1487+
$parent->add($child2);
1488+
$child2->add($grandChild);
1489+
1490+
$this->mapper->mapViolation($violation, $parent);
1491+
1492+
// The error occurred on the child of the second form with the same path
1493+
$this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
1494+
$this->assertCount(0, $child1->getErrors(), $child1->getName().' should not have an error, but has one');
1495+
$this->assertCount(0, $child2->getErrors(), $child2->getName().' should not have an error, but has one');
1496+
$this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChild->getName().' should have an error, but has none');
1497+
}
14771498
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.