diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index 4320db250f..3e577a3a54 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -18,6 +18,8 @@ CHANGELOG * added the `limit_path` parameter in violations when using `Range` constraint with the `minPropertyPath` or `maxPropertyPath` options. + * added a new `notInRangeMessage` options to the `Range` constraint that will + be used in the violation builder when both `min` and `max` are not null. 4.3.0 ----- diff --git a/src/Symfony/Component/Validator/Constraints/Range.php b/src/Symfony/Component/Validator/Constraints/Range.php index 115b9014d5..9f05edf677 100644 --- a/src/Symfony/Component/Validator/Constraints/Range.php +++ b/src/Symfony/Component/Validator/Constraints/Range.php @@ -26,15 +26,18 @@ use Symfony\Component\Validator\Exception\MissingOptionsException; class Range extends Constraint { const INVALID_CHARACTERS_ERROR = 'ad9a9798-7a99-4df7-8ce9-46e416a1e60b'; + const NOT_IN_RANGE_ERROR = '04b91c99-a946-4221-afc5-e65ebac401eb'; const TOO_HIGH_ERROR = '2d28afcb-e32e-45fb-a815-01c431a86a69'; const TOO_LOW_ERROR = '76454e69-502c-46c5-9643-f447d837c4d5'; protected static $errorNames = [ self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR', + self::NOT_IN_RANGE_ERROR => 'NOT_IN_RANGE_ERROR', self::TOO_HIGH_ERROR => 'TOO_HIGH_ERROR', self::TOO_LOW_ERROR => 'TOO_LOW_ERROR', ]; + public $notInRangeMessage = 'This value should be between {{ min }} and {{ max }}.'; public $minMessage = 'This value should be {{ limit }} or more.'; public $maxMessage = 'This value should be {{ limit }} or less.'; public $invalidMessage = 'This value should be a valid number.'; diff --git a/src/Symfony/Component/Validator/Constraints/RangeValidator.php b/src/Symfony/Component/Validator/Constraints/RangeValidator.php index 3837b0d6fa..08d6f0e38e 100644 --- a/src/Symfony/Component/Validator/Constraints/RangeValidator.php +++ b/src/Symfony/Component/Validator/Constraints/RangeValidator.php @@ -70,7 +70,30 @@ class RangeValidator extends ConstraintValidator } } - if (null !== $max && $value > $max) { + $hasLowerLimit = null !== $min; + $hasUpperLimit = null !== $max; + + if ($hasLowerLimit && $hasUpperLimit && ($value < $min || $value > $max)) { + $violationBuilder = $this->context->buildViolation($constraint->notInRangeMessage) + ->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE)) + ->setParameter('{{ min }}', $this->formatValue($min, self::PRETTY_DATE)) + ->setParameter('{{ max }}', $this->formatValue($max, self::PRETTY_DATE)) + ->setCode(Range::NOT_IN_RANGE_ERROR); + + if (null !== $constraint->maxPropertyPath) { + $violationBuilder->setParameter('{{ max_limit_path }}', $constraint->maxPropertyPath); + } + + if (null !== $constraint->minPropertyPath) { + $violationBuilder->setParameter('{{ min_limit_path }}', $constraint->minPropertyPath); + } + + $violationBuilder->addViolation(); + + return; + } + + if ($hasUpperLimit && $value > $max) { $violationBuilder = $this->context->buildViolation($constraint->maxMessage) ->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE)) ->setParameter('{{ limit }}', $this->formatValue($max, self::PRETTY_DATE)) @@ -89,7 +112,7 @@ class RangeValidator extends ConstraintValidator return; } - if (null !== $min && $value < $min) { + if ($hasLowerLimit && $value < $min) { $violationBuilder = $this->context->buildViolation($constraint->minMessage) ->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE)) ->setParameter('{{ limit }}', $this->formatValue($min, self::PRETTY_DATE)) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf index d5d9d20997..100d552076 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf @@ -362,6 +362,10 @@ This password has been leaked in a data breach, it must not be used. Please use another password. This password has been leaked in a data breach, it must not be used. Please use another password. + + This value should be between {{ min }} and {{ max }}. + This value should be between {{ min }} and {{ max }}. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf index 9b021cd682..dc7e73e3c7 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf @@ -362,6 +362,10 @@ This password has been leaked in a data breach, it must not be used. Please use another password. Ce mot de passe a été divulgué lors d'une fuite de données, il ne doit plus être utilisé. Veuillez utiliser un autre mot de passe. + + This value should be between {{ min }} and {{ max }}. + Cette valeur doit être comprise entre {{ min }} et {{ max }}. + diff --git a/src/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php index f57428cafe..4b6b666479 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php @@ -143,16 +143,16 @@ class RangeValidatorTest extends ConstraintValidatorTestCase $constraint = new Range([ 'min' => 10, 'max' => 20, - 'minMessage' => 'myMinMessage', - 'maxMessage' => 'myMaxMessage', + 'notInRangeMessage' => 'myNotInRangeMessage', ]); $this->validator->validate($value, $constraint); - $this->buildViolation('myMaxMessage') + $this->buildViolation('myNotInRangeMessage') ->setParameter('{{ value }}', $formattedValue) - ->setParameter('{{ limit }}', 20) - ->setCode(Range::TOO_HIGH_ERROR) + ->setParameter('{{ min }}', 10) + ->setParameter('{{ max }}', 20) + ->setCode(Range::NOT_IN_RANGE_ERROR) ->assertRaised(); } @@ -164,16 +164,16 @@ class RangeValidatorTest extends ConstraintValidatorTestCase $constraint = new Range([ 'min' => 10, 'max' => 20, - 'minMessage' => 'myMinMessage', - 'maxMessage' => 'myMaxMessage', + 'notInRangeMessage' => 'myNotInRangeMessage', ]); $this->validator->validate($value, $constraint); - $this->buildViolation('myMinMessage') + $this->buildViolation('myNotInRangeMessage') ->setParameter('{{ value }}', $formattedValue) - ->setParameter('{{ limit }}', 10) - ->setCode(Range::TOO_LOW_ERROR) + ->setParameter('{{ min }}', 10) + ->setParameter('{{ max }}', 20) + ->setCode(Range::NOT_IN_RANGE_ERROR) ->assertRaised(); } @@ -327,16 +327,16 @@ class RangeValidatorTest extends ConstraintValidatorTestCase $constraint = new Range([ 'min' => 'March 10, 2014', 'max' => 'March 20, 2014', - 'minMessage' => 'myMinMessage', - 'maxMessage' => 'myMaxMessage', + 'notInRangeMessage' => 'myNotInRangeMessage', ]); $this->validator->validate($value, $constraint); - $this->buildViolation('myMaxMessage') + $this->buildViolation('myNotInRangeMessage') ->setParameter('{{ value }}', $dateTimeAsString) - ->setParameter('{{ limit }}', 'Mar 20, 2014, 12:00 AM') - ->setCode(Range::TOO_HIGH_ERROR) + ->setParameter('{{ min }}', 'Mar 10, 2014, 12:00 AM') + ->setParameter('{{ max }}', 'Mar 20, 2014, 12:00 AM') + ->setCode(Range::NOT_IN_RANGE_ERROR) ->assertRaised(); } @@ -352,16 +352,16 @@ class RangeValidatorTest extends ConstraintValidatorTestCase $constraint = new Range([ 'min' => 'March 10, 2014', 'max' => 'March 20, 2014', - 'minMessage' => 'myMinMessage', - 'maxMessage' => 'myMaxMessage', + 'notInRangeMessage' => 'myNotInRangeMessage', ]); $this->validator->validate($value, $constraint); - $this->buildViolation('myMinMessage') + $this->buildViolation('myNotInRangeMessage') ->setParameter('{{ value }}', $dateTimeAsString) - ->setParameter('{{ limit }}', 'Mar 10, 2014, 12:00 AM') - ->setCode(Range::TOO_LOW_ERROR) + ->setParameter('{{ min }}', 'Mar 10, 2014, 12:00 AM') + ->setParameter('{{ max }}', 'Mar 20, 2014, 12:00 AM') + ->setCode(Range::NOT_IN_RANGE_ERROR) ->assertRaised(); } @@ -527,18 +527,18 @@ class RangeValidatorTest extends ConstraintValidatorTestCase $constraint = new Range([ 'minPropertyPath' => 'min', 'maxPropertyPath' => 'max', - 'minMessage' => 'myMinMessage', - 'maxMessage' => 'myMaxMessage', + 'notInRangeMessage' => 'myNotInRangeMessage', ]); $this->validator->validate($value, $constraint); - $this->buildViolation('myMaxMessage') + $this->buildViolation('myNotInRangeMessage') ->setParameter('{{ value }}', $formattedValue) - ->setParameter('{{ limit }}', 20) + ->setParameter('{{ min }}', 10) + ->setParameter('{{ max }}', 20) ->setParameter('{{ max_limit_path }}', 'max') ->setParameter('{{ min_limit_path }}', 'min') - ->setCode(Range::TOO_HIGH_ERROR) + ->setCode(Range::NOT_IN_RANGE_ERROR) ->assertRaised(); } @@ -552,18 +552,18 @@ class RangeValidatorTest extends ConstraintValidatorTestCase $constraint = new Range([ 'minPropertyPath' => 'min', 'maxPropertyPath' => 'max', - 'minMessage' => 'myMinMessage', - 'maxMessage' => 'myMaxMessage', + 'notInRangeMessage' => 'myNotInRangeMessage', ]); $this->validator->validate($value, $constraint); - $this->buildViolation('myMinMessage') + $this->buildViolation('myNotInRangeMessage') ->setParameter('{{ value }}', $formattedValue) - ->setParameter('{{ limit }}', 10) + ->setParameter('{{ min }}', 10) + ->setParameter('{{ max }}', 20) ->setParameter('{{ max_limit_path }}', 'max') ->setParameter('{{ min_limit_path }}', 'min') - ->setCode(Range::TOO_LOW_ERROR) + ->setCode(Range::NOT_IN_RANGE_ERROR) ->assertRaised(); } @@ -713,18 +713,18 @@ class RangeValidatorTest extends ConstraintValidatorTestCase $constraint = new Range([ 'minPropertyPath' => 'min', 'maxPropertyPath' => 'max', - 'minMessage' => 'myMinMessage', - 'maxMessage' => 'myMaxMessage', + 'notInRangeMessage' => 'myNotInRangeMessage', ]); $this->validator->validate($value, $constraint); - $this->buildViolation('myMaxMessage') + $this->buildViolation('myNotInRangeMessage') ->setParameter('{{ value }}', $dateTimeAsString) - ->setParameter('{{ limit }}', 'Mar 20, 2014, 12:00 AM') + ->setParameter('{{ min }}', 'Mar 10, 2014, 12:00 AM') + ->setParameter('{{ max }}', 'Mar 20, 2014, 12:00 AM') ->setParameter('{{ max_limit_path }}', 'max') ->setParameter('{{ min_limit_path }}', 'min') - ->setCode(Range::TOO_HIGH_ERROR) + ->setCode(Range::NOT_IN_RANGE_ERROR) ->assertRaised(); } @@ -742,18 +742,18 @@ class RangeValidatorTest extends ConstraintValidatorTestCase $constraint = new Range([ 'minPropertyPath' => 'min', 'maxPropertyPath' => 'max', - 'minMessage' => 'myMinMessage', - 'maxMessage' => 'myMaxMessage', + 'notInRangeMessage' => 'myNotInRangeMessage', ]); $this->validator->validate($value, $constraint); - $this->buildViolation('myMinMessage') + $this->buildViolation('myNotInRangeMessage') ->setParameter('{{ value }}', $dateTimeAsString) - ->setParameter('{{ limit }}', 'Mar 10, 2014, 12:00 AM') + ->setParameter('{{ min }}', 'Mar 10, 2014, 12:00 AM') + ->setParameter('{{ max }}', 'Mar 20, 2014, 12:00 AM') ->setParameter('{{ max_limit_path }}', 'max') ->setParameter('{{ min_limit_path }}', 'min') - ->setCode(Range::TOO_LOW_ERROR) + ->setCode(Range::NOT_IN_RANGE_ERROR) ->assertRaised(); } }