Commit 3ff548a4 by Carsten Brandt

Refactored DateValidator to support ICU format

parent 9edf938b
...@@ -32,7 +32,6 @@ $this->title = 'Yii Debugger'; ...@@ -32,7 +32,6 @@ $this->title = 'Yii Debugger';
if (isset($this->context->module->panels['db']) && isset($this->context->module->panels['request'])) { if (isset($this->context->module->panels['db']) && isset($this->context->module->panels['request'])) {
echo " <h1>Available Debug Data</h1>"; echo " <h1>Available Debug Data</h1>";
$timeFormatter = extension_loaded('intl') ? Yii::createObject(['class' => 'yii\i18n\Formatter']) : Yii::$app->formatter;
$codes = []; $codes = [];
foreach ($manifest as $tag => $vals) { foreach ($manifest as $tag => $vals) {
...@@ -66,8 +65,8 @@ if (isset($this->context->module->panels['db']) && isset($this->context->module- ...@@ -66,8 +65,8 @@ if (isset($this->context->module->panels['db']) && isset($this->context->module-
], ],
[ [
'attribute' => 'time', 'attribute' => 'time',
'value' => function ($data) use ($timeFormatter) { 'value' => function ($data) {
return '<span class="nowrap">' . $timeFormatter->asDateTime($data['time'], 'short') . '</span>'; return '<span class="nowrap">' . Yii::$app->formatter->asDateTime($data['time'], 'short') . '</span>';
}, },
'format' => 'html', 'format' => 'html',
], ],
......
...@@ -227,6 +227,7 @@ Yii Framework 2 Change Log ...@@ -227,6 +227,7 @@ Yii Framework 2 Change Log
- Chg #2359: Refactored formatter class. One class with or without intl extension and PHP format pattern as standard (Erik_r, cebe) - Chg #2359: Refactored formatter class. One class with or without intl extension and PHP format pattern as standard (Erik_r, cebe)
- `yii\base\Formatter` functionality has been merged into `yii\i18n\Formatter` - `yii\base\Formatter` functionality has been merged into `yii\i18n\Formatter`
- removed the `yii\base\Formatter` class - removed the `yii\base\Formatter` class
- Chg #1551: Refactored DateValidator to support ICU date format and uses the format defined in Formatter by default (cebe)
- Chg #2380: `yii\widgets\ActiveForm` will register validation js even if there are not fields inside (qiangxue) - Chg #2380: `yii\widgets\ActiveForm` will register validation js even if there are not fields inside (qiangxue)
- Chg #2898: `yii\console\controllers\AssetController` is now using hashes instead of timestamps (samdark) - Chg #2898: `yii\console\controllers\AssetController` is now using hashes instead of timestamps (samdark)
- Chg #2913: RBAC `DbManager` is now initialized via migration (samdark) - Chg #2913: RBAC `DbManager` is now initialized via migration (samdark)
......
...@@ -244,6 +244,14 @@ new ones save the following code as `convert.php` that should be placed in the s ...@@ -244,6 +244,14 @@ new ones save the following code as `convert.php` that should be placed in the s
The specification of the date and time formats is now using the ICU pattern format even if PHP intl extension is not installed. The specification of the date and time formats is now using the ICU pattern format even if PHP intl extension is not installed.
You can prefix a date format with `php:` to use the old format of the PHP `date()`-function. You can prefix a date format with `php:` to use the old format of the PHP `date()`-function.
* The DateValidator has been refactored to use the same format as the Formatter class now (see previous change).
When you use the DateValidator and did not specify a format it will now be what is configured in the formatter class instead of 'Y-m-d'.
To get the old behavior of the DateValidator you have to set the format explicitly in your validation rule:
```php
['attributeName', 'date', 'format' => 'php:Y-m-d'],
```
* `beforeValidate()`, `beforeValidateAll()`, `afterValidate()`, `afterValidateAll()`, `ajaxBeforeSend()` and `ajaxComplete()` * `beforeValidate()`, `beforeValidateAll()`, `afterValidate()`, `afterValidateAll()`, `ajaxBeforeSend()` and `ajaxComplete()`
are removed from `ActiveForm`. The same functionality is now achieved via JavaScript event mechanism like the following: are removed from `ActiveForm`. The same functionality is now achieved via JavaScript event mechanism like the following:
......
...@@ -103,10 +103,10 @@ class BaseFormatConverter ...@@ -103,10 +103,10 @@ class BaseFormatConverter
public static function convertDateIcuToPhp($pattern, $type = 'date', $locale = null) public static function convertDateIcuToPhp($pattern, $type = 'date', $locale = null)
{ {
if (isset(self::$_icuShortFormats[$pattern])) { if (isset(self::$_icuShortFormats[$pattern])) {
if ($locale === null) {
$locale = Yii::$app->language;
}
if (extension_loaded('intl')) { if (extension_loaded('intl')) {
if ($locale === null) {
$locale = Yii::$app->language;
}
if ($type === 'date') { if ($type === 'date') {
$formatter = new IntlDateFormatter($locale, self::$_icuShortFormats[$pattern], IntlDateFormatter::NONE); $formatter = new IntlDateFormatter($locale, self::$_icuShortFormats[$pattern], IntlDateFormatter::NONE);
} elseif ($type === 'time') { } elseif ($type === 'time') {
...@@ -306,10 +306,10 @@ class BaseFormatConverter ...@@ -306,10 +306,10 @@ class BaseFormatConverter
public static function convertDateIcuToJui($pattern, $type = 'date', $locale = null) public static function convertDateIcuToJui($pattern, $type = 'date', $locale = null)
{ {
if (isset(self::$_icuShortFormats[$pattern])) { if (isset(self::$_icuShortFormats[$pattern])) {
if ($locale === null) {
$locale = Yii::$app->language;
}
if (extension_loaded('intl')) { if (extension_loaded('intl')) {
if ($locale === null) {
$locale = Yii::$app->language;
}
if ($type === 'date') { if ($type === 'date') {
$formatter = new IntlDateFormatter($locale, self::$_icuShortFormats[$pattern], IntlDateFormatter::NONE); $formatter = new IntlDateFormatter($locale, self::$_icuShortFormats[$pattern], IntlDateFormatter::NONE);
} elseif ($type === 'time') { } elseif ($type === 'time') {
......
...@@ -76,6 +76,13 @@ class Formatter extends Component ...@@ -76,6 +76,13 @@ class Formatter extends Component
* It can also be a custom format as specified in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax). * It can also be a custom format as specified in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax).
* Alternatively this can be a string prefixed with `php:` representing a format that can be recognized by the * Alternatively this can be a string prefixed with `php:` representing a format that can be recognized by the
* PHP [date()](http://php.net/manual/de/function.date.php)-function. * PHP [date()](http://php.net/manual/de/function.date.php)-function.
*
* For example:
*
* ```php
* 'MM/dd/yyyy' // date in ICU format
* 'php:m/d/Y' // the same date in PHP format
* ```
*/ */
public $dateFormat = 'medium'; public $dateFormat = 'medium';
/** /**
...@@ -85,6 +92,13 @@ class Formatter extends Component ...@@ -85,6 +92,13 @@ class Formatter extends Component
* It can also be a custom format as specified in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax). * It can also be a custom format as specified in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax).
* Alternatively this can be a string prefixed with `php:` representing a format that can be recognized by the * Alternatively this can be a string prefixed with `php:` representing a format that can be recognized by the
* PHP [date()](http://php.net/manual/de/function.date.php)-function. * PHP [date()](http://php.net/manual/de/function.date.php)-function.
*
* For example:
*
* ```php
* 'HH:mm:ss' // time in ICU format
* 'php:H:i:s' // the same time in PHP format
* ```
*/ */
public $timeFormat = 'medium'; public $timeFormat = 'medium';
/** /**
...@@ -95,6 +109,13 @@ class Formatter extends Component ...@@ -95,6 +109,13 @@ class Formatter extends Component
* *
* Alternatively this can be a string prefixed with `php:` representing a format that can be recognized by the * Alternatively this can be a string prefixed with `php:` representing a format that can be recognized by the
* PHP [date()](http://php.net/manual/de/function.date.php)-function. * PHP [date()](http://php.net/manual/de/function.date.php)-function.
*
* For example:
*
* ```php
* 'MM/dd/yyyy HH:mm:ss' // date and time in ICU format
* 'php:m/d/Y H:i:s' // the same date and time in PHP format
* ```
*/ */
public $datetimeFormat = 'medium'; public $datetimeFormat = 'medium';
/** /**
...@@ -479,7 +500,7 @@ class Formatter extends Component ...@@ -479,7 +500,7 @@ class Formatter extends Component
} }
if ($this->_intlLoaded) { if ($this->_intlLoaded) {
if (strpos($format, 'php:') === 0) { if (strncmp($format, 'php:', 4) === 0) {
$format = FormatConverter::convertDatePhpToIcu(substr($format, 4)); $format = FormatConverter::convertDatePhpToIcu(substr($format, 4));
} }
if (isset($this->_dateFormats[$format])) { if (isset($this->_dateFormats[$format])) {
...@@ -498,7 +519,7 @@ class Formatter extends Component ...@@ -498,7 +519,7 @@ class Formatter extends Component
} }
return $formatter->format($value); return $formatter->format($value);
} else { } else {
if (strpos($format, 'php:') === 0) { if (strncmp($format, 'php:', 4) === 0) {
$format = substr($format, 4); $format = substr($format, 4);
} else { } else {
$format = FormatConverter::convertDateIcuToPhp($format, $type, $this->locale); $format = FormatConverter::convertDateIcuToPhp($format, $type, $this->locale);
......
...@@ -7,23 +7,52 @@ ...@@ -7,23 +7,52 @@
namespace yii\validators; namespace yii\validators;
use IntlDateFormatter;
use Yii; use Yii;
use DateTime; use DateTime;
use yii\helpers\FormatConverter;
/** /**
* DateValidator verifies if the attribute represents a date, time or datetime in a proper format. * DateValidator verifies if the attribute represents a date, time or datetime in a proper format.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0 * @since 2.0
*/ */
class DateValidator extends Validator class DateValidator extends Validator
{ {
/** /**
* @var string the date format that the value being validated should follow. * @var string the date format that the value being validated should follow.
* Please refer to <http://www.php.net/manual/en/datetime.createfromformat.php> on * 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).
* supported formats. *
* Alternatively this can be a string prefixed with `php:` representing a format that can be recognized by the PHP Datetime class.
* Please refer to <http://php.net/manual/en/datetime.createfromformat.php> on supported formats.
*
* If this property is not set, the default value will be obtained from `Yii::$app->formatter->dateFormat`, see [[\yii\i18n\Formatter::dateFormat]] for details.
*
* Here are some example values:
*
* ```php
* 'MM/dd/yyyy' // date in ICU format
* 'php:m/d/Y' // the same date in PHP format
* ```
*/ */
public $format = 'Y-m-d'; public $format;
/**
* @var string the locale ID that is used to localize the date parsing.
* This is only effective when the [PHP intl extension](http://php.net/manual/en/book.intl.php) is installed.
* If not set, the locale of the [[\yii\base\Application::formatter|formatter]] will be used.
* See also [[\yii\i18n\Formatter::locale]].
*/
public $locale;
/**
* @var string the timezone to use for parsing date and time values.
* This can be any value that may be passed to [date_default_timezone_set()](http://www.php.net/manual/en/function.date-default-timezone-set.php)
* e.g. `UTC`, `Europe/Berlin` or `America/Chicago`.
* Refer to the [php manual](http://www.php.net/manual/en/timezones.php) for available timezones.
* If this property is not set, [[\yii\base\Application::timeZone]] will be used.
*/
public $timeZone;
/** /**
* @var string the name of the attribute to receive the parsing result. * @var string the name of the attribute to receive the parsing result.
* When this property is not null and the validation is successful, the named attribute will * When this property is not null and the validation is successful, the named attribute will
...@@ -31,6 +60,16 @@ class DateValidator extends Validator ...@@ -31,6 +60,16 @@ class DateValidator extends Validator
*/ */
public $timestampAttribute; public $timestampAttribute;
/**
* @var array map of short format names to IntlDateFormatter constant values.
*/
private $_dateFormats = [
'short' => 3, // IntlDateFormatter::SHORT,
'medium' => 2, // IntlDateFormatter::MEDIUM,
'long' => 1, // IntlDateFormatter::LONG,
'full' => 0, // IntlDateFormatter::FULL,
];
/** /**
* @inheritdoc * @inheritdoc
...@@ -41,6 +80,15 @@ class DateValidator extends Validator ...@@ -41,6 +80,15 @@ class DateValidator extends Validator
if ($this->message === null) { if ($this->message === null) {
$this->message = Yii::t('yii', 'The format of {attribute} is invalid.'); $this->message = Yii::t('yii', 'The format of {attribute} is invalid.');
} }
if ($this->format === null) {
$this->format = Yii::$app->formatter->dateFormat;
}
if ($this->locale === null) {
$this->locale = Yii::$app->language;
}
if ($this->timeZone === null) {
$this->timeZone = Yii::$app->timeZone;
}
} }
/** /**
...@@ -49,12 +97,11 @@ class DateValidator extends Validator ...@@ -49,12 +97,11 @@ class DateValidator extends Validator
public function validateAttribute($object, $attribute) public function validateAttribute($object, $attribute)
{ {
$value = $object->$attribute; $value = $object->$attribute;
$result = $this->validateValue($value); $timestamp = $this->parseDateValue($value);
if (!empty($result)) { if ($timestamp === false) {
$this->addError($object, $attribute, $result[0], $result[1]); $this->addError($object, $attribute, $this->message, []);
} elseif ($this->timestampAttribute !== null) { } elseif ($this->timestampAttribute !== null) {
$date = DateTime::createFromFormat($this->format, $value); $object->{$this->timestampAttribute} = $timestamp;
$object->{$this->timestampAttribute} = $date->getTimestamp();
} }
} }
...@@ -63,13 +110,42 @@ class DateValidator extends Validator ...@@ -63,13 +110,42 @@ class DateValidator extends Validator
*/ */
protected function validateValue($value) protected function validateValue($value)
{ {
return $this->parseDateValue($value) === false ? [$this->message, []] : null;
}
protected function parseDateValue($value)
{
if (is_array($value)) { if (is_array($value)) {
return [$this->message, []]; return false;
}
$format = $this->format;
if (strncmp($this->format, 'php:', 4) === 0) {
$format = substr($format, 4);
} else {
if (extension_loaded('intl')) {
if (isset($this->_dateFormats[$format])) {
$formatter = new IntlDateFormatter($this->locale, $this->_dateFormats[$format], IntlDateFormatter::NONE, $this->timeZone);
} else {
$formatter = new IntlDateFormatter($this->locale, IntlDateFormatter::NONE, IntlDateFormatter::NONE, $this->timeZone, null, $format);
}
// enable strict parsing to avoid getting invalid date values
$formatter->setLenient(false);
return $formatter->parse($value);
} else {
// fallback to PHP if intl is not installed
$format = FormatConverter::convertDateIcuToPhp($format, 'date');
}
} }
$date = DateTime::createFromFormat($this->format, $value); $date = DateTime::createFromFormat($format, $value, new \DateTimeZone($this->timeZone));
$errors = DateTime::getLastErrors(); $errors = DateTime::getLastErrors();
$invalid = $date === false || $errors['error_count'] || $errors['warning_count']; if ($date === false || $errors['error_count'] || $errors['warning_count']) {
return false;
return $invalid ? [$this->message, []] : null; } else {
// if no time was provided in the format string set time to 0 to get a simple date timestamp
if (strpbrk($format, 'HhGgis') === false) {
$date->setTime(0, 0, 0);
}
return $date->getTimestamp();
}
} }
} }
<?php <?php
// override information about intl namespace yiiunit\framework\helpers;
namespace yii\helpers {
use yiiunit\framework\i18n\FormatterTest;
if (!function_exists('yii\helpers\extension_loaded')) {
function extension_loaded($name)
{
if ($name === 'intl' && FormatterTest::$enableIntl !== null) {
return FormatterTest::$enableIntl;
}
return \extension_loaded($name);
}
}
}
namespace yiiunit\framework\helpers {
use Yii; use Yii;
use yii\helpers\FormatConverter; use yii\helpers\FormatConverter;
use yii\i18n\Formatter; use yii\i18n\Formatter;
use yiiunit\framework\i18n\FormatterTest; use yiiunit\framework\i18n\IntlTestHelper;
use yiiunit\TestCase; use yiiunit\TestCase;
/** /**
...@@ -31,17 +17,7 @@ class FormatConverterTest extends TestCase ...@@ -31,17 +17,7 @@ class FormatConverterTest extends TestCase
{ {
parent::setUp(); parent::setUp();
// emulate disabled intl extension IntlTestHelper::setIntlStatus($this);
// enable it only for tests prefixed with testIntl
FormatterTest::$enableIntl = null;
if (strncmp($this->getName(false), 'testIntl', 8) === 0) {
if (!extension_loaded('intl')) {
$this->markTestSkipped('intl extension is not installed.');
}
FormatterTest::$enableIntl = true;
} else {
FormatterTest::$enableIntl = false;
}
$this->mockApplication([ $this->mockApplication([
'timeZone' => 'UTC', 'timeZone' => 'UTC',
...@@ -52,7 +28,7 @@ class FormatConverterTest extends TestCase ...@@ -52,7 +28,7 @@ class FormatConverterTest extends TestCase
protected function tearDown() protected function tearDown()
{ {
parent::tearDown(); parent::tearDown();
FormatterTest::$enableIntl = null; IntlTestHelper::resetIntlStatus();
} }
public function testIntlIcuToPhpShortForm() public function testIntlIcuToPhpShortForm()
...@@ -75,4 +51,3 @@ class FormatConverterTest extends TestCase ...@@ -75,4 +51,3 @@ class FormatConverterTest extends TestCase
$this->assertEquals('24.8.2014', $formatter->asDate('2014-8-24', 'd.M.yyyy')); $this->assertEquals('24.8.2014', $formatter->asDate('2014-8-24', 'd.M.yyyy'));
} }
} }
}
\ No newline at end of file
<?php <?php
// override information about intl namespace yiiunit\framework\i18n;
namespace yii\helpers {
use yiiunit\framework\i18n\FormatterTest;
if (!function_exists('yii\helpers\extension_loaded')) {
function extension_loaded($name)
{
if ($name === 'intl' && FormatterTest::$enableIntl !== null) {
return FormatterTest::$enableIntl;
}
return \extension_loaded($name);
}
}
}
// override information about intl
namespace yii\i18n {
use yiiunit\framework\i18n\FormatterTest;
function extension_loaded($name)
{
if ($name === 'intl' && FormatterTest::$enableIntl !== null) {
return FormatterTest::$enableIntl;
}
return \extension_loaded($name);
}
}
namespace yiiunit\framework\i18n {
use yii\base\InvalidParamException;
use yii\i18n\Formatter; use yii\i18n\Formatter;
use yiiunit\TestCase; use yiiunit\TestCase;
use DateTime; use DateTime;
...@@ -40,8 +12,6 @@ use DateInterval; ...@@ -40,8 +12,6 @@ use DateInterval;
*/ */
class FormatterTest extends TestCase class FormatterTest extends TestCase
{ {
public static $enableIntl;
/** /**
* @var Formatter * @var Formatter
*/ */
...@@ -51,17 +21,7 @@ class FormatterTest extends TestCase ...@@ -51,17 +21,7 @@ class FormatterTest extends TestCase
{ {
parent::setUp(); parent::setUp();
// emulate disabled intl extension IntlTestHelper::setIntlStatus($this);
// enable it only for tests prefixed with testIntl
static::$enableIntl = null;
if (strncmp($this->getName(false), 'testIntl', 8) === 0) {
if (!extension_loaded('intl')) {
$this->markTestSkipped('intl extension is not installed.');
}
static::$enableIntl = true;
} else {
static::$enableIntl = false;
}
$this->mockApplication([ $this->mockApplication([
'timeZone' => 'UTC', 'timeZone' => 'UTC',
...@@ -73,7 +33,7 @@ class FormatterTest extends TestCase ...@@ -73,7 +33,7 @@ class FormatterTest extends TestCase
protected function tearDown() protected function tearDown()
{ {
parent::tearDown(); parent::tearDown();
static::$enableIntl = null; IntlTestHelper::resetIntlStatus();
$this->formatter = null; $this->formatter = null;
} }
...@@ -857,4 +817,3 @@ class FormatterTest extends TestCase ...@@ -857,4 +817,3 @@ class FormatterTest extends TestCase
$this->assertSame("1023 bytes", $this->formatter->asSize(1023)); $this->assertSame("1023 bytes", $this->formatter->asSize(1023));
} }
} }
}
<?php
// override information about intl
namespace yiiunit\framework\i18n {
use yiiunit\TestCase;
class IntlTestHelper {
public static $enableIntl;
/**
* emulate disabled intl extension
*
* enable it only for tests prefixed with testIntl
* @param Testcase $test
*/
public static function setIntlStatus($test)
{
static::$enableIntl = null;
if (strncmp($test->getName(false), 'testIntl', 8) === 0) {
if (!extension_loaded('intl')) {
$test->markTestSkipped('intl extension is not installed.');
}
static::$enableIntl = true;
} else {
static::$enableIntl = false;
}
}
public static function resetIntlStatus()
{
static::$enableIntl = null;
}
}
}
namespace yii\i18n {
use yiiunit\framework\i18n\IntlTestHelper;
if (!function_exists('yii\i18n\extension_loaded')) {
function extension_loaded($name)
{
if ($name === 'intl' && IntlTestHelper::$enableIntl !== null) {
return IntlTestHelper::$enableIntl;
}
return \extension_loaded($name);
}
}
}
namespace yii\helpers {
use yiiunit\framework\i18n\IntlTestHelper;
if (!function_exists('yii\helpers\extension_loaded')) {
function extension_loaded($name)
{
if ($name === 'intl' && IntlTestHelper::$enableIntl !== null) {
return IntlTestHelper::$enableIntl;
}
return \extension_loaded($name);
}
}
}
namespace yii\validators {
use yiiunit\framework\i18n\IntlTestHelper;
if (!function_exists('yii\validators\extension_loaded')) {
function extension_loaded($name)
{
if ($name === 'intl' && IntlTestHelper::$enableIntl !== null) {
return IntlTestHelper::$enableIntl;
}
return \extension_loaded($name);
}
}
}
...@@ -5,6 +5,7 @@ namespace yiiunit\framework\validators; ...@@ -5,6 +5,7 @@ namespace yiiunit\framework\validators;
use DateTime; use DateTime;
use yii\validators\DateValidator; use yii\validators\DateValidator;
use yiiunit\data\validators\models\FakedValidationModel; use yiiunit\data\validators\models\FakedValidationModel;
use yiiunit\framework\i18n\IntlTestHelper;
use yiiunit\TestCase; use yiiunit\TestCase;
/** /**
...@@ -15,7 +16,19 @@ class DateValidatorTest extends TestCase ...@@ -15,7 +16,19 @@ class DateValidatorTest extends TestCase
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();
$this->mockApplication();
IntlTestHelper::setIntlStatus($this);
$this->mockApplication([
'timeZone' => 'UTC',
'language' => 'ru-RU',
]);
}
protected function tearDown()
{
parent::tearDown();
IntlTestHelper::resetIntlStatus();
} }
public function testEnsureMessageIsSet() public function testEnsureMessageIsSet()
...@@ -24,26 +37,79 @@ class DateValidatorTest extends TestCase ...@@ -24,26 +37,79 @@ class DateValidatorTest extends TestCase
$this->assertTrue($val->message !== null && strlen($val->message) > 1); $this->assertTrue($val->message !== null && strlen($val->message) > 1);
} }
public function testIntlValidateValue()
{
$this->testValidateValue();
$this->mockApplication([
'language' => 'en-GB',
'components' => [
'formatter' => [
'dateFormat' => 'short',
]
]
]);
$val = new DateValidator();
$this->assertTrue($val->validate('31/5/2017'));
$this->assertFalse($val->validate('5/31/2017'));
$val = new DateValidator(['format' => 'short', 'locale' => 'en-GB']);
$this->assertTrue($val->validate('31/5/2017'));
$this->assertFalse($val->validate('5/31/2017'));
$this->mockApplication([
'language' => 'de-DE',
'components' => [
'formatter' => [
'dateFormat' => 'short',
]
]
]);
$val = new DateValidator();
$this->assertTrue($val->validate('31.5.2017'));
$this->assertFalse($val->validate('5.31.2017'));
$val = new DateValidator(['format' => 'short', 'locale' => 'de-DE']);
$this->assertTrue($val->validate('31.5.2017'));
$this->assertFalse($val->validate('5.31.2017'));
}
public function testValidateValue() public function testValidateValue()
{ {
$val = new DateValidator; // test PHP format
$val = new DateValidator(['format' => 'php:Y-m-d']);
$this->assertFalse($val->validate('3232-32-32')); $this->assertFalse($val->validate('3232-32-32'));
$this->assertTrue($val->validate('2013-09-13')); $this->assertTrue($val->validate('2013-09-13'));
$this->assertFalse($val->validate('31.7.2013')); $this->assertFalse($val->validate('31.7.2013'));
$this->assertFalse($val->validate('31-7-2013')); $this->assertFalse($val->validate('31-7-2013'));
$this->assertFalse($val->validate(time())); $this->assertFalse($val->validate(time()));
$val->format = 'U'; $val->format = 'php:U';
$this->assertTrue($val->validate(time())); $this->assertTrue($val->validate(time()));
$val->format = 'd.m.Y'; $val->format = 'php:d.m.Y';
$this->assertTrue($val->validate('31.7.2013'));
$val->format = 'php:Y-m-!d H:i:s';
$this->assertTrue($val->validate('2009-02-15 15:16:17'));
// test ICU format
$val = new DateValidator(['format' => 'yyyy-MM-dd']);
$this->assertFalse($val->validate('3232-32-32'));
$this->assertTrue($val->validate('2013-09-13'));
$this->assertFalse($val->validate('31.7.2013'));
$this->assertFalse($val->validate('31-7-2013'));
$this->assertFalse($val->validate(time()));
$val->format = 'dd.MM.yyyy';
$this->assertTrue($val->validate('31.7.2013')); $this->assertTrue($val->validate('31.7.2013'));
$val->format = 'Y-m-!d H:i:s'; $val->format = 'yyyy-MM-dd HH:mm:ss';
$this->assertTrue($val->validate('2009-02-15 15:16:17')); $this->assertTrue($val->validate('2009-02-15 15:16:17'));
} }
public function testValidateAttribute() public function testIntlValidateAttributePHP()
{
$this->testValidateAttributePHPFormat();
}
public function testValidateAttributePHPFormat()
{ {
// error-array-add // error-array-add
$val = new DateValidator; $val = new DateValidator(['format' => 'php:Y-m-d']);
$model = new FakedValidationModel; $model = new FakedValidationModel;
$model->attr_date = '2013-09-13'; $model->attr_date = '2013-09-13';
$val->validateAttribute($model, 'attr_date'); $val->validateAttribute($model, 'attr_date');
...@@ -53,7 +119,7 @@ class DateValidatorTest extends TestCase ...@@ -53,7 +119,7 @@ class DateValidatorTest extends TestCase
$val->validateAttribute($model, 'attr_date'); $val->validateAttribute($model, 'attr_date');
$this->assertTrue($model->hasErrors('attr_date')); $this->assertTrue($model->hasErrors('attr_date'));
//// timestamp attribute //// timestamp attribute
$val = new DateValidator(['timestampAttribute' => 'attr_timestamp']); $val = new DateValidator(['format' => 'php:Y-m-d', 'timestampAttribute' => 'attr_timestamp']);
$model = new FakedValidationModel; $model = new FakedValidationModel;
$model->attr_date = '2013-09-13'; $model->attr_date = '2013-09-13';
$model->attr_timestamp = true; $model->attr_timestamp = true;
...@@ -61,10 +127,48 @@ class DateValidatorTest extends TestCase ...@@ -61,10 +127,48 @@ class DateValidatorTest extends TestCase
$this->assertFalse($model->hasErrors('attr_date')); $this->assertFalse($model->hasErrors('attr_date'));
$this->assertFalse($model->hasErrors('attr_timestamp')); $this->assertFalse($model->hasErrors('attr_timestamp'));
$this->assertEquals( $this->assertEquals(
DateTime::createFromFormat($val->format, '2013-09-13')->getTimestamp(), mktime(0, 0, 0, 9, 13, 2013), // 2013-09-13
// DateTime::createFromFormat('Y-m-d', '2013-09-13')->getTimestamp(),
$model->attr_timestamp $model->attr_timestamp
); );
$val = new DateValidator(); $val = new DateValidator(['format' => 'php:Y-m-d']);
$model = FakedValidationModel::createWithAttributes(['attr_date' => []]);
$val->validateAttribute($model, 'attr_date');
$this->assertTrue($model->hasErrors('attr_date'));
}
public function testIntlValidateAttributeICU()
{
$this->testValidateAttributeICUFormat();
}
public function testValidateAttributeICUFormat()
{
// error-array-add
$val = new DateValidator(['format' => 'yyyy-MM-dd']);
$model = new FakedValidationModel;
$model->attr_date = '2013-09-13';
$val->validateAttribute($model, 'attr_date');
$this->assertFalse($model->hasErrors('attr_date'));
$model = new FakedValidationModel;
$model->attr_date = '1375293913';
$val->validateAttribute($model, 'attr_date');
$this->assertTrue($model->hasErrors('attr_date'));
//// timestamp attribute
$val = new DateValidator(['format' => 'yyyy-MM-dd', 'timestampAttribute' => 'attr_timestamp']);
$model = new FakedValidationModel;
$model->attr_date = '2013-09-13';
$model->attr_timestamp = true;
$val->validateAttribute($model, 'attr_date');
$this->assertFalse($model->hasErrors('attr_date'));
$this->assertFalse($model->hasErrors('attr_timestamp'));
$this->assertEquals(
mktime(0, 0, 0, 9, 13, 2013), // 2013-09-13
// DateTime::createFromFormat('Y-m-d', '2013-09-13')->getTimestamp(),
$model->attr_timestamp
);
$val = new DateValidator(['format' => 'yyyy-MM-dd']);
$model = FakedValidationModel::createWithAttributes(['attr_date' => []]); $model = FakedValidationModel::createWithAttributes(['attr_date' => []]);
$val->validateAttribute($model, 'attr_date'); $val->validateAttribute($model, 'attr_date');
$this->assertTrue($model->hasErrors('attr_date')); $this->assertTrue($model->hasErrors('attr_date'));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment