From bb0ef88860b3b50575feff778d49b9a018db40ac Mon Sep 17 00:00:00 2001 From: Robbert Jan Date: Sun, 7 Feb 2016 17:22:44 +0100 Subject: [PATCH] Enhancement for DateValidator (#7177, #10165) Added parameter to define if checking for 'date' or 'dateTime' and updated parseDateValueIntl($value, $format) to facilitate this validation based on defined type. Added unit tests to for validating dateTime values when using short format validation. close #10778 --- framework/CHANGELOG.md | 1 + framework/validators/DateValidator.php | 38 ++++++++++++++++++- .../validators/DateValidatorTest.php | 29 ++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 6870b108be..ffc953c332 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -41,6 +41,7 @@ Yii Framework 2 Change Log - Bug #11280: Descendants of `yii\console\controllers\BaseMigrateController`, like the one for MongoDB, unable to create new migration (klimov-paul) - Bug: SQlite querybuilder did not create primary key with bigint for `TYPE_BIGPK` (cebe) - Enh #5469: Add mimetype validation by mask in FileValidator (kirsenn, samdark, silverfire) +- Enh #7177, #10165: Added support for validating datetime values using intl short format to `DateValidator` (VirtualRJ) - Enh #8145, #8139, #10234 #11153: `yii\validators\Validator::$attributes` property now supports `!attribute` notation to validate attribute, but do not mark it as safe (mdmunir) - Enh #8148: Implemented ability to add comment on table and column in migration (vaseninm, silverfire) - Enh #8505: `yii\db\Query` now contains a andFilterCompare() method that allows filtering using operators in the query value (lennartvdd) diff --git a/framework/validators/DateValidator.php b/framework/validators/DateValidator.php index 5ea3f41df9..5560475e8b 100644 --- a/framework/validators/DateValidator.php +++ b/framework/validators/DateValidator.php @@ -30,6 +30,19 @@ use yii\helpers\FormatConverter; */ class DateValidator extends Validator { + /** + * Constant for specifying the validation [[type]] as a date value, used for validation with intl short format. + * @since 2.0.8 + * @see type + */ + const TYPE_DATE = 'date'; + /** + * Constant for specifying the validation [[type]] as a datetime value, used for validation with intl short format. + * @since 2.0.8 + * @see type + */ + const TYPE_DATETIME = 'datetime'; + /** * @var string the date format that the value being validated should follow. * This can be a date time pattern as described in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax). @@ -143,7 +156,22 @@ class DateValidator extends Validator * @since 2.0.4 */ public $minString; - + /** + * @var string the type of the date or time format to validate, when [[format]] is one of the intl + * short formats, `short`, `medium`, `long`, or `full`. + * + * This is only effective when the [PHP intl extension](http://php.net/manual/en/book.intl.php) is installed. + * + * This property can be set to the following values: + * + * - [[TYPE_DATE]] - for validating date values only, that means only values that do not include a time range are valid. + * - [[TYPE_DATETIME]] - for validating datetime values, that contain a date part as well as a time part. + * + * Defaults to [[TYPE_DATE]]. + * @since 2.0.8 + */ + public $type = self::TYPE_DATE; + /** * @var array map of short format names to IntlDateFormatter constant values. */ @@ -297,7 +325,13 @@ class DateValidator extends Validator private function parseDateValueIntl($value, $format) { if (isset($this->_dateFormats[$format])) { - $formatter = new IntlDateFormatter($this->locale, $this->_dateFormats[$format], IntlDateFormatter::NONE, 'UTC'); + if ($this->type === self::TYPE_DATE) { + $formatter = new IntlDateFormatter($this->locale, $this->_dateFormats[$format], IntlDateFormatter::NONE, 'UTC'); + } elseif ($this->type === self::TYPE_DATETIME) { + $formatter = new IntlDateFormatter($this->locale, $this->_dateFormats[$format], $this->_dateFormats[$format], $this->timeZone); + } else { + throw new InvalidConfigException('Unknown validation type set for DateValidator::$type: ' . $this->type); + } } else { // if no time was provided in the format string set time to 0 to get a simple date timestamp $hasTimeInfo = (strpbrk($format, 'ahHkKmsSA') !== false); diff --git a/tests/framework/validators/DateValidatorTest.php b/tests/framework/validators/DateValidatorTest.php index 19d58db077..35ecc487d6 100644 --- a/tests/framework/validators/DateValidatorTest.php +++ b/tests/framework/validators/DateValidatorTest.php @@ -280,6 +280,35 @@ class DateValidatorTest extends TestCase public function testIntlValidationWithTime($timezone) { $this->testValidationWithTime($timezone); + + $this->mockApplication([ + 'language' => 'en-GB', + 'components' => [ + 'formatter' => [ + 'dateFormat' => 'short', + ] + ] + ]); + $val = new DateValidator(['type' => 'dateTime']); + $this->assertTrue($val->validate('31/5/2017 12:30')); + $this->assertFalse($val->validate('5/31/2017 12:30')); + $val = new DateValidator(['format' => 'short', 'locale' => 'en-GB', 'type' => DateValidator::TYPE_DATETIME]); + $this->assertTrue($val->validate('31/5/2017 12:30')); + $this->assertFalse($val->validate('5/31/2017 12:30')); + $this->mockApplication([ + 'language' => 'de-DE', + 'components' => [ + 'formatter' => [ + 'dateFormat' => 'short', + ] + ] + ]); + $val = new DateValidator(['type' => 'dateTime']); + $this->assertTrue($val->validate('31.5.2017 12:30')); + $this->assertFalse($val->validate('5.31.2017 12:30')); + $val = new DateValidator(['format' => 'short', 'locale' => 'de-DE', 'type' => DateValidator::TYPE_DATETIME]); + $this->assertTrue($val->validate('31.5.2017 12:30')); + $this->assertFalse($val->validate('5.31.2017 12:30')); } /**