Changeset View
Standalone View
src/view/form/control/AphrontFormDateControlValue.php
<?php | <?php | ||||
final class AphrontFormDateControlValue extends Phobject { | final class AphrontFormDateControlValue extends Phobject { | ||||
private $valueDate; | private $valueDate; | ||||
private $valueTime; | private $valueTime; | ||||
private $valueEnabled; | private $valueEnabled; | ||||
private $viewer; | private $viewer; | ||||
private $zone; | private $zone; | ||||
private $optional; | private $optional; | ||||
public function getValueDate() { | public function getValueDate() { | ||||
return $this->valueDate; | return $this->valueDate; | ||||
} | } | ||||
public function getValueTime() { | public function getValueTime() { | ||||
return $this->valueTime; | return $this->valueTime; | ||||
} | } | ||||
Show All 39 Lines | public static function newFromParts( | ||||
$year, | $year, | ||||
$month, | $month, | ||||
$day, | $day, | ||||
$time = null, | $time = null, | ||||
$enabled = true) { | $enabled = true) { | ||||
$value = new AphrontFormDateControlValue(); | $value = new AphrontFormDateControlValue(); | ||||
$value->viewer = $viewer; | $value->viewer = $viewer; | ||||
$value->valueDate = $month.'/'.$day.'/'.$year; | $value->valueDate = $value->getFormattedDateFromParts( | ||||
$year, | |||||
$month, | |||||
$day, | |||||
$value); | |||||
$value->valueTime = coalesce($time, '12:00 AM'); | $value->valueTime = coalesce($time, '12:00 AM'); | ||||
$value->valueEnabled = $enabled; | $value->valueEnabled = $enabled; | ||||
return $value; | return $value; | ||||
} | } | ||||
public static function newFromRequest(AphrontRequest $request, $key) { | public static function newFromRequest(AphrontRequest $request, $key) { | ||||
$value = new AphrontFormDateControlValue(); | $value = new AphrontFormDateControlValue(); | ||||
$value->viewer = $request->getViewer(); | $value->viewer = $request->getViewer(); | ||||
$value->valueDate = $request->getStr($key.'_d'); | |||||
$value->valueDate = $value->getFormattedDateFromDate( | |||||
$request->getStr($key.'_d'), | |||||
$value); | |||||
$value->valueTime = $request->getStr($key.'_t'); | $value->valueTime = $request->getStr($key.'_t'); | ||||
$value->valueEnabled = $request->getStr($key.'_e'); | $value->valueEnabled = $request->getStr($key.'_e'); | ||||
return $value; | return $value; | ||||
} | } | ||||
public static function newFromEpoch(PhabricatorUser $viewer, $epoch) { | public static function newFromEpoch(PhabricatorUser $viewer, $epoch) { | ||||
$value = new AphrontFormDateControlValue(); | $value = new AphrontFormDateControlValue(); | ||||
$value->viewer = $viewer; | $value->viewer = $viewer; | ||||
$readable = $value->formatTime($epoch, 'Y!m!d!g:i A'); | $readable = $value->formatTime($epoch, 'Y!m!d!g:i A'); | ||||
$readable = explode('!', $readable, 4); | $readable = explode('!', $readable, 4); | ||||
$year = $readable[0]; | $year = $readable[0]; | ||||
$month = $readable[1]; | $month = $readable[1]; | ||||
$day = $readable[2]; | $day = $readable[2]; | ||||
$value->valueDate = $month.'/'.$day.'/'.$year; | $value->valueDate = $value->getFormattedDateFromParts( | ||||
$year, | |||||
$month, | |||||
$day, | |||||
$value); | |||||
$value->valueTime = $readable[3]; | $value->valueTime = $readable[3]; | ||||
return $value; | return $value; | ||||
} | } | ||||
public static function newFromDictionary( | public static function newFromDictionary( | ||||
PhabricatorUser $viewer, | PhabricatorUser $viewer, | ||||
array $dictionary) { | array $dictionary) { | ||||
$value = new AphrontFormDateControlValue(); | $value = new AphrontFormDateControlValue(); | ||||
$value->viewer = $viewer; | $value->viewer = $viewer; | ||||
$value->valueDate = idx($dictionary, 'd'); | $value->valueDate = $value->getFormattedDateFromDate( | ||||
idx($dictionary, 'd'), | |||||
$value); | |||||
$value->valueTime = idx($dictionary, 't'); | $value->valueTime = idx($dictionary, 't'); | ||||
$value->valueEnabled = idx($dictionary, 'e'); | $value->valueEnabled = idx($dictionary, 'e'); | ||||
return $value; | return $value; | ||||
} | } | ||||
public static function newFromWild(PhabricatorUser $viewer, $wild) { | public static function newFromWild(PhabricatorUser $viewer, $wild) { | ||||
if (is_array($wild)) { | if (is_array($wild)) { | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | try { | ||||
$datetime = new DateTime("{$date} {$time}", $zone); | $datetime = new DateTime("{$date} {$time}", $zone); | ||||
$value = $datetime->format('U'); | $value = $datetime->format('U'); | ||||
} catch (Exception $ex) { | } catch (Exception $ex) { | ||||
$value = null; | $value = null; | ||||
} | } | ||||
return $value; | return $value; | ||||
} | } | ||||
private function getDateFormat() { | |||||
epriestley: This is probably stumbling into T4103 territory, but it would be nice to have only one copy of… | |||||
$preferences = $this->viewer->loadPreferences(); | |||||
$pref_date_format = PhabricatorUserPreferences::PREFERENCE_DATE_FORMAT; | |||||
return $preferences->getPreference($pref_date_format, 'Y-m-d'); | |||||
} | |||||
private function getFormattedDateFromDate($date, $value) { | |||||
$original_input = $date; | |||||
$zone = $value->getTimezone(); | |||||
$separator = $value->getFormatSeparator(); | |||||
$parts = preg_split('@[,./:-]@', $date); | |||||
Done Inline ActionsYou can maybe do this a little more cleanly with preg_split(): $parts = preg_split('@[,./:]@', $date); epriestley: You can maybe do this a little more cleanly with `preg_split()`:
$parts = preg_split('@[,./… | |||||
$date = implode($separator, $parts); | |||||
$date = id(new DateTime($date, $zone)); | |||||
if ($date) { | |||||
return $date->format($value->getDateFormat()); | |||||
} else { | |||||
Done Inline ActionsI'd expect '-' to be present on this list. epriestley: I'd expect '-' to be present on this list. | |||||
return $original_input; | |||||
} | |||||
} | |||||
Done Inline ActionsI think this may need to fall back to parsing the unmangled input if this parse of a mangled input fails. For example, suppose I enter a string like:
I'm not sure if that really works (I don't think it does), but you can imagine there likely exist some range of inputs that are valid and contain ,, ., /, or :, but are no longer valid after those characters are replaced with -. In the case above, we'd mangle into something like this:
...which would fail to parse, then could try the original:
...which could succeed. I can't actually come up with any examples of these date inputs (except date inputs which include times, I suppose), so it's possible that none exist. If you think none exist or that waiting for users to report them is fine, that's OK too. epriestley: I think this may need to fall back to parsing the unmangled input if this parse of a mangled… | |||||
private function getFormattedDateFromParts($year, $month, $day, $value) { | |||||
$zone = $value->getTimezone(); | |||||
return id(new DateTime("{$year}-{$month}-{$day}", $zone)) | |||||
->format($value->getDateFormat()); | |||||
} | |||||
private function getFormatSeparator() { | |||||
$format = $this->getDateFormat(); | |||||
switch ($format) { | |||||
case 'n/j/Y': | |||||
return '/'; | |||||
default: | |||||
return '-'; | |||||
} | |||||
} | |||||
public function getDateTime() { | public function getDateTime() { | ||||
$epoch = $this->getEpoch(); | $epoch = $this->getEpoch(); | ||||
$date = null; | $date = null; | ||||
if ($epoch) { | if ($epoch) { | ||||
$zone = $this->getTimezone(); | $zone = $this->getTimezone(); | ||||
$date = new DateTime('@'.$epoch); | $date = new DateTime('@'.$epoch); | ||||
$date->setTimeZone($zone); | $date->setTimeZone($zone); | ||||
Show All 17 Lines |
This is probably stumbling into T4103 territory, but it would be nice to have only one copy of the default value anywhere in the codebase.
I think the likely fix is T4103 + T7707 handling this, though.