@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add breadcrumbs and ApplicationSearch to Phriction

Summary: Fixes T3631. Also adds ApplicationSearch.

Test Plan: Viewed "New", "Edit"; saw breadcrumbs. Viewed "index", saw application search.

Reviewers: btrahan, chad

Reviewed By: chad

CC: aran

Maniphest Tasks: T3631

Differential Revision: https://secure.phabricator.com/D6593

+201 -228
+7 -1
src/__phutil_library_map__.php
··· 1863 1863 'PhrictionNewController' => 'applications/phriction/controller/PhrictionNewController.php', 1864 1864 'PhrictionPHIDTypeDocument' => 'applications/phriction/phid/PhrictionPHIDTypeDocument.php', 1865 1865 'PhrictionRemarkupRule' => 'applications/phriction/remarkup/PhrictionRemarkupRule.php', 1866 + 'PhrictionSearchEngine' => 'applications/phriction/query/PhrictionSearchEngine.php', 1866 1867 'PhrictionSearchIndexer' => 'applications/phriction/search/PhrictionSearchIndexer.php', 1867 1868 'PonderAddAnswerView' => 'applications/ponder/view/PonderAddAnswerView.php', 1868 1869 'PonderAddCommentView' => 'applications/ponder/view/PonderAddCommentView.php', ··· 3957 3958 'PhrictionDocumentTestCase' => 'PhabricatorTestCase', 3958 3959 'PhrictionEditController' => 'PhrictionController', 3959 3960 'PhrictionHistoryController' => 'PhrictionController', 3960 - 'PhrictionListController' => 'PhrictionController', 3961 + 'PhrictionListController' => 3962 + array( 3963 + 0 => 'PhrictionController', 3964 + 1 => 'PhabricatorApplicationSearchResultsControllerInterface', 3965 + ), 3961 3966 'PhrictionMoveController' => 'PhrictionController', 3962 3967 'PhrictionNewController' => 'PhrictionController', 3963 3968 'PhrictionPHIDTypeDocument' => 'PhabricatorPHIDType', 3964 3969 'PhrictionRemarkupRule' => 'PhutilRemarkupRule', 3970 + 'PhrictionSearchEngine' => 'PhabricatorApplicationSearchEngine', 3965 3971 'PhrictionSearchIndexer' => 'PhabricatorSearchDocumentIndexer', 3966 3972 'PonderAddAnswerView' => 'AphrontView', 3967 3973 'PonderAddCommentView' => 'AphrontView',
+1 -2
src/applications/phriction/application/PhabricatorApplicationPhriction.php
··· 42 42 '/w/(?P<slug>.+/)' => 'PhrictionDocumentController', 43 43 44 44 '/phriction/' => array( 45 - '' => 'PhrictionListController', 46 - 'list/(?P<view>[^/]+)/' => 'PhrictionListController', 45 + '(?:query/(?P<queryKey>[^/]+)/)?' => 'PhrictionListController', 47 46 48 47 'history(?P<slug>/)' => 'PhrictionHistoryController', 49 48 'history/(?P<slug>.+/)' => 'PhrictionHistoryController',
+9 -26
src/applications/phriction/controller/PhrictionController.php
··· 5 5 */ 6 6 abstract class PhrictionController extends PhabricatorController { 7 7 8 - public function buildStandardPageResponse($view, array $data) { 9 - 10 - $page = $this->buildStandardPageView(); 11 - 12 - $page->setApplicationName(pht('Phriction')); 13 - $page->setBaseURI('/w/'); 14 - $page->setTitle(idx($data, 'title')); 15 - $page->setGlyph("\xE2\x9A\xA1"); 16 - 17 - $page->appendChild($view); 18 - $page->setSearchDefaultScope(PhabricatorSearchScope::SCOPE_WIKI); 19 - 20 - $response = new AphrontWebpageResponse(); 21 - return $response->setContent($page->render()); 22 - } 23 - 24 - public function buildSideNavView($filter = null, $for_app = false) { 8 + public function buildSideNavView($for_app = false) { 25 9 $user = $this->getRequest()->getUser(); 26 10 27 11 $nav = new AphrontSideNavFilterView(); 28 - $nav->setBaseURI(new PhutilURI('/phriction/list/')); 12 + $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); 29 13 30 14 if ($for_app) { 31 - $nav->addFilter('', pht('Root Document'), '/w/'); 32 - $nav->addFilter('', pht('New Document'), '/phriction/new'); 15 + $nav->addFilter('create', pht('New Document')); 16 + $nav->addFilter('/phriction/', pht('Index')); 33 17 } 34 18 35 - $nav->addLabel(pht('Filters')); 36 - $nav->addFilter('active', pht('Active Documents')); 37 - $nav->addFilter('all', pht('All Documents')); 38 - $nav->addFilter('updates', pht('Recently Updated')); 19 + id(new PhrictionSearchEngine()) 20 + ->setViewer($user) 21 + ->addNavigationItems($nav->getMenu()); 39 22 40 - $nav->selectFilter($filter, 'active'); 23 + $nav->selectFilter(null); 41 24 42 25 return $nav; 43 26 } 44 27 45 28 public function buildApplicationMenu() { 46 - return $this->buildSideNavView(null, true)->getMenu(); 29 + return $this->buildSideNavView(true)->getMenu(); 47 30 } 48 31 49 32 public function buildApplicationCrumbs() {
+16 -1
src/applications/phriction/controller/PhrictionEditController.php
··· 248 248 'uri' => '/phriction/preview/?draftkey='.$draft_key, 249 249 )); 250 250 251 + $crumbs = $this->buildApplicationCrumbs(); 252 + if ($document->getID()) { 253 + $crumbs->addCrumb( 254 + id(new PhabricatorCrumbView()) 255 + ->setName($content->getTitle()) 256 + ->setHref(PhrictionDocument::getSlugURI($document->getSlug()))); 257 + $crumbs->addCrumb( 258 + id(new PhabricatorCrumbView()) 259 + ->setName(pht('Edit'))); 260 + } else { 261 + $crumbs->addCrumb( 262 + id(new PhabricatorCrumbView()) 263 + ->setName(pht('Create'))); 264 + } 265 + 251 266 return $this->buildApplicationPage( 252 267 array( 268 + $crumbs, 253 269 $draft_note, 254 270 $error_view, 255 - $header, 256 271 $form, 257 272 $preview_panel, 258 273 ),
+56 -198
src/applications/phriction/controller/PhrictionListController.php
··· 1 1 <?php 2 2 3 - /** 4 - * @group phriction 5 - */ 6 3 final class PhrictionListController 7 - extends PhrictionController { 4 + extends PhrictionController 5 + implements PhabricatorApplicationSearchResultsControllerInterface { 8 6 9 - private $view; 7 + private $queryKey; 10 8 11 - private $documents; 12 - private $handles; 9 + public function shouldAllowPublic() { 10 + return true; 11 + } 13 12 14 13 public function willProcessRequest(array $data) { 15 - $this->view = idx($data, 'view'); 14 + $this->queryKey = idx($data, 'queryKey'); 16 15 } 17 16 18 17 public function processRequest() { 19 - 20 18 $request = $this->getRequest(); 21 - $user = $request->getUser(); 22 - 23 - $views = array( 24 - 'active' => pht('Active Documents'), 25 - 'all' => pht('All Documents'), 26 - 'updates' => pht('Recently Updated'), 27 - ); 28 - 29 - if (empty($views[$this->view])) { 30 - $this->view = 'active'; 31 - } 32 - 33 - $nav = $this->buildSideNavView($this->view); 34 - 35 - $crumbs = $this->buildApplicationCrumbs(); 36 - $crumbs->addCrumb(id(new PhabricatorCrumbView()) 37 - ->setName($views[$this->view]) 38 - ->setHref($this->getApplicationURI('list/' . $this->view))); 19 + $controller = id(new PhabricatorApplicationSearchController($request)) 20 + ->setQueryKey($this->queryKey) 21 + ->setSearchEngine(new PhrictionSearchEngine()) 22 + ->setNavigation($this->buildSideNavView()); 39 23 40 - $nav->appendChild( 41 - array( 42 - $crumbs, 43 - )); 24 + return $this->delegateToController($controller); 25 + } 44 26 45 - $pager = id(new AphrontCursorPagerView()) 46 - ->readFromRequest($request); 27 + public function renderResultsList( 28 + array $documents, 29 + PhabricatorSavedQuery $query) { 30 + assert_instances_of($documents, 'PhrictionDocument'); 47 31 48 - $query = id(new PhrictionDocumentQuery()) 49 - ->setViewer($user); 50 - 51 - switch ($this->view) { 52 - case 'active': 53 - $query->withStatus(PhrictionDocumentQuery::STATUS_OPEN); 54 - break; 55 - case 'all': 56 - $query->withStatus(PhrictionDocumentQuery::STATUS_NONSTUB); 57 - break; 58 - case 'updates': 59 - $query->withStatus(PhrictionDocumentQuery::STATUS_NONSTUB); 60 - $query->setOrder(PhrictionDocumentQuery::ORDER_UPDATED); 61 - break; 62 - default: 63 - throw new Exception("Unknown view '{$this->view}'!"); 64 - } 65 - 66 - $this->documents = $query->executeWithCursorPager($pager); 67 - 68 - $changeref_docs = array(); 69 - if ($this->view == 'updates') { 70 - // Loading some documents here since they may not appear in the query 71 - // results. 72 - $changeref_ids = array_filter(mpull( 73 - mpull($this->documents, 'getContent'), 'getChangeRef')); 74 - if ($changeref_ids) { 75 - $changeref_docs = id(new PhrictionDocumentQuery()) 76 - ->setViewer($user) 77 - ->withIDs($changeref_ids) 78 - ->execute(); 79 - } 80 - } 32 + $viewer = $this->getRequest()->getUser(); 81 33 82 34 $phids = array(); 83 - foreach ($this->documents as $document) { 84 - $phids[] = $document->getContent()->getAuthorPHID(); 35 + foreach ($documents as $document) { 36 + $content = $document->getContent(); 85 37 if ($document->hasProject()) { 86 38 $phids[] = $document->getProject()->getPHID(); 87 39 } 40 + $phids[] = $content->getAuthorPHID(); 88 41 } 89 42 90 - $this->handles = $this->loadViewerHandles($phids); 43 + $this->loadHandles($phids); 91 44 92 45 $list = new PhabricatorObjectItemListView(); 93 - 94 - foreach ($this->documents as $document) { 95 - if ($this->view == 'updates') { 96 - $list->addItem( 97 - $this->buildItemForUpdates($document, $changeref_docs)); 98 - } else { 99 - $list->addItem( 100 - $this->buildItemTheCasualWay($document)); 101 - } 102 - } 103 - 104 - $nav->appendChild($list); 105 - $nav->appendChild($pager); 106 - 107 - return $this->buildApplicationPage( 108 - $nav, 109 - array( 110 - 'title' => pht('Document Index'), 111 - 'dust' => true, 112 - )); 113 - } 114 - 115 - private function buildItemTheCasualWay(PhrictionDocument $document) { 116 - $user = $this->getRequest()->getUser(); 117 - 118 - $project_link = null; 119 - if ($document->hasProject()) { 120 - $project_phid = $document->getProject()->getPHID(); 121 - $project_link = $this->handles[$project_phid]->renderLink(); 122 - } 123 - 124 - $content = $document->getContent(); 125 - $author = $this->handles[$content->getAuthorPHID()]->renderLink(); 126 - $title = $content->getTitle(); 127 - 128 - $slug = $document->getSlug(); 129 - $slug_uri = PhrictionDocument::getSlugURI($slug); 130 - $edit_uri = '/phriction/edit/' . $document->getID() . '/'; 131 - $history_uri = PhrictionDocument::getSlugURI($slug, 'history'); 132 - 133 - $item = id(new PhabricatorObjectItemView()) 134 - ->setHeader($title) 135 - ->setHref($slug_uri) 136 - ->addAttribute(pht('By %s', $author)) 137 - ->addAttribute(pht('Updated: %s', 138 - phabricator_datetime($content->getDateCreated(), $user))) 139 - ->addAttribute($slug_uri); 46 + $list->setUser($viewer); 47 + foreach ($documents as $document) { 48 + $content = $document->getContent(); 49 + $slug = $document->getSlug(); 50 + $author_phid = $content->getAuthorPHID(); 51 + $slug_uri = PhrictionDocument::getSlugURI($slug); 140 52 141 - if ($project_link) { 142 - $item->addAttribute(pht('Project %s', $project_link)); 143 - } 53 + $byline = pht( 54 + 'Edited by %s', 55 + $this->getHandle($author_phid)->renderLink()); 144 56 145 - return $item; 146 - } 57 + $updated = phabricator_datetime( 58 + $content->getDateCreated(), 59 + $viewer); 147 60 148 - private function buildItemForUpdates(PhrictionDocument $document, 149 - array $docs_from_refs) { 61 + $item = id(new PhabricatorObjectItemView()) 62 + ->setHeader($content->getTitle()) 63 + ->setHref($slug_uri) 64 + ->addByline($byline) 65 + ->addIcon('none', $updated); 150 66 151 - $user = $this->getRequest()->getUser(); 67 + if ($document->hasProject()) { 68 + $item->addAttribute( 69 + $this->getHandle($document->getProject()->getPHID())->renderLink()); 70 + } 152 71 153 - $content = $document->getContent(); 154 - $version = $content->getVersion(); 155 - $author = $this->handles[$content->getAuthorPHID()]->renderLink(); 156 - $title = $content->getTitle(); 72 + $item->addAttribute($slug_uri); 157 73 158 - $slug = $document->getSlug(); 159 - $slug_uri = PhrictionDocument::getSlugURI($slug); 160 - $document_link = hsprintf('<a href="%s">%s</a>', $slug_uri, $title); 74 + switch ($document->getStatus()) { 75 + case PhrictionDocumentStatus::STATUS_DELETED: 76 + $item->setDisabled(true); 77 + $item->addIcon('delete', pht('Deleted')); 78 + break; 79 + case PhrictionDocumentStatus::STATUS_MOVED: 80 + $item->setDisabled(true); 81 + $item->addIcon('arrow-right', pht('Moved Away')); 82 + break; 83 + } 161 84 162 - $change_type = $content->getChangeType(); 163 - switch ($content->getChangeType()) { 164 - case PhrictionChangeType::CHANGE_DELETE: 165 - $change_type = pht('%s deleted %s', $author, $document_link); 166 - break; 167 - case PhrictionChangeType::CHANGE_EDIT: 168 - $change_type = pht('%s edited %s', $author, $document_link); 169 - break; 170 - case PhrictionChangeType::CHANGE_MOVE_HERE: 171 - case PhrictionChangeType::CHANGE_MOVE_AWAY: 172 - $change_ref = $content->getChangeRef(); 173 - $ref_doc = idx($docs_from_refs, $change_ref); 174 - if (!$ref_doc) { 175 - if ($change_type == PhrictionChangeType::CHANGE_MOVE_HERE) { 176 - $change_type = pht( 177 - '%s moved %s from elsewhere', 178 - $author, 179 - $document_link); 180 - } else { 181 - $change_type = pht( 182 - '%s moved %s to elsewhere', 183 - $author, 184 - $document_link); 185 - } 186 - } else { 187 - $ref_doc_slug = PhrictionDocument::getSlugURI($ref_doc->getSlug()); 188 - $ref_doc_link = hsprintf('<a href="%s">%1$s</a>', $ref_doc_slug); 189 - 190 - if ($change_type == PhrictionChangeType::CHANGE_MOVE_HERE) { 191 - $change_type = pht( 192 - '%s moved %s from %s', 193 - $author, 194 - $document_link, 195 - $ref_doc_link); 196 - } else { 197 - $change_type = pht( 198 - '%s moved %s to %s', 199 - $author, 200 - $document_link, 201 - $ref_doc_link); 202 - } 203 - } 204 - break; 205 - default: 206 - throw new Exception("Unknown change type!"); 207 - break; 85 + $list->addItem($item); 208 86 } 209 87 210 - $item = id(new PhabricatorObjectItemView()) 211 - ->setHeader($change_type) 212 - ->addAttribute(phabricator_datetime($content->getDateCreated(), $user)) 213 - ->addAttribute($slug_uri); 214 - 215 - if ($content->getDescription()) { 216 - $item->addAttribute($content->getDescription()); 217 - } 218 - 219 - if ($version > 1) { 220 - $diff_uri = new PhutilURI('/phriction/diff/'.$document->getID().'/'); 221 - $uri = $diff_uri->alter('l', $version - 1)->alter('r', $version); 222 - $item->addIcon('history', pht('View Change'), 223 - array( 224 - 'href' => $uri, 225 - )); 226 - } else { 227 - $item->addIcon('history-grey', pht('No diff available')); 228 - } 229 - 230 - return $item; 88 + return $list; 231 89 } 232 90 233 91 }
+112
src/applications/phriction/query/PhrictionSearchEngine.php
··· 1 + <?php 2 + 3 + final class PhrictionSearchEngine 4 + extends PhabricatorApplicationSearchEngine { 5 + 6 + public function buildSavedQueryFromRequest(AphrontRequest $request) { 7 + $saved = new PhabricatorSavedQuery(); 8 + 9 + $saved->setParameter('status', $request->getArr('status')); 10 + $saved->setParameter('order', $request->getArr('order')); 11 + 12 + return $saved; 13 + } 14 + 15 + public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { 16 + $query = id(new PhrictionDocumentQuery()) 17 + ->withStatus(PhrictionDocumentQuery::STATUS_NONSTUB); 18 + 19 + $status = $saved->getParameter('status'); 20 + $status = idx($this->getStatusValues(), $status); 21 + if ($status) { 22 + $query->withStatus($status); 23 + } 24 + 25 + $order = $saved->getParameter('order'); 26 + $order = idx($this->getOrderValues(), $order); 27 + if ($order) { 28 + $query->setOrder($order); 29 + } 30 + 31 + return $query; 32 + } 33 + 34 + public function buildSearchForm( 35 + AphrontFormView $form, 36 + PhabricatorSavedQuery $saved_query) { 37 + 38 + $form 39 + ->appendChild( 40 + id(new AphrontFormSelectControl()) 41 + ->setLabel(pht('Status')) 42 + ->setName('status') 43 + ->setOptions($this->getStatusOptions()) 44 + ->setValue($saved_query->getParameter('status'))) 45 + ->appendChild( 46 + id(new AphrontFormSelectControl()) 47 + ->setLabel(pht('Order')) 48 + ->setName('order') 49 + ->setOptions($this->getOrderOptions()) 50 + ->setValue($saved_query->getParameter('order'))); 51 + } 52 + 53 + protected function getURI($path) { 54 + return '/phriction/'.$path; 55 + } 56 + 57 + public function getBuiltinQueryNames() { 58 + $names = array( 59 + 'active' => pht('Active'), 60 + 'updated' => pht('Updated'), 61 + 'all' => pht('All'), 62 + ); 63 + 64 + return $names; 65 + } 66 + 67 + public function buildSavedQueryFromBuiltin($query_key) { 68 + 69 + $query = $this->newSavedQuery(); 70 + $query->setQueryKey($query_key); 71 + 72 + switch ($query_key) { 73 + case 'active': 74 + return $query->setParameter('status', 'active'); 75 + case 'all': 76 + return $query; 77 + case 'updated': 78 + return $query->setParameter('order', 'updated'); 79 + } 80 + 81 + return parent::buildSavedQueryFromBuiltin($query_key); 82 + } 83 + 84 + private function getStatusOptions() { 85 + return array( 86 + 'active' => pht('Show Active Documents'), 87 + 'all' => pht('Show All Documents'), 88 + ); 89 + } 90 + 91 + private function getStatusValues() { 92 + return array( 93 + 'active' => PhrictionDocumentQuery::STATUS_OPEN, 94 + 'all' => PhrictionDocumentQuery::STATUS_NONSTUB, 95 + ); 96 + } 97 + 98 + private function getOrderOptions() { 99 + return array( 100 + 'created' => pht('Date Created'), 101 + 'updated' => pht('Date Updated'), 102 + ); 103 + } 104 + 105 + private function getOrderValues() { 106 + return array( 107 + 'created' => PhrictionDocumentQuery::ORDER_CREATED, 108 + 'updated' => PhrictionDocumentQuery::ORDER_UPDATED, 109 + ); 110 + } 111 + 112 + }