diff --git a/src/Symfony/Component/Validator/Constraints/Date.php b/src/Symfony/Component/Validator/Constraints/Date.php index f9923052e0cf1..ddb198d6d6031 100644 --- a/src/Symfony/Component/Validator/Constraints/Date.php +++ b/src/Symfony/Component/Validator/Constraints/Date.php @@ -23,4 +23,6 @@ class Date extends Constraint { public $message = 'This value is not a valid date.'; + public $after; + public $before; } diff --git a/src/Symfony/Component/Validator/Constraints/DateTime.php b/src/Symfony/Component/Validator/Constraints/DateTime.php index 0618bc9b99923..f1d88eaa7658f 100644 --- a/src/Symfony/Component/Validator/Constraints/DateTime.php +++ b/src/Symfony/Component/Validator/Constraints/DateTime.php @@ -23,4 +23,6 @@ class DateTime extends Constraint { public $message = 'This value is not a valid datetime.'; + public $after; + public $before; } diff --git a/src/Symfony/Component/Validator/Constraints/DateTimeValidator.php b/src/Symfony/Component/Validator/Constraints/DateTimeValidator.php index 49e04b94f2bd8..3e42cf2070005 100644 --- a/src/Symfony/Component/Validator/Constraints/DateTimeValidator.php +++ b/src/Symfony/Component/Validator/Constraints/DateTimeValidator.php @@ -18,5 +18,6 @@ */ class DateTimeValidator extends DateValidator { + const FORMAT = 'Y-m-d H:i:s'; const PATTERN = '/^(\d{4})-(\d{2})-(\d{2}) (0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/'; } diff --git a/src/Symfony/Component/Validator/Constraints/DateValidator.php b/src/Symfony/Component/Validator/Constraints/DateValidator.php index f891f9d621a9b..365d44cfa5fb5 100644 --- a/src/Symfony/Component/Validator/Constraints/DateValidator.php +++ b/src/Symfony/Component/Validator/Constraints/DateValidator.php @@ -22,6 +22,7 @@ */ class DateValidator extends ConstraintValidator { + const FORMAT = 'Y-m-d'; const PATTERN = '/^(\d{4})-(\d{2})-(\d{2})$/'; /** @@ -29,18 +30,38 @@ class DateValidator extends ConstraintValidator */ public function validate($value, Constraint $constraint) { - if (null === $value || '' === $value || $value instanceof \DateTime) { + if (null === $value || '' === $value) { return; } - if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { - throw new UnexpectedTypeException($value, 'string'); + if (!$value instanceof \DateTime) { + if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { + throw new UnexpectedTypeException($value, 'string'); + } + + $value = (string) $value; + + if (!preg_match(static::PATTERN, $value, $matches) || !checkdate($matches[2], $matches[3], $matches[1])) { + $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); + } + } + + if (!$constraint->before && !$constraint->after) { + return; + } + + if ($value instanceof \DateTime) { + $timestamp = $value->getTimestamp(); + } else { + $timestamp = strtotime($value); } - $value = (string) $value; + if ($constraint->before && $timestamp > strtotime($constraint->before)) { + $this->context->addViolation($constraint->message, array('{{ value }}' => date(static::FORMAT, $timestamp))); + } - if (!preg_match(static::PATTERN, $value, $matches) || !checkdate($matches[2], $matches[3], $matches[1])) { - $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); + if ($constraint->after && $timestamp < strtotime($constraint->after)) { + $this->context->addViolation($constraint->message, array('{{ value }}' => date(static::FORMAT, $timestamp))); } } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.php index 0776848fdbd47..4d3d8191184c6 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.php @@ -117,4 +117,33 @@ public function getInvalidDateTimes() array('2010-01-01 00:00:60'), ); } + + /** + * @dataProvider getBeforeAndAfter + */ + public function testBeforeAndAfter($date, $before, $after, $valid) + { + $this->context->expects($valid ? $this->never() : $this->once()) + ->method('addViolation'); + + $this->validator->validate($date, new DateTime(array( + 'before' => $before, + 'after' => $after, + ))); + } + + public function getBeforeAndAfter() + { + return array( + array('2010-01-02 15:00:33', '2010-01-02 16:30:00', '2010-01-01', true), + array('2008-01-02 12:00:00', '2012-02-02', '2010-01-01', false), + array('2010-01-02 00:00:00', '2012-02-02', null, true), + array('2013-01-02 01:02:03', '2012-02-02', null, false), + array('2010-01-02 10:10:10', null, '2012-02-02', false), + array('2013-01-02 15:12:00', null, '2012-02-02', true), + array(date('Y-m-d H:i:s', strtotime('+1 day')), null, 'now', true), + array(new \DateTime('-1 hour'), 'now', null, true), + array(new \DateTime('-5 minutes'), 'now', '-3 minutes', false), + ); + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.php index b9cf8816b76a5..43438464d25b3 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.php @@ -113,4 +113,33 @@ public function getInvalidDates() array('2010-02-29'), ); } + + /** + * @dataProvider getBeforeAndAfter + */ + public function testBeforeAndAfter($date, $before, $after, $valid) + { + $this->context->expects($valid ? $this->never() : $this->once()) + ->method('addViolation'); + + $this->validator->validate($date, new Date(array( + 'before' => $before, + 'after' => $after, + ))); + } + + public function getBeforeAndAfter() + { + return array( + array('2010-01-02', '2012-02-02', '2010-01-01', true), + array('2008-01-02', '2012-02-02', '2010-01-01', false), + array('2010-01-02', '2012-02-02', null, true), + array('2013-01-02', '2012-02-02', null, false), + array('2010-01-02', null, '2012-02-02', false), + array('2013-01-02', null, '2012-02-02', true), + array(date('Y-m-d', strtotime('+1 day')), null, 'now', true), + array(new \DateTime('-1 day'), 'now', null, true), + array(new \DateTime('-5 days'), 'now', '-3 days', false), + ); + } }