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 95d68a1

Browse filesBrowse files
committed
feature #12021 [Validator] Added error codes to all constraints with multiple error causes (webmozart)
This PR was merged into the 2.6-dev branch. Discussion ---------- [Validator] Added error codes to all constraints with multiple error causes | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #7276 | License | MIT | Doc PR | TODO This PR depends on #12015 and #12016 being merged first. However, a few changes in 52cb7df first must be backported to #12016. This PR introduces error codes for all constraints with multiple error paths. This lets you determine what exactly the reason was that a constraint failed: ```php $validator = Validation::createValidator(); $violations = $validator->validate('0-4X19-92619812', new Isbn()); foreach ($violations as $violation) { var_dump($violation->getCode()); // => int(3) var_dump(Isbn::getErrorName($violation->getCode())); // => string(24) "ERROR_INVALID_CHARACTERS" var_dump($violation->getConstraint()->getErrorName($violation->getCode())); // => string(24) "ERROR_INVALID_CHARACTERS" } ``` The `getErrorName()` method is especially helpful for REST APIs, where you can return both an error code and a description of that error now. **Todos** - [x] Backport a few structural changes to #12016 - [x] Update constraints outside of the Validator component - [x] Rebase on master (after merging #12015 and #12016) Commits ------- 3b50bf2 [Validator] Added error codes to all constraints with multiple error causes
2 parents 2f3bb66 + 3b50bf2 commit 95d68a1
Copy full SHA for 95d68a1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner
Expand file treeCollapse file tree

61 files changed

+845
-224
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Extension/Validator/Constraints/Form.php
+10-1Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,20 @@
1818
*/
1919
class Form extends Constraint
2020
{
21+
const NOT_SYNCHRONIZED_ERROR = 1;
22+
const NO_SUCH_FIELD_ERROR = 2;
23+
2124
/**
22-
* Violation code marking an invalid form.
25+
* @deprecated Deprecated since Symfony 2.6, to be removed in 3.0. Use
26+
* {@self NOT_SYNCHRONIZED_ERROR} instead.
2327
*/
2428
const ERR_INVALID = 1;
2529

30+
protected static $errorNames = array(
31+
self::NOT_SYNCHRONIZED_ERROR => 'NOT_SYNCHRONIZED_ERROR',
32+
self::NO_SUCH_FIELD_ERROR => 'NO_SUCH_FIELD_ERROR',
33+
);
34+
2635
/**
2736
* {@inheritdoc}
2837
*/

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public function validate($form, Constraint $constraint)
102102
$this->buildViolation($config->getOption('invalid_message'))
103103
->setParameters(array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters')))
104104
->setInvalidValue($form->getViewData())
105-
->setCode(Form::ERR_INVALID)
105+
->setCode(Form::NOT_SYNCHRONIZED_ERROR)
106106
->setCause($form->getTransformationFailure())
107107
->addViolation();
108108
}
@@ -113,6 +113,7 @@ public function validate($form, Constraint $constraint)
113113
$this->buildViolation($config->getOption('extra_fields_message'))
114114
->setParameter('{{ extra_fields }}', implode('", "', array_keys($form->getExtraData())))
115115
->setInvalidValue($form->getExtraData())
116+
->setCode(Form::NO_SUCH_FIELD_ERROR)
116117
->addViolation();
117118
}
118119
}

‎src/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public function validateForm(FormEvent $event)
6666
foreach ($violations as $violation) {
6767
// Allow the "invalid" constraint to be put onto
6868
// non-synchronized forms
69-
$allowNonSynchronized = Form::ERR_INVALID === $violation->getCode();
69+
$allowNonSynchronized = $violation->getConstraint() instanceof Form && Form::NOT_SYNCHRONIZED_ERROR === $violation->getCode();
7070

7171
$this->violationMapper->mapViolation($violation, $form, $allowNonSynchronized);
7272
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php
+8-6Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ function () { throw new TransformationFailedException(); }
231231
->setParameter('{{ value }}', 'foo')
232232
->setParameter('{{ foo }}', 'bar')
233233
->setInvalidValue('foo')
234-
->setCode(Form::ERR_INVALID)
234+
->setCode(Form::NOT_SYNCHRONIZED_ERROR)
235235
->setCause($is2Dot4Api ? null : $form->getTransformationFailure())
236236
->assertRaised();
237237
}
@@ -268,7 +268,7 @@ function () { throw new TransformationFailedException(); }
268268
->setParameter('{{ value }}', 'foo')
269269
->setParameter('{{ foo }}', 'bar')
270270
->setInvalidValue('foo')
271-
->setCode(Form::ERR_INVALID)
271+
->setCode(Form::NOT_SYNCHRONIZED_ERROR)
272272
->setCause($is2Dot4Api ? null : $form->getTransformationFailure())
273273
->assertRaised();
274274
}
@@ -304,7 +304,7 @@ function () { throw new TransformationFailedException(); }
304304
$this->buildViolation('invalid_message_key')
305305
->setParameter('{{ value }}', 'foo')
306306
->setInvalidValue('foo')
307-
->setCode(Form::ERR_INVALID)
307+
->setCode(Form::NOT_SYNCHRONIZED_ERROR)
308308
->setCause($is2Dot4Api ? null : $form->getTransformationFailure())
309309
->assertRaised();
310310
}
@@ -558,9 +558,11 @@ public function testViolationIfExtraData()
558558

559559
$this->validator->validate($form, new Form());
560560

561-
$this->assertViolation('Extra!', array(
562-
'{{ extra_fields }}' => 'foo',
563-
), 'property.path', array('foo' => 'bar'));
561+
$this->buildViolation('Extra!')
562+
->setParameter('{{ extra_fields }}', 'foo')
563+
->setInvalidValue(array('foo' => 'bar'))
564+
->setCode(Form::NO_SUCH_FIELD_ERROR)
565+
->assertRaised();
564566
}
565567

566568
public function testNoViolationIfAllowExtraData()

‎src/Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ protected function setUp()
6666

6767
private function getConstraintViolation($code = null)
6868
{
69-
return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, 'prop.path', null, null, $code);
69+
return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, 'prop.path', null, null, $code, new Form());
7070
}
7171

7272
private function getBuilder($name = 'name', $propertyPath = null, $dataClass = null)
@@ -109,7 +109,7 @@ public function testMapViolation()
109109

110110
public function testMapViolationAllowsNonSyncIfInvalid()
111111
{
112-
$violation = $this->getConstraintViolation(Form::ERR_INVALID);
112+
$violation = $this->getConstraintViolation(Form::NOT_SYNCHRONIZED_ERROR);
113113
$form = $this->getForm('street');
114114

115115
$this->validator->expects($this->once())

‎src/Symfony/Component/Validator/Constraint.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Constraint.php
+29Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Validator;
1313

1414
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
15+
use Symfony\Component\Validator\Exception\InvalidArgumentException;
1516
use Symfony\Component\Validator\Exception\InvalidOptionsException;
1617
use Symfony\Component\Validator\Exception\MissingOptionsException;
1718

@@ -50,12 +51,40 @@ abstract class Constraint
5051
*/
5152
const PROPERTY_CONSTRAINT = 'property';
5253

54+
/**
55+
* Maps error codes to the names of their constants
56+
* @var array
57+
*/
58+
protected static $errorNames = array();
59+
5360
/**
5461
* Domain-specific data attached to a constraint
5562
* @var mixed
5663
*/
5764
public $payload;
5865

66+
/**
67+
* Returns the name of the given error code.
68+
*
69+
* @param int $errorCode The error code
70+
*
71+
* @return string The name of the error code
72+
*
73+
* @throws InvalidArgumentException If the error code does not exist
74+
*/
75+
public static function getErrorName($errorCode)
76+
{
77+
if (!isset(static::$errorNames[$errorCode])) {
78+
throw new InvalidArgumentException(sprintf(
79+
'The error code "%s" does not exist for constraint of type "%s".',
80+
$errorCode,
81+
get_called_class()
82+
));
83+
}
84+
85+
return static::$errorNames[$errorCode];
86+
}
87+
5988
/**
6089
* Initializes the constraint with options.
6190
*

‎src/Symfony/Component/Validator/Constraints/CardScheme.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Constraints/CardScheme.php
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,18 @@
2020
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
2121
*
2222
* @author Tim Nagel <t.nagel@infinite.net.au>
23+
* @author Bernhard Schussek <bschussek@gmail.com>
2324
*/
2425
class CardScheme extends Constraint
2526
{
27+
const NOT_NUMERIC_ERROR = 1;
28+
const INVALID_FORMAT_ERROR = 2;
29+
30+
protected static $errorNames = array(
31+
self::NOT_NUMERIC_ERROR => 'NOT_NUMERIC_ERROR',
32+
self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR',
33+
);
34+
2635
public $message = 'Unsupported card type or invalid card number.';
2736
public $schemes;
2837

‎src/Symfony/Component/Validator/Constraints/CardSchemeValidator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Constraints/CardSchemeValidator.php
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ public function validate($value, Constraint $constraint)
117117
if (!is_numeric($value)) {
118118
$this->buildViolation($constraint->message)
119119
->setParameter('{{ value }}', $this->formatValue($value))
120+
->setCode(CardScheme::NOT_NUMERIC_ERROR)
120121
->addViolation();
121122

122123
return;
@@ -135,6 +136,7 @@ public function validate($value, Constraint $constraint)
135136

136137
$this->buildViolation($constraint->message)
137138
->setParameter('{{ value }}', $this->formatValue($value))
139+
->setCode(CardScheme::INVALID_FORMAT_ERROR)
138140
->addViolation();
139141
}
140142
}

‎src/Symfony/Component/Validator/Constraints/Choice.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Constraints/Choice.php
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@
2323
*/
2424
class Choice extends Constraint
2525
{
26+
const NO_SUCH_CHOICE_ERROR = 1;
27+
const TOO_FEW_ERROR = 2;
28+
const TOO_MANY_ERROR = 3;
29+
30+
protected static $errorNames = array(
31+
self::NO_SUCH_CHOICE_ERROR => 'NO_SUCH_CHOICE_ERROR',
32+
self::TOO_FEW_ERROR => 'TOO_FEW_ERROR',
33+
self::TOO_MANY_ERROR => 'TOO_MANY_ERROR',
34+
);
35+
2636
public $choices;
2737
public $callback;
2838
public $multiple = false;

‎src/Symfony/Component/Validator/Constraints/ChoiceValidator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Constraints/ChoiceValidator.php
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public function validate($value, Constraint $constraint)
6565
if (!in_array($_value, $choices, $constraint->strict)) {
6666
$this->buildViolation($constraint->multipleMessage)
6767
->setParameter('{{ value }}', $this->formatValue($_value))
68+
->setCode(Choice::NO_SUCH_CHOICE_ERROR)
6869
->setInvalidValue($_value)
6970
->addViolation();
7071

@@ -78,6 +79,7 @@ public function validate($value, Constraint $constraint)
7879
$this->buildViolation($constraint->minMessage)
7980
->setParameter('{{ limit }}', $constraint->min)
8081
->setPlural((int) $constraint->min)
82+
->setCode(Choice::TOO_FEW_ERROR)
8183
->addViolation();
8284

8385
return;
@@ -87,13 +89,15 @@ public function validate($value, Constraint $constraint)
8789
$this->buildViolation($constraint->maxMessage)
8890
->setParameter('{{ limit }}', $constraint->max)
8991
->setPlural((int) $constraint->max)
92+
->setCode(Choice::TOO_MANY_ERROR)
9093
->addViolation();
9194

9295
return;
9396
}
9497
} elseif (!in_array($value, $choices, $constraint->strict)) {
9598
$this->buildViolation($constraint->message)
9699
->setParameter('{{ value }}', $this->formatValue($value))
100+
->setCode(Choice::NO_SUCH_CHOICE_ERROR)
97101
->addViolation();
98102
}
99103
}

‎src/Symfony/Component/Validator/Constraints/Collection.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Constraints/Collection.php
+8-1Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
namespace Symfony\Component\Validator\Constraints;
1313

14-
use Symfony\Component\Validator\Constraint;
1514
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
1615

1716
/**
@@ -24,6 +23,14 @@
2423
*/
2524
class Collection extends Composite
2625
{
26+
const MISSING_FIELD_ERROR = 1;
27+
const NO_SUCH_FIELD_ERROR = 2;
28+
29+
protected static $errorNames = array(
30+
self::MISSING_FIELD_ERROR => 'MISSING_FIELD_ERROR',
31+
self::NO_SUCH_FIELD_ERROR => 'NO_SUCH_FIELD_ERROR',
32+
);
33+
2734
public $fields = array();
2835
public $allowExtraFields = false;
2936
public $allowMissingFields = false;

‎src/Symfony/Component/Validator/Constraints/CollectionValidator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Constraints/CollectionValidator.php
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ public function validate($value, Constraint $constraint)
7373
->atPath('['.$field.']')
7474
->setParameter('{{ field }}', $this->formatValue($field))
7575
->setInvalidValue(null)
76+
->setCode(Collection::MISSING_FIELD_ERROR)
7677
->addViolation();
7778
}
7879
}
@@ -84,6 +85,7 @@ public function validate($value, Constraint $constraint)
8485
->atPath('['.$field.']')
8586
->setParameter('{{ field }}', $this->formatValue($field))
8687
->setInvalidValue($fieldValue)
88+
->setCode(Collection::NO_SUCH_FIELD_ERROR)
8789
->addViolation();
8890
}
8991
}

‎src/Symfony/Component/Validator/Constraints/Count.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Constraints/Count.php
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@
2424
*/
2525
class Count extends Constraint
2626
{
27+
const TOO_FEW_ERROR = 1;
28+
const TOO_MANY_ERROR = 2;
29+
30+
protected static $errorNames = array(
31+
self::TOO_FEW_ERROR => 'TOO_FEW_ERROR',
32+
self::TOO_MANY_ERROR => 'TOO_MANY_ERROR',
33+
);
34+
2735
public $minMessage = 'This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.';
2836
public $maxMessage = 'This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.';
2937
public $exactMessage = 'This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.';

‎src/Symfony/Component/Validator/Constraints/CountValidator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Constraints/CountValidator.php
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public function validate($value, Constraint $constraint)
4141
->setParameter('{{ limit }}', $constraint->max)
4242
->setInvalidValue($value)
4343
->setPlural((int) $constraint->max)
44+
->setCode(Count::TOO_MANY_ERROR)
4445
->addViolation();
4546

4647
return;
@@ -52,6 +53,7 @@ public function validate($value, Constraint $constraint)
5253
->setParameter('{{ limit }}', $constraint->min)
5354
->setInvalidValue($value)
5455
->setPlural((int) $constraint->min)
56+
->setCode(Count::TOO_FEW_ERROR)
5557
->addViolation();
5658
}
5759
}

‎src/Symfony/Component/Validator/Constraints/Date.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Constraints/Date.php
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,13 @@
2323
*/
2424
class Date extends Constraint
2525
{
26+
const INVALID_FORMAT_ERROR = 1;
27+
const INVALID_DATE_ERROR = 2;
28+
29+
protected static $errorNames = array(
30+
self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR',
31+
self::INVALID_DATE_ERROR => 'INVALID_DATE_ERROR',
32+
);
33+
2634
public $message = 'This value is not a valid date.';
2735
}

‎src/Symfony/Component/Validator/Constraints/DateTime.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Constraints/DateTime.php
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,15 @@
2323
*/
2424
class DateTime extends Constraint
2525
{
26+
const INVALID_FORMAT_ERROR = 1;
27+
const INVALID_DATE_ERROR = 2;
28+
const INVALID_TIME_ERROR = 3;
29+
30+
protected static $errorNames = array(
31+
self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR',
32+
self::INVALID_DATE_ERROR => 'INVALID_DATE_ERROR',
33+
self::INVALID_TIME_ERROR => 'INVALID_TIME_ERROR',
34+
);
35+
2636
public $message = 'This value is not a valid datetime.';
2737
}

‎src/Symfony/Component/Validator/Constraints/DateTimeValidator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Constraints/DateTimeValidator.php
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public function validate($value, Constraint $constraint)
4545
if (!preg_match(static::PATTERN, $value, $matches)) {
4646
$this->buildViolation($constraint->message)
4747
->setParameter('{{ value }}', $this->formatValue($value))
48+
->setCode(DateTime::INVALID_FORMAT_ERROR)
4849
->addViolation();
4950

5051
return;
@@ -53,12 +54,14 @@ public function validate($value, Constraint $constraint)
5354
if (!DateValidator::checkDate($matches[1], $matches[2], $matches[3])) {
5455
$this->buildViolation($constraint->message)
5556
->setParameter('{{ value }}', $this->formatValue($value))
57+
->setCode(DateTime::INVALID_DATE_ERROR)
5658
->addViolation();
5759
}
5860

5961
if (!TimeValidator::checkTime($matches[4], $matches[5], $matches[6])) {
6062
$this->buildViolation($constraint->message)
6163
->setParameter('{{ value }}', $this->formatValue($value))
64+
->setCode(DateTime::INVALID_TIME_ERROR)
6265
->addViolation();
6366
}
6467
}

‎src/Symfony/Component/Validator/Constraints/DateValidator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Constraints/DateValidator.php
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public function validate($value, Constraint $constraint)
6262
if (!preg_match(static::PATTERN, $value, $matches)) {
6363
$this->buildViolation($constraint->message)
6464
->setParameter('{{ value }}', $this->formatValue($value))
65+
->setCode(Date::INVALID_FORMAT_ERROR)
6566
->addViolation();
6667

6768
return;
@@ -70,6 +71,7 @@ public function validate($value, Constraint $constraint)
7071
if (!self::checkDate($matches[1], $matches[2], $matches[3])) {
7172
$this->buildViolation($constraint->message)
7273
->setParameter('{{ value }}', $this->formatValue($value))
74+
->setCode(Date::INVALID_DATE_ERROR)
7375
->addViolation();
7476
}
7577
}

‎src/Symfony/Component/Validator/Constraints/Email.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Constraints/Email.php
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@
2323
*/
2424
class Email extends Constraint
2525
{
26+
const INVALID_FORMAT_ERROR = 1;
27+
const MX_CHECK_FAILED_ERROR = 2;
28+
const HOST_CHECK_FAILED_ERROR = 3;
29+
30+
protected static $errorNames = array(
31+
self::INVALID_FORMAT_ERROR => 'STRICT_CHECK_FAILED_ERROR',
32+
self::MX_CHECK_FAILED_ERROR => 'MX_CHECK_FAILED_ERROR',
33+
self::HOST_CHECK_FAILED_ERROR => 'HOST_CHECK_FAILED_ERROR',
34+
);
35+
2636
public $message = 'This value is not a valid email address.';
2737
public $checkMX = false;
2838
public $checkHost = false;

0 commit comments

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