silverstripe-framework/forms/TimeField.php
Ingo Schommer c945e23c62 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 $timeformat 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 $futureOnly 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.

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/branches/2.4@99360 467b73ca-7a2a-4603-9d3b-597d59a354a9
2011-02-02 14:18:38 +13:00

233 lines
5.9 KiB
PHP
Executable File

<?php
require_once 'Zend/Date.php';
/**
* Form field to display editable time values in an <input type="text">
* field. Can optionally display a dropdown with predefined time ranges
* through `setConfig('showdropdown', true)`.
*
* # Configuration
*
* - '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'.
* - 'showdropdown': Show a dropdown with suggested date values.
* CAUTION: The dropdown does not support localization.
*
* # Localization
*
* See {@link DateField}
*
* @todo Timezone support
* @todo 'showdropdown' localization
*
* @package forms
* @subpackage fields-datetime
*/
class TimeField extends TextField {
protected $config = array(
'showdropdown' => false,
'timeformat' => null,
'use_strtotime' => true,
'datavalueformat' => 'HH:mm:ss'
);
/**
* @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;
/**
* Constructor saves the format difference. Timefields shouldn't
* have a problem with length as times can only be represented in on way.
*
* @param $name string The name of the field
* @param $title string The Title of the field
* @param $value string the value for the field
* @param $timeformat string The Time format in ISO format (see Zend_Date)
*/
function __construct($name, $title = null, $value = "",$timeformat = 'HH:mm:ss'){
if($timeformat) {
$this->setConfig('timeformat', $timeformat);
} else {
$this->setConfig('timeformat', Zend_Locale_Format::getTimeFormat($this->locale));
}
parent::__construct($name,$title,$value);
}
function Field() {
$html = parent::Field();
$html = $this->FieldDriver($html);
return $html;
}
/**
* Internal volatile API.
*
* @see DateField->FieldDriver()
*/
protected function FieldDriver($html) {
if($this->getConfig('showdropdown')) {
Requirements::javascript(SAPPHIRE_DIR . '/javascript/TimeField_dropdown.js');
Requirements::css(SAPPHIRE_DIR . '/css/TimeField_dropdown.css');
$html .= sprintf('<img src="sapphire/images/clock-icon.gif" id="%s-icon"/>', $this->id());
$html .= sprintf('<div class="dropdownpopup" id="%s-dropdowntime"></div>', $this->id());
$html = '<div class="dropdowntime">' . $html . '</div>';
}
return $html;
}
/**
* Sets the internal value to ISO date format.
*
* @param String|Array $val
*/
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())
else if(Zend_Date::isDate($val, $this->getConfig('datavalueformat'))) {
$this->valueObj = new Zend_Date($val, $this->getConfig('datavalueformat'));
$this->value = $this->valueObj->get($this->getConfig('timeformat'));
}
// Set in current locale (as string)
else if(Zend_Date::isDate($val, $this->getConfig('timeformat'), $this->locale)) {
$this->valueObj = new Zend_Date($val, $this->getConfig('timeformat'), $this->locale);
$this->value = $this->valueObj->get($this->getConfig('timeformat'));
}
// Fallback: Set incorrect value so validate() can pick it up
else {
$this->value = $val;
$this->valueObj = null;
}
}
/**
* @return String ISO 8601 date, suitable for insertion into database
*/
function dataValue() {
if($this->valueObj) {
return $this->valueObj->toString($this->getConfig('datavalueformat'));
} else {
return null;
}
}
/**
* @return Boolean
*/
function validate($validator) {
$valid = true;
// 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('DateField.VALIDDATEFORMAT', "Please enter a valid time format."),
"validation",
false
);
return false;
}
return true;
}
/**
* @return string
*/
function getLocale() {
return $this->locale;
}
/**
* @param String $locale
*/
function setLocale($locale) {
$this->locale = $locale;
}
/**
* @param string $name
* @param mixed $val
*/
function setConfig($name, $val) {
$this->config[$name] = $val;
}
/**
* @param String $name
* @return mixed
*/
function getConfig($name) {
return $this->config[$name];
}
/**
* Creates a new readonly field specified below
*/
function performReadonlyTransformation() {
return new TimeField_Readonly($this->name, $this->title, $this->dataValue(), $this->getConfig('timeformat'));
}
}
/**
* The readonly class for our {@link TimeField}.
*
* @package forms
* @subpackage fields-datetime
*/
class TimeField_Readonly extends TimeField {
protected $readonly = true;
function Field() {
if($this->valueObj) {
$val = Convert::raw2xml($this->valueObj->toString($this->getConfig('timeformat')));
} else {
// TODO Localization
$val = '<i>(not set)</i>';
}
return "<span class=\"readonly\" id=\"" . $this->id() . "\">$val</span>";
}
function jsValidation() {
return null;
}
function validate($validator) {
return true;
}
}
?>