Something went wrong. Try again.
@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
Something went wrong. Try again.
PHP
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393<?php
final class AphrontFormDateControl extends AphrontFormControl {
private $initialTime; private $zone;
private $valueDate; private $valueTime; private $allowNull; private $continueOnInvalidDate = false; private $isTimeDisabled; private $isDisabled; private $endDateID;
public function setAllowNull($allow_null) { $this->allowNull = $allow_null; return $this; }
public function setIsTimeDisabled($is_disabled) { $this->isTimeDisabled = $is_disabled; return $this; }
public function setIsDisabled($is_datepicker_disabled) { $this->isDisabled = $is_datepicker_disabled; return $this; }
public function setEndDateID($value) { $this->endDateID = $value; return $this; }
const TIME_START_OF_DAY = 'start-of-day'; const TIME_END_OF_DAY = 'end-of-day'; const TIME_START_OF_BUSINESS = 'start-of-business'; const TIME_END_OF_BUSINESS = 'end-of-business';
public function setInitialTime($time) { $this->initialTime = $time; return $this; }
public function readValueFromRequest(AphrontRequest $request) { $date = $request->getStr($this->getDateInputName()); $time = $request->getStr($this->getTimeInputName()); $enabled = $request->getBool($this->getCheckboxInputName());
if ($this->allowNull && !$enabled) { $this->setError(null); $this->setValue(null); return; }
$err = $this->getError();
if ($date || $time) { $this->valueDate = $date; $this->valueTime = $time;
// Assume invalid. $err = pht('Invalid');
$zone = $this->getTimezone();
try { $datetime = new DateTime("{$date} {$time}", $zone); $value = $datetime->format('U'); } catch (Exception $ex) { $value = null; }
if ($value) { $this->setValue($value); $err = null; } else { $this->setValue(null); } } else { $value = $this->getInitialValue(); if ($value) { $this->setValue($value); } else { $this->setValue(null); } }
$this->setError($err);
return $this->getValue(); }
protected function getCustomControlClass() { return 'aphront-form-control-date'; }
public function setValue($epoch) { if ($epoch instanceof AphrontFormDateControlValue) { $this->continueOnInvalidDate = true; $this->valueDate = $epoch->getValueDate(); $this->valueTime = $epoch->getValueTime(); $this->allowNull = $epoch->getOptional(); $this->isDisabled = $epoch->isDisabled();
return parent::setValue($epoch->getEpoch()); }
$result = parent::setValue($epoch);
if ($epoch === null) { return $result; }
$readable = $this->formatTime($epoch, 'Y!m!d!'.$this->getTimeFormat()); $readable = explode('!', $readable, 4);
$year = $readable[0]; $month = $readable[1]; $day = $readable[2];
$this->valueDate = $month.'/'.$day.'/'.$year; $this->valueTime = $readable[3];
return $result; }
private function getDateInputValue() { $date_format = $this->getDateFormat(); $timezone = $this->getTimezone();
try { $datetime = new DateTime($this->valueDate, $timezone); } catch (Exception $ex) { return $this->valueDate; }
return $datetime->format($date_format); }
private function getTimeFormat() { $viewer = $this->getViewer(); $time_key = PhabricatorTimeFormatSetting::SETTINGKEY; return $viewer->getUserSetting($time_key); }
private function getDateFormat() { $viewer = $this->getViewer(); $date_key = PhabricatorDateFormatSetting::SETTINGKEY; return $viewer->getUserSetting($date_key); }
private function getTimeInputValue() { return $this->valueTime; }
private function formatTime($epoch, $fmt) { return phabricator_format_local_time( $epoch, $this->getViewer(), $fmt); }
private function getDateInputName() { return $this->getName().'_d'; }
private function getTimeInputName() { return $this->getName().'_t'; }
private function getCheckboxInputName() { return $this->getName().'_e'; }
protected function renderInput() {
$disabled = null; if ($this->getValue() === null && !$this->continueOnInvalidDate) { $this->setValue($this->getInitialValue()); if ($this->allowNull) { $disabled = 'disabled'; } }
if ($this->isDisabled) { $disabled = 'disabled'; }
$checkbox = null; if ($this->allowNull) { $checkbox = javelin_tag( 'input', array( 'type' => 'checkbox', 'name' => $this->getCheckboxInputName(), 'sigil' => 'calendar-enable', 'class' => 'aphront-form-date-enabled-input', 'value' => 1, 'checked' => ($disabled === null ? 'checked' : null), )); }
$date_sel = javelin_tag( 'input', array( 'autocomplete' => 'off', 'name' => $this->getDateInputName(), 'sigil' => 'date-input', 'value' => $this->getDateInputValue(), 'type' => 'text', 'class' => 'aphront-form-date-input', ), '');
$date_div = javelin_tag( 'div', array( 'class' => 'aphront-form-date-input-container', ), $date_sel);
$cicon = id(new PHUIIconView()) ->setIcon('fa-calendar');
$cal_icon = javelin_tag( 'a', array( 'href' => '#', 'class' => 'calendar-button', 'sigil' => 'calendar-button', 'aria-label' => pht('Calendar date picker'), ), $cicon);
$values = $this->getTimeTypeaheadValues();
$time_id = celerity_generate_unique_node_id(); Javelin::initBehavior('time-typeahead', array( 'startTimeID' => $time_id, 'endTimeID' => $this->endDateID, 'timeValues' => $values, 'format' => $this->getTimeFormat(), ));
$time_sel = javelin_tag( 'input', array( 'autocomplete' => 'off', 'name' => $this->getTimeInputName(), 'sigil' => 'time-input', 'value' => $this->getTimeInputValue(), 'type' => 'text', 'class' => 'aphront-form-time-input', ), '');
$time_div = javelin_tag( 'div', array( 'id' => $time_id, 'class' => 'aphront-form-time-input-container', ), $time_sel);
$viewer = $this->getViewer(); $week_key = PhabricatorWeekStartDaySetting::SETTINGKEY; $week_start = $viewer->getUserSetting($week_key);
$date_pht = array( 'S|M|T|W|T|F|S' => pht('S|M|T|W|T|F|S'), 'January' => pht('January'), 'February' => pht('February'), 'March' => pht('March'), 'April' => pht('April'), 'May' => pht('May'), 'June' => pht('June'), 'July' => pht('July'), 'August' => pht('August'), 'September' => pht('September'), 'October' => pht('October'), 'November' => pht('November'), 'December' => pht('December'), ); Javelin::initBehavior('fancy-datepicker', array( 'format' => $this->getDateFormat(), 'weekStart' => $week_start, 'pht' => $date_pht, ));
$classes = array(); $classes[] = 'aphront-form-date-container'; if ($disabled) { $classes[] = 'datepicker-disabled'; } if ($this->isTimeDisabled) { $classes[] = 'no-time'; }
return javelin_tag( 'div', array( 'class' => implode(' ', $classes), 'sigil' => 'phabricator-date-control', 'meta' => array( 'disabled' => (bool)$disabled, ), 'id' => $this->getID(), ), array( $checkbox, $date_div, $cal_icon, $time_div, )); }
private function getTimezone() { if ($this->zone) { return $this->zone; }
$viewer = $this->getViewer();
$user_zone = $viewer->getTimezoneIdentifier(); $this->zone = new DateTimeZone($user_zone); return $this->zone; }
private function getInitialValue() { $zone = $this->getTimezone();
// TODO: We could eventually allow these to be customized per install or // per user or both, but let's wait and see. switch ($this->initialTime) { case self::TIME_START_OF_DAY: default: $time = '12:00 AM'; break; case self::TIME_START_OF_BUSINESS: $time = '9:00 AM'; break; case self::TIME_END_OF_BUSINESS: $time = '5:00 PM'; break; case self::TIME_END_OF_DAY: $time = '11:59 PM'; break; }
$today = $this->formatTime(time(), 'Y-m-d'); try { $date = new DateTime("{$today} {$time}", $zone); $value = $date->format('U'); } catch (Exception $ex) { $value = null; }
return $value; }
private function getTimeTypeaheadValues() { $time_format = $this->getTimeFormat(); $times = array();
if ($time_format == 'g:i A') { $am_pm_list = array('AM', 'PM');
foreach ($am_pm_list as $am_pm) { for ($hour = 0; $hour < 12; $hour++) { $actual_hour = ($hour == 0) ? 12 : $hour; $times[] = $actual_hour.':00 '.$am_pm; $times[] = $actual_hour.':30 '.$am_pm; } } } else if ($time_format == 'H:i') { for ($hour = 0; $hour < 24; $hour++) { $written_hour = ($hour > 9) ? $hour : '0'.$hour; $times[] = $written_hour.':00'; $times[] = $written_hour.':30'; } }
foreach ($times as $key => $time) { $times[$key] = array($key, $time); }
return $times; }
}