Skip to content

Commit

Permalink
Merge pull request #8340 from ypnos-web/patch-4
Browse files Browse the repository at this point in the history
Add localizedTime() validation rule
  • Loading branch information
markstory committed Mar 16, 2016
2 parents 7e19725 + 866a469 commit 1c1320d
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 0 deletions.
28 changes: 28 additions & 0 deletions src/Validation/Validation.php
Expand Up @@ -14,6 +14,7 @@
*/
namespace Cake\Validation;

use Cake\I18n\Time;
use Cake\Utility\Text;
use DateTimeInterface;
use LogicException;
Expand Down Expand Up @@ -456,6 +457,33 @@ public static function time($check)
return static::_check($check, '%^((0?[1-9]|1[012])(:[0-5]\d){0,2} ?([AP]M|[ap]m))$|^([01]\d|2[0-3])(:[0-5]\d){0,2}$%');
}

/**
* Date and/or time string validation.
* Uses `I18n::Time` to parse the date. This means parsing is locale dependent.
*
* @param string|\DateTime $check a date string or object (will always pass)
* @param string $type Parser type, one out of 'date', 'time', and 'datetime'
* @param string|int|null $format any format accepted by IntlDateFormatter
* @return bool Success
* @throws \InvalidArgumentException when unsupported $type given
* @see \Cake\I18N\Time::parseDate(), \Cake\I18N\Time::parseTime(), \Cake\I18N\Time::parseDateTime()
*/
public static function localizedTime($check, $type = 'datetime', $format = null)
{
if ($check instanceof DateTimeInterface) {
return true;
}
static $methods = [
'date' => 'parseDate',
'time' => 'parseTime',
'datetime' => 'parseDateTime',
];
if (empty($methods[$type])) {
throw new \InvalidArgumentException('Unsupported parser type given.');
}
return (Time::{$methods[$type]}($check, $format) !== null);
}

/**
* Boolean validation, determines if value passed is a boolean integer or true/false.
*
Expand Down
19 changes: 19 additions & 0 deletions src/Validation/Validator.php
Expand Up @@ -824,6 +824,25 @@ public function time($field, $message = null, $when = null)
]);
}

/**
* Add a localized time, date or datetime format validation rule to a field.
*
* @param string $field The field you want to apply the rule to.
* @param string $type Parser type, one out of 'date', 'time', and 'datetime'
* @param string|null $message The error message when the rule fails.
* @param string|callable|null $when Either 'create' or 'update' or a callable that returns
* true when the validation rule should be applied.
* @see \Cake\Validation\Validation::localizedTime()
* @return $this
*/
public function localizedTime($field, $type = 'datetime', $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
return $this->add($field, 'localizedTime', $extra + [
'rule' => ['localizedTime', $type]
]);
}

/**
* Add a boolean validation rule to a field.
*
Expand Down
42 changes: 42 additions & 0 deletions tests/TestCase/Validation/ValidationTest.php
Expand Up @@ -16,6 +16,7 @@

use Cake\Core\Configure;
use Cake\Filesystem\File;
use Cake\I18n\I18n;
use Cake\TestSuite\TestCase;
use Cake\Validation\Validation;
use Locale;
Expand Down Expand Up @@ -900,11 +901,13 @@ public function testDateTimeObject()
$this->assertTrue(Validation::date($dateTime));
$this->assertTrue(Validation::time($dateTime));
$this->assertTrue(Validation::dateTime($dateTime));
$this->assertTrue(Validation::localizedTime($dateTime));

$dateTime = new \DateTimeImmutable();
$this->assertTrue(Validation::date($dateTime));
$this->assertTrue(Validation::time($dateTime));
$this->assertTrue(Validation::dateTime($dateTime));
$this->assertTrue(Validation::localizedTime($dateTime));
}

/**
Expand Down Expand Up @@ -1549,6 +1552,45 @@ public function testDateTimeWithMeriadian()
$this->assertFalse(Validation::dateTime('12/04/2017 58:38AM', ['dmy']));
}

/**
* Test localizedTime
*
* @return void
*/
public function testLocalizedTime()
{
$locale = I18N::locale();

$this->assertFalse(Validation::localizedTime('', 'date'));
$this->assertFalse(Validation::localizedTime('invalid', 'date'));

/* English (US) */
I18N::locale('en_US');
$this->assertTrue(Validation::localizedTime('12/31/2006', 'date'));
$this->assertTrue(Validation::localizedTime('6.40pm', 'time'));
$this->assertTrue(Validation::localizedTime('12/31/2006 6.40pm', 'datetime'));
$this->assertTrue(Validation::localizedTime('December 31, 2006', 'date'));

$this->assertFalse(Validation::localizedTime('31. Dezember 2006', 'date')); // non-US format
$this->assertFalse(Validation::localizedTime('18:40', 'time')); // non-US format

/* German */
I18N::locale('de_DE');
$this->assertTrue(Validation::localizedTime('31.12.2006', 'date'));
$this->assertTrue(Validation::localizedTime('31. Dezember 2006', 'date'));
$this->assertTrue(Validation::localizedTime('18:40', 'time'));

$this->assertFalse(Validation::localizedTime('December 31, 2006', 'date')); // non-German format

/* Russian */
I18N::locale('ru_RU');
$this->assertTrue(Validation::localizedTime('31 декабря 2006', 'date'));

$this->assertFalse(Validation::localizedTime('December 31, 2006', 'date')); // non-Russian format

I18N::locale($locale);
}


/**
* testBoolean method
Expand Down
12 changes: 12 additions & 0 deletions tests/TestCase/Validation/ValidatorTest.php
Expand Up @@ -1241,6 +1241,18 @@ public function testTime()
$this->assertNotEmpty($validator->errors(['username' => 'not a time']));
}

/**
* Tests the localizedTime proxy method
*
* @return void
*/
public function testLocalizedTime()
{
$validator = new Validator();
$this->assertProxyMethod($validator, 'localizedTime', 'date', ['date']);
$this->assertNotEmpty($validator->errors(['username' => 'not a date']));
}

/**
* Tests the boolean proxy method
*
Expand Down

0 comments on commit 1c1320d

Please sign in to comment.