Skip to content

Commit b82ff49

Browse files
committed
collect all transformation failures
1 parent cf66f03 commit b82ff49

File tree

3 files changed

+69
-41
lines changed

3 files changed

+69
-41
lines changed

src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php

+11-7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Symfony\Component\Validator\Constraints\Valid;
1919
use Symfony\Component\Validator\ConstraintValidator;
2020
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
21+
use Symfony\Component\Validator\Validator\ContextualValidatorInterface;
2122

2223
/**
2324
* @author Bernhard Schussek <bschussek@gmail.com>
@@ -89,9 +90,7 @@ public function validate($form, Constraint $formConstraint)
8990
// sequence recursively, thus some fields could fail
9091
// in different steps without breaking early enough
9192
$this->resolvedGroups[$field] = (array) $group;
92-
$fieldFormConstraint = new Form();
93-
$this->context->setNode($this->context->getValue(), $field, $this->context->getMetadata(), $this->context->getPropertyPath());
94-
$validator->atPath(sprintf('children[%s]', $field->getName()))->validate($field, $fieldFormConstraint);
93+
$this->validateChildForm($validator, $field);
9594
}
9695
}
9796

@@ -129,9 +128,7 @@ public function validate($form, Constraint $formConstraint)
129128
foreach ($form->all() as $field) {
130129
if ($field->isSubmitted()) {
131130
$this->resolvedGroups[$field] = $groups;
132-
$fieldFormConstraint = new Form();
133-
$this->context->setNode($this->context->getValue(), $field, $this->context->getMetadata(), $this->context->getPropertyPath());
134-
$validator->atPath(sprintf('children[%s]', $field->getName()))->validate($field, $fieldFormConstraint);
131+
$this->validateChildForm($validator, $field);
135132
}
136133
}
137134
}
@@ -146,8 +143,8 @@ public function validate($form, Constraint $formConstraint)
146143
/** @var FormInterface $child */
147144
foreach ($form as $child) {
148145
if (!$child->isSynchronized()) {
146+
$this->validateChildForm($validator, $child);
149147
$childrenSynchronized = false;
150-
break;
151148
}
152149
}
153150

@@ -250,4 +247,11 @@ private static function getConstraintsInGroups($constraints, $group)
250247
return \in_array($group, $constraint->groups, true);
251248
});
252249
}
250+
251+
private function validateChildForm(ContextualValidatorInterface $validator, FormInterface $form)
252+
{
253+
$fieldFormConstraint = new Form();
254+
$this->context->setNode($this->context->getValue(), $form, $this->context->getMetadata(), $this->context->getPropertyPath());
255+
$validator->atPath(sprintf('children[%s]', $form->getName()))->validate($form, $fieldFormConstraint);
256+
}
253257
}

src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorFunctionalTest.php

+58
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Form\AbstractType;
16+
use Symfony\Component\Form\CallbackTransformer;
17+
use Symfony\Component\Form\Exception\TransformationFailedException;
18+
use Symfony\Component\Form\Extension\Core\Type\DateType;
1619
use Symfony\Component\Form\Extension\Core\Type\FormType;
1720
use Symfony\Component\Form\Extension\Core\Type\TextType;
1821
use Symfony\Component\Form\Extension\Validator\ValidatorExtension;
@@ -329,6 +332,61 @@ public function testContextIsPopulatedWithFormBeingValidatedUsingGroupSequence()
329332

330333
$this->assertCount(0, $violations);
331334
}
335+
336+
public function testSubmitFormChoiceInvalid()
337+
{
338+
$form = $this->formFactory->create(DateType::class, null, [
339+
'widget' => 'choice',
340+
'years' => [2021],
341+
]);
342+
343+
$form->submit([
344+
'day' => '13',
345+
'month' => '13',
346+
'year' => '2020',
347+
]);
348+
349+
$this->assertTrue($form->isSubmitted());
350+
$this->assertFalse($form->isValid());
351+
$this->assertCount(2, $form->getErrors());
352+
$this->assertSame('This value is not valid.', $form->getErrors()[0]->getMessage());
353+
$this->assertSame('This value is not valid.', $form->getErrors()[1]->getMessage());
354+
}
355+
356+
public function testDontMarkInvalidIfAnyChildIsNotSynchronized()
357+
{
358+
$formBuilder = $this->formFactory->createBuilder()
359+
->add('field1')
360+
->add('field2')
361+
->addModelTransformer(new CallbackTransformer(
362+
function () {
363+
},
364+
function () {
365+
throw new TransformationFailedException('This value is invalid.');
366+
}
367+
));
368+
$formBuilder->get('field2')->addModelTransformer(new CallbackTransformer(
369+
function () {
370+
},
371+
function () {
372+
throw new TransformationFailedException('This value is invalid.');
373+
}
374+
));
375+
$form = $formBuilder->getForm();
376+
377+
$form->submit([
378+
'field1' => 'foo',
379+
'field2' => 'bar',
380+
]);
381+
382+
$this->assertTrue($form->isSubmitted());
383+
$this->assertFalse($form->isValid());
384+
$this->assertCount(0, $form->getErrors());
385+
$this->assertTrue($form->get('field1')->isValid());
386+
$this->assertCount(0, $form->get('field1')->getErrors());
387+
$this->assertFalse($form->get('field2')->isValid());
388+
$this->assertCount(1, $form->get('field2')->getErrors());
389+
}
332390
}
333391

334392
class Foo

src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php

-34
Original file line numberDiff line numberDiff line change
@@ -362,40 +362,6 @@ function () { throw new TransformationFailedException(); }
362362
->assertRaised();
363363
}
364364

365-
// https://github.com/symfony/symfony/issues/4359
366-
public function testDontMarkInvalidIfAnyChildIsNotSynchronized()
367-
{
368-
$object = new \stdClass();
369-
$object->child = 'bar';
370-
371-
$failingTransformer = new CallbackTransformer(
372-
function ($data) { return $data; },
373-
function () { throw new TransformationFailedException(); }
374-
);
375-
376-
$form = $this->getBuilder('name', '\stdClass')
377-
->setData($object)
378-
->addViewTransformer($failingTransformer)
379-
->setCompound(true)
380-
->setDataMapper(new PropertyPathMapper())
381-
->add(
382-
$this->getBuilder('child')
383-
->addViewTransformer($failingTransformer)
384-
)
385-
->getForm();
386-
387-
// Launch transformer
388-
$form->submit(['child' => 'foo']);
389-
390-
$this->assertTrue($form->isSubmitted());
391-
$this->assertFalse($form->isSynchronized());
392-
$this->expectNoValidate();
393-
394-
$this->validator->validate($form, new Form());
395-
396-
$this->assertNoViolation();
397-
}
398-
399365
public function testHandleGroupSequenceValidationGroups()
400366
{
401367
$object = new \stdClass();

0 commit comments

Comments
 (0)