Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15414273
D16668.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Referenced Files
None
Subscribers
None
D16668.diff
View Options
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
@@ -165,70 +165,54 @@
// discard anything outside of the time window.
$events = $this->getEventsInRange($events);
- $enforced_end = null;
+ $generate_from = $this->rangeBegin;
+ $generate_until = $this->rangeEnd;
foreach ($parents as $key => $event) {
- $sequence_start = 0;
- $sequence_end = null;
- $start = null;
-
$duration = $event->getDuration();
- $frequency = $event->getFrequencyUnit();
- $modify_key = '+1 '.$frequency;
-
- if (($this->rangeBegin !== null) &&
- ($this->rangeBegin > $event->getStartDateTimeEpoch())) {
- $max_date = $this->rangeBegin - $duration;
- $date = $event->getStartDateTimeEpoch();
- $datetime = PhabricatorTime::getDateTimeFromEpoch($date, $viewer);
+ $start_date = $this->getRecurrenceWindowStart(
+ $event,
+ $generate_from - $duration);
- while ($date < $max_date) {
- // TODO: optimize this to not loop through all off-screen events
- $sequence_start++;
- $datetime = PhabricatorTime::getDateTimeFromEpoch($date, $viewer);
- $date = $datetime->modify($modify_key)->format('U');
- }
+ $end_date = $this->getRecurrenceWindowEnd(
+ $event,
+ $generate_until);
- $start = $this->rangeBegin;
- } else {
- $start = $event->getStartDateTimeEpoch() - $duration;
- }
+ $limit = $this->getRecurrenceLimit($event, $raw_limit);
- $date = $start;
- $datetime = PhabricatorTime::getDateTimeFromEpoch($date, $viewer);
+ $set = $event->newRecurrenceSet();
- // Select the minimum end time we need to generate events until.
- $end_times = array();
- if ($this->rangeEnd) {
- $end_times[] = $this->rangeEnd;
- }
+ $recurrences = $set->getEventsBetween(
+ null,
+ $end_date,
+ $limit + 1);
- if ($event->getUntilDateTimeEpoch()) {
- $end_times[] = $event->getUntilDateTimeEpoch();
+ // We're generating events from the beginning and then filtering them
+ // here (instead of only generating events starting at the start date)
+ // because we need to know the proper sequence indexes to generate ghost
+ // events. This may change after RDATE support.
+ if ($start_date) {
+ $start_epoch = $start_date->getEpoch();
+ } else {
+ $start_epoch = null;
}
- if ($enforced_end) {
- $end_times[] = $enforced_end;
- }
+ foreach ($recurrences as $sequence_index => $sequence_datetime) {
+ if (!$sequence_index) {
+ // This is the parent event, which we already have.
+ continue;
+ }
- if ($end_times) {
- $end = min($end_times);
- $sequence_end = $sequence_start;
- while ($date < $end) {
- $sequence_end++;
- $datetime->modify($modify_key);
- $date = $datetime->format('U');
- if ($sequence_end > $raw_limit + $sequence_start) {
- break;
+ if ($start_epoch) {
+ if ($sequence_datetime->getEpoch() < $start_epoch) {
+ continue;
}
}
- } else {
- $sequence_end = $raw_limit + $sequence_start;
- }
- $sequence_start = max(1, $sequence_start);
- for ($index = $sequence_start; $index < $sequence_end; $index++) {
- $events[] = $event->newGhost($viewer, $index);
+ $events[] = $event->newGhost(
+ $viewer,
+ $sequence_index,
+ $sequence_datetime);
}
// NOTE: We're slicing results every time because this makes it cheaper
@@ -240,7 +224,7 @@
if (count($events) > $raw_limit) {
$events = msort($events, 'getStartDateTimeEpoch');
$events = array_slice($events, 0, $raw_limit, true);
- $enforced_end = last($events)->getStartDateTimeEpoch();
+ $generate_until = last($events)->getEndDateTimeEpoch();
}
}
}
@@ -525,4 +509,44 @@
return $events;
}
+ private function getRecurrenceWindowStart(
+ PhabricatorCalendarEvent $event,
+ $generate_from) {
+
+ if (!$generate_from) {
+ return null;
+ }
+
+ return PhutilCalendarAbsoluteDateTime::newFromEpoch($generate_from);
+ }
+
+ private function getRecurrenceWindowEnd(
+ PhabricatorCalendarEvent $event,
+ $generate_until) {
+
+ $end_epochs = array();
+ if ($generate_until) {
+ $end_epochs[] = $generate_until;
+ }
+
+ $until_epoch = $event->getUntilDateTimeEpoch();
+ if ($until_epoch) {
+ $end_epochs[] = $until_epoch;
+ }
+
+ if (!$end_epochs) {
+ return null;
+ }
+
+ return PhutilCalendarAbsoluteDateTime::newFromEpoch(min($end_epochs));
+ }
+
+ private function getRecurrenceLimit(
+ PhabricatorCalendarEvent $event,
+ $raw_limit) {
+
+ return $raw_limit;
+ }
+
+
}
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
@@ -103,7 +103,10 @@
->applyViewerTimezone($actor);
}
- private function newChild(PhabricatorUser $actor, $sequence) {
+ private function newChild(
+ PhabricatorUser $actor,
+ $sequence,
+ PhutilCalendarDateTime $start = null) {
if (!$this->isParentEvent()) {
throw new Exception(
pht(
@@ -124,7 +127,7 @@
->setDateFrom(0)
->setDateTo(0);
- return $child->copyFromParent($actor);
+ return $child->copyFromParent($actor, $start);
}
protected function readField($field) {
@@ -156,7 +159,10 @@
}
- public function copyFromParent(PhabricatorUser $actor) {
+ public function copyFromParent(
+ PhabricatorUser $actor,
+ PhutilCalendarDateTime $start = null) {
+
if (!$this->isChildEvent()) {
throw new Exception(
pht(
@@ -176,11 +182,18 @@
->setDescription($parent->getDescription());
$sequence = $this->getSequenceIndex();
- $start_datetime = $parent->newSequenceIndexDateTime($sequence);
- if (!$start_datetime) {
- throw new Exception(
- "Sequence {$sequence} does not exist for event!");
+ if ($start) {
+ $start_datetime = $start;
+ } else {
+ $start_datetime = $parent->newSequenceIndexDateTime($sequence);
+
+ if (!$start_datetime) {
+ throw new Exception(
+ pht(
+ 'Sequence "%s" is not valid for event!',
+ $sequence));
+ }
}
$duration = $parent->newDuration();
@@ -225,8 +238,12 @@
return $stub;
}
- public function newGhost(PhabricatorUser $actor, $sequence) {
- $ghost = $this->newChild($actor, $sequence);
+ public function newGhost(
+ PhabricatorUser $actor,
+ $sequence,
+ PhutilCalendarDateTime $start = null) {
+
+ $ghost = $this->newChild($actor, $sequence, $start);
$ghost
->setIsGhostEvent(true)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Mar 20, 11:51 PM (2 d, 2 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7707563
Default Alt Text
D16668.diff (7 KB)
Attached To
Mode
D16668: Drive calendar event queries through the RRULE engine
Attached
Detach File
Event Timeline
Log In to Comment