Path: blob/master/src/view/form/control/AphrontFormDateControl.php
12262 views
<?php12final class AphrontFormDateControl extends AphrontFormControl {34private $initialTime;5private $zone;67private $valueDate;8private $valueTime;9private $allowNull;10private $continueOnInvalidDate = false;11private $isTimeDisabled;12private $isDisabled;13private $endDateID;1415public function setAllowNull($allow_null) {16$this->allowNull = $allow_null;17return $this;18}1920public function setIsTimeDisabled($is_disabled) {21$this->isTimeDisabled = $is_disabled;22return $this;23}2425public function setIsDisabled($is_datepicker_disabled) {26$this->isDisabled = $is_datepicker_disabled;27return $this;28}2930public function setEndDateID($value) {31$this->endDateID = $value;32return $this;33}3435const TIME_START_OF_DAY = 'start-of-day';36const TIME_END_OF_DAY = 'end-of-day';37const TIME_START_OF_BUSINESS = 'start-of-business';38const TIME_END_OF_BUSINESS = 'end-of-business';3940public function setInitialTime($time) {41$this->initialTime = $time;42return $this;43}4445public function readValueFromRequest(AphrontRequest $request) {46$date = $request->getStr($this->getDateInputName());47$time = $request->getStr($this->getTimeInputName());48$enabled = $request->getBool($this->getCheckboxInputName());4950if ($this->allowNull && !$enabled) {51$this->setError(null);52$this->setValue(null);53return;54}5556$err = $this->getError();5758if ($date || $time) {59$this->valueDate = $date;60$this->valueTime = $time;6162// Assume invalid.63$err = pht('Invalid');6465$zone = $this->getTimezone();6667try {68$datetime = new DateTime("{$date} {$time}", $zone);69$value = $datetime->format('U');70} catch (Exception $ex) {71$value = null;72}7374if ($value) {75$this->setValue($value);76$err = null;77} else {78$this->setValue(null);79}80} else {81$value = $this->getInitialValue();82if ($value) {83$this->setValue($value);84} else {85$this->setValue(null);86}87}8889$this->setError($err);9091return $this->getValue();92}9394protected function getCustomControlClass() {95return 'aphront-form-control-date';96}9798public function setValue($epoch) {99if ($epoch instanceof AphrontFormDateControlValue) {100$this->continueOnInvalidDate = true;101$this->valueDate = $epoch->getValueDate();102$this->valueTime = $epoch->getValueTime();103$this->allowNull = $epoch->getOptional();104$this->isDisabled = $epoch->isDisabled();105106return parent::setValue($epoch->getEpoch());107}108109$result = parent::setValue($epoch);110111if ($epoch === null) {112return $result;113}114115$readable = $this->formatTime($epoch, 'Y!m!d!'.$this->getTimeFormat());116$readable = explode('!', $readable, 4);117118$year = $readable[0];119$month = $readable[1];120$day = $readable[2];121122$this->valueDate = $month.'/'.$day.'/'.$year;123$this->valueTime = $readable[3];124125return $result;126}127128private function getDateInputValue() {129$date_format = $this->getDateFormat();130$timezone = $this->getTimezone();131132try {133$datetime = new DateTime($this->valueDate, $timezone);134} catch (Exception $ex) {135return $this->valueDate;136}137138return $datetime->format($date_format);139}140141private function getTimeFormat() {142$viewer = $this->getViewer();143$time_key = PhabricatorTimeFormatSetting::SETTINGKEY;144return $viewer->getUserSetting($time_key);145}146147private function getDateFormat() {148$viewer = $this->getViewer();149$date_key = PhabricatorDateFormatSetting::SETTINGKEY;150return $viewer->getUserSetting($date_key);151}152153private function getTimeInputValue() {154return $this->valueTime;155}156157private function formatTime($epoch, $fmt) {158return phabricator_format_local_time(159$epoch,160$this->getViewer(),161$fmt);162}163164private function getDateInputName() {165return $this->getName().'_d';166}167168private function getTimeInputName() {169return $this->getName().'_t';170}171172private function getCheckboxInputName() {173return $this->getName().'_e';174}175176protected function renderInput() {177178$disabled = null;179if ($this->getValue() === null && !$this->continueOnInvalidDate) {180$this->setValue($this->getInitialValue());181if ($this->allowNull) {182$disabled = 'disabled';183}184}185186if ($this->isDisabled) {187$disabled = 'disabled';188}189190$checkbox = null;191if ($this->allowNull) {192$checkbox = javelin_tag(193'input',194array(195'type' => 'checkbox',196'name' => $this->getCheckboxInputName(),197'sigil' => 'calendar-enable',198'class' => 'aphront-form-date-enabled-input',199'value' => 1,200'checked' => ($disabled === null ? 'checked' : null),201));202}203204$date_sel = javelin_tag(205'input',206array(207'autocomplete' => 'off',208'name' => $this->getDateInputName(),209'sigil' => 'date-input',210'value' => $this->getDateInputValue(),211'type' => 'text',212'class' => 'aphront-form-date-input',213),214'');215216$date_div = javelin_tag(217'div',218array(219'class' => 'aphront-form-date-input-container',220),221$date_sel);222223$cicon = id(new PHUIIconView())224->setIcon('fa-calendar');225226$cal_icon = javelin_tag(227'a',228array(229'href' => '#',230'class' => 'calendar-button',231'sigil' => 'calendar-button',232),233$cicon);234235$values = $this->getTimeTypeaheadValues();236237$time_id = celerity_generate_unique_node_id();238Javelin::initBehavior('time-typeahead', array(239'startTimeID' => $time_id,240'endTimeID' => $this->endDateID,241'timeValues' => $values,242'format' => $this->getTimeFormat(),243));244245$time_sel = javelin_tag(246'input',247array(248'autocomplete' => 'off',249'name' => $this->getTimeInputName(),250'sigil' => 'time-input',251'value' => $this->getTimeInputValue(),252'type' => 'text',253'class' => 'aphront-form-time-input',254),255'');256257$time_div = javelin_tag(258'div',259array(260'id' => $time_id,261'class' => 'aphront-form-time-input-container',262),263$time_sel);264265$viewer = $this->getViewer();266$week_key = PhabricatorWeekStartDaySetting::SETTINGKEY;267$week_start = $viewer->getUserSetting($week_key);268269Javelin::initBehavior('fancy-datepicker', array(270'format' => $this->getDateFormat(),271'weekStart' => $week_start,272));273274$classes = array();275$classes[] = 'aphront-form-date-container';276if ($disabled) {277$classes[] = 'datepicker-disabled';278}279if ($this->isTimeDisabled) {280$classes[] = 'no-time';281}282283return javelin_tag(284'div',285array(286'class' => implode(' ', $classes),287'sigil' => 'phabricator-date-control',288'meta' => array(289'disabled' => (bool)$disabled,290),291'id' => $this->getID(),292),293array(294$checkbox,295$date_div,296$cal_icon,297$time_div,298));299}300301private function getTimezone() {302if ($this->zone) {303return $this->zone;304}305306$viewer = $this->getViewer();307308$user_zone = $viewer->getTimezoneIdentifier();309$this->zone = new DateTimeZone($user_zone);310return $this->zone;311}312313private function getInitialValue() {314$zone = $this->getTimezone();315316// TODO: We could eventually allow these to be customized per install or317// per user or both, but let's wait and see.318switch ($this->initialTime) {319case self::TIME_START_OF_DAY:320default:321$time = '12:00 AM';322break;323case self::TIME_START_OF_BUSINESS:324$time = '9:00 AM';325break;326case self::TIME_END_OF_BUSINESS:327$time = '5:00 PM';328break;329case self::TIME_END_OF_DAY:330$time = '11:59 PM';331break;332}333334$today = $this->formatTime(time(), 'Y-m-d');335try {336$date = new DateTime("{$today} {$time}", $zone);337$value = $date->format('U');338} catch (Exception $ex) {339$value = null;340}341342return $value;343}344345private function getTimeTypeaheadValues() {346$time_format = $this->getTimeFormat();347$times = array();348349if ($time_format == 'g:i A') {350$am_pm_list = array('AM', 'PM');351352foreach ($am_pm_list as $am_pm) {353for ($hour = 0; $hour < 12; $hour++) {354$actual_hour = ($hour == 0) ? 12 : $hour;355$times[] = $actual_hour.':00 '.$am_pm;356$times[] = $actual_hour.':30 '.$am_pm;357}358}359} else if ($time_format == 'H:i') {360for ($hour = 0; $hour < 24; $hour++) {361$written_hour = ($hour > 9) ? $hour : '0'.$hour;362$times[] = $written_hour.':00';363$times[] = $written_hour.':30';364}365}366367foreach ($times as $key => $time) {368$times[$key] = array($key, $time);369}370371return $times;372}373374}375376377