From 29a3a7e0d6ea12d686789f549afcfb1137f85367 Mon Sep 17 00:00:00 2001 From: "Konstantin.Myakshin" Date: Mon, 1 Aug 2016 11:29:35 +0300 Subject: [PATCH] Add ability retrieve errors by their code. --- .../Component/Form/FormErrorIterator.php | 22 +++++++ .../Form/Tests/FormErrorIteratorTest.php | 62 +++++++++++++++++++ .../Validator/ConstraintViolationList.php | 20 ++++++ .../Tests/ConstraintViolationListTest.php | 31 +++++++++- 4 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/Form/Tests/FormErrorIteratorTest.php diff --git a/src/Symfony/Component/Form/FormErrorIterator.php b/src/Symfony/Component/Form/FormErrorIterator.php index 41a1297d30f57..5ab88e57f31b0 100644 --- a/src/Symfony/Component/Form/FormErrorIterator.php +++ b/src/Symfony/Component/Form/FormErrorIterator.php @@ -14,6 +14,7 @@ use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\OutOfBoundsException; use Symfony\Component\Form\Exception\BadMethodCallException; +use Symfony\Component\Validator\ConstraintViolation; /** * Iterates over the errors of a form. @@ -265,6 +266,27 @@ public function seek($position) } } + /** + * Creates iterator for errors with specific codes. + * + * @param string|string[] $codes The codes to find + * + * @return static New instance which contains only specific errors. + */ + public function findByCodes($codes) + { + $codes = (array) $codes; + $errors = array(); + foreach ($this as $error) { + $cause = $error->getCause(); + if ($cause instanceof ConstraintViolation && in_array($cause->getCode(), $codes, true)) { + $errors[] = $error; + } + } + + return new static($this->form, $errors); + } + /** * Utility function for indenting multi-line strings. * diff --git a/src/Symfony/Component/Form/Tests/FormErrorIteratorTest.php b/src/Symfony/Component/Form/Tests/FormErrorIteratorTest.php new file mode 100644 index 0000000000000..a3d97b320cdff --- /dev/null +++ b/src/Symfony/Component/Form/Tests/FormErrorIteratorTest.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\FormError; +use Symfony\Component\Form\FormErrorIterator; +use Symfony\Component\Validator\ConstraintViolation; + +class FormErrorIteratorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @dataProvider findByCodesProvider + */ + public function testFindByCodes($code, $violationsCount) + { + if (!class_exists(ConstraintViolation::class)) { + $this->markTestSkipped('Validator component required.'); + } + + $formBuilder = new FormBuilder( + 'form', + null, + new EventDispatcher(), + $this->getMock('Symfony\Component\Form\FormFactoryInterface'), + 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 ConstraintViolation('Error 2!', null, array(), null, '', null, null, 'code1'); + $form->addError(new FormError('Error 2!', null, array(), null, $cause)); + $cause = new ConstraintViolation('Error 3!', null, array(), null, '', null, null, 'code2'); + $form->addError(new FormError('Error 3!', null, array(), null, $cause)); + $formErrors = $form->getErrors(); + + $specificFormErrors = $formErrors->findByCodes($code); + $this->assertInstanceOf(FormErrorIterator::class, $specificFormErrors); + $this->assertCount($violationsCount, $specificFormErrors); + } + + public function findByCodesProvider() + { + return array( + array('code1', 2), + array(array('code1', 'code2'), 3), + array('code3', 0), + ); + } +} diff --git a/src/Symfony/Component/Validator/ConstraintViolationList.php b/src/Symfony/Component/Validator/ConstraintViolationList.php index 3490237bc2d6b..f2da581e4efb0 100644 --- a/src/Symfony/Component/Validator/ConstraintViolationList.php +++ b/src/Symfony/Component/Validator/ConstraintViolationList.php @@ -158,4 +158,24 @@ public function offsetUnset($offset) { $this->remove($offset); } + + /** + * Creates iterator for errors with specific codes. + * + * @param string|string[] $codes The codes to find + * + * @return static New instance which contains only specific errors. + */ + public function findByCodes($codes) + { + $codes = (array) $codes; + $violations = array(); + foreach ($this as $violation) { + if (in_array($violation->getCode(), $codes, true)) { + $violations[] = $violation; + } + } + + return new static($violations); + } } diff --git a/src/Symfony/Component/Validator/Tests/ConstraintViolationListTest.php b/src/Symfony/Component/Validator/Tests/ConstraintViolationListTest.php index 18ec52d7a417b..1100c13e2725a 100644 --- a/src/Symfony/Component/Validator/Tests/ConstraintViolationListTest.php +++ b/src/Symfony/Component/Validator/Tests/ConstraintViolationListTest.php @@ -127,8 +127,35 @@ public function testToString() $this->assertEquals($expected, (string) $this->list); } - protected function getViolation($message, $root = null, $propertyPath = null) + /** + * @dataProvider findByCodesProvider + */ + public function testFindByCodes($code, $violationsCount) { - return new ConstraintViolation($message, $message, array(), $root, $propertyPath, null); + $violations = array( + $this->getViolation('Error', null, null, 'code1'), + $this->getViolation('Error', null, null, 'code1'), + $this->getViolation('Error', null, null, 'code2'), + ); + $list = new ConstraintViolationList($violations); + + $specificErrors = $list->findByCodes($code); + + $this->assertInstanceOf(ConstraintViolationList::class, $specificErrors); + $this->assertCount($violationsCount, $specificErrors); + } + + public function findByCodesProvider() + { + return array( + array('code1', 2), + array(array('code1', 'code2'), 3), + array('code3', 0), + ); + } + + protected function getViolation($message, $root = null, $propertyPath = null, $code = null) + { + return new ConstraintViolation($message, $message, array(), $root, $propertyPath, null, null, $code); } }