Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14731535
D16274.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
22 KB
Referenced Files
None
Subscribers
None
D16274.diff
View Options
diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventDragController.php b/src/applications/calendar/controller/PhabricatorCalendarEventDragController.php
--- a/src/applications/calendar/controller/PhabricatorCalendarEventDragController.php
+++ b/src/applications/calendar/controller/PhabricatorCalendarEventDragController.php
@@ -29,7 +29,7 @@
$xactions = array();
- $duration = $event->getDateTo() - $event->getDateFrom();
+ $duration = $event->getDuration();
$start = $request->getInt('start');
$start_value = id(AphrontFormDateControlValue::newFromEpoch(
@@ -50,7 +50,6 @@
->setTransactionType(PhabricatorCalendarEventTransaction::TYPE_END_DATE)
->setNewValue($end_value);
-
$editor = id(new PhabricatorCalendarEventEditor())
->setActor($viewer)
->setContinueOnMissingFields(true)
diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php b/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php
--- a/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php
+++ b/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php
@@ -91,10 +91,10 @@
$end_value = AphrontFormDateControlValue::newFromEpoch(
$viewer,
- $event->getDateTo());
+ $event->getViewerDateTo());
$start_value = AphrontFormDateControlValue::newFromEpoch(
$viewer,
- $event->getDateFrom());
+ $event->getViewerDateFrom());
$recurrence_end_date_value = id(clone $end_value)
->setOptional(true);
@@ -137,7 +137,17 @@
$view_policy = $event->getViewPolicy();
$space = $event->getSpacePHID();
+
if ($request->isFormPost()) {
+ $is_all_day = $request->getStr('isAllDay');
+
+ if ($is_all_day) {
+ // TODO: This is a very gross temporary hack to get this working
+ // reasonably: if this is an all day event, force the viewer's
+ // timezone to UTC so the date controls get interpreted as UTC.
+ $viewer->overrideTimezoneIdentifier('UTC');
+ }
+
$xactions = array();
$name = $request->getStr('name');
@@ -159,7 +169,6 @@
$space = $request->getStr('spacePHID');
$is_recurring = $request->getStr('isRecurring') ? 1 : 0;
$frequency = $request->getStr('frequency');
- $is_all_day = $request->getStr('isAllDay');
$icon = $request->getStr('icon');
$invitees = $request->getArr('invitees');
@@ -192,7 +201,7 @@
$xactions[] = id(new PhabricatorCalendarEventTransaction())
->setTransactionType(
PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE)
- ->setNewValue($recurrence_end_date_value);
+ ->setNewValue($recurrence_end_date_value->getEpoch());
}
}
@@ -210,12 +219,12 @@
$xactions[] = id(new PhabricatorCalendarEventTransaction())
->setTransactionType(
PhabricatorCalendarEventTransaction::TYPE_START_DATE)
- ->setNewValue($start_value);
+ ->setNewValue($start_value->getEpoch());
$xactions[] = id(new PhabricatorCalendarEventTransaction())
->setTransactionType(
PhabricatorCalendarEventTransaction::TYPE_END_DATE)
- ->setNewValue($end_value);
+ ->setNewValue($end_value->getEpoch());
}
diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php b/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php
--- a/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php
+++ b/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php
@@ -198,29 +198,29 @@
->setUser($viewer);
if ($event->getIsAllDay()) {
- $date_start = phabricator_date($event->getDateFrom(), $viewer);
- $date_end = phabricator_date($event->getDateTo(), $viewer);
+ $date_start = phabricator_date($event->getViewerDateFrom(), $viewer);
+ $date_end = phabricator_date($event->getViewerDateTo(), $viewer);
if ($date_start == $date_end) {
$properties->addProperty(
pht('Time'),
- phabricator_date($event->getDateFrom(), $viewer));
+ phabricator_date($event->getViewerDateFrom(), $viewer));
} else {
$properties->addProperty(
pht('Starts'),
- phabricator_date($event->getDateFrom(), $viewer));
+ phabricator_date($event->getViewerDateFrom(), $viewer));
$properties->addProperty(
pht('Ends'),
- phabricator_date($event->getDateTo(), $viewer));
+ phabricator_date($event->getViewerDateTo(), $viewer));
}
} else {
$properties->addProperty(
pht('Starts'),
- phabricator_datetime($event->getDateFrom(), $viewer));
+ phabricator_datetime($event->getViewerDateFrom(), $viewer));
$properties->addProperty(
pht('Ends'),
- phabricator_datetime($event->getDateTo(), $viewer));
+ phabricator_datetime($event->getViewerDateTo(), $viewer));
}
if ($event->getIsRecurring()) {
diff --git a/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php b/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
--- a/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
+++ b/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
@@ -22,8 +22,6 @@
array $xactions) {
$actor = $this->requireActor();
- $object->removeViewerTimezone($actor);
-
if ($object->getIsStub()) {
$this->materializeStub($object);
}
@@ -151,7 +149,7 @@
case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
- return $xaction->getNewValue()->getEpoch();
+ return $xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
@@ -308,6 +306,8 @@
}
if ($phids) {
+ $object->applyViewerTimezone($this->getActor());
+
$user = new PhabricatorUser();
$conn_w = $user->establishConnection('w');
queryfx(
@@ -344,15 +344,16 @@
foreach ($xactions as $xaction) {
if ($xaction->getTransactionType() == $start_date_xaction) {
- $start_date = $xaction->getNewValue()->getEpoch();
+ $start_date = $xaction->getNewValue();
} else if ($xaction->getTransactionType() == $end_date_xaction) {
- $end_date = $xaction->getNewValue()->getEpoch();
+ $end_date = $xaction->getNewValue();
} else if ($xaction->getTransactionType() == $recurrence_end_xaction) {
$recurrence_end = $xaction->getNewValue();
} else if ($xaction->getTransactionType() == $is_recurrence_xaction) {
$is_recurring = $xaction->getNewValue();
}
}
+
if ($start_date > $end_date) {
$type = PhabricatorCalendarEventTransaction::TYPE_END_DATE;
$errors[] = new PhabricatorApplicationTransactionValidationError(
@@ -399,20 +400,6 @@
$errors[] = $error;
}
break;
- case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
- case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
- case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
- foreach ($xactions as $xaction) {
- $date_value = $xaction->getNewValue();
- if (!$date_value->isValid()) {
- $errors[] = new PhabricatorApplicationTransactionValidationError(
- $type,
- pht('Invalid'),
- pht('Invalid date.'),
- $xaction);
- }
- }
- break;
}
return $errors;
diff --git a/src/applications/calendar/query/PhabricatorCalendarEventQuery.php b/src/applications/calendar/query/PhabricatorCalendarEventQuery.php
--- a/src/applications/calendar/query/PhabricatorCalendarEventQuery.php
+++ b/src/applications/calendar/query/PhabricatorCalendarEventQuery.php
@@ -90,7 +90,7 @@
protected function getPagingValueMap($cursor, array $keys) {
$event = $this->loadCursorObject($cursor);
return array(
- 'start' => $event->getDateFrom(),
+ 'start' => $event->getViewerDateFrom(),
'id' => $event->getID(),
);
}
@@ -121,7 +121,7 @@
foreach ($events as $key => $event) {
$sequence_start = 0;
$sequence_end = null;
- $duration = $event->getDateTo() - $event->getDateFrom();
+ $duration = $event->getDuration();
$end = null;
$instance_of = $event->getInstanceOfEventPHID();
@@ -137,9 +137,10 @@
$frequency = $event->getFrequencyUnit();
$modify_key = '+1 '.$frequency;
- if ($this->rangeBegin && $this->rangeBegin > $event->getDateFrom()) {
+ if (($this->rangeBegin !== null) &&
+ ($this->rangeBegin > $event->getViewerDateFrom())) {
$max_date = $this->rangeBegin - $duration;
- $date = $event->getDateFrom();
+ $date = $event->getViewerDateFrom();
$datetime = PhabricatorTime::getDateTimeFromEpoch($date, $viewer);
while ($date < $max_date) {
@@ -151,7 +152,7 @@
$start = $this->rangeBegin;
} else {
- $start = $event->getDateFrom() - $duration;
+ $start = $event->getViewerDateFrom() - $duration;
}
$date = $start;
@@ -199,9 +200,9 @@
if ($raw_limit) {
if (count($events) >= $raw_limit) {
- $events = msort($events, 'getDateFrom');
+ $events = msort($events, 'getViewerDateFrom');
$events = array_slice($events, 0, $raw_limit, true);
- $enforced_end = last($events)->getDateFrom();
+ $enforced_end = last($events)->getViewerDateFrom();
}
}
}
@@ -303,18 +304,22 @@
$this->phids);
}
+ // NOTE: The date ranges we query for are larger than the requested ranges
+ // because we need to catch all-day events. We'll refine this range later
+ // after adjusting the visible range of events we load.
+
if ($this->rangeBegin) {
$where[] = qsprintf(
$conn,
'event.dateTo >= %d OR event.isRecurring = 1',
- $this->rangeBegin);
+ $this->rangeBegin - phutil_units('16 hours in seconds'));
}
if ($this->rangeEnd) {
$where[] = qsprintf(
$conn,
'event.dateFrom <= %d',
- $this->rangeEnd);
+ $this->rangeEnd + phutil_units('16 hours in seconds'));
}
if ($this->inviteePHIDs !== null) {
@@ -399,8 +404,8 @@
$viewer = $this->getViewer();
foreach ($events as $key => $event) {
- $event_start = $event->getDateFrom();
- $event_end = $event->getDateTo();
+ $event_start = $event->getViewerDateFrom();
+ $event_end = $event->getViewerDateTo();
if ($range_start && $event_end < $range_start) {
unset($events[$key]);
@@ -466,7 +471,7 @@
}
}
- $events = msort($events, 'getDateFrom');
+ $events = msort($events, 'getViewerDateFrom');
return $events;
}
diff --git a/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php b/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php
--- a/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php
+++ b/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php
@@ -311,11 +311,10 @@
$item->addAttribute($attending);
}
- if (strlen($event->getDuration()) > 0) {
+ if ($event->getDuration()) {
$duration = pht(
'Duration: %s',
- $event->getDuration());
-
+ $event->getDisplayDuration());
$item->addIcon('none', $duration);
}
@@ -370,7 +369,9 @@
$viewer_is_invited = $status->getIsUserInvited($viewer->getPHID());
$event = new AphrontCalendarEventView();
- $event->setEpochRange($status->getDateFrom(), $status->getDateTo());
+ $event->setEpochRange(
+ $status->getViewerDateFrom(),
+ $status->getViewerDateTo());
$event->setIsAllDay($status->getIsAllDay());
$event->setIcon($status->getIcon());
@@ -434,7 +435,9 @@
$event = new AphrontCalendarEventView();
$event->setCanEdit($can_edit);
$event->setEventID($status->getID());
- $event->setEpochRange($status->getDateFrom(), $status->getDateTo());
+ $event->setEpochRange(
+ $status->getViewerDateFrom(),
+ $status->getViewerDateTo());
$event->setIsAllDay($status->getIsAllDay());
$event->setIcon($status->getIcon());
$event->setViewerIsInvited($viewer_is_invited);
@@ -553,10 +556,10 @@
$viewer = $this->requireViewer();
$from_datetime = PhabricatorTime::getDateTimeFromEpoch(
- $event->getDateFrom(),
+ $event->getViewerDateFrom(),
$viewer);
$to_datetime = PhabricatorTime::getDateTimeFromEpoch(
- $event->getDateTo(),
+ $event->getViewerDateTo(),
$viewer);
$from_date_formatted = $from_datetime->format('Y m d');
@@ -566,23 +569,23 @@
if ($from_date_formatted == $to_date_formatted) {
return pht(
'%s, All Day',
- phabricator_date($event->getDateFrom(), $viewer));
+ phabricator_date($event->getViewerDateFrom(), $viewer));
} else {
return pht(
'%s - %s, All Day',
- phabricator_date($event->getDateFrom(), $viewer),
- phabricator_date($event->getDateTo(), $viewer));
+ phabricator_date($event->getViewerDateFrom(), $viewer),
+ phabricator_date($event->getViewerDateTo(), $viewer));
}
} else if ($from_date_formatted == $to_date_formatted) {
return pht(
'%s - %s',
- phabricator_datetime($event->getDateFrom(), $viewer),
- phabricator_time($event->getDateTo(), $viewer));
+ phabricator_datetime($event->getViewerDateFrom(), $viewer),
+ phabricator_time($event->getViewerDateTo(), $viewer));
} else {
return pht(
'%s - %s',
- phabricator_datetime($event->getDateFrom(), $viewer),
- phabricator_datetime($event->getDateTo(), $viewer));
+ phabricator_datetime($event->getViewerDateFrom(), $viewer),
+ phabricator_datetime($event->getViewerDateTo(), $viewer));
}
}
}
diff --git a/src/applications/calendar/storage/PhabricatorCalendarEvent.php b/src/applications/calendar/storage/PhabricatorCalendarEvent.php
--- a/src/applications/calendar/storage/PhabricatorCalendarEvent.php
+++ b/src/applications/calendar/storage/PhabricatorCalendarEvent.php
@@ -41,7 +41,9 @@
private $parentEvent = self::ATTACHABLE;
private $invitees = self::ATTACHABLE;
- private $appliedViewer;
+
+ private $viewerDateFrom;
+ private $viewerDateTo;
// Frequency Constants
const FREQUENCY_DAILY = 'daily';
@@ -157,7 +159,7 @@
$date_time->modify($modify_key);
$date = $date_time->format('U');
- $duration = $parent->getDateTo() - $parent->getDateFrom();
+ $duration = $this->getDuration();
$this
->setDateFrom($date)
@@ -192,74 +194,49 @@
return $ghost;
}
- public function applyViewerTimezone(PhabricatorUser $viewer) {
- if ($this->appliedViewer) {
- throw new Exception(pht('Viewer timezone is already applied!'));
+ public function getViewerDateFrom() {
+ if ($this->viewerDateFrom === null) {
+ throw new PhutilInvalidStateException('applyViewerTimezone');
}
- $this->appliedViewer = $viewer;
+ return $this->viewerDateFrom;
+ }
- if (!$this->getIsAllDay()) {
- return $this;
+ public function getViewerDateTo() {
+ if ($this->viewerDateTo === null) {
+ throw new PhutilInvalidStateException('applyViewerTimezone');
}
- $zone = $viewer->getTimeZone();
+ return $this->viewerDateTo;
+ }
+ public function applyViewerTimezone(PhabricatorUser $viewer) {
+ if (!$this->getIsAllDay()) {
+ $this->viewerDateFrom = $this->getDateFrom();
+ $this->viewerDateTo = $this->getDateTo();
+ } else {
+ $zone = $viewer->getTimeZone();
- $this->setDateFrom(
- $this->getDateEpochForTimeZone(
+ $this->viewerDateFrom = $this->getDateEpochForTimeZone(
$this->getDateFrom(),
- new DateTimeZone('Pacific/Kiritimati'),
+ new DateTimeZone('UTC'),
'Y-m-d',
null,
- $zone));
+ $zone);
- $this->setDateTo(
- $this->getDateEpochForTimeZone(
+ $this->viewerDateTo = $this->getDateEpochForTimeZone(
$this->getDateTo(),
- new DateTimeZone('Pacific/Midway'),
+ new DateTimeZone('UTC'),
'Y-m-d 23:59:00',
- '-1 day',
- $zone));
+ null,
+ $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('Pacific/Kiritimati')));
-
- $this->setDateTo(
- $this->getDateEpochForTimeZone(
- $this->getDateTo(),
- $zone,
- 'Y-m-d',
- '+1 day',
- new DateTimeZone('Pacific/Midway')));
-
- return $this;
+ public function getDuration() {
+ return $this->getDateTo() - $this->getDateFrom();
}
private function getDateEpochForTimeZone(
@@ -281,12 +258,6 @@
}
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);
}
@@ -298,13 +269,13 @@
* Get the event start epoch for evaluating invitee availability.
*
* When assessing availability, we pretend events start earlier than they
- * really. This allows us to mark users away for the entire duration of a
+ * really do. This allows us to mark users away for the entire duration of a
* series of back-to-back meetings, even if they don't strictly overlap.
*
* @return int Event start date for availability caches.
*/
public function getDateFromForCache() {
- return ($this->getDateFrom() - phutil_units('15 minutes in seconds'));
+ return ($this->getViewerDateFrom() - phutil_units('15 minutes in seconds'));
}
protected function getConfiguration() {
@@ -456,8 +427,8 @@
return false;
}
- public function getDuration() {
- $seconds = $this->dateTo - $this->dateFrom;
+ public function getDisplayDuration() {
+ $seconds = $this->getDuration();
$minutes = round($seconds / 60, 1);
$hours = round($minutes / 60, 3);
$days = round($hours / 24, 2);
@@ -470,12 +441,12 @@
round($days, 1));
} else if ($hours >= 1) {
return pht(
- '%s hour(s)',
- round($hours, 1));
+ '%s hour(s)',
+ round($hours, 1));
} else if ($minutes >= 1) {
return pht(
- '%s minute(s)',
- round($minutes, 0));
+ '%s minute(s)',
+ round($minutes, 0));
}
}
diff --git a/src/applications/people/controller/PhabricatorPeopleProfileViewController.php b/src/applications/people/controller/PhabricatorPeopleProfileViewController.php
--- a/src/applications/people/controller/PhabricatorPeopleProfileViewController.php
+++ b/src/applications/people/controller/PhabricatorPeopleProfileViewController.php
@@ -189,41 +189,44 @@
$range_start = $midnight->format('U');
$range_end = $week_end->format('U');
- $query = id(new PhabricatorCalendarEventQuery())
+ $events = id(new PhabricatorCalendarEventQuery())
->setViewer($viewer)
->withDateRange($range_start, $range_end)
->withInvitedPHIDs(array($user->getPHID()))
- ->withIsCancelled(false);
-
- $statuses = $query->execute();
- $phids = mpull($statuses, 'getUserPHID');
- $events = array();
+ ->withIsCancelled(false)
+ ->execute();
- foreach ($statuses as $status) {
- $viewer_is_invited = $status->getIsUserInvited($user->getPHID());
+ $event_views = array();
+ foreach ($events as $event) {
+ $viewer_is_invited = $event->getIsUserInvited($viewer->getPHID());
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
- $status,
+ $event,
PhabricatorPolicyCapability::CAN_EDIT);
- $event = id(new AphrontCalendarEventView())
+ $epoch_min = $event->getViewerDateFrom();
+ $epoch_max = $event->getViewerDateTo();
+
+ $event_view = id(new AphrontCalendarEventView())
->setCanEdit($can_edit)
- ->setEventID($status->getID())
- ->setEpochRange($status->getDateFrom(), $status->getDateTo())
- ->setIsAllDay($status->getIsAllDay())
- ->setIcon($status->getIcon())
+ ->setEventID($event->getID())
+ ->setEpochRange($epoch_min, $epoch_max)
+ ->setIsAllDay($event->getIsAllDay())
+ ->setIcon($event->getIcon())
->setViewerIsInvited($viewer_is_invited)
- ->setName($status->getName())
- ->setURI($status->getURI());
- $events[] = $event;
+ ->setName($event->getName())
+ ->setURI($event->getURI());
+
+ $event_views[] = $event_view;
}
- $events = msort($events, 'getEpochStart');
+ $event_views = msort($event_views, 'getEpochStart');
+
$day_view = id(new PHUICalendarWeekView())
->setViewer($viewer)
->setView('week')
- ->setEvents($events)
+ ->setEvents($event_views)
->setWeekLength(3)
->render();
diff --git a/src/applications/people/query/PhabricatorPeopleQuery.php b/src/applications/people/query/PhabricatorPeopleQuery.php
--- a/src/applications/people/query/PhabricatorPeopleQuery.php
+++ b/src/applications/people/query/PhabricatorPeopleQuery.php
@@ -413,6 +413,13 @@
foreach ($rebuild as $phid => $user) {
$events = idx($map, $phid, array());
+ // We loaded events with the omnipotent user, but want to shift them
+ // into the user's timezone before building the cache because they will
+ // be unavailable during their own local day.
+ foreach ($events as $event) {
+ $event->applyViewerTimezone($user);
+ }
+
$cursor = $min_range;
if ($events) {
// Find the next time when the user has no meetings. If we move forward
@@ -420,7 +427,7 @@
while (true) {
foreach ($events as $event) {
$from = $event->getDateFromForCache();
- $to = $event->getDateTo();
+ $to = $event->getViewerDateTo();
if (($from <= $cursor) && ($to > $cursor)) {
$cursor = $to;
continue 2;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Jan 19, 8:24 AM (21 h, 38 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6999165
Default Alt Text
D16274.diff (22 KB)
Attached To
Mode
D16274: Prepare event dates for EditEngine/API
Attached
Detach File
Event Timeline
Log In to Comment