@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.

Use ApplicationSearch in Feed

Summary: Ref T2625. This doesn't do anything fancy, but gives feed a little more flexibility.

Test Plan: Viewed `/feed/`.

Reviewers: btrahan, chad

Reviewed By: chad

CC: aran

Maniphest Tasks: T2625

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

+184 -96
+9 -3
src/__phutil_library_map__.php
··· 1117 1117 'PhabricatorFeedController' => 'applications/feed/controller/PhabricatorFeedController.php', 1118 1118 'PhabricatorFeedDAO' => 'applications/feed/storage/PhabricatorFeedDAO.php', 1119 1119 'PhabricatorFeedDetailController' => 'applications/feed/controller/PhabricatorFeedDetailController.php', 1120 - 'PhabricatorFeedMainController' => 'applications/feed/controller/PhabricatorFeedMainController.php', 1120 + 'PhabricatorFeedListController' => 'applications/feed/controller/PhabricatorFeedListController.php', 1121 1121 'PhabricatorFeedManagementRepublishWorkflow' => 'applications/feed/management/PhabricatorFeedManagementRepublishWorkflow.php', 1122 1122 'PhabricatorFeedManagementWorkflow' => 'applications/feed/management/PhabricatorFeedManagementWorkflow.php', 1123 1123 'PhabricatorFeedPublicStreamController' => 'applications/feed/controller/PhabricatorFeedPublicStreamController.php', 1124 - 'PhabricatorFeedQuery' => 'applications/feed/PhabricatorFeedQuery.php', 1124 + 'PhabricatorFeedQuery' => 'applications/feed/query/PhabricatorFeedQuery.php', 1125 + 'PhabricatorFeedSearchEngine' => 'applications/feed/query/PhabricatorFeedSearchEngine.php', 1125 1126 'PhabricatorFeedStory' => 'applications/feed/story/PhabricatorFeedStory.php', 1126 1127 'PhabricatorFeedStoryAggregate' => 'applications/feed/story/PhabricatorFeedStoryAggregate.php', 1127 1128 'PhabricatorFeedStoryAudit' => 'applications/feed/story/PhabricatorFeedStoryAudit.php', ··· 3159 3160 'PhabricatorFeedController' => 'PhabricatorController', 3160 3161 'PhabricatorFeedDAO' => 'PhabricatorLiskDAO', 3161 3162 'PhabricatorFeedDetailController' => 'PhabricatorFeedController', 3162 - 'PhabricatorFeedMainController' => 'PhabricatorFeedController', 3163 + 'PhabricatorFeedListController' => 3164 + array( 3165 + 0 => 'PhabricatorFeedController', 3166 + 1 => 'PhabricatorApplicationSearchResultsControllerInterface', 3167 + ), 3163 3168 'PhabricatorFeedManagementRepublishWorkflow' => 'PhabricatorFeedManagementWorkflow', 3164 3169 'PhabricatorFeedManagementWorkflow' => 'PhutilArgumentWorkflow', 3165 3170 'PhabricatorFeedPublicStreamController' => 'PhabricatorFeedController', 3166 3171 'PhabricatorFeedQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 3172 + 'PhabricatorFeedSearchEngine' => 'PhabricatorApplicationSearchEngine', 3167 3173 'PhabricatorFeedStory' => 'PhabricatorPolicyInterface', 3168 3174 'PhabricatorFeedStoryAggregate' => 'PhabricatorFeedStory', 3169 3175 'PhabricatorFeedStoryAudit' => 'PhabricatorFeedStory',
src/applications/feed/PhabricatorFeedQuery.php src/applications/feed/query/PhabricatorFeedQuery.php
+1 -1
src/applications/feed/application/PhabricatorApplicationFeed.php
··· 23 23 '/feed/' => array( 24 24 'public/' => 'PhabricatorFeedPublicStreamController', 25 25 '(?P<id>\d+)/' => 'PhabricatorFeedDetailController', 26 - '(?:(?P<filter>[^/]+)/)?' => 'PhabricatorFeedMainController', 26 + '(?:query/(?P<queryKey>[^/]+)/)?' => 'PhabricatorFeedListController', 27 27 ), 28 28 ); 29 29 }
+7 -3
src/applications/feed/controller/PhabricatorFeedController.php
··· 23 23 } 24 24 25 25 protected function buildSideNavView() { 26 + $user = $this->getRequest()->getUser(); 27 + 26 28 $nav = new AphrontSideNavFilterView(); 27 29 $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); 28 30 29 - $nav->addLabel(pht('Feed')); 30 - $nav->addFilter('all', pht('All Activity')); 31 - $nav->addFilter('projects', pht('My Projects')); 31 + id(new PhabricatorFeedSearchEngine()) 32 + ->setViewer($user) 33 + ->addNavigationItems($nav->getMenu()); 34 + 35 + $nav->selectFilter(null); 32 36 33 37 return $nav; 34 38 }
+39
src/applications/feed/controller/PhabricatorFeedListController.php
··· 1 + <?php 2 + 3 + final class PhabricatorFeedListController extends PhabricatorFeedController 4 + implements PhabricatorApplicationSearchResultsControllerInterface { 5 + 6 + private $queryKey; 7 + 8 + public function shouldAllowPublic() { 9 + return true; 10 + } 11 + 12 + public function willProcessRequest(array $data) { 13 + $this->queryKey = idx($data, 'queryKey'); 14 + } 15 + 16 + public function processRequest() { 17 + $request = $this->getRequest(); 18 + $controller = id(new PhabricatorApplicationSearchController($request)) 19 + ->setQueryKey($this->queryKey) 20 + ->setSearchEngine(new PhabricatorFeedSearchEngine()) 21 + ->setNavigation($this->buildSideNavView()); 22 + 23 + return $this->delegateToController($controller); 24 + } 25 + 26 + public function renderResultsList( 27 + array $feed, 28 + PhabricatorSavedQuery $query) { 29 + 30 + $builder = new PhabricatorFeedBuilder($feed); 31 + $builder->setUser($this->getRequest()->getUser()); 32 + $view = $builder->buildView(); 33 + 34 + return hsprintf( 35 + '<div class="phabricator-feed-frame">%s</div>', 36 + $view); 37 + } 38 + 39 + }
-89
src/applications/feed/controller/PhabricatorFeedMainController.php
··· 1 - <?php 2 - 3 - final class PhabricatorFeedMainController extends PhabricatorFeedController { 4 - 5 - private $filter; 6 - 7 - public function willProcessRequest(array $data) { 8 - $this->filter = idx($data, 'filter'); 9 - } 10 - 11 - public function processRequest() { 12 - $request = $this->getRequest(); 13 - $user = $request->getUser(); 14 - 15 - $nav = $this->buildSideNavView(); 16 - $filter = $nav->selectFilter($this->filter, 'all'); 17 - 18 - $pager = new AphrontCursorPagerView(); 19 - $pager->readFromRequest($request); 20 - $pager->setPageSize(200); 21 - 22 - 23 - $query = id(new PhabricatorFeedQuery()) 24 - ->setViewer($user); 25 - 26 - $nodata = null; 27 - switch ($filter) { 28 - case 'all': 29 - $title = pht('Feed'); 30 - break; 31 - case 'projects': 32 - $projects = id(new PhabricatorProjectQuery()) 33 - ->setViewer($user) 34 - ->withMemberPHIDs(array($user->getPHID())) 35 - ->execute(); 36 - 37 - if (!$projects) { 38 - $nodata = pht('You have not joined any projects.'); 39 - } else { 40 - $query->setFilterPHIDs(mpull($projects, 'getPHID')); 41 - } 42 - 43 - $title = pht('Feed: My Projects'); 44 - break; 45 - } 46 - 47 - if ($nodata) { 48 - $feed_view = id(new AphrontErrorView()) 49 - ->setSeverity(AphrontErrorView::SEVERITY_NODATA) 50 - ->setTitle(pht('No Stories')) 51 - ->appendChild($nodata); 52 - } else { 53 - $feed = $query->executeWithCursorPager($pager); 54 - 55 - $builder = new PhabricatorFeedBuilder($feed); 56 - $builder->setUser($user); 57 - $feed_view = $builder->buildView(); 58 - } 59 - 60 - $feed_view = hsprintf( 61 - '<div class="phabricator-feed-frame">%s</div>', 62 - $feed_view); 63 - 64 - $crumbs = $this 65 - ->buildApplicationCrumbs($nav) 66 - ->addCrumb( 67 - id(new PhabricatorCrumbView()) 68 - ->setName($title) 69 - ->setHref($this->getApplicationURI('filter/'.$filter.'/'))); 70 - 71 - $nav->setCrumbs($crumbs); 72 - 73 - 74 - $nav->appendChild( 75 - array( 76 - $feed_view, 77 - $pager, 78 - )); 79 - 80 - return $this->buildApplicationPage( 81 - $nav, 82 - array( 83 - 'title' => $title, 84 - 'device' => true, 85 - 'dust' => true, 86 - )); 87 - } 88 - 89 - }
+128
src/applications/feed/query/PhabricatorFeedSearchEngine.php
··· 1 + <?php 2 + 3 + final class PhabricatorFeedSearchEngine 4 + extends PhabricatorApplicationSearchEngine { 5 + 6 + public function buildSavedQueryFromRequest(AphrontRequest $request) { 7 + $saved = new PhabricatorSavedQuery(); 8 + 9 + $saved->setParameter( 10 + 'userPHIDs', 11 + array_values($request->getArr('userPHIDs'))); 12 + 13 + $saved->setParameter( 14 + 'projectPHIDs', 15 + array_values($request->getArr('projectPHIDs'))); 16 + 17 + $saved->setParameter( 18 + 'viewerProjects', 19 + $request->getBool('viewerProjects')); 20 + 21 + return $saved; 22 + } 23 + 24 + public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { 25 + $query = id(new PhabricatorFeedQuery()); 26 + 27 + $phids = array(); 28 + 29 + $user_phids = $saved->getParameter('userPHIDs'); 30 + if ($user_phids) { 31 + $phids[] = $user_phids; 32 + } 33 + 34 + $proj_phids = $saved->getParameter('projectPHIDs'); 35 + if ($proj_phids) { 36 + $phids[] = $proj_phids; 37 + } 38 + 39 + $viewer_projects = $saved->getParameter('viewerProjects'); 40 + if ($viewer_projects) { 41 + $viewer = $this->requireViewer(); 42 + $projects = id(new PhabricatorProjectQuery()) 43 + ->setViewer($viewer) 44 + ->withMemberPHIDs(array($viewer->getPHID())) 45 + ->execute(); 46 + $phids[] = mpull($projects, 'getPHID'); 47 + } 48 + 49 + $phids = array_mergev($phids); 50 + if ($phids) { 51 + $query->setFilterPHIDs($phids); 52 + } 53 + 54 + return $query; 55 + } 56 + 57 + public function buildSearchForm( 58 + AphrontFormView $form, 59 + PhabricatorSavedQuery $saved_query) { 60 + 61 + $user_phids = $saved_query->getParameter('userPHIDs', array()); 62 + $proj_phids = $saved_query->getParameter('projectPHIDs', array()); 63 + 64 + $phids = array_merge($user_phids, $proj_phids); 65 + $handles = id(new PhabricatorHandleQuery()) 66 + ->setViewer($this->requireViewer()) 67 + ->withPHIDs($phids) 68 + ->execute(); 69 + $tokens = mpull($handles, 'getFullName', 'getPHID'); 70 + $user_tokens = array_select_keys($tokens, $user_phids); 71 + $proj_tokens = array_select_keys($tokens, $proj_phids); 72 + 73 + $viewer_projects = $saved_query->getParameter('viewerProjects'); 74 + 75 + $form 76 + ->appendChild( 77 + id(new AphrontFormTokenizerControl()) 78 + ->setDatasource('/typeahead/common/users/') 79 + ->setName('userPHIDs') 80 + ->setLabel(pht('Include Users')) 81 + ->setValue($user_tokens)) 82 + ->appendChild( 83 + id(new AphrontFormTokenizerControl()) 84 + ->setDatasource('/typeahead/common/projects/') 85 + ->setName('projectPHIDs') 86 + ->setLabel(pht('Include Projects')) 87 + ->setValue($proj_tokens)) 88 + ->appendChild( 89 + id(new AphrontFormCheckboxControl()) 90 + ->addCheckbox( 91 + 'viewerProjects', 92 + 1, 93 + pht('Include stories about projects I am a member of.'), 94 + $viewer_projects)); 95 + } 96 + 97 + protected function getURI($path) { 98 + return '/feed/'.$path; 99 + } 100 + 101 + public function getBuiltinQueryNames() { 102 + $names = array( 103 + 'all' => pht('All Stories'), 104 + ); 105 + 106 + if ($this->requireViewer()->isLoggedIn()) { 107 + $names['projects'] = pht('Projects'); 108 + } 109 + 110 + return $names; 111 + } 112 + 113 + public function buildSavedQueryFromBuiltin($query_key) { 114 + 115 + $query = $this->newSavedQuery(); 116 + $query->setQueryKey($query_key); 117 + 118 + switch ($query_key) { 119 + case 'all': 120 + return $query; 121 + case 'projects': 122 + return $query->setParameter('viewerProjects', true); 123 + } 124 + 125 + return parent::buildSavedQueryFromBuiltin($query_key); 126 + } 127 + 128 + }