2014-02-06 19:10:18 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
final class PhabricatorCalendarEventSearchEngine
|
|
|
|
extends PhabricatorApplicationSearchEngine {
|
|
|
|
|
2015-05-03 01:17:05 +02:00
|
|
|
private $calendarYear;
|
|
|
|
private $calendarMonth;
|
2015-05-04 01:57:18 +02:00
|
|
|
private $calendarDay;
|
2015-05-03 01:17:05 +02:00
|
|
|
|
2014-06-12 22:22:20 +02:00
|
|
|
public function getResultTypeDescription() {
|
|
|
|
return pht('Calendar Events');
|
|
|
|
}
|
|
|
|
|
2015-02-05 00:47:48 +01:00
|
|
|
public function getApplicationClassName() {
|
2014-07-23 02:03:09 +02:00
|
|
|
return 'PhabricatorCalendarApplication';
|
2014-05-08 18:18:02 +02:00
|
|
|
}
|
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
public function newQuery() {
|
|
|
|
return new PhabricatorCalendarEventQuery();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function shouldShowOrderField() {
|
|
|
|
return false;
|
|
|
|
}
|
2014-02-06 19:10:18 +01:00
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
protected function buildCustomSearchFields() {
|
|
|
|
return array(
|
|
|
|
id(new PhabricatorSearchDatasourceField())
|
|
|
|
->setLabel(pht('Created By'))
|
|
|
|
->setKey('creatorPHIDs')
|
|
|
|
->setDatasource(new PhabricatorPeopleUserFunctionDatasource()),
|
|
|
|
id(new PhabricatorSearchDatasourceField())
|
|
|
|
->setLabel(pht('Invited'))
|
|
|
|
->setKey('invitedPHIDs')
|
|
|
|
->setDatasource(new PhabricatorPeopleUserFunctionDatasource()),
|
|
|
|
id(new PhabricatorSearchDateControlField())
|
|
|
|
->setLabel(pht('Occurs After'))
|
|
|
|
->setKey('rangeStart'),
|
|
|
|
id(new PhabricatorSearchDateControlField())
|
|
|
|
->setLabel(pht('Occurs Before'))
|
|
|
|
->setKey('rangeEnd')
|
|
|
|
->setAliases(array('rangeEnd')),
|
|
|
|
id(new PhabricatorSearchCheckboxesField())
|
|
|
|
->setKey('upcoming')
|
|
|
|
->setOptions(array(
|
|
|
|
'upcoming' => pht('Show only upcoming events.'),
|
|
|
|
)),
|
|
|
|
id(new PhabricatorSearchSelectField())
|
|
|
|
->setLabel(pht('Cancelled Events'))
|
|
|
|
->setKey('isCancelled')
|
|
|
|
->setOptions($this->getCancelledOptions())
|
|
|
|
->setDefault('active'),
|
|
|
|
id(new PhabricatorSearchSelectField())
|
|
|
|
->setLabel(pht('Display Options'))
|
|
|
|
->setKey('display')
|
|
|
|
->setOptions($this->getViewOptions())
|
|
|
|
->setDefault('month'),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
private function getCancelledOptions() {
|
|
|
|
return array(
|
|
|
|
'active' => pht('Active Events Only'),
|
|
|
|
'cancelled' => pht('Cancelled Events Only'),
|
|
|
|
'both' => pht('Both Cancelled and Active Events'),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
private function getViewOptions() {
|
|
|
|
return array(
|
|
|
|
'month' => pht('Month View'),
|
|
|
|
'day' => pht('Day View'),
|
|
|
|
'list' => pht('List View'),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function buildQueryFromParameters(array $map) {
|
|
|
|
$query = $this->newQuery();
|
|
|
|
$viewer = $this->requireViewer();
|
|
|
|
|
|
|
|
if ($map['creatorPHIDs']) {
|
|
|
|
$query->withCreatorPHIDs($map['creatorPHIDs']);
|
|
|
|
}
|
2014-02-06 19:10:18 +01:00
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
if ($map['invitedPHIDs']) {
|
|
|
|
$query->withInvitedPHIDs($map['invitedPHIDs']);
|
|
|
|
}
|
2014-02-06 19:10:18 +01:00
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
$range_start = $map['rangeStart'];
|
|
|
|
$range_end = $map['rangeEnd'];
|
|
|
|
$display = $map['display'];
|
2014-02-06 19:10:18 +01:00
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
if ($map['upcoming'] && $map['upcoming'][0] == 'upcoming') {
|
|
|
|
$upcoming = true;
|
|
|
|
} else {
|
|
|
|
$upcoming = false;
|
|
|
|
}
|
2014-02-06 19:10:18 +01:00
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
list($range_start, $range_end) = $this->getQueryDateRange(
|
|
|
|
$range_start,
|
|
|
|
$range_end,
|
|
|
|
$display,
|
|
|
|
$upcoming);
|
2014-02-06 19:10:18 +01:00
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
$query->withDateRange($range_start, $range_end);
|
Canceling calendar events should deactivate the event
Summary: Closes T7943, Canceling calendar event should deactivate the event instead of destroying data.
Test Plan: Create an event, cancel it, see changed status icon, query for active events, event should not appear, query for deactivated events, event should appear in results.
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: Korvin, epriestley
Maniphest Tasks: T7943
Differential Revision: https://secure.phabricator.com/D12604
2015-04-29 17:39:39 +02:00
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
switch ($map['isCancelled']) {
|
|
|
|
case 'active':
|
|
|
|
$query->withIsCancelled(false);
|
|
|
|
break;
|
|
|
|
case 'cancelled':
|
|
|
|
$query->withIsCancelled(true);
|
|
|
|
break;
|
|
|
|
}
|
2015-05-03 00:27:33 +02:00
|
|
|
|
Generate "stub" events earlier, so more infrastructure works with Calendar
Summary:
Ref T9275. When you create a recurring event which recurs forever, we want to avoid writing an infinite number of rows to the database.
Currently, we write a row to the database right before you edit the event. Until then, we refer to it as `E123/999` or whatever ("instance 999 of event 123").
This creates a big mess with trying to make recurring events work with EditEngine, Subscriptions, Projects, Flags, Tokens, etc -- all of this stuff assumes that whatever you're working with has a PHID.
I poked at letting this stuff work without a PHID a little bit, but that looked like a gigantic mess.
Instead, generate an event "stub" a little sooner (when you look at the event detail page). This is basically just an ID/PHID to refer to the instance.
Then, when you edit the stub, "materialize" it into a real event.
This still has some issues, but I think it's more promising than the other approach was.
Also:
- Removes dead user profile calendar controller.
- Replaces comments with EditEngine comments.
Test Plan:
- Commented on a recurring event.
- Awarded tokens to a recurring event.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T9275
Differential Revision: https://secure.phabricator.com/D16248
2016-07-07 16:19:58 +02:00
|
|
|
// Generate ghosts (and ignore stub events) if we aren't querying for
|
|
|
|
// specific events.
|
|
|
|
if (!$map['ids'] && !$map['phids']) {
|
|
|
|
$query
|
|
|
|
->withIsStub(false)
|
|
|
|
->setGenerateGhosts(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $query;
|
2014-02-06 19:10:18 +01:00
|
|
|
}
|
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
private function getQueryDateRange(
|
|
|
|
$start_date_wild,
|
|
|
|
$end_date_wild,
|
|
|
|
$display,
|
|
|
|
$upcoming) {
|
|
|
|
|
|
|
|
$start_date_value = $this->getSafeDate($start_date_wild);
|
|
|
|
$end_date_value = $this->getSafeDate($end_date_wild);
|
|
|
|
|
2015-05-03 01:17:05 +02:00
|
|
|
$viewer = $this->requireViewer();
|
2015-05-06 01:04:00 +02:00
|
|
|
$timezone = new DateTimeZone($viewer->getTimezoneIdentifier());
|
2015-06-22 22:27:37 +02:00
|
|
|
$min_range = null;
|
|
|
|
$max_range = null;
|
2014-02-06 19:10:18 +01:00
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
$min_range = $start_date_value->getEpoch();
|
|
|
|
$max_range = $end_date_value->getEpoch();
|
2015-06-16 22:38:11 +02:00
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
if ($display == 'month' || $display == 'day') {
|
2015-05-06 01:04:00 +02:00
|
|
|
list($start_year, $start_month, $start_day) =
|
2015-06-22 22:27:37 +02:00
|
|
|
$this->getDisplayYearAndMonthAndDay($min_range, $max_range, $display);
|
2015-05-06 01:04:00 +02:00
|
|
|
|
|
|
|
$start_day = new DateTime(
|
|
|
|
"{$start_year}-{$start_month}-{$start_day}",
|
|
|
|
$timezone);
|
|
|
|
$next = clone $start_day;
|
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
if ($display == 'month') {
|
2015-05-06 01:04:00 +02:00
|
|
|
$next->modify('+1 month');
|
2015-06-22 22:27:37 +02:00
|
|
|
} else if ($display == 'day') {
|
|
|
|
$next->modify('+7 day');
|
2015-05-06 01:04:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$display_start = $start_day->format('U');
|
|
|
|
$display_end = $next->format('U');
|
|
|
|
|
Convert some loadPreferences() to getUserSetting()
Summary:
Ref T4103. This doesn't get everything, but takes care of most of the easy stuff.
The tricky-ish bit here is that I need to move timezones, pronouns and translations to proper settings. I expect to pursue that next.
Test Plan:
- Grepped for `loadPreferences` to identify callsites.
- Changed start-of-week setting, loaded Calendar, saw correct start.
- Visited welcome page, read "Adjust Settings" point.
- Loaded Conpherence -- I changed behavior here slightly (switching threads drops the title glyph) but it wasn't consistent to start with and this seems like a good thing to push to the next version of Conpherence.
- Enabled Filetree, toggled in Differential.
- Disabled Filetree, no longer visible in Differential.
- Changed "Unified Diffs" preference to "Small Screens" vs "Always".
- Toggled filetree in Diffusion.
- Edited a task, saw sensible projects in policy dropdown.
- Viewed user profile, uncollapsed/collapsed side nav, reloaded page, sticky'd.
- Toggled "monospaced textareas", used a comment box, got appropriate fonts.
- Toggled durable column.
- Disabled title glyphs.
- Changed monospaced font to 18px/36px impact.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4103
Differential Revision: https://secure.phabricator.com/D16004
2016-06-01 22:59:08 +02:00
|
|
|
$start_of_week = $viewer->getUserSetting(
|
|
|
|
PhabricatorWeekStartDaySetting::SETTINGKEY);
|
2015-05-17 05:13:25 +02:00
|
|
|
|
|
|
|
$end_of_week = ($start_of_week + 6) % 7;
|
2015-05-14 04:02:33 +02:00
|
|
|
|
|
|
|
$first_of_month = $start_day->format('w');
|
|
|
|
$last_of_month = id(clone $next)->modify('-1 day')->format('w');
|
|
|
|
|
2015-05-06 01:04:00 +02:00
|
|
|
if (!$min_range || ($min_range < $display_start)) {
|
|
|
|
$min_range = $display_start;
|
2015-05-14 04:02:33 +02:00
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
if ($display == 'month' &&
|
2015-05-17 05:13:25 +02:00
|
|
|
$first_of_month !== $start_of_week) {
|
|
|
|
$interim_day_num = ($first_of_month + 7 - $start_of_week) % 7;
|
2015-05-14 04:02:33 +02:00
|
|
|
$min_range = id(clone $start_day)
|
2015-05-17 05:13:25 +02:00
|
|
|
->modify('-'.$interim_day_num.' days')
|
2015-05-14 04:02:33 +02:00
|
|
|
->format('U');
|
|
|
|
}
|
2015-05-03 01:17:05 +02:00
|
|
|
}
|
2015-05-06 01:04:00 +02:00
|
|
|
if (!$max_range || ($max_range > $display_end)) {
|
|
|
|
$max_range = $display_end;
|
2015-05-14 04:02:33 +02:00
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
if ($display == 'month' &&
|
2015-05-17 05:13:25 +02:00
|
|
|
$last_of_month !== $end_of_week) {
|
|
|
|
$interim_day_num = ($end_of_week + 7 - $last_of_month) % 7;
|
2015-05-14 04:02:33 +02:00
|
|
|
$max_range = id(clone $next)
|
2015-05-17 05:13:25 +02:00
|
|
|
->modify('+'.$interim_day_num.' days')
|
2015-05-14 04:02:33 +02:00
|
|
|
->format('U');
|
|
|
|
}
|
2015-05-03 01:17:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
if ($upcoming) {
|
2016-07-13 18:29:02 +02:00
|
|
|
$now = PhabricatorTime::getNow();
|
2014-02-06 19:10:18 +01:00
|
|
|
if ($min_range) {
|
2016-07-13 18:29:02 +02:00
|
|
|
$min_range = max($now, $min_range);
|
2014-02-06 19:10:18 +01:00
|
|
|
} else {
|
2016-07-13 18:29:02 +02:00
|
|
|
$min_range = $now;
|
2014-02-06 19:10:18 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
return array($min_range, $max_range);
|
2014-02-06 19:10:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
protected function getURI($path) {
|
2015-05-03 00:27:33 +02:00
|
|
|
return '/calendar/'.$path;
|
2014-02-06 19:10:18 +01:00
|
|
|
}
|
|
|
|
|
2015-01-06 21:34:51 +01:00
|
|
|
protected function getBuiltinQueryNames() {
|
2014-02-06 19:10:18 +01:00
|
|
|
$names = array(
|
2015-05-03 00:27:33 +02:00
|
|
|
'month' => pht('Month View'),
|
2015-05-08 06:18:48 +02:00
|
|
|
'day' => pht('Day View'),
|
2014-02-06 19:10:18 +01:00
|
|
|
'upcoming' => pht('Upcoming Events'),
|
2015-05-03 00:27:33 +02:00
|
|
|
'all' => pht('All Events'),
|
2014-02-06 19:10:18 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
return $names;
|
|
|
|
}
|
|
|
|
|
2015-05-05 21:51:32 +02:00
|
|
|
public function setCalendarYearAndMonthAndDay($year, $month, $day = null) {
|
2015-05-03 01:17:05 +02:00
|
|
|
$this->calendarYear = $year;
|
|
|
|
$this->calendarMonth = $month;
|
2015-05-05 21:51:32 +02:00
|
|
|
$this->calendarDay = $day;
|
2015-05-03 01:17:05 +02:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2014-02-06 19:10:18 +01:00
|
|
|
public function buildSavedQueryFromBuiltin($query_key) {
|
|
|
|
$query = $this->newSavedQuery();
|
|
|
|
$query->setQueryKey($query_key);
|
|
|
|
|
|
|
|
switch ($query_key) {
|
2015-05-03 00:27:33 +02:00
|
|
|
case 'month':
|
|
|
|
return $query->setParameter('display', 'month');
|
2015-05-08 06:18:48 +02:00
|
|
|
case 'day':
|
|
|
|
return $query->setParameter('display', 'day');
|
2014-02-06 19:10:18 +01:00
|
|
|
case 'upcoming':
|
2015-06-25 23:40:06 +02:00
|
|
|
return $query
|
|
|
|
->setParameter('display', 'list')
|
|
|
|
->setParameter('upcoming', array(
|
|
|
|
0 => 'upcoming',
|
|
|
|
));
|
2014-02-06 19:10:18 +01:00
|
|
|
case 'all':
|
|
|
|
return $query;
|
|
|
|
}
|
|
|
|
|
|
|
|
return parent::buildSavedQueryFromBuiltin($query_key);
|
|
|
|
}
|
|
|
|
|
2014-05-08 18:18:02 +02:00
|
|
|
protected function renderResultList(
|
|
|
|
array $events,
|
|
|
|
PhabricatorSavedQuery $query,
|
|
|
|
array $handles) {
|
2015-05-03 00:27:33 +02:00
|
|
|
|
2015-05-12 03:15:27 +02:00
|
|
|
if ($this->isMonthView($query)) {
|
2015-05-03 00:27:33 +02:00
|
|
|
return $this->buildCalendarView($events, $query, $handles);
|
2015-05-12 03:15:27 +02:00
|
|
|
} else if ($this->isDayView($query)) {
|
2015-05-04 01:57:18 +02:00
|
|
|
return $this->buildCalendarDayView($events, $query, $handles);
|
2015-05-03 00:27:33 +02:00
|
|
|
}
|
|
|
|
|
2014-05-08 18:18:02 +02:00
|
|
|
assert_instances_of($events, 'PhabricatorCalendarEvent');
|
|
|
|
$viewer = $this->requireViewer();
|
|
|
|
$list = new PHUIObjectItemListView();
|
2015-06-22 22:27:37 +02:00
|
|
|
|
2014-05-08 18:18:02 +02:00
|
|
|
foreach ($events as $event) {
|
2015-06-23 03:44:08 +02:00
|
|
|
$event_date_info = $this->getEventDateLabel($event);
|
2015-06-18 20:02:12 +02:00
|
|
|
$attendees = array();
|
2015-06-23 03:44:08 +02:00
|
|
|
|
2015-06-18 20:02:12 +02:00
|
|
|
foreach ($event->getInvitees() as $invitee) {
|
2016-04-21 19:19:19 +02:00
|
|
|
$status_attending = PhabricatorCalendarEventInvitee::STATUS_ATTENDING;
|
|
|
|
if ($invitee->getStatus() === $status_attending) {
|
|
|
|
$attendees[] = $invitee->getInviteePHID();
|
|
|
|
}
|
2015-06-18 20:02:12 +02:00
|
|
|
}
|
|
|
|
|
2015-08-03 16:01:42 +02:00
|
|
|
if ($event->getIsGhostEvent()) {
|
|
|
|
$title_text = $event->getMonogram()
|
|
|
|
.' ('
|
|
|
|
.$event->getSequenceIndex()
|
|
|
|
.'): '
|
|
|
|
.$event->getName();
|
|
|
|
} else {
|
|
|
|
$title_text = $event->getMonogram().': '.$event->getName();
|
|
|
|
}
|
|
|
|
|
2014-05-08 18:18:02 +02:00
|
|
|
$item = id(new PHUIObjectItemView())
|
Events should offer Spaces as the view policy options
Summary: Ref T8687, Events should offer Spaces as the view policy options
Test Plan: Create event, choose default Space, save, edit, choose different Space, save, new policy should be reflected on Event.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: epriestley, Korvin
Maniphest Tasks: T8687
Differential Revision: https://secure.phabricator.com/D13459
2015-06-27 19:26:24 +02:00
|
|
|
->setUser($viewer)
|
|
|
|
->setObject($event)
|
2015-08-03 16:01:42 +02:00
|
|
|
->setHeader($title_text)
|
|
|
|
->setHref($event->getURI())
|
2016-02-07 19:00:14 +01:00
|
|
|
->addAttribute($event_date_info);
|
|
|
|
|
|
|
|
if ($attendees) {
|
|
|
|
$attending = pht(
|
|
|
|
'Attending: %s',
|
|
|
|
$viewer->renderHandleList($attendees)
|
|
|
|
->setAsInline(1)
|
|
|
|
->render());
|
|
|
|
|
|
|
|
$item->addAttribute($attending);
|
|
|
|
}
|
|
|
|
|
2016-07-12 00:29:11 +02:00
|
|
|
if ($event->getDuration()) {
|
2016-02-07 19:00:14 +01:00
|
|
|
$duration = pht(
|
|
|
|
'Duration: %s',
|
2016-07-12 00:29:11 +02:00
|
|
|
$event->getDisplayDuration());
|
2016-02-07 19:00:14 +01:00
|
|
|
$item->addIcon('none', $duration);
|
|
|
|
}
|
2014-05-08 18:18:02 +02:00
|
|
|
|
|
|
|
$list->addItem($item);
|
|
|
|
}
|
|
|
|
|
2015-06-19 12:46:20 +02:00
|
|
|
$result = new PhabricatorApplicationSearchResultView();
|
|
|
|
$result->setObjectList($list);
|
|
|
|
$result->setNoDataString(pht('No events found.'));
|
|
|
|
|
|
|
|
return $result;
|
2014-05-08 18:18:02 +02:00
|
|
|
}
|
|
|
|
|
2015-05-03 00:27:33 +02:00
|
|
|
private function buildCalendarView(
|
|
|
|
array $statuses,
|
|
|
|
PhabricatorSavedQuery $query,
|
|
|
|
array $handles) {
|
2015-06-22 22:27:37 +02:00
|
|
|
|
2015-05-03 00:27:33 +02:00
|
|
|
$viewer = $this->requireViewer();
|
|
|
|
$now = time();
|
|
|
|
|
2015-05-05 21:51:32 +02:00
|
|
|
list($start_year, $start_month) =
|
2015-06-22 22:27:37 +02:00
|
|
|
$this->getDisplayYearAndMonthAndDay(
|
|
|
|
$this->getQueryDateFrom($query)->getEpoch(),
|
|
|
|
$this->getQueryDateTo($query)->getEpoch(),
|
|
|
|
$query->getParameter('display'));
|
2015-05-03 00:27:33 +02:00
|
|
|
|
|
|
|
$now_year = phabricator_format_local_time($now, $viewer, 'Y');
|
|
|
|
$now_month = phabricator_format_local_time($now, $viewer, 'm');
|
|
|
|
$now_day = phabricator_format_local_time($now, $viewer, 'j');
|
|
|
|
|
2015-05-03 01:17:05 +02:00
|
|
|
if ($start_month == $now_month && $start_year == $now_year) {
|
|
|
|
$month_view = new PHUICalendarMonthView(
|
2015-06-22 22:27:37 +02:00
|
|
|
$this->getQueryDateFrom($query),
|
|
|
|
$this->getQueryDateTo($query),
|
2015-05-03 01:17:05 +02:00
|
|
|
$start_month,
|
|
|
|
$start_year,
|
|
|
|
$now_day);
|
2015-05-03 00:27:33 +02:00
|
|
|
} else {
|
2015-05-03 01:17:05 +02:00
|
|
|
$month_view = new PHUICalendarMonthView(
|
2015-06-22 22:27:37 +02:00
|
|
|
$this->getQueryDateFrom($query),
|
|
|
|
$this->getQueryDateTo($query),
|
2015-05-03 01:17:05 +02:00
|
|
|
$start_month,
|
|
|
|
$start_year);
|
2015-05-03 00:27:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$month_view->setUser($viewer);
|
|
|
|
|
2016-07-13 20:33:43 +02:00
|
|
|
$phids = mpull($statuses, 'getHostPHID');
|
|
|
|
$handles = $viewer->loadHandles($phids);
|
2015-05-03 00:27:33 +02:00
|
|
|
|
|
|
|
foreach ($statuses as $status) {
|
2015-05-15 04:20:44 +02:00
|
|
|
$viewer_is_invited = $status->getIsUserInvited($viewer->getPHID());
|
|
|
|
|
2015-05-03 00:27:33 +02:00
|
|
|
$event = new AphrontCalendarEventView();
|
2016-07-12 00:29:11 +02:00
|
|
|
$event->setEpochRange(
|
|
|
|
$status->getViewerDateFrom(),
|
|
|
|
$status->getViewerDateTo());
|
2015-05-12 03:15:27 +02:00
|
|
|
$event->setIsAllDay($status->getIsAllDay());
|
2015-05-20 01:55:36 +02:00
|
|
|
$event->setIcon($status->getIcon());
|
2015-05-03 00:27:33 +02:00
|
|
|
|
2016-07-13 20:33:43 +02:00
|
|
|
$name_text = $handles[$status->getHostPHID()]->getName();
|
2015-05-10 19:40:55 +02:00
|
|
|
$status_text = $status->getName();
|
2016-07-13 20:33:43 +02:00
|
|
|
$event->setHostPHID($status->getHostPHID());
|
2015-05-03 00:27:33 +02:00
|
|
|
$event->setDescription(pht('%s (%s)', $name_text, $status_text));
|
|
|
|
$event->setName($status_text);
|
2015-05-29 02:27:25 +02:00
|
|
|
$event->setURI($status->getURI());
|
2015-05-15 04:20:44 +02:00
|
|
|
$event->setViewerIsInvited($viewer_is_invited);
|
2015-05-03 00:27:33 +02:00
|
|
|
$month_view->addEvent($event);
|
|
|
|
}
|
|
|
|
|
2015-05-03 01:17:05 +02:00
|
|
|
$month_view->setBrowseURI(
|
|
|
|
$this->getURI('query/'.$query->getQueryKey().'/'));
|
|
|
|
|
2015-06-19 12:46:20 +02:00
|
|
|
// TODO redesign-2015 : Move buttons out of PHUICalendarView?
|
|
|
|
$result = new PhabricatorApplicationSearchResultView();
|
|
|
|
$result->setContent($month_view);
|
|
|
|
|
|
|
|
return $result;
|
2015-05-03 01:17:05 +02:00
|
|
|
}
|
|
|
|
|
2015-05-04 01:57:18 +02:00
|
|
|
private function buildCalendarDayView(
|
|
|
|
array $statuses,
|
|
|
|
PhabricatorSavedQuery $query,
|
|
|
|
array $handles) {
|
2015-06-22 22:27:37 +02:00
|
|
|
|
2015-05-04 01:57:18 +02:00
|
|
|
$viewer = $this->requireViewer();
|
2015-06-22 22:27:37 +02:00
|
|
|
|
2015-05-05 21:51:32 +02:00
|
|
|
list($start_year, $start_month, $start_day) =
|
2015-06-22 22:27:37 +02:00
|
|
|
$this->getDisplayYearAndMonthAndDay(
|
|
|
|
$this->getQueryDateFrom($query)->getEpoch(),
|
|
|
|
$this->getQueryDateTo($query)->getEpoch(),
|
|
|
|
$query->getParameter('display'));
|
2015-05-04 01:57:18 +02:00
|
|
|
|
2015-05-24 20:22:33 +02:00
|
|
|
$day_view = id(new PHUICalendarDayView(
|
2015-06-22 22:27:37 +02:00
|
|
|
$this->getQueryDateFrom($query)->getEpoch(),
|
|
|
|
$this->getQueryDateTo($query)->getEpoch(),
|
2015-05-04 01:57:18 +02:00
|
|
|
$start_year,
|
2015-05-05 21:51:32 +02:00
|
|
|
$start_month,
|
2015-05-24 20:22:33 +02:00
|
|
|
$start_day))
|
|
|
|
->setQuery($query->getQueryKey());
|
2015-05-04 01:57:18 +02:00
|
|
|
|
|
|
|
$day_view->setUser($viewer);
|
|
|
|
|
2016-07-13 20:33:43 +02:00
|
|
|
$phids = mpull($statuses, 'getHostPHID');
|
2015-05-04 01:57:18 +02:00
|
|
|
|
|
|
|
foreach ($statuses as $status) {
|
2015-05-08 22:27:48 +02:00
|
|
|
if ($status->getIsCancelled()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-05-15 04:20:44 +02:00
|
|
|
$viewer_is_invited = $status->getIsUserInvited($viewer->getPHID());
|
|
|
|
|
2015-05-24 20:22:33 +02:00
|
|
|
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
|
|
|
$viewer,
|
|
|
|
$status,
|
|
|
|
PhabricatorPolicyCapability::CAN_EDIT);
|
|
|
|
|
2015-05-07 04:19:14 +02:00
|
|
|
$event = new AphrontCalendarEventView();
|
2015-05-24 20:22:33 +02:00
|
|
|
$event->setCanEdit($can_edit);
|
2015-05-05 06:23:18 +02:00
|
|
|
$event->setEventID($status->getID());
|
2016-07-12 00:29:11 +02:00
|
|
|
$event->setEpochRange(
|
|
|
|
$status->getViewerDateFrom(),
|
|
|
|
$status->getViewerDateTo());
|
2015-05-08 22:27:48 +02:00
|
|
|
$event->setIsAllDay($status->getIsAllDay());
|
2015-05-20 01:55:36 +02:00
|
|
|
$event->setIcon($status->getIcon());
|
2015-05-15 04:20:44 +02:00
|
|
|
$event->setViewerIsInvited($viewer_is_invited);
|
2015-05-04 01:57:18 +02:00
|
|
|
|
|
|
|
$event->setName($status->getName());
|
2015-05-29 02:27:25 +02:00
|
|
|
$event->setURI($status->getURI());
|
2015-05-04 01:57:18 +02:00
|
|
|
$day_view->addEvent($event);
|
|
|
|
}
|
|
|
|
|
2015-05-05 21:51:32 +02:00
|
|
|
$day_view->setBrowseURI(
|
|
|
|
$this->getURI('query/'.$query->getQueryKey().'/'));
|
|
|
|
|
2015-06-19 12:46:20 +02:00
|
|
|
$result = new PhabricatorApplicationSearchResultView();
|
|
|
|
$result->setContent($day_view);
|
|
|
|
|
|
|
|
return $result;
|
2015-05-04 01:57:18 +02:00
|
|
|
}
|
|
|
|
|
2015-05-05 21:51:32 +02:00
|
|
|
private function getDisplayYearAndMonthAndDay(
|
2015-06-22 22:27:37 +02:00
|
|
|
$range_start,
|
|
|
|
$range_end,
|
|
|
|
$display) {
|
|
|
|
|
2015-05-03 01:17:05 +02:00
|
|
|
$viewer = $this->requireViewer();
|
2015-06-22 22:27:37 +02:00
|
|
|
$epoch = null;
|
|
|
|
|
2015-05-03 01:17:05 +02:00
|
|
|
if ($this->calendarYear && $this->calendarMonth) {
|
|
|
|
$start_year = $this->calendarYear;
|
|
|
|
$start_month = $this->calendarMonth;
|
2015-05-05 21:51:32 +02:00
|
|
|
$start_day = $this->calendarDay ? $this->calendarDay : 1;
|
2015-05-04 01:57:18 +02:00
|
|
|
} else {
|
2015-06-22 22:27:37 +02:00
|
|
|
if ($range_start) {
|
|
|
|
$epoch = $range_start;
|
|
|
|
} else if ($range_end) {
|
|
|
|
$epoch = $range_end;
|
|
|
|
} else {
|
|
|
|
$epoch = time();
|
2015-05-04 01:57:18 +02:00
|
|
|
}
|
2015-06-22 22:27:37 +02:00
|
|
|
if ($display == 'month') {
|
2015-05-12 03:15:27 +02:00
|
|
|
$day = 1;
|
|
|
|
} else {
|
|
|
|
$day = phabricator_format_local_time($epoch, $viewer, 'd');
|
|
|
|
}
|
2015-05-04 01:57:18 +02:00
|
|
|
$start_year = phabricator_format_local_time($epoch, $viewer, 'Y');
|
|
|
|
$start_month = phabricator_format_local_time($epoch, $viewer, 'm');
|
2015-05-12 03:15:27 +02:00
|
|
|
$start_day = $day;
|
2015-05-04 01:57:18 +02:00
|
|
|
}
|
|
|
|
return array($start_year, $start_month, $start_day);
|
|
|
|
}
|
|
|
|
|
2015-05-03 01:17:05 +02:00
|
|
|
public function getPageSize(PhabricatorSavedQuery $saved) {
|
2015-06-03 03:26:51 +02:00
|
|
|
if ($this->isMonthView($saved) || $this->isDayView($saved)) {
|
|
|
|
return $saved->getParameter('limit', 1000);
|
|
|
|
} else {
|
|
|
|
return $saved->getParameter('limit', 100);
|
|
|
|
}
|
2015-05-03 00:27:33 +02:00
|
|
|
}
|
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
private function getQueryDateFrom(PhabricatorSavedQuery $saved) {
|
|
|
|
return $this->getQueryDate($saved, 'rangeStart');
|
2015-05-04 19:08:49 +02:00
|
|
|
}
|
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
private function getQueryDateTo(PhabricatorSavedQuery $saved) {
|
|
|
|
return $this->getQueryDate($saved, 'rangeEnd');
|
2015-05-04 19:08:49 +02:00
|
|
|
}
|
|
|
|
|
2015-06-22 22:27:37 +02:00
|
|
|
private function getQueryDate(PhabricatorSavedQuery $saved, $key) {
|
2015-05-04 19:08:49 +02:00
|
|
|
$viewer = $this->requireViewer();
|
|
|
|
|
|
|
|
$wild = $saved->getParameter($key);
|
2015-06-22 22:27:37 +02:00
|
|
|
return $this->getSafeDate($wild);
|
|
|
|
}
|
|
|
|
|
|
|
|
private function getSafeDate($value) {
|
|
|
|
$viewer = $this->requireViewer();
|
|
|
|
if ($value) {
|
|
|
|
// ideally this would be consistent and always pass in the same type
|
|
|
|
if ($value instanceof AphrontFormDateControlValue) {
|
|
|
|
return $value;
|
|
|
|
} else {
|
|
|
|
$value = AphrontFormDateControlValue::newFromWild($viewer, $value);
|
|
|
|
}
|
2015-05-04 19:08:49 +02:00
|
|
|
} else {
|
|
|
|
$value = AphrontFormDateControlValue::newFromEpoch(
|
|
|
|
$viewer,
|
2015-05-07 03:41:48 +02:00
|
|
|
PhabricatorTime::getTodayMidnightDateTime($viewer)->format('U'));
|
2015-05-04 19:08:49 +02:00
|
|
|
$value->setEnabled(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
$value->setOptional(true);
|
|
|
|
|
|
|
|
return $value;
|
|
|
|
}
|
|
|
|
|
2015-05-12 03:15:27 +02:00
|
|
|
private function isMonthView(PhabricatorSavedQuery $query) {
|
|
|
|
if ($this->isDayView($query)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if ($query->getParameter('display') == 'month') {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private function isDayView(PhabricatorSavedQuery $query) {
|
|
|
|
if ($query->getParameter('display') == 'day') {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if ($this->calendarDay) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2015-06-23 03:44:08 +02:00
|
|
|
|
|
|
|
private function getEventDateLabel($event) {
|
|
|
|
$viewer = $this->requireViewer();
|
|
|
|
|
|
|
|
$from_datetime = PhabricatorTime::getDateTimeFromEpoch(
|
2016-07-12 00:29:11 +02:00
|
|
|
$event->getViewerDateFrom(),
|
2015-06-23 03:44:08 +02:00
|
|
|
$viewer);
|
|
|
|
$to_datetime = PhabricatorTime::getDateTimeFromEpoch(
|
2016-07-12 00:29:11 +02:00
|
|
|
$event->getViewerDateTo(),
|
2015-06-23 03:44:08 +02:00
|
|
|
$viewer);
|
|
|
|
|
|
|
|
$from_date_formatted = $from_datetime->format('Y m d');
|
|
|
|
$to_date_formatted = $to_datetime->format('Y m d');
|
|
|
|
|
|
|
|
if ($event->getIsAllDay()) {
|
|
|
|
if ($from_date_formatted == $to_date_formatted) {
|
|
|
|
return pht(
|
|
|
|
'%s, All Day',
|
2016-07-12 00:29:11 +02:00
|
|
|
phabricator_date($event->getViewerDateFrom(), $viewer));
|
2015-06-23 03:44:08 +02:00
|
|
|
} else {
|
|
|
|
return pht(
|
|
|
|
'%s - %s, All Day',
|
2016-07-12 00:29:11 +02:00
|
|
|
phabricator_date($event->getViewerDateFrom(), $viewer),
|
|
|
|
phabricator_date($event->getViewerDateTo(), $viewer));
|
2015-06-23 03:44:08 +02:00
|
|
|
}
|
|
|
|
} else if ($from_date_formatted == $to_date_formatted) {
|
|
|
|
return pht(
|
|
|
|
'%s - %s',
|
2016-07-12 00:29:11 +02:00
|
|
|
phabricator_datetime($event->getViewerDateFrom(), $viewer),
|
|
|
|
phabricator_time($event->getViewerDateTo(), $viewer));
|
2015-06-23 03:44:08 +02:00
|
|
|
} else {
|
|
|
|
return pht(
|
|
|
|
'%s - %s',
|
2016-07-12 00:29:11 +02:00
|
|
|
phabricator_datetime($event->getViewerDateFrom(), $viewer),
|
|
|
|
phabricator_datetime($event->getViewerDateTo(), $viewer));
|
2015-06-23 03:44:08 +02:00
|
|
|
}
|
|
|
|
}
|
2014-02-06 19:10:18 +01:00
|
|
|
}
|