mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-19 03:50:54 +01:00
Translate "All Day" events into the viewer's time
Summary: Ref T8021. - When "All Day" events are loaded, convert them into the viewer's time. - When "All Day" events are saved, convert them into a +24 hour range. Test Plan: - Created and updated "All Day" events. - Created and updated normal events. - Changed timezones, edited and viewed "All Day" events and normal events. - In all cases, "All Day" events appeared to be 12:00AM - 11:59:59PM to the viewer, on the correct day. - Normal events shifted around properly according to timezones. Reviewers: lpriestley Reviewed By: lpriestley Subscribers: epriestley Maniphest Tasks: T8021 Differential Revision: https://secure.phabricator.com/D12765
This commit is contained in:
parent
57e22e3ce5
commit
f3d76a90f0
6 changed files with 142 additions and 2 deletions
|
@ -74,6 +74,7 @@ final class PhabricatorCalendarEventEditController
|
|||
$name = $event->getName();
|
||||
$description = $event->getDescription();
|
||||
$type = $event->getStatus();
|
||||
$is_all_day = $event->getIsAllDay();
|
||||
|
||||
$current_policies = id(new PhabricatorPolicyQuery())
|
||||
->setViewer($user)
|
||||
|
@ -95,6 +96,7 @@ final class PhabricatorCalendarEventEditController
|
|||
$subscribers = $request->getArr('subscribers');
|
||||
$edit_policy = $request->getStr('editPolicy');
|
||||
$view_policy = $request->getStr('viewPolicy');
|
||||
$is_all_day = $request->getStr('isAllDay');
|
||||
|
||||
$invitees = $request->getArr('invitees');
|
||||
$new_invitees = $this->getNewInviteeList($invitees, $event);
|
||||
|
@ -111,6 +113,11 @@ final class PhabricatorCalendarEventEditController
|
|||
PhabricatorCalendarEventTransaction::TYPE_NAME)
|
||||
->setNewValue($name);
|
||||
|
||||
$xactions[] = id(new PhabricatorCalendarEventTransaction())
|
||||
->setTransactionType(
|
||||
PhabricatorCalendarEventTransaction::TYPE_ALL_DAY)
|
||||
->setNewValue($is_all_day);
|
||||
|
||||
$xactions[] = id(new PhabricatorCalendarEventTransaction())
|
||||
->setTransactionType(
|
||||
PhabricatorCalendarEventTransaction::TYPE_START_DATE)
|
||||
|
@ -184,6 +191,13 @@ final class PhabricatorCalendarEventEditController
|
|||
->setValue($type)
|
||||
->setOptions($event->getStatusOptions());
|
||||
|
||||
$all_day_select = id(new AphrontFormCheckboxControl())
|
||||
->addCheckbox(
|
||||
'isAllDay',
|
||||
1,
|
||||
pht('All Day Event'),
|
||||
$is_all_day);
|
||||
|
||||
$start_control = id(new AphrontFormDateControl())
|
||||
->setUser($user)
|
||||
->setName('start')
|
||||
|
@ -234,6 +248,7 @@ final class PhabricatorCalendarEventEditController
|
|||
->setUser($user)
|
||||
->appendChild($name)
|
||||
->appendChild($status_select)
|
||||
->appendChild($all_day_select)
|
||||
->appendChild($start_control)
|
||||
->appendChild($end_control)
|
||||
->appendControl($view_policies)
|
||||
|
|
|
@ -183,6 +183,16 @@ final class PhabricatorCalendarEventEditor
|
|||
return parent::applyCustomExternalTransaction($object, $xaction);
|
||||
}
|
||||
|
||||
protected function didApplyInternalEffects(
|
||||
PhabricatorLiskDAO $object,
|
||||
array $xactions) {
|
||||
|
||||
$object->removeViewerTimezone($this->requireActor());
|
||||
|
||||
return $xactions;
|
||||
}
|
||||
|
||||
|
||||
protected function validateAllTransactions(
|
||||
PhabricatorLiskDAO $object,
|
||||
array $xactions) {
|
||||
|
|
|
@ -56,7 +56,13 @@ final class PhabricatorCalendarEventQuery
|
|||
$this->buildOrderClause($conn_r),
|
||||
$this->buildLimitClause($conn_r));
|
||||
|
||||
return $table->loadAllFromArray($data);
|
||||
$events = $table->loadAllFromArray($data);
|
||||
|
||||
foreach ($events as $event) {
|
||||
$event->applyViewerTimezone($this->getViewer());
|
||||
}
|
||||
|
||||
return $events;
|
||||
}
|
||||
|
||||
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn_r) {
|
||||
|
|
|
@ -24,6 +24,7 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
|
|||
protected $editPolicy;
|
||||
|
||||
private $invitees = self::ATTACHABLE;
|
||||
private $appliedViewer;
|
||||
|
||||
const STATUS_AWAY = 1;
|
||||
const STATUS_SPORADIC = 2;
|
||||
|
@ -37,15 +38,112 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
|
|||
return id(new PhabricatorCalendarEvent())
|
||||
->setUserPHID($actor->getPHID())
|
||||
->setIsCancelled(0)
|
||||
->setIsAllDay(0)
|
||||
->setViewPolicy($actor->getPHID())
|
||||
->setEditPolicy($actor->getPHID())
|
||||
->attachInvitees(array());
|
||||
->attachInvitees(array())
|
||||
->applyViewerTimezone($actor);
|
||||
}
|
||||
|
||||
public function applyViewerTimezone(PhabricatorUser $viewer) {
|
||||
if ($this->appliedViewer) {
|
||||
throw new Exception(pht('Viewer timezone is already applied!'));
|
||||
}
|
||||
|
||||
$this->appliedViewer = $viewer;
|
||||
|
||||
if (!$this->getIsAllDay()) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$zone = $viewer->getTimeZone();
|
||||
|
||||
|
||||
$this->setDateFrom(
|
||||
$this->getDateEpochForTimeZone(
|
||||
$this->getDateFrom(),
|
||||
new DateTimeZone('GMT+12'),
|
||||
'Y-m-d',
|
||||
null,
|
||||
$zone));
|
||||
|
||||
$this->setDateTo(
|
||||
$this->getDateEpochForTimeZone(
|
||||
$this->getDateTo(),
|
||||
new DateTimeZone('GMT-12'),
|
||||
'Y-m-d 23:59:59',
|
||||
'-1 day',
|
||||
$zone));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function removeViewerTimezone(PhabricatorUser $viewer) {
|
||||
if (!$this->appliedViewer) {
|
||||
throw new Exception(pht('Viewer timezone is not applied!'));
|
||||
}
|
||||
|
||||
if ($viewer->getPHID() != $this->appliedViewer->getPHID()) {
|
||||
throw new Exception(pht('Removed viewer must match applied viewer!'));
|
||||
}
|
||||
|
||||
$this->appliedViewer = null;
|
||||
|
||||
if (!$this->getIsAllDay()) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$zone = $viewer->getTimeZone();
|
||||
|
||||
$this->setDateFrom(
|
||||
$this->getDateEpochForTimeZone(
|
||||
$this->getDateFrom(),
|
||||
$zone,
|
||||
'Y-m-d',
|
||||
null,
|
||||
new DateTimeZone('GMT+12')));
|
||||
|
||||
$this->setDateTo(
|
||||
$this->getDateEpochForTimeZone(
|
||||
$this->getDateTo(),
|
||||
$zone,
|
||||
'Y-m-d',
|
||||
'+1 day',
|
||||
new DateTimeZone('GMT-12')));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function getDateEpochForTimeZone(
|
||||
$epoch,
|
||||
$src_zone,
|
||||
$format,
|
||||
$adjust,
|
||||
$dst_zone) {
|
||||
|
||||
$src = new DateTime('@'.$epoch);
|
||||
$src->setTimeZone($src_zone);
|
||||
|
||||
if (strlen($adjust)) {
|
||||
$adjust = ' '.$adjust;
|
||||
}
|
||||
|
||||
$dst = new DateTime($src->format($format).$adjust, $dst_zone);
|
||||
return $dst->format('U');
|
||||
}
|
||||
|
||||
public function save() {
|
||||
if ($this->appliedViewer) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Can not save event with viewer timezone still applied!'));
|
||||
}
|
||||
|
||||
if (!$this->mailKey) {
|
||||
$this->mailKey = Filesystem::readRandomCharacters(20);
|
||||
}
|
||||
|
||||
return parent::save();
|
||||
}
|
||||
|
||||
|
|
|
@ -682,6 +682,10 @@ EOBODY;
|
|||
}
|
||||
}
|
||||
|
||||
public function getTimeZone() {
|
||||
return new DateTimeZone($this->getTimezoneIdentifier());
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->getUsername();
|
||||
}
|
||||
|
|
|
@ -569,6 +569,11 @@ abstract class PhabricatorApplicationTransactionEditor
|
|||
return $xaction;
|
||||
}
|
||||
|
||||
protected function didApplyInternalEffects(
|
||||
PhabricatorLiskDAO $object,
|
||||
array $xactions) {
|
||||
return $xactions;
|
||||
}
|
||||
|
||||
protected function applyFinalEffects(
|
||||
PhabricatorLiskDAO $object,
|
||||
|
@ -731,6 +736,8 @@ abstract class PhabricatorApplicationTransactionEditor
|
|||
$this->applyInternalEffects($object, $xaction);
|
||||
}
|
||||
|
||||
$xactions = $this->didApplyInternalEffects($object, $xactions);
|
||||
|
||||
$object->save();
|
||||
|
||||
foreach ($xactions as $xaction) {
|
||||
|
|
Loading…
Reference in a new issue