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

Move notifications to ApplicationSearch

Summary: Ref T5891. This just modernizes infrastructure.

Test Plan: Viewed "All" and "Unread" notifications.

Reviewers: btrahan, chad

Reviewed By: chad

Subscribers: epriestley

Maniphest Tasks: T5891

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

+170 -88
+2
src/__phutil_library_map__.php
··· 1759 1759 'PhabricatorNotificationListController' => 'applications/notification/controller/PhabricatorNotificationListController.php', 1760 1760 'PhabricatorNotificationPanelController' => 'applications/notification/controller/PhabricatorNotificationPanelController.php', 1761 1761 'PhabricatorNotificationQuery' => 'applications/notification/query/PhabricatorNotificationQuery.php', 1762 + 'PhabricatorNotificationSearchEngine' => 'applications/notification/query/PhabricatorNotificationSearchEngine.php', 1762 1763 'PhabricatorNotificationStatusController' => 'applications/notification/controller/PhabricatorNotificationStatusController.php', 1763 1764 'PhabricatorNotificationStatusView' => 'applications/notification/view/PhabricatorNotificationStatusView.php', 1764 1765 'PhabricatorNotificationTestController' => 'applications/notification/controller/PhabricatorNotificationTestController.php', ··· 4591 4592 'PhabricatorNotificationListController' => 'PhabricatorNotificationController', 4592 4593 'PhabricatorNotificationPanelController' => 'PhabricatorNotificationController', 4593 4594 'PhabricatorNotificationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 4595 + 'PhabricatorNotificationSearchEngine' => 'PhabricatorApplicationSearchEngine', 4594 4596 'PhabricatorNotificationStatusController' => 'PhabricatorNotificationController', 4595 4597 'PhabricatorNotificationStatusView' => 'AphrontTagView', 4596 4598 'PhabricatorNotificationTestController' => 'PhabricatorNotificationController',
+1 -1
src/applications/notification/application/PhabricatorNotificationsApplication.php
··· 17 17 public function getRoutes() { 18 18 return array( 19 19 '/notification/' => array( 20 - '(?:(?P<filter>all|unread)/)?' 20 + '(?:query/(?P<queryKey>[^/]+)/)?' 21 21 => 'PhabricatorNotificationListController', 22 22 'panel/' => 'PhabricatorNotificationPanelController', 23 23 'individual/' => 'PhabricatorNotificationIndividualController',
+1 -1
src/applications/notification/controller/PhabricatorNotificationIndividualController.php
··· 9 9 10 10 $stories = id(new PhabricatorNotificationQuery()) 11 11 ->setViewer($user) 12 - ->setUserPHID($user->getPHID()) 12 + ->withUserPHIDs(array($user->getPHID())) 13 13 ->withKeys(array($request->getStr('key'))) 14 14 ->execute(); 15 15
+17 -72
src/applications/notification/controller/PhabricatorNotificationListController.php
··· 3 3 final class PhabricatorNotificationListController 4 4 extends PhabricatorNotificationController { 5 5 6 - private $filter; 6 + private $queryKey; 7 7 8 8 public function willProcessRequest(array $data) { 9 - $this->filter = idx($data, 'filter'); 9 + $this->queryKey = idx($data, 'queryKey'); 10 10 } 11 11 12 12 public function processRequest() { 13 13 $request = $this->getRequest(); 14 - $user = $request->getUser(); 14 + $controller = id(new PhabricatorApplicationSearchController($request)) 15 + ->setQueryKey($this->queryKey) 16 + ->setSearchEngine(new PhabricatorNotificationSearchEngine()) 17 + ->setNavigation($this->buildSideNavView()); 15 18 16 - $nav = new AphrontSideNavFilterView(); 17 - $nav->setBaseURI(new PhutilURI('/notification/')); 18 - $nav->addFilter('all', pht('All Notifications')); 19 - $nav->addFilter('unread', pht('Unread Notifications')); 20 - $filter = $nav->selectFilter($this->filter, 'all'); 19 + return $this->delegateToController($controller); 20 + } 21 21 22 - $pager = new AphrontPagerView(); 23 - $pager->setURI($request->getRequestURI(), 'offset'); 24 - $pager->setOffset($request->getInt('offset')); 22 + public function buildSideNavView() { 23 + $user = $this->getRequest()->getUser(); 25 24 26 - $query = new PhabricatorNotificationQuery(); 27 - $query->setViewer($user); 28 - $query->setUserPHID($user->getPHID()); 25 + $nav = new AphrontSideNavFilterView(); 26 + $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); 29 27 30 - switch ($filter) { 31 - case 'unread': 32 - $query->withUnread(true); 33 - $header = pht('Unread Notifications'); 34 - $no_data = pht('You have no unread notifications.'); 35 - break; 36 - default: 37 - $header = pht('Notifications'); 38 - $no_data = pht('You have no notifications.'); 39 - break; 40 - } 28 + id(new PhabricatorNotificationSearchEngine()) 29 + ->setViewer($user) 30 + ->addNavigationItems($nav->getMenu()); 31 + $nav->selectFilter(null); 41 32 42 - $image = id(new PHUIIconView()) 43 - ->setIconFont('fa-eye-slash'); 44 - $button = id(new PHUIButtonView()) 45 - ->setTag('a') 46 - ->addSigil('workflow') 47 - ->setColor(PHUIButtonView::SIMPLE) 48 - ->setIcon($image) 49 - ->setText(pht('Mark All Read')); 50 - 51 - $notifications = $query->executeWithOffsetPager($pager); 52 - $clear_uri = id(new PhutilURI('/notification/clear/')); 53 - if ($notifications) { 54 - $builder = new PhabricatorNotificationBuilder($notifications); 55 - $builder->setUser($user); 56 - $view = $builder->buildView()->render(); 57 - $clear_uri->setQueryParam( 58 - 'chronoKey', 59 - head($notifications)->getChronologicalKey()); 60 - } else { 61 - $view = phutil_tag_div( 62 - 'phabricator-notification no-notifications', 63 - $no_data); 64 - $button->setDisabled(true); 65 - } 66 - $button->setHref((string) $clear_uri); 67 - 68 - $view = id(new PHUIBoxView()) 69 - ->addPadding(PHUI::PADDING_MEDIUM) 70 - ->addClass('phabricator-notification-list') 71 - ->appendChild($view); 72 - 73 - $notif_header = id(new PHUIHeaderView()) 74 - ->setHeader($header) 75 - ->addActionLink($button); 76 - 77 - $box = id(new PHUIObjectBoxView()) 78 - ->setHeader($notif_header) 79 - ->appendChild($view); 80 - 81 - $nav->appendChild($box); 82 - $nav->appendChild($pager); 83 - 84 - return $this->buildApplicationPage( 85 - $nav, 86 - array( 87 - 'title' => pht('Notifications'), 88 - )); 33 + return $nav; 89 34 } 90 35 91 36 }
+4 -4
src/applications/notification/controller/PhabricatorNotificationPanelController.php
··· 8 8 $request = $this->getRequest(); 9 9 $user = $request->getUser(); 10 10 11 - $query = new PhabricatorNotificationQuery(); 12 - $query->setViewer($user); 13 - $query->setUserPHID($user->getPHID()); 14 - $query->setLimit(15); 11 + $query = id(new PhabricatorNotificationQuery()) 12 + ->setViewer($user) 13 + ->withUserPHIDs(array($user->getPHID())) 14 + ->setLimit(15); 15 15 16 16 $stories = $query->execute(); 17 17
+6 -10
src/applications/notification/query/PhabricatorNotificationQuery.php
··· 7 7 final class PhabricatorNotificationQuery 8 8 extends PhabricatorCursorPagedPolicyAwareQuery { 9 9 10 - private $userPHID; 10 + private $userPHIDs; 11 11 private $keys; 12 12 private $unread; 13 13 ··· 15 15 /* -( Configuring the Query )---------------------------------------------- */ 16 16 17 17 18 - public function setUserPHID($user_phid) { 19 - $this->userPHID = $user_phid; 18 + public function withUserPHIDs(array $user_phids) { 19 + $this->userPHIDs = $user_phids; 20 20 return $this; 21 21 } 22 22 ··· 46 46 47 47 48 48 protected function loadPage() { 49 - if (!$this->userPHID) { 50 - throw new Exception('Call setUser() before executing the query'); 51 - } 52 - 53 49 $story_table = new PhabricatorFeedStoryData(); 54 50 $notification_table = new PhabricatorFeedStoryNotification(); 55 51 ··· 83 79 private function buildWhereClause(AphrontDatabaseConnection $conn_r) { 84 80 $where = array(); 85 81 86 - if ($this->userPHID) { 82 + if ($this->userPHIDs !== null) { 87 83 $where[] = qsprintf( 88 84 $conn_r, 89 - 'notif.userPHID = %s', 90 - $this->userPHID); 85 + 'notif.userPHID IN (%Ls)', 86 + $this->userPHIDs); 91 87 } 92 88 93 89 if ($this->unread !== null) {
+139
src/applications/notification/query/PhabricatorNotificationSearchEngine.php
··· 1 + <?php 2 + 3 + final class PhabricatorNotificationSearchEngine 4 + extends PhabricatorApplicationSearchEngine { 5 + 6 + public function getResultTypeDescription() { 7 + return pht('Notifications'); 8 + } 9 + 10 + public function getApplicationClassName() { 11 + return 'PhabricatorNotificationsApplication'; 12 + } 13 + 14 + public function buildSavedQueryFromRequest(AphrontRequest $request) { 15 + $saved = new PhabricatorSavedQuery(); 16 + 17 + $saved->setParameter( 18 + 'unread', 19 + $this->readBoolFromRequest($request, 'unread')); 20 + 21 + return $saved; 22 + } 23 + 24 + public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { 25 + $query = id(new PhabricatorNotificationQuery()) 26 + ->withUserPHIDs(array($this->requireViewer()->getPHID())); 27 + 28 + if ($saved->getParameter('unread')) { 29 + $query->withUnread(true); 30 + } 31 + 32 + return $query; 33 + } 34 + 35 + public function buildSearchForm( 36 + AphrontFormView $form, 37 + PhabricatorSavedQuery $saved) { 38 + 39 + $unread = $saved->getParameter('unread'); 40 + 41 + $form->appendChild( 42 + id(new AphrontFormCheckboxControl()) 43 + ->setLabel(pht('Unread')) 44 + ->addCheckbox( 45 + 'unread', 46 + 1, 47 + pht('Show only unread notifications.'), 48 + $unread)); 49 + } 50 + 51 + protected function getURI($path) { 52 + return '/notification/'.$path; 53 + } 54 + 55 + public function getBuiltinQueryNames() { 56 + 57 + $names = array( 58 + 'all' => pht('All Notifications'), 59 + 'unread' => pht('Unread Notifications'), 60 + ); 61 + 62 + return $names; 63 + } 64 + 65 + public function buildSavedQueryFromBuiltin($query_key) { 66 + $query = $this->newSavedQuery(); 67 + $query->setQueryKey($query_key); 68 + 69 + switch ($query_key) { 70 + case 'all': 71 + return $query; 72 + case 'unread': 73 + return $query->setParameter('unread', true); 74 + } 75 + 76 + return parent::buildSavedQueryFromBuiltin($query_key); 77 + } 78 + 79 + protected function renderResultList( 80 + array $notifications, 81 + PhabricatorSavedQuery $query, 82 + array $handles) { 83 + assert_instances_of($notifications, 'PhabricatorFeedStory'); 84 + 85 + $viewer = $this->requireViewer(); 86 + 87 + $image = id(new PHUIIconView()) 88 + ->setIconFont('fa-eye-slash'); 89 + 90 + $button = id(new PHUIButtonView()) 91 + ->setTag('a') 92 + ->addSigil('workflow') 93 + ->setColor(PHUIButtonView::SIMPLE) 94 + ->setIcon($image) 95 + ->setText(pht('Mark All Read')); 96 + 97 + switch ($query->getQueryKey()) { 98 + case 'unread': 99 + $header = pht('Unread Notifications'); 100 + $no_data = pht('You have no unread notifications.'); 101 + break; 102 + default: 103 + $header = pht('Notifications'); 104 + $no_data = pht('You have no notifications.'); 105 + break; 106 + } 107 + 108 + $clear_uri = id(new PhutilURI('/notification/clear/')); 109 + if ($notifications) { 110 + $builder = id(new PhabricatorNotificationBuilder($notifications)) 111 + ->setUser($viewer); 112 + 113 + $view = $builder->buildView(); 114 + $clear_uri->setQueryParam( 115 + 'chronoKey', 116 + head($notifications)->getChronologicalKey()); 117 + } else { 118 + $view = phutil_tag_div( 119 + 'phabricator-notification no-notifications', 120 + $no_data); 121 + $button->setDisabled(true); 122 + } 123 + $button->setHref((string)$clear_uri); 124 + 125 + $view = id(new PHUIBoxView()) 126 + ->addPadding(PHUI::PADDING_MEDIUM) 127 + ->addClass('phabricator-notification-list') 128 + ->appendChild($view); 129 + 130 + $notif_header = id(new PHUIHeaderView()) 131 + ->setHeader($header) 132 + ->addActionLink($button); 133 + 134 + return id(new PHUIObjectBoxView()) 135 + ->setHeader($notif_header) 136 + ->appendChild($view); 137 + } 138 + 139 + }