'g:i a', 'count' => 1, 'mode' => self::MODE_ELEMENT, 'required' => null, 'minutesInterval' => 15, 'minuteOptions' => null, 'emptyOptions' => false, 'smartOptions' => true, // automatically insert value into options 'dayPrefix' => 'Day %s ', 'startTimeLabel' => 'Start Time:', 'endTimeLabel' => 'End Time:', ); protected $_params = array( 'format', 'count', 'mode', 'required', 'minutesInterval', 'minuteOptions', 'emptyOptions', 'smartOptions' ); protected function _getInfo($name, $value = null, $attribs = null, $options = null, $listsep = null) { $info = parent::_getInfo($name, $value, $attribs, $options, $listsep); foreach ($this->_params as $paramName) { if (isset($info['attribs'][$paramName])) { $this->{$paramName} = $info['attribs'][$paramName]; unset($info['attribs'][$paramName]); } else { $this->{$paramName} = $this->_defaults[$paramName]; } } return $info; } /** * @param string $name * @param array|null $value [['H:i:s', 'H:i:s'], ...] * @param array|null $attribs * @return string */ public function formTimeRanges($name, $value = null, $attribs = null) { $info = $this->_getInfo($name, $value, $attribs); $id = $name = $value = $attribs = $disable = $escape = null; extract($info); $this->name = $name; $this->disable = $disable; $value = (array) $value; if (self::MODE_TEMPLATE === $this->mode) { list($time1, $time2) = reset($value); return $this->_renderRow('{index}', $time1, $time2); } $keys = array_keys($value); $keyCount = count($keys); $content = ''; for ($i = 0; $i < $this->count; ++$i) { $time1 = $time2 = null; if ($i < $keyCount) { list($time1, $time2) = $value[$keys[$i]]; } $rowIndex = $i + 1; $content .= $this->_renderRow($rowIndex, $time1, $time2); } if ($content) { $attribs['id'] = $id; $_attribs = $this->_htmlAttribs(array_filter($attribs)); $content = "{$content}
"; } return $content; } /** * @param string $index * @param string|null $time1 * @param string|null $time2 * @return string */ protected function _renderRow($index, $time1 = null, $time2 = null) { $element1 = $this->_renderElement($index, 0, $time1); $element2 = $this->_renderElement($index, 1, $time2); $dayPrefix = sprintf($this->dayPrefix, $index); $label1 = $this->startTimeLabel; $label2 = $this->endTimeLabel; $content = "{$dayPrefix} {$label1}
{$element1}" . "{$dayPrefix} {$label2}
{$element2}"; return $content; } /** * @param int $row * @param int $index * @param string $time Time in "H:i:s" format * @return string */ protected function _renderElement($row, $index, $time = null) { $content = ''; $dateTime = ($time) ? DateTime::createFromFormat('H:i:s', $time) : null; for ($i = 0, $length = strlen($this->format); $i < $length; ++$i) { $char = $this->format[$i]; switch ($char) { case 'H': $options = range(0, 23); $options = array_combine($options, $options); break; case 'i': if ($this->minuteOptions) { $options = (array) $this->minuteOptions; } else { $options = range(0, 59, $this->minutesInterval ?: 1); } if ($this->smartOptions && $dateTime && !in_array(($_value = $dateTime->format($char)), $options)) { $options[] = $_value; sort($options); } $options = array_map(function ($option) { return str_pad($option, 2, '0'); }, $options); $options = array_combine($options, $options); break; case 's': $options = range(0, 59); $options = array_combine($options, $options); break; case 'g': $options = range(1, 12); $options = array_combine($options, $options); break; case 'a': $options = array('am' => 'am', 'pm' => 'pm'); break; case 'A': $options = array('AM' => 'AM', 'PM' => 'PM'); break; default: $content .= $char; continue 2; } $_value = ($dateTime) ? $dateTime->format($char) : null; $_attribs = array('class' => 'time_' . $char); if ($this->disable) { $_attribs['disabled'] = 'disabled'; } if (!$this->required || $this->emptyOptions) { $options = array('' => '') + (array) $options; } $name = trim($this->name, '[]') . "[{$row}][{$index}][{$char}]"; $content .= $this->view->formSelect($name, $_value, $_attribs, $options); } return $content; } }