/system/library/PEAR/HTML/QuickForm2/Element/Date.php
PHP | 398 lines | 231 code | 15 blank | 152 comment | 25 complexity | 7f599b71ffc52326ed11a8ebe3c4e092 MD5 | raw file
Possible License(s): BSD-2-Clause
- <?php
- /**
- * Date element
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * Copyright (c) 2006-2012, Alexey Borzov <avb@php.net>,
- * Bertrand Mansion <golgote@mamasam.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * The names of the authors may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @category HTML
- * @package HTML_QuickForm2
- * @author Alexey Borzov <avb@php.net>
- * @author Bertrand Mansion <golgote@mamasam.com>
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version SVN: $Id: Date.php 323363 2012-02-19 15:09:07Z avb $
- * @link http://pear.php.net/package/HTML_QuickForm2
- */
- /**
- * Base class for HTML_QuickForm2 group of elements
- */
- require_once 'HTML/QuickForm2/Container/Group.php';
- /**
- * Base class for HTML_QuickForm2 select element
- */
- require_once 'HTML/QuickForm2/Element/Select.php';
- /**
- * Class for a group of elements used to input dates (and times).
- *
- * @category HTML
- * @package HTML_QuickForm2
- * @author Alexey Borzov <avb@php.net>
- * @author Bertrand Mansion <golgote@mamasam.com>
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 2.0.0
- * @link http://pear.php.net/package/HTML_QuickForm2
- */
- class HTML_QuickForm2_Element_Date extends HTML_QuickForm2_Container_Group
- {
- public function getType()
- {
- return 'date';
- }
- /**
- * Various options to control the element's display.
- * @var array
- */
- protected $data = array(
- 'format' => 'dMY',
- 'minYear' => 2001,
- 'maxYear' => null, // set in the constructor
- 'addEmptyOption' => false,
- 'emptyOptionValue' => '',
- 'emptyOptionText' => ' ',
- 'optionIncrement' => array('i' => 1, 's' => 1),
- // request #4061: max and min hours (only for 'H' modifier)
- 'minHour' => 0,
- 'maxHour' => 23,
- // request #5957: max and min months
- 'minMonth' => 1,
- 'maxMonth' => 12
- );
- /**
- * Language code
- * @var string
- */
- protected $language = null;
- /**
- * Message provider for option texts
- * @var callback|HTML_QuickForm2_MessageProvider
- */
- protected $messageProvider;
- /**
- * Class constructor
- *
- * The following keys may appear in $data array:
- * - 'messageProvider': a callback or an instance of a class implementing
- * HTML_QuickForm2_MessageProvider interface, this will be used to get
- * localized names of months and weekdays. Some of the default ones will
- * be used if not given.
- * - 'language': date language, use 'locale' here to display month / weekday
- * names according to the current locale.
- * - 'format': Format of the date, based on PHP's date() function.
- * The following characters are currently recognised in format string:
- * <pre>
- * D => Short names of days
- * l => Long names of days
- * d => Day numbers
- * M => Short names of months
- * F => Long names of months
- * m => Month numbers
- * Y => Four digit year
- * y => Two digit year
- * h => 12 hour format
- * H => 24 hour format
- * i => Minutes
- * s => Seconds
- * a => am/pm
- * A => AM/PM
- * </pre>
- * - 'minYear': Minimum year in year select
- * - 'maxYear': Maximum year in year select
- * - 'addEmptyOption': Should an empty option be added to the top of
- * each select box?
- * - 'emptyOptionValue': The value passed by the empty option.
- * - 'emptyOptionText': The text displayed for the empty option.
- * - 'optionIncrement': Step to increase the option values by (works for 'i' and 's')
- * - 'minHour': Minimum hour in hour select (only for 24 hour format!)
- * - 'maxHour': Maximum hour in hour select (only for 24 hour format!)
- * - 'minMonth': Minimum month in month select
- * - 'maxMonth': Maximum month in month select
- *
- * @param string $name Element name
- * @param string|array $attributes Attributes (either a string or an array)
- * @param array $data Element data (label, options and data used for element creation)
- */
- public function __construct($name = null, $attributes = null, array $data = array())
- {
- if (isset($data['messageProvider'])) {
- if (!is_callable($data['messageProvider'])
- && !$data['messageProvider'] instanceof HTML_QuickForm2_MessageProvider
- ) {
- throw new HTML_QuickForm2_InvalidArgumentException(
- "messageProvider: expecting a callback or an implementation"
- . " of HTML_QuickForm2_MessageProvider"
- );
- }
- $this->messageProvider = $data['messageProvider'];
- } else {
- if (isset($data['language']) && 'locale' == $data['language']) {
- HTML_QuickForm2_Loader::loadClass('HTML_QuickForm2_MessageProvider_Strftime');
- $this->messageProvider = new HTML_QuickForm2_MessageProvider_Strftime();
- } else {
- HTML_QuickForm2_Loader::loadClass('HTML_QuickForm2_MessageProvider_Default');
- $this->messageProvider = HTML_QuickForm2_MessageProvider_Default::getInstance();
- }
- }
- if (isset($data['language'])) {
- $this->language = $data['language'];
- }
- unset($data['messageProvider'], $data['language']);
- // http://pear.php.net/bugs/bug.php?id=18171
- $this->data['maxYear'] = date('Y');
- parent::__construct($name, $attributes, $data);
- $backslash = false;
- $separators = array();
- $separator = '';
- for ($i = 0, $length = strlen($this->data['format']); $i < $length; $i++) {
- $sign = $this->data['format'][$i];
- if ($backslash) {
- $backslash = false;
- $separator .= $sign;
- } else {
- $loadSelect = true;
- switch ($sign) {
- case 'D':
- // Sunday is 0 like with 'w' in date()
- $options = $this->messageProvider instanceof HTML_QuickForm2_MessageProvider
- ? $this->messageProvider->get(array('date', 'weekdays_short'), $this->language)
- : call_user_func($this->messageProvider, array('date', 'weekdays_short'), $this->language);
- break;
- case 'l':
- $options = $this->messageProvider instanceof HTML_QuickForm2_MessageProvider
- ? $this->messageProvider->get(array('date', 'weekdays_long'), $this->language)
- : call_user_func($this->messageProvider, array('date', 'weekdays_long'), $this->language);
- break;
- case 'd':
- $options = $this->createOptionList(1, 31);
- break;
- case 'M':
- case 'm':
- case 'F':
- $options = $this->createOptionList(
- $this->data['minMonth'],
- $this->data['maxMonth'],
- $this->data['minMonth'] > $this->data['maxMonth'] ? -1 : 1
- );
- if ('M' == $sign || 'F' == $sign) {
- $key = 'M' == $sign ? 'months_short' : 'months_long';
- $names = $this->messageProvider instanceof HTML_QuickForm2_MessageProvider
- ? $this->messageProvider->get(array('date', $key), $this->language)
- : call_user_func($this->messageProvider, array('date', $key), $this->language);
- foreach ($options as $k => &$v) {
- $v = $names[$k - 1];
- }
- }
- break;
- case 'Y':
- $options = $this->createOptionList(
- $this->data['minYear'],
- $this->data['maxYear'],
- $this->data['minYear'] > $this->data['maxYear']? -1: 1
- );
- break;
- case 'y':
- $options = $this->createOptionList(
- $this->data['minYear'],
- $this->data['maxYear'],
- $this->data['minYear'] > $this->data['maxYear']? -1: 1
- );
- array_walk($options, create_function('&$v,$k', '$v = substr($v,-2);'));
- break;
- case 'h':
- $options = $this->createOptionList(1, 12);
- break;
- case 'g':
- $options = $this->createOptionList(1, 12);
- array_walk($options, create_function('&$v,$k', '$v = intval($v);'));
- break;
- case 'H':
- $options = $this->createOptionList(
- $this->data['minHour'],
- $this->data['maxHour'],
- $this->data['minHour'] > $this->data['maxHour'] ? -1 : 1
- );
- break;
- case 'i':
- $options = $this->createOptionList(0, 59, $this->data['optionIncrement']['i']);
- break;
- case 's':
- $options = $this->createOptionList(0, 59, $this->data['optionIncrement']['s']);
- break;
- case 'a':
- $options = array('am' => 'am', 'pm' => 'pm');
- break;
- case 'A':
- $options = array('AM' => 'AM', 'PM' => 'PM');
- break;
- case 'W':
- $options = $this->createOptionList(1, 53);
- break;
- case '\\':
- $backslash = true;
- $loadSelect = false;
- break;
- default:
- $separator .= (' ' == $sign? ' ': $sign);
- $loadSelect = false;
- }
- if ($loadSelect) {
- if (0 < count($this)) {
- $separators[] = $separator;
- }
- $separator = '';
- // Should we add an empty option to the top of the select?
- if (!is_array($this->data['addEmptyOption']) && $this->data['addEmptyOption']
- || is_array($this->data['addEmptyOption']) && !empty($this->data['addEmptyOption'][$sign])
- ) {
- // Using '+' array operator to preserve the keys
- if (is_array($this->data['emptyOptionText']) && !empty($this->data['emptyOptionText'][$sign])) {
- $options = array($this->data['emptyOptionValue'] => $this->data['emptyOptionText'][$sign]) + $options;
- } else {
- $options = array($this->data['emptyOptionValue'] => $this->data['emptyOptionText']) + $options;
- }
- }
- $this->addSelect($sign, array('id' => self::generateId($this->getName() . "[{$sign}]"))
- + $this->getAttributes())
- ->loadOptions($options);
- }
- }
- }
- $separators[] = $separator . ($backslash? '\\': '');
- $this->setSeparator($separators);
- }
- /**
- * Creates an option list containing the numbers from the start number to the end, inclusive
- *
- * @param int $start The start number
- * @param int $end The end number
- * @param int $step Increment by this value
- *
- * @return array An array of numeric options.
- */
- protected function createOptionList($start, $end, $step = 1)
- {
- for ($i = $start, $options = array(); $start > $end? $i >= $end: $i <= $end; $i += $step) {
- $options[$i] = sprintf('%02d', $i);
- }
- return $options;
- }
- /**
- * Trims leading zeros from the (numeric) string
- *
- * @param string $str A numeric string, possibly with leading zeros
- *
- * @return string String with leading zeros removed
- */
- protected function trimLeadingZeros($str)
- {
- if (0 == strcmp($str, $this->data['emptyOptionValue'])) {
- return $str;
- }
- $trimmed = ltrim($str, '0');
- return strlen($trimmed)? $trimmed: '0';
- }
- /**
- * Tries to convert the given value to a usable date before setting the
- * element value
- *
- * @param int|string|array $value A timestamp, a string compatible with strtotime()
- * or an array that fits the element names
- *
- * @return HTML_QuickForm2_Element_Date
- */
- public function setValue($value)
- {
- if (empty($value)) {
- $value = array();
- } elseif (is_scalar($value)) {
- if (!is_numeric($value)) {
- $value = strtotime($value);
- }
- // might be a unix epoch, then we fill all possible values
- $arr = explode('-', date('w-j-n-Y-g-G-i-s-a-A-W', (int)$value));
- $value = array(
- 'D' => $arr[0],
- 'l' => $arr[0],
- 'd' => $arr[1],
- 'M' => $arr[2],
- 'm' => $arr[2],
- 'F' => $arr[2],
- 'Y' => $arr[3],
- 'y' => $arr[3],
- 'h' => $arr[4],
- 'g' => $arr[4],
- 'H' => $arr[5],
- 'i' => $this->trimLeadingZeros($arr[6]),
- 's' => $this->trimLeadingZeros($arr[7]),
- 'a' => $arr[8],
- 'A' => $arr[9],
- 'W' => $this->trimLeadingZeros($arr[10])
- );
- } else {
- $value = array_map(array($this, 'trimLeadingZeros'), $value);
- }
- return parent::setValue($value);
- }
- /**
- * Called when the element needs to update its value from form's data sources
- *
- * Since the date element also accepts a timestamp as value, the default
- * group behavior is changed.
- */
- protected function updateValue()
- {
- $name = $this->getName();
- foreach ($this->getDataSources() as $ds) {
- if (null !== ($value = $ds->getValue($name))) {
- $this->setValue($value);
- return;
- }
- }
- parent::updateValue();
- }
- }
- ?>