From a943c6d1d882f79429400bd9c196745a027d9393 Mon Sep 17 00:00:00 2001 From: Besnik Br Date: Sat, 28 Sep 2013 22:51:42 +0200 Subject: [PATCH 1/6] [Validator] Time constraint should support for values with hours only, with minutes and with minutes and seconds | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - --- .../Component/Validator/Constraints/Time.php | 16 +++ .../Validator/Constraints/TimeValidator.php | 39 ++++-- .../InvalidConfigurationException.php | 16 +++ .../Tests/Constraints/TimeValidatorTest.php | 113 +++++++++++++++++- 4 files changed, 176 insertions(+), 8 deletions(-) create mode 100644 src/Symfony/Component/Validator/Exception/InvalidConfigurationException.php diff --git a/src/Symfony/Component/Validator/Constraints/Time.php b/src/Symfony/Component/Validator/Constraints/Time.php index 42ede04325bea..5b4459d5440be 100644 --- a/src/Symfony/Component/Validator/Constraints/Time.php +++ b/src/Symfony/Component/Validator/Constraints/Time.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidConfigurationException; /** * @Annotation @@ -24,4 +25,19 @@ class Time extends Constraint { public $message = 'This value is not a valid time.'; + public $withMinutes = true; + public $withSeconds = true; + + public function __construct($options = null) + { + parent::__construct($options); + + if (isset($options['withMinutes']) && !isset($options['withSeconds']) && $options['withMinutes'] == false) { + $this->withSeconds = false; + } + + if ($this->withSeconds == true && $this->withMinutes == false) { + throw new InvalidConfigurationException('You can not disable minutes if you have enabled seconds.'); + } + } } diff --git a/src/Symfony/Component/Validator/Constraints/TimeValidator.php b/src/Symfony/Component/Validator/Constraints/TimeValidator.php index cf252b1d28dd6..a819dae83c856 100644 --- a/src/Symfony/Component/Validator/Constraints/TimeValidator.php +++ b/src/Symfony/Component/Validator/Constraints/TimeValidator.php @@ -22,10 +22,8 @@ */ class TimeValidator extends ConstraintValidator { - const PATTERN = '/^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/'; - /** - * {@inheritdoc} + * {@inheritDoc} */ public function validate($value, Constraint $constraint) { @@ -43,10 +41,37 @@ public function validate($value, Constraint $constraint) $value = (string) $value; - if (!preg_match(static::PATTERN, $value)) { - $this->context->addViolation($constraint->message, array( - '{{ value }}' => $this->formatValue($value), - )); + $pattern = $this->getPattern($constraint->withMinutes, $constraint->withSeconds); + + if (!preg_match($pattern, $value)) { + $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } + + /** + * Returns the regex pattern for validating + * + * @param $withMinutes + * @param $withSeconds + * @return string + */ + protected function getPattern($withMinutes, $withSeconds) + { + // pattern for hours + $pattern = "(0[0-9]|1[0-9]|2[0-3])"; + + if ($withMinutes) + { + // pattern for minutes + $pattern .= "(:([0-5][0-9]))"; + + if ($withSeconds) + { + // because the pattern for seconds is the same as that for minutes, we repeat it twice + $pattern .= "{2}"; + } + } + + return "/^".$pattern."$/"; + } } diff --git a/src/Symfony/Component/Validator/Exception/InvalidConfigurationException.php b/src/Symfony/Component/Validator/Exception/InvalidConfigurationException.php new file mode 100644 index 0000000000000..7e3587f20ea1a --- /dev/null +++ b/src/Symfony/Component/Validator/Exception/InvalidConfigurationException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Exception; + +class InvalidConfigurationException extends InvalidArgumentException +{ +} diff --git a/src/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.php index 8d8f9fb6498dc..9e51c20f71b92 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.php @@ -14,6 +14,7 @@ use Symfony\Component\Validator\Constraints\Time; use Symfony\Component\Validator\Constraints\TimeValidator; use Symfony\Component\Validator\Validation; +use Symfony\Component\Validator\Tests\Fixtures\InvalidConstraint; class TimeValidatorTest extends AbstractConstraintValidatorTest { @@ -27,6 +28,17 @@ protected function createValidator() return new TimeValidator(); } + /** + * @expectedException \Symfony\Component\Validator\Exception\InvalidConfigurationException + */ + public function testThrowsExceptionIfConfigurationIsInvalid() + { + new Time(array( + 'withMinutes' => false, + 'withSeconds' => true, + )); + } + public function testNullIsValid() { $this->validator->validate(null, new Time()); @@ -75,6 +87,48 @@ public function getValidTimes() ); } + /** + * @dataProvider getValidTimesWithoutMinutes + */ + public function testValidTimesWithoutMinutes($time) + { + $this->validator->validate($time, new Time(array( + 'withMinutes' => false, + ))); + + $this->assertNoViolation(); + } + + public function getValidTimesWithoutMinutes() + { + return array( + array('01'), + array('00'), + array('23'), + ); + } + + /** + * @dataProvider getValidTimesWithoutSeconds + */ + public function testValidTimesWithoutSeconds($time) + { + $this->validator->validate($time, new Time(array( + 'withSeconds' => false, + ))); + + $this->assertNoViolation(); + } + + public function getValidTimesWithoutSeconds() + { + return array( + array('01:02'), + array('00:00'), + array('23:59'), + ); + } + /** * @dataProvider getInvalidTimes */ @@ -87,7 +141,7 @@ public function testInvalidTimes($time) $this->validator->validate($time, $constraint); $this->assertViolation('myMessage', array( - '{{ value }}' => '"'.$time.'"', + '{{ value }}' => $time, )); } @@ -103,4 +157,61 @@ public function getInvalidTimes() array('00:00:60'), ); } + + /** + * @dataProvider getInvalidTimesWithoutMinutes + */ + public function testInvalidTimesWithoutMinutes($time) + { + $constraint = new Time(array( + 'message' => 'myMessage', + 'withMinutes' => false, + )); + + $this->validator->validate($time, $constraint); + + $this->assertViolation('myMessage', array( + '{{ value }}' => $time, + )); + } + + public function getInvalidTimesWithoutMinutes() + { + return array( + array('foobar'), + array('foobar 12'), + array('12 foobar'), + array('24'), + array('60'), + ); + } + + /** + * @dataProvider getInvalidTimesWithoutSeconds + */ + public function testInvalidTimesWithoutSeconds($time) + { + $constraint = new Time(array( + 'message' => 'myMessage', + 'withSeconds' => false, + )); + + $this->validator->validate($time, $constraint); + + $this->assertViolation('myMessage', array( + '{{ value }}' => $time, + )); + } + + public function getInvalidTimesWithoutSeconds() + { + return array( + array('foobar'), + array('foobar 12:34'), + array('12:34 foobar'), + array('01:02:03'), + array('24:00'), + array('00:60'), + ); + } } From ab5388b18d37200b65a1be710057772bc5638832 Mon Sep 17 00:00:00 2001 From: Besnik Br Date: Sun, 29 Sep 2013 15:14:59 +0200 Subject: [PATCH 2/6] fixed code see: https://github.com/symfony/symfony/pull/9163#discussion_r6647044 --- src/Symfony/Component/Validator/Constraints/Time.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Constraints/Time.php b/src/Symfony/Component/Validator/Constraints/Time.php index 5b4459d5440be..b9a88e12a2d31 100644 --- a/src/Symfony/Component/Validator/Constraints/Time.php +++ b/src/Symfony/Component/Validator/Constraints/Time.php @@ -36,7 +36,7 @@ public function __construct($options = null) $this->withSeconds = false; } - if ($this->withSeconds == true && $this->withMinutes == false) { + if ($this->withSeconds && !$this->withMinutes) { throw new InvalidConfigurationException('You can not disable minutes if you have enabled seconds.'); } } From ffd618f4f513c3fd2ec40f82a80f6a289ca8d315 Mon Sep 17 00:00:00 2001 From: Besnik Br Date: Sun, 29 Sep 2013 15:40:53 +0200 Subject: [PATCH 3/6] added parameter type --- .../Component/Validator/Constraints/TimeValidator.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Validator/Constraints/TimeValidator.php b/src/Symfony/Component/Validator/Constraints/TimeValidator.php index a819dae83c856..ebc938415cc20 100644 --- a/src/Symfony/Component/Validator/Constraints/TimeValidator.php +++ b/src/Symfony/Component/Validator/Constraints/TimeValidator.php @@ -51,8 +51,8 @@ public function validate($value, Constraint $constraint) /** * Returns the regex pattern for validating * - * @param $withMinutes - * @param $withSeconds + * @param Boolean $withMinutes + * @param Boolean $withSeconds * @return string */ protected function getPattern($withMinutes, $withSeconds) @@ -60,13 +60,11 @@ protected function getPattern($withMinutes, $withSeconds) // pattern for hours $pattern = "(0[0-9]|1[0-9]|2[0-3])"; - if ($withMinutes) - { + if ($withMinutes) { // pattern for minutes $pattern .= "(:([0-5][0-9]))"; - if ($withSeconds) - { + if ($withSeconds) { // because the pattern for seconds is the same as that for minutes, we repeat it twice $pattern .= "{2}"; } From 5010a24261ba8401d450528a53223178f9ed3d01 Mon Sep 17 00:00:00 2001 From: Besnik Br Date: Mon, 1 Sep 2014 22:27:57 +0200 Subject: [PATCH 4/6] allow hour without leading zero --- src/Symfony/Component/Validator/Constraints/TimeValidator.php | 2 +- .../Validator/Tests/Constraints/TimeValidatorTest.php | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Constraints/TimeValidator.php b/src/Symfony/Component/Validator/Constraints/TimeValidator.php index ebc938415cc20..37b741d270732 100644 --- a/src/Symfony/Component/Validator/Constraints/TimeValidator.php +++ b/src/Symfony/Component/Validator/Constraints/TimeValidator.php @@ -58,7 +58,7 @@ public function validate($value, Constraint $constraint) protected function getPattern($withMinutes, $withSeconds) { // pattern for hours - $pattern = "(0[0-9]|1[0-9]|2[0-3])"; + $pattern = "(0?[0-9]|1[0-9]|2[0-3])"; if ($withMinutes) { // pattern for minutes diff --git a/src/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.php index 9e51c20f71b92..cd303565040e2 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.php @@ -104,7 +104,9 @@ public function getValidTimesWithoutMinutes() return array( array('01'), array('00'), + array('0'), array('23'), + array('5'), ); } @@ -125,6 +127,7 @@ public function getValidTimesWithoutSeconds() return array( array('01:02'), array('00:00'), + array('4:00'), array('23:59'), ); } @@ -152,6 +155,7 @@ public function getInvalidTimes() array('foobar 12:34:56'), array('12:34:56 foobar'), array('00:00'), + array('05:3'), array('24:00:00'), array('00:60:00'), array('00:00:60'), From a76b08ef1bd8f279154f18300ce61c4ee7ef8683 Mon Sep 17 00:00:00 2001 From: Besnik Br Date: Mon, 1 Sep 2014 22:29:41 +0200 Subject: [PATCH 5/6] used '=== false' instead of '== false' --- src/Symfony/Component/Validator/Constraints/Time.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Constraints/Time.php b/src/Symfony/Component/Validator/Constraints/Time.php index b9a88e12a2d31..824016f3861a1 100644 --- a/src/Symfony/Component/Validator/Constraints/Time.php +++ b/src/Symfony/Component/Validator/Constraints/Time.php @@ -32,7 +32,7 @@ public function __construct($options = null) { parent::__construct($options); - if (isset($options['withMinutes']) && !isset($options['withSeconds']) && $options['withMinutes'] == false) { + if (isset($options['withMinutes']) && !isset($options['withSeconds']) && $options['withMinutes'] === false) { $this->withSeconds = false; } From dec3ddb7b78cd85fe15dadf4404217ba079d5495 Mon Sep 17 00:00:00 2001 From: Besnik Br Date: Mon, 1 Sep 2014 22:41:48 +0200 Subject: [PATCH 6/6] fixed coding standard and php doc/type issues --- .../Component/Validator/Constraints/TimeValidator.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Validator/Constraints/TimeValidator.php b/src/Symfony/Component/Validator/Constraints/TimeValidator.php index 37b741d270732..a39098b49e1c1 100644 --- a/src/Symfony/Component/Validator/Constraints/TimeValidator.php +++ b/src/Symfony/Component/Validator/Constraints/TimeValidator.php @@ -23,7 +23,7 @@ class TimeValidator extends ConstraintValidator { /** - * {@inheritDoc} + * {@inheritdoc} */ public function validate($value, Constraint $constraint) { @@ -51,8 +51,8 @@ public function validate($value, Constraint $constraint) /** * Returns the regex pattern for validating * - * @param Boolean $withMinutes - * @param Boolean $withSeconds + * @param bool $withMinutes + * @param bool $withSeconds * @return string */ protected function getPattern($withMinutes, $withSeconds)