Skip to content

Commit

Permalink
feature #36326 [Validator] Add invalid datetime message in Range vali…
Browse files Browse the repository at this point in the history
…dator (przemyslaw-bogusz)

This PR was squashed before being merged into the 5.2-dev branch.

Discussion
----------

[Validator] Add invalid datetime message in Range validator

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | -
| License       | MIT
| Doc PR        | -

When the validated value is invalid (it isn't a number nor a datetime), but `min` or `max` option indicate that the `Range` constraint is being used to validate a datetime, the displayed message will be `This value should be a valid datetime` instead of `This value should be a valid number`. This PR replaces #35998.

Commits
-------

c777306 [Validator] Add invalid datetime message in Range validator
  • Loading branch information
fabpot committed Sep 24, 2020
2 parents 59f7124 + c777306 commit 2bdcf4a
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 11 deletions.
1 change: 1 addition & 0 deletions src/Symfony/Component/Validator/Constraints/Range.php
Expand Up @@ -41,6 +41,7 @@ class Range extends Constraint
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.';
public $invalidDateTimeMessage = 'This value should be a valid datetime.';
public $min;
public $minPropertyPath;
public $max;
Expand Down
40 changes: 33 additions & 7 deletions src/Symfony/Component/Validator/Constraints/RangeValidator.php
Expand Up @@ -44,18 +44,25 @@ public function validate($value, Constraint $constraint)
return;
}

$min = $this->getLimit($constraint->minPropertyPath, $constraint->min, $constraint);
$max = $this->getLimit($constraint->maxPropertyPath, $constraint->max, $constraint);

if (!is_numeric($value) && !$value instanceof \DateTimeInterface) {
$this->context->buildViolation($constraint->invalidMessage)
->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE))
->setCode(Range::INVALID_CHARACTERS_ERROR)
->addViolation();
if ($this->isParsableDatetimeString($min) && $this->isParsableDatetimeString($max)) {
$this->context->buildViolation($constraint->invalidDateTimeMessage)
->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE))
->setCode(Range::INVALID_CHARACTERS_ERROR)
->addViolation();
} else {
$this->context->buildViolation($constraint->invalidMessage)
->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE))
->setCode(Range::INVALID_CHARACTERS_ERROR)
->addViolation();
}

return;
}

$min = $this->getLimit($constraint->minPropertyPath, $constraint->min, $constraint);
$max = $this->getLimit($constraint->maxPropertyPath, $constraint->max, $constraint);

// Convert strings to DateTimes if comparing another DateTime
// This allows to compare with any date/time value supported by
// the DateTime constructor:
Expand Down Expand Up @@ -182,4 +189,23 @@ private function getPropertyAccessor(): PropertyAccessorInterface

return $this->propertyAccessor;
}

private function isParsableDatetimeString($boundary): bool
{
if (null === $boundary) {
return true;
}

if (!\is_string($boundary)) {
return false;
}

try {
new \DateTime($boundary);
} catch (\Exception $e) {
return false;
}

return true;
}
}
Expand Up @@ -379,13 +379,102 @@ public function getInvalidValues()

public function testNonNumeric()
{
$this->validator->validate('abcd', new Range([
$constraint = new Range([
'min' => 10,
'max' => 20,
'invalidMessage' => 'myMessage',
]));
]);

$this->buildViolation('myMessage')
$this->validator->validate('abcd', $constraint);

$this->buildViolation($constraint->invalidMessage)
->setParameter('{{ value }}', '"abcd"')
->setCode(Range::INVALID_CHARACTERS_ERROR)
->assertRaised();
}

public function testNonNumericWithParsableDatetimeMinAndMaxNull()
{
$constraint = new Range([
'min' => 'March 10, 2014',
]);

$this->validator->validate('abcd', $constraint);

$this->buildViolation($constraint->invalidDateTimeMessage)
->setParameter('{{ value }}', '"abcd"')
->setCode(Range::INVALID_CHARACTERS_ERROR)
->assertRaised();
}

public function testNonNumericWithParsableDatetimeMaxAndMinNull()
{
$constraint = new Range([
'max' => 'March 20, 2014',
]);

$this->validator->validate('abcd', $constraint);

$this->buildViolation($constraint->invalidDateTimeMessage)
->setParameter('{{ value }}', '"abcd"')
->setCode(Range::INVALID_CHARACTERS_ERROR)
->assertRaised();
}

public function testNonNumericWithParsableDatetimeMinAndMax()
{
$constraint = new Range([
'min' => 'March 10, 2014',
'max' => 'March 20, 2014',
]);

$this->validator->validate('abcd', $constraint);

$this->buildViolation($constraint->invalidDateTimeMessage)
->setParameter('{{ value }}', '"abcd"')
->setCode(Range::INVALID_CHARACTERS_ERROR)
->assertRaised();
}

public function testNonNumericWithNonParsableDatetimeMin()
{
$constraint = new Range([
'min' => 'March 40, 2014',
'max' => 'March 20, 2014',
]);

$this->validator->validate('abcd', $constraint);

$this->buildViolation($constraint->invalidMessage)
->setParameter('{{ value }}', '"abcd"')
->setCode(Range::INVALID_CHARACTERS_ERROR)
->assertRaised();
}

public function testNonNumericWithNonParsableDatetimeMax()
{
$constraint = new Range([
'min' => 'March 10, 2014',
'max' => 'March 50, 2014',
]);

$this->validator->validate('abcd', $constraint);

$this->buildViolation($constraint->invalidMessage)
->setParameter('{{ value }}', '"abcd"')
->setCode(Range::INVALID_CHARACTERS_ERROR)
->assertRaised();
}

public function testNonNumericWithNonParsableDatetimeMinAndMax()
{
$constraint = new Range([
'min' => 'March 40, 2014',
'max' => 'March 50, 2014',
]);

$this->validator->validate('abcd', $constraint);

$this->buildViolation($constraint->invalidMessage)
->setParameter('{{ value }}', '"abcd"')
->setCode(Range::INVALID_CHARACTERS_ERROR)
->assertRaised();
Expand Down

0 comments on commit 2bdcf4a

Please sign in to comment.