diff --git a/src/Symfony/Component/Validator/Constraints/Time.php b/src/Symfony/Component/Validator/Constraints/Time.php index 42ede04325bea..824016f3861a1 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 && !$this->withMinutes) { + 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..a39098b49e1c1 100644 --- a/src/Symfony/Component/Validator/Constraints/TimeValidator.php +++ b/src/Symfony/Component/Validator/Constraints/TimeValidator.php @@ -22,8 +22,6 @@ */ class TimeValidator extends ConstraintValidator { - const PATTERN = '/^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/'; - /** * {@inheritdoc} */ @@ -43,10 +41,35 @@ 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 bool $withMinutes + * @param bool $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..cd303565040e2 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,51 @@ 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('0'), + array('23'), + array('5'), + ); + } + + /** + * @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('4:00'), + array('23:59'), + ); + } + /** * @dataProvider getInvalidTimes */ @@ -87,7 +144,7 @@ public function testInvalidTimes($time) $this->validator->validate($time, $constraint); $this->assertViolation('myMessage', array( - '{{ value }}' => '"'.$time.'"', + '{{ value }}' => $time, )); } @@ -98,9 +155,67 @@ 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'), ); } + + /** + * @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'), + ); + } }