diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -4160,6 +4160,7 @@ 'PhabricatorProjectBoardController' => 'applications/project/controller/PhabricatorProjectBoardController.php', 'PhabricatorProjectBoardDefaultController' => 'applications/project/controller/PhabricatorProjectBoardDefaultController.php', 'PhabricatorProjectBoardDisableController' => 'applications/project/controller/PhabricatorProjectBoardDisableController.php', + 'PhabricatorProjectBoardFilterController' => 'applications/project/controller/PhabricatorProjectBoardFilterController.php', 'PhabricatorProjectBoardImportController' => 'applications/project/controller/PhabricatorProjectBoardImportController.php', 'PhabricatorProjectBoardManageController' => 'applications/project/controller/PhabricatorProjectBoardManageController.php', 'PhabricatorProjectBoardReorderController' => 'applications/project/controller/PhabricatorProjectBoardReorderController.php', @@ -10424,6 +10425,7 @@ 'PhabricatorProjectBoardController' => 'PhabricatorProjectController', 'PhabricatorProjectBoardDefaultController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardDisableController' => 'PhabricatorProjectBoardController', + 'PhabricatorProjectBoardFilterController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardImportController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardManageController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardReorderController' => 'PhabricatorProjectBoardController', diff --git a/src/applications/project/application/PhabricatorProjectApplication.php b/src/applications/project/application/PhabricatorProjectApplication.php --- a/src/applications/project/application/PhabricatorProjectApplication.php +++ b/src/applications/project/application/PhabricatorProjectApplication.php @@ -66,7 +66,6 @@ 'subprojects/(?P[1-9]\d*)/' => 'PhabricatorProjectSubprojectsController', 'board/(?P[1-9]\d*)/'. - '(?Pfilter/)?'. '(?:query/(?P[^/]+)/)?' => 'PhabricatorProjectBoardViewController', 'move/(?P[1-9]\d*)/' => 'PhabricatorProjectMoveController', @@ -92,6 +91,8 @@ => 'PhabricatorProjectBoardBackgroundController', 'default/(?P[^/]+)/' => 'PhabricatorProjectBoardDefaultController', + 'filter/(?:query/(?P[^/]+)/)?' + => 'PhabricatorProjectBoardFilterController', ), 'column/' => array( 'remove/(?P\d+)/' => diff --git a/src/applications/project/controller/PhabricatorProjectBoardController.php b/src/applications/project/controller/PhabricatorProjectBoardController.php --- a/src/applications/project/controller/PhabricatorProjectBoardController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardController.php @@ -22,7 +22,7 @@ ->readFromRequest($request); } - final protected function newBoardDialog() { + final protected function newWorkboardDialog() { $dialog = $this->newDialog(); $state = $this->getViewState(); diff --git a/src/applications/project/controller/PhabricatorProjectBoardDefaultController.php b/src/applications/project/controller/PhabricatorProjectBoardDefaultController.php --- a/src/applications/project/controller/PhabricatorProjectBoardDefaultController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardDefaultController.php @@ -72,7 +72,7 @@ return id(new AphrontRedirectResponse())->setURI($board_uri); } - return $this->newBoardDialog() + return $this->newWorkboardDialog() ->setTitle($title) ->appendChild($body) ->addCancelButton($board_uri) diff --git a/src/applications/project/controller/PhabricatorProjectBoardFilterController.php b/src/applications/project/controller/PhabricatorProjectBoardFilterController.php new file mode 100644 --- /dev/null +++ b/src/applications/project/controller/PhabricatorProjectBoardFilterController.php @@ -0,0 +1,56 @@ +getViewer(); + + $response = $this->loadProject(); + if ($response) { + return $response; + } + + $project = $this->getProject(); + $state = $this->getViewState(); + $board_uri = $state->newWorkboardURI(); + + $search_engine = $state->getSearchEngine(); + + $is_submit = $request->isFormPost(); + + if ($is_submit) { + $saved_query = $search_engine->buildSavedQueryFromRequest($request); + $search_engine->saveQuery($saved_query); + } else { + $saved_query = $state->getSavedQuery(); + if (!$saved_query) { + return new Aphront404Response(); + } + } + + $filter_form = id(new AphrontFormView()) + ->setUser($viewer); + + $search_engine->buildSearchForm($filter_form, $saved_query); + + $errors = $search_engine->getErrors(); + + if ($is_submit && !$errors) { + $query_key = $saved_query->getQueryKey(); + + $state->setQueryKey($query_key); + $board_uri = $state->newWorkboardURI(); + + return id(new AphrontRedirectResponse())->setURI($board_uri); + } + + return $this->newWorkboardDialog() + ->setWidth(AphrontDialogView::WIDTH_FULL) + ->setTitle(pht('Advanced Filter')) + ->appendChild($filter_form->buildLayoutView()) + ->setErrors($errors) + ->addSubmitButton(pht('Apply Filter')) + ->addCancelButton($board_uri); + } +} diff --git a/src/applications/project/controller/PhabricatorProjectBoardViewController.php b/src/applications/project/controller/PhabricatorProjectBoardViewController.php --- a/src/applications/project/controller/PhabricatorProjectBoardViewController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardViewController.php @@ -21,68 +21,17 @@ $state = $this->getViewState(); $board_uri = $project->getWorkboardURI(); - $search_engine = id(new ManiphestTaskSearchEngine()) - ->setViewer($viewer) - ->setBaseURI($board_uri) - ->setIsBoardView(true); - - if ($request->isFormPost() - && !$request->getBool('initialize') - && !$request->getStr('move') - && !$request->getStr('queryColumnID')) { - $saved = $search_engine->buildSavedQueryFromRequest($request); - $search_engine->saveQuery($saved); - $filter_form = id(new AphrontFormView()) - ->setUser($viewer); - $search_engine->buildSearchForm($filter_form, $saved); - if ($search_engine->getErrors()) { - return $this->newDialog() - ->setWidth(AphrontDialogView::WIDTH_FULL) - ->setTitle(pht('Advanced Filter')) - ->appendChild($filter_form->buildLayoutView()) - ->setErrors($search_engine->getErrors()) - ->setSubmitURI($board_uri) - ->addSubmitButton(pht('Apply Filter')) - ->addCancelButton($board_uri); - } - - $query_key = $saved->getQueryKey(); - $results_uri = $search_engine->getQueryResultsPageURI($query_key); - $results_uri = $state->newURI($results_uri); - - return id(new AphrontRedirectResponse())->setURI($results_uri); - } - + $search_engine = $state->getSearchEngine(); $query_key = $state->getQueryKey(); - - $custom_query = null; - if ($search_engine->isBuiltinQuery($query_key)) { - $saved = $search_engine->buildSavedQueryFromBuiltin($query_key); - } else { - $saved = id(new PhabricatorSavedQueryQuery()) - ->setViewer($viewer) - ->withQueryKeys(array($query_key)) - ->executeOne(); - - if (!$saved) { - return new Aphront404Response(); - } - - $custom_query = $saved; + $saved = $state->getSavedQuery(); + if (!$saved) { + return new Aphront404Response(); } - if ($request->getURIData('filter')) { - $filter_form = id(new AphrontFormView()) - ->setUser($viewer); - $search_engine->buildSearchForm($filter_form, $saved); - - return $this->newDialog() - ->setWidth(AphrontDialogView::WIDTH_FULL) - ->setTitle(pht('Advanced Filter')) - ->appendChild($filter_form->buildLayoutView()) - ->setSubmitURI($board_uri) - ->addSubmitButton(pht('Apply Filter')) - ->addCancelButton($board_uri); + if ($saved->getID()) { + $custom_query = $saved; + } else { + $custom_query = null; } $task_query = $search_engine->buildQueryFromSavedQuery($saved); diff --git a/src/applications/project/state/PhabricatorWorkboardViewState.php b/src/applications/project/state/PhabricatorWorkboardViewState.php --- a/src/applications/project/state/PhabricatorWorkboardViewState.php +++ b/src/applications/project/state/PhabricatorWorkboardViewState.php @@ -3,8 +3,11 @@ final class PhabricatorWorkboardViewState extends Phobject { + private $viewer; private $project; private $requestState = array(); + private $savedQuery; + private $searchEngine; public function setProject(PhabricatorProject $project) { $this->project = $project; @@ -40,9 +43,62 @@ $this->requestState['filter'] = $request->getURIData('queryKey'); } + $this->viewer = $request->getViewer(); + return $this; } + public function getViewer() { + return $this->viewer; + } + + public function getSavedQuery() { + if ($this->savedQuery === null) { + $this->savedQuery = $this->newSavedQuery(); + } + + return $this->savedQuery; + } + + private function newSavedQuery() { + $search_engine = $this->getSearchEngine(); + $query_key = $this->getQueryKey(); + $viewer = $this->getViewer(); + + if ($search_engine->isBuiltinQuery($query_key)) { + $saved_query = $search_engine->buildSavedQueryFromBuiltin($query_key); + } else { + $saved_query = id(new PhabricatorSavedQueryQuery()) + ->setViewer($viewer) + ->withQueryKeys(array($query_key)) + ->executeOne(); + } + + return $saved_query; + } + + public function getSearchEngine() { + if ($this->searchEngine === null) { + $this->searchEngine = $this->newSearchEngine(); + } + + return $this->searchEngine; + } + + private function newSearchEngine() { + $viewer = $this->getViewer(); + + // TODO: This URI is not fully state-preserving, because "SearchEngine" + // does not preserve URI parameters when constructing some URIs at time of + // writing. + $board_uri = $this->getProject()->getWorkboardURI(); + + return id(new ManiphestTaskSearchEngine()) + ->setViewer($viewer) + ->setBaseURI($board_uri) + ->setIsBoardView(true); + } + public function newWorkboardURI($path = null) { $project = $this->getProject(); $uri = urisprintf('%p%p', $project->getWorkboardURI(), $path); @@ -118,6 +174,11 @@ return $this->getDefaultQueryKey(); } + public function setQueryKey($query_key) { + $this->requestState['filter'] = $query_key; + return $this; + } + private function isValidOrder($order) { $map = PhabricatorProjectColumnOrder::getEnabledOrders(); return isset($map[$order]);