Framework: Get DateTimePicker's value as timestamp and add input validation
refs #4440
This commit is contained in:
parent
a82d750d6a
commit
ba00fd39df
|
@ -28,7 +28,11 @@
|
|||
|
||||
namespace Icinga\Web\Form\Element;
|
||||
|
||||
use \DateTime;
|
||||
use \DateTimeZone;
|
||||
use \Exception;
|
||||
use Zend_Form_Element_Xhtml;
|
||||
use Icinga\Application\Icinga;
|
||||
|
||||
/**
|
||||
* Datetime form element
|
||||
|
@ -40,4 +44,112 @@ class DateTimePicker extends Zend_Form_Element_Xhtml
|
|||
* @var string
|
||||
*/
|
||||
public $helper = 'formDateTime';
|
||||
|
||||
/**
|
||||
* Time zone
|
||||
* @var mixed
|
||||
*/
|
||||
private $timeZone;
|
||||
|
||||
/**
|
||||
* Getter for the time zone
|
||||
*
|
||||
* If the time zone has never been set, the user's time zone is returned
|
||||
*
|
||||
* @return DateTimeZone
|
||||
* @see setTimeZone()
|
||||
*/
|
||||
public function getTimeZone()
|
||||
{
|
||||
$timeZone = $this->timeZone;
|
||||
if ($timeZone === null) {
|
||||
$timeZone = Icinga::app()->getFrontController()->getRequest()->getUser()->getTimeZone();
|
||||
}
|
||||
return $timeZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the time zone
|
||||
*
|
||||
* @param DateTimeZone $timeZone
|
||||
* @return self
|
||||
*/
|
||||
public function setTimeZone(DateTimeZone $timeZone)
|
||||
{
|
||||
$this->timeZone = $timeZone;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds whether a variable is a Unix timestamp
|
||||
*
|
||||
* @param mixed $timestamp
|
||||
* @return bool
|
||||
*/
|
||||
public function isUnixTimestamp($timestamp)
|
||||
{
|
||||
return ((string) (int) $timestamp === (string) $timestamp)
|
||||
&& ($timestamp <= PHP_INT_MAX)
|
||||
&& ($timestamp >= ~PHP_INT_MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve element value as unix timestamp respecting the user's timezone
|
||||
*
|
||||
* @param mixed $timeZone
|
||||
* @return int
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
$valueFiltered = parent::getValue();
|
||||
if ($this->isUnixTimestamp($valueFiltered)) {
|
||||
// Using the Unix timestamp format to construct a new DateTime
|
||||
$valueFiltered = '@' . $valueFiltered;
|
||||
}
|
||||
$dt = new DateTime($valueFiltered, $this->getTimeZone());
|
||||
return $dt->getTimestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate filtered date/time strings
|
||||
*
|
||||
* Expects formats that the php date parser understands
|
||||
*
|
||||
* @param string $value
|
||||
* @param mixed $context
|
||||
* @return bool
|
||||
* @see DateTime::__construct()
|
||||
*/
|
||||
public function isValid($value, $context = null)
|
||||
{
|
||||
if (!parent::isValid(parent::getValue(), $context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_string($value) && !is_int($value)) {
|
||||
$this->addErrorMessage(
|
||||
_('Invalid type given. Date/time string or Unix timestamp expected')
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->isUnixTimestamp($value)) {
|
||||
// Using the Unix timestamp format to construct a new DateTime
|
||||
$value = '@' . $value;
|
||||
}
|
||||
|
||||
try {
|
||||
new DateTime($value);
|
||||
} catch (Exception $e) {
|
||||
$this->addErrorMessage(
|
||||
_(
|
||||
'Failed to parse datetime string. See '
|
||||
. 'http://www.php.net/manual/en/datetime.formats.php for valid formats'
|
||||
)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
namespace Test\Icinga\Web\Form\Element;
|
||||
|
||||
require_once 'Zend/Form/Element/Xhtml.php';
|
||||
require_once __DIR__ . '/../../../../../../../library/Icinga/Application/Icinga.php';
|
||||
require_once __DIR__ . '/../../../../../../../library/Icinga/Web/Form/Element/DateTimePicker.php';
|
||||
|
||||
use \DateTimeZone;
|
||||
use Icinga\Web\Form\Element\DateTimePicker;
|
||||
|
||||
class DateTimeTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
// Set default timezone else new DateTime calls will die with the Exception that it's
|
||||
// not safe to rely on the system's timezone
|
||||
date_default_timezone_set('UTC');
|
||||
}
|
||||
|
||||
public function testValidateInvalidInput()
|
||||
{
|
||||
$dt = new DateTimePicker('foo');
|
||||
// Set element's timezone else it'll try to load the time zone from the user
|
||||
// which requires Icinga::app() to be bootstrapped which is not the case
|
||||
// within tests - so without a ProgrammingError will be thrown
|
||||
$dt->setTimeZone(new DateTimeZone('UTC'));
|
||||
|
||||
$this->assertFalse(
|
||||
$dt->isValid('bar'),
|
||||
'Arbitrary strings must not be valid input'
|
||||
);
|
||||
$this->assertFalse(
|
||||
$dt->isValid('13736a16223'),
|
||||
'Invalid Unix timestamps must not be valid input'
|
||||
);
|
||||
}
|
||||
|
||||
public function testValidateValidInput()
|
||||
{
|
||||
$dt = new DateTimePicker('foo');
|
||||
$dt->setTimeZone(new DateTimeZone('UTC'));
|
||||
|
||||
$this->assertTrue(
|
||||
$dt->isValid('2013-07-12 08:03:43'),
|
||||
'Using a valid date/time string must not fail'
|
||||
);
|
||||
$this->assertTrue(
|
||||
$dt->isValid('@' . 1373616223),
|
||||
'Using the Unix timestamp format must not fail'
|
||||
);
|
||||
$this->assertTrue(
|
||||
$dt->isValid(1373616223),
|
||||
'Using valid Unix timestamps must not fail'
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetValueReturnsUnixTimestamp()
|
||||
{
|
||||
$dt = new DateTimePicker('foo');
|
||||
$dt->setTimeZone(new DateTimeZone('UTC'))
|
||||
->setValue('2013-07-12 08:03:43');
|
||||
|
||||
$this->assertEquals(
|
||||
$dt->getValue(),
|
||||
1373616223,
|
||||
'getValue did not return the correct Unix timestamp according to the given date/time '
|
||||
. 'string'
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetValueIsTimeZoneAware()
|
||||
{
|
||||
$dt = new DateTimePicker('foo');
|
||||
$dt->setTimeZone(new DateTimeZone('Europe/Berlin'))
|
||||
->setValue('2013-07-12 08:03:43');
|
||||
|
||||
$this->assertEquals(
|
||||
$dt->getValue(),
|
||||
1373609023,
|
||||
'getValue did not return the correct Unix timestamp according to the given date/time '
|
||||
. 'string'
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue