diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 11520bf1fb..bbdaccf6ea 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1863,6 +1863,7 @@ phutil_register_library_map(array( 'PhrictionNewController' => 'applications/phriction/controller/PhrictionNewController.php', 'PhrictionPHIDTypeDocument' => 'applications/phriction/phid/PhrictionPHIDTypeDocument.php', 'PhrictionRemarkupRule' => 'applications/phriction/remarkup/PhrictionRemarkupRule.php', + 'PhrictionSearchEngine' => 'applications/phriction/query/PhrictionSearchEngine.php', 'PhrictionSearchIndexer' => 'applications/phriction/search/PhrictionSearchIndexer.php', 'PonderAddAnswerView' => 'applications/ponder/view/PonderAddAnswerView.php', 'PonderAddCommentView' => 'applications/ponder/view/PonderAddCommentView.php', @@ -3957,11 +3958,16 @@ phutil_register_library_map(array( 'PhrictionDocumentTestCase' => 'PhabricatorTestCase', 'PhrictionEditController' => 'PhrictionController', 'PhrictionHistoryController' => 'PhrictionController', - 'PhrictionListController' => 'PhrictionController', + 'PhrictionListController' => + array( + 0 => 'PhrictionController', + 1 => 'PhabricatorApplicationSearchResultsControllerInterface', + ), 'PhrictionMoveController' => 'PhrictionController', 'PhrictionNewController' => 'PhrictionController', 'PhrictionPHIDTypeDocument' => 'PhabricatorPHIDType', 'PhrictionRemarkupRule' => 'PhutilRemarkupRule', + 'PhrictionSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhrictionSearchIndexer' => 'PhabricatorSearchDocumentIndexer', 'PonderAddAnswerView' => 'AphrontView', 'PonderAddCommentView' => 'AphrontView', diff --git a/src/applications/phriction/application/PhabricatorApplicationPhriction.php b/src/applications/phriction/application/PhabricatorApplicationPhriction.php index f27d3ef299..508dc772cc 100644 --- a/src/applications/phriction/application/PhabricatorApplicationPhriction.php +++ b/src/applications/phriction/application/PhabricatorApplicationPhriction.php @@ -42,8 +42,7 @@ final class PhabricatorApplicationPhriction extends PhabricatorApplication { '/w/(?P.+/)' => 'PhrictionDocumentController', '/phriction/' => array( - '' => 'PhrictionListController', - 'list/(?P[^/]+)/' => 'PhrictionListController', + '(?:query/(?P[^/]+)/)?' => 'PhrictionListController', 'history(?P/)' => 'PhrictionHistoryController', 'history/(?P.+/)' => 'PhrictionHistoryController', diff --git a/src/applications/phriction/controller/PhrictionController.php b/src/applications/phriction/controller/PhrictionController.php index d904294b4f..c8d93fffa9 100644 --- a/src/applications/phriction/controller/PhrictionController.php +++ b/src/applications/phriction/controller/PhrictionController.php @@ -5,45 +5,28 @@ */ abstract class PhrictionController extends PhabricatorController { - public function buildStandardPageResponse($view, array $data) { - - $page = $this->buildStandardPageView(); - - $page->setApplicationName(pht('Phriction')); - $page->setBaseURI('/w/'); - $page->setTitle(idx($data, 'title')); - $page->setGlyph("\xE2\x9A\xA1"); - - $page->appendChild($view); - $page->setSearchDefaultScope(PhabricatorSearchScope::SCOPE_WIKI); - - $response = new AphrontWebpageResponse(); - return $response->setContent($page->render()); - } - - public function buildSideNavView($filter = null, $for_app = false) { + public function buildSideNavView($for_app = false) { $user = $this->getRequest()->getUser(); $nav = new AphrontSideNavFilterView(); - $nav->setBaseURI(new PhutilURI('/phriction/list/')); + $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); if ($for_app) { - $nav->addFilter('', pht('Root Document'), '/w/'); - $nav->addFilter('', pht('New Document'), '/phriction/new'); + $nav->addFilter('create', pht('New Document')); + $nav->addFilter('/phriction/', pht('Index')); } - $nav->addLabel(pht('Filters')); - $nav->addFilter('active', pht('Active Documents')); - $nav->addFilter('all', pht('All Documents')); - $nav->addFilter('updates', pht('Recently Updated')); + id(new PhrictionSearchEngine()) + ->setViewer($user) + ->addNavigationItems($nav->getMenu()); - $nav->selectFilter($filter, 'active'); + $nav->selectFilter(null); return $nav; } public function buildApplicationMenu() { - return $this->buildSideNavView(null, true)->getMenu(); + return $this->buildSideNavView(true)->getMenu(); } public function buildApplicationCrumbs() { diff --git a/src/applications/phriction/controller/PhrictionEditController.php b/src/applications/phriction/controller/PhrictionEditController.php index 7f9c94202e..56ac847c1a 100644 --- a/src/applications/phriction/controller/PhrictionEditController.php +++ b/src/applications/phriction/controller/PhrictionEditController.php @@ -248,11 +248,26 @@ final class PhrictionEditController 'uri' => '/phriction/preview/?draftkey='.$draft_key, )); + $crumbs = $this->buildApplicationCrumbs(); + if ($document->getID()) { + $crumbs->addCrumb( + id(new PhabricatorCrumbView()) + ->setName($content->getTitle()) + ->setHref(PhrictionDocument::getSlugURI($document->getSlug()))); + $crumbs->addCrumb( + id(new PhabricatorCrumbView()) + ->setName(pht('Edit'))); + } else { + $crumbs->addCrumb( + id(new PhabricatorCrumbView()) + ->setName(pht('Create'))); + } + return $this->buildApplicationPage( array( + $crumbs, $draft_note, $error_view, - $header, $form, $preview_panel, ), diff --git a/src/applications/phriction/controller/PhrictionListController.php b/src/applications/phriction/controller/PhrictionListController.php index b1dbadd92a..a7369c5b55 100644 --- a/src/applications/phriction/controller/PhrictionListController.php +++ b/src/applications/phriction/controller/PhrictionListController.php @@ -1,233 +1,91 @@ view = idx($data, 'view'); + $this->queryKey = idx($data, 'queryKey'); } public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + $controller = id(new PhabricatorApplicationSearchController($request)) + ->setQueryKey($this->queryKey) + ->setSearchEngine(new PhrictionSearchEngine()) + ->setNavigation($this->buildSideNavView()); - $views = array( - 'active' => pht('Active Documents'), - 'all' => pht('All Documents'), - 'updates' => pht('Recently Updated'), - ); + return $this->delegateToController($controller); + } - if (empty($views[$this->view])) { - $this->view = 'active'; - } + public function renderResultsList( + array $documents, + PhabricatorSavedQuery $query) { + assert_instances_of($documents, 'PhrictionDocument'); - $nav = $this->buildSideNavView($this->view); - - $crumbs = $this->buildApplicationCrumbs(); - $crumbs->addCrumb(id(new PhabricatorCrumbView()) - ->setName($views[$this->view]) - ->setHref($this->getApplicationURI('list/' . $this->view))); - - $nav->appendChild( - array( - $crumbs, - )); - - $pager = id(new AphrontCursorPagerView()) - ->readFromRequest($request); - - $query = id(new PhrictionDocumentQuery()) - ->setViewer($user); - - switch ($this->view) { - case 'active': - $query->withStatus(PhrictionDocumentQuery::STATUS_OPEN); - break; - case 'all': - $query->withStatus(PhrictionDocumentQuery::STATUS_NONSTUB); - break; - case 'updates': - $query->withStatus(PhrictionDocumentQuery::STATUS_NONSTUB); - $query->setOrder(PhrictionDocumentQuery::ORDER_UPDATED); - break; - default: - throw new Exception("Unknown view '{$this->view}'!"); - } - - $this->documents = $query->executeWithCursorPager($pager); - - $changeref_docs = array(); - if ($this->view == 'updates') { - // Loading some documents here since they may not appear in the query - // results. - $changeref_ids = array_filter(mpull( - mpull($this->documents, 'getContent'), 'getChangeRef')); - if ($changeref_ids) { - $changeref_docs = id(new PhrictionDocumentQuery()) - ->setViewer($user) - ->withIDs($changeref_ids) - ->execute(); - } - } + $viewer = $this->getRequest()->getUser(); $phids = array(); - foreach ($this->documents as $document) { - $phids[] = $document->getContent()->getAuthorPHID(); + foreach ($documents as $document) { + $content = $document->getContent(); if ($document->hasProject()) { $phids[] = $document->getProject()->getPHID(); } + $phids[] = $content->getAuthorPHID(); } - $this->handles = $this->loadViewerHandles($phids); + $this->loadHandles($phids); $list = new PhabricatorObjectItemListView(); + $list->setUser($viewer); + foreach ($documents as $document) { + $content = $document->getContent(); + $slug = $document->getSlug(); + $author_phid = $content->getAuthorPHID(); + $slug_uri = PhrictionDocument::getSlugURI($slug); - foreach ($this->documents as $document) { - if ($this->view == 'updates') { - $list->addItem( - $this->buildItemForUpdates($document, $changeref_docs)); - } else { - $list->addItem( - $this->buildItemTheCasualWay($document)); + $byline = pht( + 'Edited by %s', + $this->getHandle($author_phid)->renderLink()); + + $updated = phabricator_datetime( + $content->getDateCreated(), + $viewer); + + $item = id(new PhabricatorObjectItemView()) + ->setHeader($content->getTitle()) + ->setHref($slug_uri) + ->addByline($byline) + ->addIcon('none', $updated); + + if ($document->hasProject()) { + $item->addAttribute( + $this->getHandle($document->getProject()->getPHID())->renderLink()); } + + $item->addAttribute($slug_uri); + + switch ($document->getStatus()) { + case PhrictionDocumentStatus::STATUS_DELETED: + $item->setDisabled(true); + $item->addIcon('delete', pht('Deleted')); + break; + case PhrictionDocumentStatus::STATUS_MOVED: + $item->setDisabled(true); + $item->addIcon('arrow-right', pht('Moved Away')); + break; + } + + $list->addItem($item); } - $nav->appendChild($list); - $nav->appendChild($pager); - - return $this->buildApplicationPage( - $nav, - array( - 'title' => pht('Document Index'), - 'dust' => true, - )); - } - - private function buildItemTheCasualWay(PhrictionDocument $document) { - $user = $this->getRequest()->getUser(); - - $project_link = null; - if ($document->hasProject()) { - $project_phid = $document->getProject()->getPHID(); - $project_link = $this->handles[$project_phid]->renderLink(); - } - - $content = $document->getContent(); - $author = $this->handles[$content->getAuthorPHID()]->renderLink(); - $title = $content->getTitle(); - - $slug = $document->getSlug(); - $slug_uri = PhrictionDocument::getSlugURI($slug); - $edit_uri = '/phriction/edit/' . $document->getID() . '/'; - $history_uri = PhrictionDocument::getSlugURI($slug, 'history'); - - $item = id(new PhabricatorObjectItemView()) - ->setHeader($title) - ->setHref($slug_uri) - ->addAttribute(pht('By %s', $author)) - ->addAttribute(pht('Updated: %s', - phabricator_datetime($content->getDateCreated(), $user))) - ->addAttribute($slug_uri); - - if ($project_link) { - $item->addAttribute(pht('Project %s', $project_link)); - } - - return $item; - } - - private function buildItemForUpdates(PhrictionDocument $document, - array $docs_from_refs) { - - $user = $this->getRequest()->getUser(); - - $content = $document->getContent(); - $version = $content->getVersion(); - $author = $this->handles[$content->getAuthorPHID()]->renderLink(); - $title = $content->getTitle(); - - $slug = $document->getSlug(); - $slug_uri = PhrictionDocument::getSlugURI($slug); - $document_link = hsprintf('%s', $slug_uri, $title); - - $change_type = $content->getChangeType(); - switch ($content->getChangeType()) { - case PhrictionChangeType::CHANGE_DELETE: - $change_type = pht('%s deleted %s', $author, $document_link); - break; - case PhrictionChangeType::CHANGE_EDIT: - $change_type = pht('%s edited %s', $author, $document_link); - break; - case PhrictionChangeType::CHANGE_MOVE_HERE: - case PhrictionChangeType::CHANGE_MOVE_AWAY: - $change_ref = $content->getChangeRef(); - $ref_doc = idx($docs_from_refs, $change_ref); - if (!$ref_doc) { - if ($change_type == PhrictionChangeType::CHANGE_MOVE_HERE) { - $change_type = pht( - '%s moved %s from elsewhere', - $author, - $document_link); - } else { - $change_type = pht( - '%s moved %s to elsewhere', - $author, - $document_link); - } - } else { - $ref_doc_slug = PhrictionDocument::getSlugURI($ref_doc->getSlug()); - $ref_doc_link = hsprintf('%1$s', $ref_doc_slug); - - if ($change_type == PhrictionChangeType::CHANGE_MOVE_HERE) { - $change_type = pht( - '%s moved %s from %s', - $author, - $document_link, - $ref_doc_link); - } else { - $change_type = pht( - '%s moved %s to %s', - $author, - $document_link, - $ref_doc_link); - } - } - break; - default: - throw new Exception("Unknown change type!"); - break; - } - - $item = id(new PhabricatorObjectItemView()) - ->setHeader($change_type) - ->addAttribute(phabricator_datetime($content->getDateCreated(), $user)) - ->addAttribute($slug_uri); - - if ($content->getDescription()) { - $item->addAttribute($content->getDescription()); - } - - if ($version > 1) { - $diff_uri = new PhutilURI('/phriction/diff/'.$document->getID().'/'); - $uri = $diff_uri->alter('l', $version - 1)->alter('r', $version); - $item->addIcon('history', pht('View Change'), - array( - 'href' => $uri, - )); - } else { - $item->addIcon('history-grey', pht('No diff available')); - } - - return $item; + return $list; } } diff --git a/src/applications/phriction/query/PhrictionSearchEngine.php b/src/applications/phriction/query/PhrictionSearchEngine.php new file mode 100644 index 0000000000..1aae7e02d3 --- /dev/null +++ b/src/applications/phriction/query/PhrictionSearchEngine.php @@ -0,0 +1,112 @@ +setParameter('status', $request->getArr('status')); + $saved->setParameter('order', $request->getArr('order')); + + return $saved; + } + + public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { + $query = id(new PhrictionDocumentQuery()) + ->withStatus(PhrictionDocumentQuery::STATUS_NONSTUB); + + $status = $saved->getParameter('status'); + $status = idx($this->getStatusValues(), $status); + if ($status) { + $query->withStatus($status); + } + + $order = $saved->getParameter('order'); + $order = idx($this->getOrderValues(), $order); + if ($order) { + $query->setOrder($order); + } + + return $query; + } + + public function buildSearchForm( + AphrontFormView $form, + PhabricatorSavedQuery $saved_query) { + + $form + ->appendChild( + id(new AphrontFormSelectControl()) + ->setLabel(pht('Status')) + ->setName('status') + ->setOptions($this->getStatusOptions()) + ->setValue($saved_query->getParameter('status'))) + ->appendChild( + id(new AphrontFormSelectControl()) + ->setLabel(pht('Order')) + ->setName('order') + ->setOptions($this->getOrderOptions()) + ->setValue($saved_query->getParameter('order'))); + } + + protected function getURI($path) { + return '/phriction/'.$path; + } + + public function getBuiltinQueryNames() { + $names = array( + 'active' => pht('Active'), + 'updated' => pht('Updated'), + 'all' => pht('All'), + ); + + return $names; + } + + public function buildSavedQueryFromBuiltin($query_key) { + + $query = $this->newSavedQuery(); + $query->setQueryKey($query_key); + + switch ($query_key) { + case 'active': + return $query->setParameter('status', 'active'); + case 'all': + return $query; + case 'updated': + return $query->setParameter('order', 'updated'); + } + + return parent::buildSavedQueryFromBuiltin($query_key); + } + + private function getStatusOptions() { + return array( + 'active' => pht('Show Active Documents'), + 'all' => pht('Show All Documents'), + ); + } + + private function getStatusValues() { + return array( + 'active' => PhrictionDocumentQuery::STATUS_OPEN, + 'all' => PhrictionDocumentQuery::STATUS_NONSTUB, + ); + } + + private function getOrderOptions() { + return array( + 'created' => pht('Date Created'), + 'updated' => pht('Date Updated'), + ); + } + + private function getOrderValues() { + return array( + 'created' => PhrictionDocumentQuery::ORDER_CREATED, + 'updated' => PhrictionDocumentQuery::ORDER_UPDATED, + ); + } + +}