silverstripe-framework/src/Forms/TimeField.php

267 lines
7.2 KiB
PHP
Raw Normal View History

<?php
namespace SilverStripe\Forms;
use SilverStripe\Core\Convert;
use SilverStripe\i18n\i18n;
use Zend_Date;
FEATURE New DatetimeField class (form field wrapper composed of DateField andTimeField) FEATURE New DateField and TimeField form classes with more consistent API and easier localization API CHANGE Date/time parsing in DateField, TimeField and DatetimeField defaults to i18n::get_locale() ('en_US') instead of using en_NZ/en_GB specific parsing. Use i18n::set_locale('en_NZ') in mysite/_config.php to revert to old behaviour. API CHANGE constructor parameter in TimeField needs to be in ISO date notation (not PHP's date()) API CHANGE TimeField, DateField and related subclasses use Zend_Date for date parsing, meaning they're stricer than the previously used strtotime() API CHANGE Removed DMYCalendarDateField and CalendarDateField, use DateField with setConfig('showcalendar') API CHANGE Removed CompositeDateField, DMYDateField, use DateField with setConfig('dmyfields') API CHANGE Removed DropdownTimeField, use TimeField with setConfig('showdropdown') API CHANGE Removed PopupDateTimeField, use DatetimeField API CHANGE Changed 'date', 'month' and 'year' HTML field names to lowercase in DMYDateField API CHANGE Removed support for ambiguous date formats in DateField, e.g. '06/03/03'. Use DateField->setConfig('dateformat', '<format>') to revert to this behaviour. API CHANGE Removed flag from DateField, CalendarDateField etc., use DateField->setConfig('min') and DateField->setConfig('max') ENHANCEMENT Using Zend_Date for DateField and TimeField, with more robust date handling, starting localization support. Set globally via i18n::set_locale(), or for a field instance through setLocale(). Note: Javascript validation is not localized yet. (from r99360) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@102859 467b73ca-7a2a-4603-9d3b-597d59a354a9
2010-04-14 06:38:40 +02:00
require_once 'Zend/Date.php';
/**
2014-08-15 08:53:05 +02:00
* Form field to display editable time values in an <input type="text"> field.
*
FEATURE New DatetimeField class (form field wrapper composed of DateField andTimeField) FEATURE New DateField and TimeField form classes with more consistent API and easier localization API CHANGE Date/time parsing in DateField, TimeField and DatetimeField defaults to i18n::get_locale() ('en_US') instead of using en_NZ/en_GB specific parsing. Use i18n::set_locale('en_NZ') in mysite/_config.php to revert to old behaviour. API CHANGE constructor parameter in TimeField needs to be in ISO date notation (not PHP's date()) API CHANGE TimeField, DateField and related subclasses use Zend_Date for date parsing, meaning they're stricer than the previously used strtotime() API CHANGE Removed DMYCalendarDateField and CalendarDateField, use DateField with setConfig('showcalendar') API CHANGE Removed CompositeDateField, DMYDateField, use DateField with setConfig('dmyfields') API CHANGE Removed DropdownTimeField, use TimeField with setConfig('showdropdown') API CHANGE Removed PopupDateTimeField, use DatetimeField API CHANGE Changed 'date', 'month' and 'year' HTML field names to lowercase in DMYDateField API CHANGE Removed support for ambiguous date formats in DateField, e.g. '06/03/03'. Use DateField->setConfig('dateformat', '<format>') to revert to this behaviour. API CHANGE Removed flag from DateField, CalendarDateField etc., use DateField->setConfig('min') and DateField->setConfig('max') ENHANCEMENT Using Zend_Date for DateField and TimeField, with more robust date handling, starting localization support. Set globally via i18n::set_locale(), or for a field instance through setLocale(). Note: Javascript validation is not localized yet. (from r99360) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@102859 467b73ca-7a2a-4603-9d3b-597d59a354a9
2010-04-14 06:38:40 +02:00
* # Configuration
2014-08-15 08:53:05 +02:00
*
FEATURE New DatetimeField class (form field wrapper composed of DateField andTimeField) FEATURE New DateField and TimeField form classes with more consistent API and easier localization API CHANGE Date/time parsing in DateField, TimeField and DatetimeField defaults to i18n::get_locale() ('en_US') instead of using en_NZ/en_GB specific parsing. Use i18n::set_locale('en_NZ') in mysite/_config.php to revert to old behaviour. API CHANGE constructor parameter in TimeField needs to be in ISO date notation (not PHP's date()) API CHANGE TimeField, DateField and related subclasses use Zend_Date for date parsing, meaning they're stricer than the previously used strtotime() API CHANGE Removed DMYCalendarDateField and CalendarDateField, use DateField with setConfig('showcalendar') API CHANGE Removed CompositeDateField, DMYDateField, use DateField with setConfig('dmyfields') API CHANGE Removed DropdownTimeField, use TimeField with setConfig('showdropdown') API CHANGE Removed PopupDateTimeField, use DatetimeField API CHANGE Changed 'date', 'month' and 'year' HTML field names to lowercase in DMYDateField API CHANGE Removed support for ambiguous date formats in DateField, e.g. '06/03/03'. Use DateField->setConfig('dateformat', '<format>') to revert to this behaviour. API CHANGE Removed flag from DateField, CalendarDateField etc., use DateField->setConfig('min') and DateField->setConfig('max') ENHANCEMENT Using Zend_Date for DateField and TimeField, with more robust date handling, starting localization support. Set globally via i18n::set_locale(), or for a field instance through setLocale(). Note: Javascript validation is not localized yet. (from r99360) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@102859 467b73ca-7a2a-4603-9d3b-597d59a354a9
2010-04-14 06:38:40 +02:00
* - 'timeformat' (string): Time format compatible with Zend_Date.
* Usually set to default format for {@link locale}
* through {@link Zend_Locale_Format::getTimeFormat()}.
* - 'use_strtotime' (boolean): Accept values in PHP's built-in strtotime() notation, in addition
* to the format specified in `timeformat`. Example inputs: 'now', '11pm', '23:59:59'.
2014-08-15 08:53:05 +02:00
*
FEATURE New DatetimeField class (form field wrapper composed of DateField andTimeField) FEATURE New DateField and TimeField form classes with more consistent API and easier localization API CHANGE Date/time parsing in DateField, TimeField and DatetimeField defaults to i18n::get_locale() ('en_US') instead of using en_NZ/en_GB specific parsing. Use i18n::set_locale('en_NZ') in mysite/_config.php to revert to old behaviour. API CHANGE constructor parameter in TimeField needs to be in ISO date notation (not PHP's date()) API CHANGE TimeField, DateField and related subclasses use Zend_Date for date parsing, meaning they're stricer than the previously used strtotime() API CHANGE Removed DMYCalendarDateField and CalendarDateField, use DateField with setConfig('showcalendar') API CHANGE Removed CompositeDateField, DMYDateField, use DateField with setConfig('dmyfields') API CHANGE Removed DropdownTimeField, use TimeField with setConfig('showdropdown') API CHANGE Removed PopupDateTimeField, use DatetimeField API CHANGE Changed 'date', 'month' and 'year' HTML field names to lowercase in DMYDateField API CHANGE Removed support for ambiguous date formats in DateField, e.g. '06/03/03'. Use DateField->setConfig('dateformat', '<format>') to revert to this behaviour. API CHANGE Removed flag from DateField, CalendarDateField etc., use DateField->setConfig('min') and DateField->setConfig('max') ENHANCEMENT Using Zend_Date for DateField and TimeField, with more robust date handling, starting localization support. Set globally via i18n::set_locale(), or for a field instance through setLocale(). Note: Javascript validation is not localized yet. (from r99360) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@102859 467b73ca-7a2a-4603-9d3b-597d59a354a9
2010-04-14 06:38:40 +02:00
* # Localization
2014-08-15 08:53:05 +02:00
*
FEATURE New DatetimeField class (form field wrapper composed of DateField andTimeField) FEATURE New DateField and TimeField form classes with more consistent API and easier localization API CHANGE Date/time parsing in DateField, TimeField and DatetimeField defaults to i18n::get_locale() ('en_US') instead of using en_NZ/en_GB specific parsing. Use i18n::set_locale('en_NZ') in mysite/_config.php to revert to old behaviour. API CHANGE constructor parameter in TimeField needs to be in ISO date notation (not PHP's date()) API CHANGE TimeField, DateField and related subclasses use Zend_Date for date parsing, meaning they're stricer than the previously used strtotime() API CHANGE Removed DMYCalendarDateField and CalendarDateField, use DateField with setConfig('showcalendar') API CHANGE Removed CompositeDateField, DMYDateField, use DateField with setConfig('dmyfields') API CHANGE Removed DropdownTimeField, use TimeField with setConfig('showdropdown') API CHANGE Removed PopupDateTimeField, use DatetimeField API CHANGE Changed 'date', 'month' and 'year' HTML field names to lowercase in DMYDateField API CHANGE Removed support for ambiguous date formats in DateField, e.g. '06/03/03'. Use DateField->setConfig('dateformat', '<format>') to revert to this behaviour. API CHANGE Removed flag from DateField, CalendarDateField etc., use DateField->setConfig('min') and DateField->setConfig('max') ENHANCEMENT Using Zend_Date for DateField and TimeField, with more robust date handling, starting localization support. Set globally via i18n::set_locale(), or for a field instance through setLocale(). Note: Javascript validation is not localized yet. (from r99360) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@102859 467b73ca-7a2a-4603-9d3b-597d59a354a9
2010-04-14 06:38:40 +02:00
* See {@link DateField}
2014-08-15 08:53:05 +02:00
*
FEATURE New DatetimeField class (form field wrapper composed of DateField andTimeField) FEATURE New DateField and TimeField form classes with more consistent API and easier localization API CHANGE Date/time parsing in DateField, TimeField and DatetimeField defaults to i18n::get_locale() ('en_US') instead of using en_NZ/en_GB specific parsing. Use i18n::set_locale('en_NZ') in mysite/_config.php to revert to old behaviour. API CHANGE constructor parameter in TimeField needs to be in ISO date notation (not PHP's date()) API CHANGE TimeField, DateField and related subclasses use Zend_Date for date parsing, meaning they're stricer than the previously used strtotime() API CHANGE Removed DMYCalendarDateField and CalendarDateField, use DateField with setConfig('showcalendar') API CHANGE Removed CompositeDateField, DMYDateField, use DateField with setConfig('dmyfields') API CHANGE Removed DropdownTimeField, use TimeField with setConfig('showdropdown') API CHANGE Removed PopupDateTimeField, use DatetimeField API CHANGE Changed 'date', 'month' and 'year' HTML field names to lowercase in DMYDateField API CHANGE Removed support for ambiguous date formats in DateField, e.g. '06/03/03'. Use DateField->setConfig('dateformat', '<format>') to revert to this behaviour. API CHANGE Removed flag from DateField, CalendarDateField etc., use DateField->setConfig('min') and DateField->setConfig('max') ENHANCEMENT Using Zend_Date for DateField and TimeField, with more robust date handling, starting localization support. Set globally via i18n::set_locale(), or for a field instance through setLocale(). Note: Javascript validation is not localized yet. (from r99360) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@102859 467b73ca-7a2a-4603-9d3b-597d59a354a9
2010-04-14 06:38:40 +02:00
* @todo Timezone support
*/
2016-11-29 00:31:16 +01:00
class TimeField extends TextField
{
/**
* @config
* @var array
*/
private static $default_config = array(
'timeformat' => null,
'use_strtotime' => true,
'datavalueformat' => 'HH:mm:ss'
);
/**
* @var array
*/
protected $config;
/**
* @var String
*/
protected $locale = null;
/**
* @var Zend_Date Just set if the date is valid.
* {@link $value} will always be set to aid validation,
* and might contain invalid values.
*/
protected $valueObj = null;
protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_TIME;
public function __construct($name, $title = null, $value = "")
{
if (!$this->locale) {
$this->locale = i18n::get_locale();
}
$this->config = $this->config()->default_config;
if (!$this->getConfig('timeformat')) {
$this->setConfig('timeformat', i18n::config()->get('time_format'));
}
parent::__construct($name, $title, $value);
}
public function Field($properties = array())
{
$config = array(
'timeformat' => $this->getConfig('timeformat')
);
$config = array_filter($config);
$this->addExtraClass(Convert::raw2json($config));
return parent::Field($properties);
}
public function Type()
{
return 'time text';
}
/**
* Parses a time into a Zend_Date object
*
* @param string $value Raw value
* @param string $format Format string to check against
* @param string $locale Optional locale to parse against
* @param boolean $exactMatch Flag indicating that the date must be in this
* exact format, and is unchanged after being parsed and written out
*
* @return Zend_Date Returns the Zend_Date, or null if not in the specified format
*/
protected function parseTime($value, $format, $locale = null, $exactMatch = false)
{
// Check if the date is in the correct format
if (!Zend_Date::isDate($value, $format)) {
return null;
}
// Parse the value
$valueObject = new Zend_Date($value, $format, $locale);
// For exact matches, ensure the value preserves formatting after conversion
if ($exactMatch && ($value !== $valueObject->get($format))) {
return null;
} else {
return $valueObject;
}
}
/**
* Sets the internal value to ISO date format.
*
* @param mixed $val
* @return $this
*/
public function setValue($val)
{
// Fuzzy matching through strtotime() to support a wider range of times,
// e.g. 11am. This means that validate() might not fire.
// Note: Time formats are assumed to be less ambiguous than dates across locales.
if ($this->getConfig('use_strtotime') && !empty($val)) {
if ($parsedTimestamp = strtotime($val)) {
$parsedObj = new Zend_Date($parsedTimestamp, Zend_Date::TIMESTAMP);
$val = $parsedObj->get($this->getConfig('timeformat'));
unset($parsedObj);
}
}
if (empty($val)) {
$this->value = null;
$this->valueObj = null;
} // load ISO time from database (usually through Form->loadDataForm())
// Requires exact format to prevent false positives from locale specific times
elseif ($this->valueObj = $this->parseTime($val, $this->getConfig('datavalueformat'), null, true)) {
$this->value = $this->valueObj->get($this->getConfig('timeformat'));
} // Set in current locale (as string)
elseif ($this->valueObj = $this->parseTime($val, $this->getConfig('timeformat'), $this->locale)) {
$this->value = $this->valueObj->get($this->getConfig('timeformat'));
} // Fallback: Set incorrect value so validate() can pick it up
elseif (is_string($val)) {
$this->value = $val;
$this->valueObj = null;
} else {
$this->value = null;
$this->valueObj = null;
}
return $this;
}
/**
* @return String ISO 8601 date, suitable for insertion into database
*/
public function dataValue()
{
if ($this->valueObj) {
return $this->valueObj->toString($this->getConfig('datavalueformat'));
} else {
return null;
}
}
/**
* Validate this field
*
* @param Validator $validator
* @return bool
*/
public function validate($validator)
{
// Don't validate empty fields
if (empty($this->value)) {
return true;
}
if (!Zend_Date::isDate($this->value, $this->getConfig('timeformat'), $this->locale)) {
$validator->validationError(
$this->name,
_t(
'TimeField.VALIDATEFORMAT',
"Please enter a valid time format ({format})",
array('format' => $this->getConfig('timeformat'))
),
"validation"
);
return false;
}
return true;
}
/**
* @return string
*/
public function getLocale()
{
return $this->locale;
}
/**
* @param string $locale
* @return $this
*/
public function setLocale($locale)
{
$this->locale = $locale;
return $this;
}
/**
* @param string $name
* @param mixed $val
* @return $this
*/
public function setConfig($name, $val)
{
$this->config[$name] = $val;
return $this;
}
/**
* @param String $name Optional, returns the whole configuration array if empty
* @return mixed|array
*/
public function getConfig($name = null)
{
if ($name) {
return isset($this->config[$name]) ? $this->config[$name] : null;
} else {
return $this->config;
}
}
/**
* Creates a new readonly field specified below
*/
public function performReadonlyTransformation()
{
return $this->castedCopy('SilverStripe\\Forms\\TimeField_Readonly');
}
public function castedCopy($class)
{
$copy = parent::castedCopy($class);
if ($copy->hasMethod('setConfig')) {
$config = $this->getConfig();
foreach ($config as $k => $v) {
/** @var TimeField $copy */
$copy->setConfig($k, $v);
}
}
return $copy;
}
}