Version: current

      1 <?php
      2 require_once 'Zend/Date.php';
      3
      4 /**
      5  * Form field to display editable time values in an <input type="text">
      6  * field. Can optionally display a dropdown with predefined time ranges
      7  * through `setConfig('showdropdown', true)`.
      8  *
      9  * # Configuration
     10  *
     11  * - 'timeformat' (string): Time format compatible with Zend_Date.
     12  *    Usually set to default format for {@link locale}
     13  *    through {@link Zend_Locale_Format::getTimeFormat()}.
     14  * - 'use_strtotime' (boolean): Accept values in PHP's built-in strtotime() notation, in addition
     15  *    to the format specified in `timeformat`. Example inputs: 'now', '11pm', '23:59:59'.
     16  * - 'showdropdown': Show a dropdown with suggested date values.
     17  *    CAUTION: The dropdown does not support localization.
     18  *
     19  * # Localization
     20  *
     21  * See {@link DateField}
     22  *
     23  * @todo Timezone support
     24  * @todo 'showdropdown' localization
     25  *
     26  * @package forms
     27  * @subpackage fields-datetime
     28  */
     29 class TimeField extends TextField {
     30
     31     protected $config = array(
     32         'showdropdown' => false,
     33         'timeformat' => 'HH:mm:ss',
     34         'use_strtotime' => true,
     35         'datavalueformat' => 'HH:mm:ss'
     36     );
     37
     38     /**
     39      * @var String
     40      */
     41     protected $locale = null;
     42
     43     /**
     44      * @var Zend_Date Just set if the date is valid.
     45      * {@link $value} will always be set to aid validation,
     46      * and might contain invalid values.
     47      */
     48     protected $valueObj = null;
     49
     50     function __construct($name, $title = null, $value = ""){
     51         if(!$this->locale) {
     52             $this->locale = i18n::get_locale();
     53         }
     54
     55         if(!$this->getConfig('timeformat')) {
     56             $this->setConfig('timeformat', Zend_Locale_Format::getDateFormat($this->locale));
     57         }
     58         $this->setHTML5Attribute('type', 'time');
     59
     60         parent::__construct($name,$title,$value);
     61     }
     62     /*
     63     function Field() {
     64         $html = parent::Field();
     65         if($this->getConfig('showdropdown')) {
     66             $html = $this->customise(array(
     67                 'ShowDropdown' => true,
     68                 'HTML' => $html
     69             ))->renderWith($this->fieldTemplates());
     70         }
     71         return $html;
     72     }
     73     */
     74
     75     /**
     76      * Internal volatile API.
     77      *
     78      * @see DateField->FieldDriver()
     79      */
     80     protected function FieldDriver($html) {
     81         if($this->getConfig('showdropdown')) {
     82             Requirements::javascript(SAPPHIRE_DIR . '/javascript/TimeField_dropdown.js');
     83             Requirements::css(SAPPHIRE_DIR . '/css/TimeField_dropdown.css');
     84
     85             $html .= sprintf('<img src="sapphire/images/clock-icon.gif" id="%s-icon"/>', $this->id());
     86             $html .= sprintf('<div class="dropdownpopup" id="%s-dropdowntime"></div>', $this->id());
     87             $html = '<div class="dropdowntime">' . $html . '</div>';
     88         }
     89
     90         return $html;
     91     }
     92
     93     /**
     94      * Sets the internal value to ISO date format.
     95      *
     96      * @param String|Array $val
     97      */
     98     function setValue($val) {
     99         // Fuzzy matching through strtotime() to support a wider range of times,
    100         // e.g. 11am. This means that validate() might not fire.
    101         // Note: Time formats are assumed to be less ambiguous than dates across locales.
    102         if($this->getConfig('use_strtotime') && !empty($val)) {
    103             if($parsedTimestamp = strtotime($val)) {
    104                 $parsedObj = new Zend_Date($parsedTimestamp, Zend_Date::TIMESTAMP);
    105                 $val = $parsedObj->get($this->getConfig('timeformat'));
    106                 unset($parsedObj);
    107             }
    108         }
    109
    110         if(empty($val)) {
    111             $this->value = null;
    112             $this->valueObj = null;
    113         }
    114         // load ISO time from database (usually through Form->loadDataForm())
    115         else if(Zend_Date::isDate($val, $this->getConfig('datavalueformat'))) {
    116             $this->valueObj = new Zend_Date($val, $this->getConfig('datavalueformat'));
    117             $this->value = $this->valueObj->get($this->getConfig('timeformat'));
    118         }
    119         // Set in current locale (as string)
    120         else if(Zend_Date::isDate($val, $this->getConfig('timeformat'), $this->locale)) {
    121             $this->valueObj = new Zend_Date($val, $this->getConfig('timeformat'), $this->locale);
    122             $this->value = $this->valueObj->get($this->getConfig('timeformat'));
    123         }
    124         // Fallback: Set incorrect value so validate() can pick it up
    125         else {
    126             $this->value = $val;
    127             $this->valueObj = null;
    128         }
    129     }
    130
    131     /**
    132      * @return String ISO 8601 date, suitable for insertion into database
    133      */
    134     function dataValue() {
    135         if($this->valueObj) {
    136             return $this->valueObj->toString($this->getConfig('datavalueformat'));
    137         } else {
    138             return null;
    139         }
    140     }
    141
    142     /**
    143      * @return Boolean
    144      */
    145     function validate($validator) {
    146         $valid = true;
    147
    148         // Don't validate empty fields
    149         if(empty($this->value)) return true;
    150
    151         if(!Zend_Date::isDate($this->value, $this->getConfig('timeformat'), $this->locale)) {
    152             $validator->validationError(
    153                 $this->name,
    154                 _t('DateField.VALIDDATEFORMAT', "Please enter a valid time format."),
    155                 "validation",
    156                 false
    157             );
    158             return false;
    159         }
    160         return true;
    161     }
    162
    163     function ShowDropdown() {
    164         if($this->getConfig('showdropdown')) {
    165             return true;
    166         }
    167         return false;
    168     }
    169
    170     /**
    171      * @return string
    172      */
    173     function getLocale() {
    174         return $this->locale;
    175     }
    176
    177     /**
    178      * @param String $locale
    179      */
    180     function setLocale($locale) {
    181         $this->locale = $locale;
    182     }
    183
    184     /**
    185      * @param string $name
    186      * @param mixed $val
    187      */
    188     function setConfig($name, $val) {
    189         $this->config[$name] = $val;
    190     }
    191
    192     /**
    193      * @param String $name
    194      * @return mixed
    195      */
    196     function getConfig($name) {
    197         return $this->config[$name];
    198     }
    199
    200     /**
    201      * Creates a new readonly field specified below
    202      */
    203     function performReadonlyTransformation() {
    204         return new TimeField_Readonly($this->name, $this->title, $this->dataValue(), $this->getConfig('timeformat'));
    205     }
    206
    207 }
    208
    209 /**
    210  * The readonly class for our {@link TimeField}.
    211  *
    212  * @package forms
    213  * @subpackage fields-datetime
    214  */
    215 class TimeField_Readonly extends TimeField {
    216
    217     protected $readonly = true;
    218
    219     function Field() {
    220         if($this->valueObj) {
    221             $val = Convert::raw2xml($this->valueObj->toString($this->getConfig('timeformat')));
    222         } else {
    223             // TODO Localization
    224             $val = '<i>(not set)</i>';
    225         }
    226
    227         return "<span class=\"readonly\" id=\"" . $this->id() . "\">$val</span>";
    228     }
    229
    230     function jsValidation() {
    231         return null;
    232     }
    233
    234     function validate($validator) {
    235         return true;
    236     }
    237 }
    238 ?>

[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -