diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md index d5e8cc7004b70..25f47c7aa903e 100644 --- a/src/Symfony/Component/Form/CHANGELOG.md +++ b/src/Symfony/Component/Form/CHANGELOG.md @@ -39,6 +39,7 @@ CHANGELOG * deprecated calling `FormRenderer::searchAndRenderBlock` for fields which were already rendered * added a cause when a CSRF error has occurred * deprecated the `scale` option of the `IntegerType` + * findByCodes of `FormErrorIterator` is able to also filter causes that are string or objects that implement the `__toString` method * removed restriction on allowed HTTP methods 4.1.0 diff --git a/src/Symfony/Component/Form/FormErrorIterator.php b/src/Symfony/Component/Form/FormErrorIterator.php index 919b61596988c..10bcaf23ea01c 100644 --- a/src/Symfony/Component/Form/FormErrorIterator.php +++ b/src/Symfony/Component/Form/FormErrorIterator.php @@ -267,6 +267,16 @@ public function findByCodes($codes) $cause = $error->getCause(); if ($cause instanceof ConstraintViolation && \in_array($cause->getCode(), $codes, true)) { $errors[] = $error; + continue; + } + + if (!is_scalar($cause) && !(\is_object($cause) && method_exists($cause, '__toString'))) { + continue; + } + + $cause = (string) $cause; + if (\in_array($cause, $codes, true)) { + $errors[] = $error; } } diff --git a/src/Symfony/Component/Form/Tests/FormErrorIteratorTest.php b/src/Symfony/Component/Form/Tests/FormErrorIteratorTest.php index 04eddd1c32350..60398d8e9cefb 100644 --- a/src/Symfony/Component/Form/Tests/FormErrorIteratorTest.php +++ b/src/Symfony/Component/Form/Tests/FormErrorIteratorTest.php @@ -23,7 +23,7 @@ class FormErrorIteratorTest extends TestCase /** * @dataProvider findByCodesProvider */ - public function testFindByCodes($code, $violationsCount) + public function testFindByCodesWhenAllCausesAreViolationConstraints($code, $violationsCount) { if (!class_exists(ConstraintViolation::class)) { $this->markTestSkipped('Validator component required.'); @@ -52,6 +52,43 @@ public function testFindByCodes($code, $violationsCount) $this->assertCount($violationsCount, $specificFormErrors); } + /** + * @dataProvider findByCodesProvider + */ + public function testFindByCodesWhenAllCausesAreVariousObjectsOrSimpleStrings($code, $violationsCount) + { + if (!class_exists(ConstraintViolation::class)) { + $this->markTestSkipped('Validator component required.'); + } + + $formBuilder = new FormBuilder( + 'form', + null, + new EventDispatcher(), + $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock(), + array() + ); + + $form = $formBuilder->getForm(); + + $cause = new ConstraintViolation('Error 1!', null, array(), null, '', null, null, 'code1'); + $form->addError(new FormError('Error 1!', null, array(), null, $cause)); + $cause = new class() { + public function __toString() + { + return 'code1'; + } + }; + + $form->addError(new FormError('Error 2!', null, array(), null, $cause)); + $form->addError(new FormError('Error 3!', null, array(), null, 'code2')); + $formErrors = $form->getErrors(); + + $specificFormErrors = $formErrors->findByCodes($code); + $this->assertInstanceOf(FormErrorIterator::class, $specificFormErrors); + $this->assertCount($violationsCount, $specificFormErrors); + } + public function findByCodesProvider() { return array(