From 37617a8e53a53817f165fccadb9b906c0923b33a Mon Sep 17 00:00:00 2001 From: Dmitriy Derepko Date: Tue, 1 Aug 2023 17:27:16 +0200 Subject: [PATCH] [Validator] Add ability to validate time without seconds --- src/Symfony/Component/Validator/CHANGELOG.md | 1 + .../Component/Validator/Constraints/Time.php | 5 +- .../Validator/Constraints/TimeValidator.php | 5 +- .../Tests/Constraints/TimeValidatorTest.php | 50 +++++++++++++++++++ 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index 3ce7032d9c3fb..86da5aeba183d 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -11,6 +11,7 @@ CHANGELOG * Deprecate `ValidatorBuilder::setDoctrineAnnotationReader()` * Deprecate `ValidatorBuilder::addDefaultDoctrineAnnotationReader()` * Add `number`, `finite-number` and `finite-float` types to `Type` constraint + * Add the `withSeconds` option to the `Time` constraint that allows to pass time without seconds 6.3 --- diff --git a/src/Symfony/Component/Validator/Constraints/Time.php b/src/Symfony/Component/Validator/Constraints/Time.php index f281ae1ee85b3..a6ce0aae8acd9 100644 --- a/src/Symfony/Component/Validator/Constraints/Time.php +++ b/src/Symfony/Component/Validator/Constraints/Time.php @@ -35,16 +35,19 @@ class Time extends Constraint */ protected static $errorNames = self::ERROR_NAMES; + public $withSeconds = true; public $message = 'This value is not a valid time.'; public function __construct( array $options = null, string $message = null, array $groups = null, - mixed $payload = null + mixed $payload = null, + bool $withSeconds = null, ) { parent::__construct($options, $groups, $payload); + $this->withSeconds = $withSeconds ?? $this->withSeconds; $this->message = $message ?? $this->message; } } diff --git a/src/Symfony/Component/Validator/Constraints/TimeValidator.php b/src/Symfony/Component/Validator/Constraints/TimeValidator.php index c6d111cfe3874..473c9e8e01ef2 100644 --- a/src/Symfony/Component/Validator/Constraints/TimeValidator.php +++ b/src/Symfony/Component/Validator/Constraints/TimeValidator.php @@ -22,6 +22,7 @@ class TimeValidator extends ConstraintValidator { public const PATTERN = '/^(\d{2}):(\d{2}):(\d{2})$/'; + public const PATTERN_WITHOUT_SECONDS = '/^(\d{2}):(\d{2})$/'; /** * Checks whether a time is valid. @@ -52,7 +53,7 @@ public function validate(mixed $value, Constraint $constraint) $value = (string) $value; - if (!preg_match(static::PATTERN, $value, $matches)) { + if (!preg_match($constraint->withSeconds ? static::PATTERN : static::PATTERN_WITHOUT_SECONDS, $value, $matches)) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Time::INVALID_FORMAT_ERROR) @@ -61,7 +62,7 @@ public function validate(mixed $value, Constraint $constraint) return; } - if (!self::checkTime($matches[1], $matches[2], $matches[3])) { + if (!self::checkTime($matches[1], $matches[2], $constraint->withSeconds ? $matches[3] : 0)) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Time::INVALID_TIME_ERROR) diff --git a/src/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.php index 5995ae15d68f4..91d6778ed4ec1 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.php @@ -30,6 +30,13 @@ public function testNullIsValid() $this->assertNoViolation(); } + public function testDefaultWithSeconds() + { + $this->validator->validate('10:15:25', new Time()); + + $this->assertNoViolation(); + } + public function testEmptyStringIsValid() { $this->validator->validate('', new Time()); @@ -62,6 +69,49 @@ public static function getValidTimes() ]; } + /** + * @dataProvider getValidTimesWithoutSeconds + */ + public function testValidTimesWithoutSeconds(string $time) + { + $this->validator->validate($time, new Time([ + 'withSeconds' => false, + ])); + + $this->assertNoViolation(); + } + + public static function getValidTimesWithoutSeconds() + { + return [ + ['01:02'], + ['00:00'], + ['23:59'], + ]; + } + + /** + * @dataProvider getInvalidTimesWithoutSeconds + */ + public function testInvalidTimesWithoutSeconds(string $time) + { + $this->validator->validate($time, $constraint = new Time()); + + $this->buildViolation($constraint->message) + ->setParameter('{{ value }}', '"'.$time.'"') + ->setCode(Time::INVALID_FORMAT_ERROR) + ->assertRaised(); + } + + public static function getInvalidTimesWithoutSeconds() + { + return [ + ['01:02'], + ['00:00'], + ['23:59'], + ]; + } + /** * @dataProvider getInvalidTimes */