diff --git a/src/applications/calendar/application/PhabricatorCalendarApplication.php b/src/applications/calendar/application/PhabricatorCalendarApplication.php --- a/src/applications/calendar/application/PhabricatorCalendarApplication.php +++ b/src/applications/calendar/application/PhabricatorCalendarApplication.php @@ -42,7 +42,7 @@ return array( '/E(?P[1-9]\d*)' => 'PhabricatorCalendarEventViewController', '/calendar/' => array( - '(?:query/(?P[^/]+)/)?' + '(?:query/(?P[^/]+)/(?:(?P\d+)/(?P\d+)/)?)?' => 'PhabricatorCalendarEventListController', 'event/' => array( 'create/' diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventListController.php b/src/applications/calendar/controller/PhabricatorCalendarEventListController.php --- a/src/applications/calendar/controller/PhabricatorCalendarEventListController.php +++ b/src/applications/calendar/controller/PhabricatorCalendarEventListController.php @@ -3,20 +3,22 @@ final class PhabricatorCalendarEventListController extends PhabricatorCalendarController { - private $queryKey; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $year = $request->getURIData('year'); + $month = $request->getURIData('month'); + $engine = new PhabricatorCalendarEventSearchEngine(); + + if ($month && $year) { + $engine->setCalendarYearAndMonth($year, $month); + } - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) - ->setSearchEngine(new PhabricatorCalendarEventSearchEngine()) + ->setQueryKey($request->getURIData('queryKey')) + ->setSearchEngine($engine) ->setNavigation($this->buildSideNav()); return $this->delegateToController($controller); } 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 @@ -3,6 +3,9 @@ final class PhabricatorCalendarEventSearchEngine extends PhabricatorApplicationSearchEngine { + private $calendarYear; + private $calendarMonth; + public function getResultTypeDescription() { return pht('Calendar Events'); } @@ -47,6 +50,7 @@ public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { $query = id(new PhabricatorCalendarEventQuery()); + $viewer = $this->requireViewer(); $min_range = null; $max_range = null; @@ -59,6 +63,33 @@ $max_range = $saved->getParameter('rangeEnd'); } + if ($saved->getParameter('display') == 'month') { + list($start_month, $start_year) = $this->getDisplayMonthAndYear($saved); + $start_day = 1; + + $end_year = ($start_month == 12) ? $start_year + 1 : $start_year; + $end_month = ($start_month == 12) ? 1 : $start_month + 1; + $end_day = 1; + + $calendar_start = AphrontFormDateControlValue::newFromParts( + $viewer, + $start_year, + $start_month, + $start_day)->getEpoch(); + $calendar_end = AphrontFormDateControlValue::newFromParts( + $viewer, + $end_year, + $end_month, + $end_day)->getEpoch(); + + if (!$min_range || ($min_range < $calendar_start)) { + $min_range = $calendar_start; + } + if (!$max_range || ($max_range > $calendar_end)) { + $max_range = $calendar_end; + } + } + if ($saved->getParameter('upcoming')) { if ($min_range) { $min_range = max(time(), $min_range); @@ -178,6 +209,13 @@ return $names; } + public function setCalendarYearAndMonth($year, $month) { + $this->calendarYear = $year; + $this->calendarMonth = $month; + + return $this; + } + public function buildSavedQueryFromBuiltin($query_key) { $query = $this->newSavedQuery(); $query->setQueryKey($query_key); @@ -252,25 +290,21 @@ $viewer = $this->requireViewer(); $now = time(); - $epoch = $query->getParameter('rangeStart'); - if (!$epoch) { - $epoch = $query->getParameter('rangeEnd'); - if (!$epoch) { - $epoch = time(); - } - } - - $year = phabricator_format_local_time($epoch, $viewer, 'Y'); - $month = phabricator_format_local_time($epoch, $viewer, 'm'); + list($start_month, $start_year) = $this->getDisplayMonthAndYear($query); $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'); - if ($month == $now_month && $year == $now_year) { - $month_view = new PHUICalendarMonthView($month, $year, $now_day); + if ($start_month == $now_month && $start_year == $now_year) { + $month_view = new PHUICalendarMonthView( + $start_month, + $start_year, + $now_day); } else { - $month_view = new PHUICalendarMonthView($month, $year); + $month_view = new PHUICalendarMonthView( + $start_month, + $start_year); } $month_view->setUser($viewer); @@ -309,9 +343,37 @@ $month_view->addEvent($event); } + $month_view->setBrowseURI( + $this->getURI('query/'.$query->getQueryKey().'/')); + return $month_view; + } + + private function getDisplayMonthAndYear( + PhabricatorSavedQuery $query) { + $viewer = $this->requireViewer(); + // get month/year from url + if ($this->calendarYear && $this->calendarMonth) { + $start_year = $this->calendarYear; + $start_month = $this->calendarMonth; + } else { + $epoch = $query->getParameter('rangeStart'); + if (!$epoch) { + $epoch = $query->getParameter('rangeEnd'); + if (!$epoch) { + $epoch = time(); + } + } + $start_year = phabricator_format_local_time($epoch, $viewer, 'Y'); + $start_month = phabricator_format_local_time($epoch, $viewer, 'm'); + } + + return array($start_month, $start_year); + } + public function getPageSize(PhabricatorSavedQuery $saved) { + return $saved->getParameter('limit', 1000); } } diff --git a/src/view/form/control/AphrontFormDateControlValue.php b/src/view/form/control/AphrontFormDateControlValue.php --- a/src/view/form/control/AphrontFormDateControlValue.php +++ b/src/view/form/control/AphrontFormDateControlValue.php @@ -30,6 +30,23 @@ return ($this->getEpoch() !== null); } + public static function newFromParts( + PhabricatorUser $viewer, + $year, + $month, + $day, + $time = '12:00 AM') { + + $value = new AphrontFormDateControlValue(); + $value->viewer = $viewer; + $value->valueYear = $year; + $value->valueMonth = $month; + $value->valueDay = $day; + $value->valueTime = $time; + + return $value; + } + public static function newFromRequest($request, $key) { $value = new AphrontFormDateControlValue(); $value->viewer = $request->getViewer(); diff --git a/src/view/phui/calendar/PHUICalendarMonthView.php b/src/view/phui/calendar/PHUICalendarMonthView.php --- a/src/view/phui/calendar/PHUICalendarMonthView.php +++ b/src/view/phui/calendar/PHUICalendarMonthView.php @@ -205,14 +205,11 @@ // check for a browseURI, which means we need "fancy" prev / next UI $uri = $this->getBrowseURI(); if ($uri) { - $uri = new PhutilURI($uri); list($prev_year, $prev_month) = $this->getPrevYearAndMonth(); - $query = array('year' => $prev_year, 'month' => $prev_month); - $prev_uri = (string) $uri->setQueryParams($query); + $prev_uri = $uri.$prev_year.'/'.$prev_month.'/'; list($next_year, $next_month) = $this->getNextYearAndMonth(); - $query = array('year' => $next_year, 'month' => $next_month); - $next_uri = (string) $uri->setQueryParams($query); + $next_uri = $uri.$next_year.'/'.$next_month.'/'; $button_bar = new PHUIButtonBarView();