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

Modernize DifferentialRevisionSearchEngine

Summary:
Ref T10939. Ref T4144. This moves the revision SearchEngine to modern code so I can add some kind of bucketing layer on top of it.

This seems to have worked pretty cleanly. One thing is that I removed the ability to search for "pending drafts":

- This was added in D1927 from a bootcamp task, was an indirect solution to a questionable problem, and almost certainly would not meet the bar today.
- Later, in D3324, we added the icons to the list. I think this is a better solution in general. In particular, it specifically addressed the query being kind of junky.
- At the time, Differential had a prebuilt "Drafts" filter. This was removed in D6347 with the move to ApplicationSearch, which simplified the large number of prebuilt filters. Although we got a lot of feedback about that, none requested that the drafts filter be restored.

Test Plan: Searched for responsible users, subscribers, orders, projects, repositories.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T4144, T10939

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

+81 -215
+33 -45
src/applications/differential/query/DifferentialRevisionQuery.php
··· 92 92 } 93 93 94 94 /** 95 - * Filter results to revisions with comments authored by the given PHIDs. 96 - * 97 - * @param array List of PHIDs of authors 98 - * @return this 99 - * @task config 100 - */ 101 - public function withDraftRepliesByAuthors(array $author_phids) { 102 - $this->draftAuthors = $author_phids; 103 - return $this; 104 - } 105 - 106 - /** 107 95 * Filter results to revisions which CC one of the listed people. Calling this 108 96 * function will clear anything set by previous calls to @{method:withCCs}. 109 97 * ··· 239 227 } 240 228 241 229 242 - /** 243 - * Set result ordering. Provide a class constant, such as 244 - * `DifferentialRevisionQuery::ORDER_CREATED`. 245 - * 246 - * @task config 247 - */ 248 - public function setOrder($order_constant) { 249 - switch ($order_constant) { 250 - case self::ORDER_CREATED: 251 - $this->setOrderVector(array('id')); 252 - break; 253 - case self::ORDER_MODIFIED: 254 - $this->setOrderVector(array('updated', 'id')); 255 - break; 256 - default: 257 - throw new Exception(pht('Unknown order "%s".', $order_constant)); 258 - } 259 - 260 - return $this; 261 - } 262 - 263 230 264 231 /** 265 232 * Set whether or not the query will load and attach relationships. ··· 371 338 /* -( Query Execution )---------------------------------------------------- */ 372 339 373 340 341 + public function newResultObject() { 342 + return new DifferentialRevision(); 343 + } 344 + 345 + 374 346 /** 375 347 * Execute the query as configured, returning matching 376 348 * @{class:DifferentialRevision} objects. ··· 379 351 * @task exec 380 352 */ 381 353 protected function loadPage() { 382 - $table = new DifferentialRevision(); 383 - $conn_r = $table->establishConnection('r'); 384 - 385 354 $data = $this->loadData(); 386 355 356 + $table = $this->newResultObject(); 387 357 return $table->loadAllFromArray($data); 388 358 } 389 359 ··· 519 489 } 520 490 521 491 private function loadData() { 522 - $table = new DifferentialRevision(); 492 + $table = $this->newResultObject(); 523 493 $conn_r = $table->establishConnection('r'); 524 494 525 495 $selects = array(); ··· 605 575 606 576 $joins = $this->buildJoinsClause($conn_r); 607 577 $where = $this->buildWhereClause($conn_r); 608 - $group_by = $this->buildGroupByClause($conn_r); 578 + $group_by = $this->buildGroupClause($conn_r); 609 579 $having = $this->buildHavingClause($conn_r); 610 580 611 581 $this->buildingGlobalOrder = false; ··· 849 819 /** 850 820 * @task internal 851 821 */ 852 - private function buildGroupByClause($conn_r) { 822 + protected function shouldGroupQueryResultRows() { 823 + 853 824 $join_triggers = array_merge( 854 825 $this->pathIDs, 855 826 $this->ccs, 856 827 $this->reviewers); 857 828 858 - $needs_distinct = (count($join_triggers) > 1); 829 + if (count($join_triggers) > 1) { 830 + return true; 831 + } 832 + 833 + return parent::shouldGroupQueryResultRows(); 834 + } 835 + 836 + public function getBuiltinOrders() { 837 + $orders = parent::getBuiltinOrders() + array( 838 + 'updated' => array( 839 + 'vector' => array('updated', 'id'), 840 + 'name' => pht('Date Updated (Latest First)'), 841 + 'aliases' => array(self::ORDER_MODIFIED), 842 + ), 843 + 'outdated' => array( 844 + 'vector' => array('-updated', '-id'), 845 + 'name' => pht('Date Updated (Oldest First)'), 846 + ), 847 + ); 848 + 849 + // Alias the "newest" builtin to the historical key for it. 850 + $orders['newest']['aliases'][] = self::ORDER_CREATED; 859 851 860 - if ($needs_distinct) { 861 - return 'GROUP BY r.id'; 862 - } else { 863 - return ''; 864 - } 852 + return $orders; 865 853 } 866 854 867 855 protected function getDefaultOrderVector() {
+47 -168
src/applications/differential/query/DifferentialRevisionSearchEngine.php
··· 25 25 return parent::getPageSize($saved); 26 26 } 27 27 28 - public function buildSavedQueryFromRequest(AphrontRequest $request) { 29 - $saved = new PhabricatorSavedQuery(); 30 28 31 - $saved->setParameter( 32 - 'responsiblePHIDs', 33 - $this->readUsersFromRequest($request, 'responsibles')); 34 - 35 - $saved->setParameter( 36 - 'authorPHIDs', 37 - $this->readUsersFromRequest($request, 'authors')); 38 - 39 - $saved->setParameter( 40 - 'reviewerPHIDs', 41 - $this->readUsersFromRequest( 42 - $request, 43 - 'reviewers', 44 - array( 45 - PhabricatorProjectProjectPHIDType::TYPECONST, 46 - ))); 47 - 48 - $saved->setParameter( 49 - 'subscriberPHIDs', 50 - $this->readSubscribersFromRequest($request, 'subscribers')); 51 - 52 - $saved->setParameter( 53 - 'repositoryPHIDs', 54 - $request->getArr('repositories')); 55 - 56 - $saved->setParameter( 57 - 'projects', 58 - $this->readProjectsFromRequest($request, 'projects')); 59 - 60 - $saved->setParameter( 61 - 'draft', 62 - $request->getBool('draft')); 63 - 64 - $saved->setParameter( 65 - 'order', 66 - $request->getStr('order')); 67 - 68 - $saved->setParameter( 69 - 'status', 70 - $request->getStr('status')); 71 - 72 - return $saved; 73 - } 74 - 75 - public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { 76 - $query = id(new DifferentialRevisionQuery()) 77 - ->needFlags(true) 78 - ->needDrafts(true) 79 - ->needRelationships(true); 80 - 81 - $user_datasource = id(new PhabricatorPeopleUserFunctionDatasource()) 82 - ->setViewer($this->requireViewer()); 83 - 84 - $responsible_phids = $saved->getParameter('responsiblePHIDs', array()); 85 - $responsible_phids = $user_datasource->evaluateTokens($responsible_phids); 86 - if ($responsible_phids) { 87 - $query->withResponsibleUsers($responsible_phids); 88 - } 89 - 90 - $this->setQueryProjects($query, $saved); 29 + protected function buildQueryFromParameters(array $map) { 30 + $query = $this->newQuery(); 91 31 92 - $author_phids = $saved->getParameter('authorPHIDs', array()); 93 - $author_phids = $user_datasource->evaluateTokens($author_phids); 94 - if ($author_phids) { 95 - $query->withAuthors($author_phids); 96 - } 97 - 98 - $reviewer_phids = $saved->getParameter('reviewerPHIDs', array()); 99 - if ($reviewer_phids) { 100 - $query->withReviewers($reviewer_phids); 101 - } 102 - 103 - $sub_datasource = id(new PhabricatorMetaMTAMailableFunctionDatasource()) 104 - ->setViewer($this->requireViewer()); 105 - $subscriber_phids = $saved->getParameter('subscriberPHIDs', array()); 106 - $subscriber_phids = $sub_datasource->evaluateTokens($subscriber_phids); 107 - if ($subscriber_phids) { 108 - $query->withCCs($subscriber_phids); 32 + if ($map['responsiblePHIDs']) { 33 + $query->withResponsibleUsers($map['responsiblePHIDs']); 109 34 } 110 35 111 - $repository_phids = $saved->getParameter('repositoryPHIDs', array()); 112 - if ($repository_phids) { 113 - $query->withRepositoryPHIDs($repository_phids); 36 + if ($map['authorPHIDs']) { 37 + $query->withAuthors($map['authorPHIDs']); 114 38 } 115 39 116 - $draft = $saved->getParameter('draft', false); 117 - if ($draft && $this->requireViewer()->isLoggedIn()) { 118 - $query->withDraftRepliesByAuthors( 119 - array($this->requireViewer()->getPHID())); 40 + if ($map['reviewerPHIDs']) { 41 + $query->withReviewers($map['reviewerPHIDs']); 120 42 } 121 43 122 - $status = $saved->getParameter('status'); 123 - if (idx($this->getStatusOptions(), $status)) { 124 - $query->withStatus($status); 44 + if ($map['repositoryPHIDs']) { 45 + $query->withRepositoryPHIDs($map['repositoryPHIDs']); 125 46 } 126 47 127 - $order = $saved->getParameter('order'); 128 - if (idx($this->getOrderOptions(), $order)) { 129 - $query->setOrder($order); 130 - } else { 131 - $query->setOrder(DifferentialRevisionQuery::ORDER_CREATED); 48 + if ($map['status']) { 49 + $query->withStatus($map['status']); 132 50 } 133 51 134 52 return $query; 135 53 } 136 54 137 - public function buildSearchForm( 138 - AphrontFormView $form, 139 - PhabricatorSavedQuery $saved) { 140 - 141 - $responsible_phids = $saved->getParameter('responsiblePHIDs', array()); 142 - $author_phids = $saved->getParameter('authorPHIDs', array()); 143 - $reviewer_phids = $saved->getParameter('reviewerPHIDs', array()); 144 - $subscriber_phids = $saved->getParameter('subscriberPHIDs', array()); 145 - $repository_phids = $saved->getParameter('repositoryPHIDs', array()); 146 - $only_draft = $saved->getParameter('draft', false); 147 - $projects = $saved->getParameter('projects', array()); 148 - 149 - $form 150 - ->appendControl( 151 - id(new AphrontFormTokenizerControl()) 152 - ->setLabel(pht('Responsible Users')) 153 - ->setName('responsibles') 154 - ->setDatasource(new PhabricatorPeopleUserFunctionDatasource()) 155 - ->setValue($responsible_phids)) 156 - ->appendControl( 157 - id(new AphrontFormTokenizerControl()) 158 - ->setLabel(pht('Authors')) 159 - ->setName('authors') 160 - ->setDatasource(new PhabricatorPeopleUserFunctionDatasource()) 161 - ->setValue($author_phids)) 162 - ->appendControl( 163 - id(new AphrontFormTokenizerControl()) 164 - ->setLabel(pht('Reviewers')) 165 - ->setName('reviewers') 166 - ->setDatasource(new PhabricatorProjectOrUserDatasource()) 167 - ->setValue($reviewer_phids)) 168 - ->appendControl( 169 - id(new AphrontFormTokenizerControl()) 170 - ->setLabel(pht('Subscribers')) 171 - ->setName('subscribers') 172 - ->setDatasource(new PhabricatorMetaMTAMailableFunctionDatasource()) 173 - ->setValue($subscriber_phids)) 174 - ->appendControl( 175 - id(new AphrontFormTokenizerControl()) 176 - ->setLabel(pht('Repositories')) 177 - ->setName('repositories') 178 - ->setDatasource(new DiffusionRepositoryDatasource()) 179 - ->setValue($repository_phids)) 180 - ->appendControl( 181 - id(new AphrontFormTokenizerControl()) 182 - ->setLabel(pht('Tags')) 183 - ->setName('projects') 184 - ->setDatasource(new PhabricatorProjectLogicalDatasource()) 185 - ->setValue($projects)) 186 - ->appendChild( 187 - id(new AphrontFormSelectControl()) 188 - ->setLabel(pht('Status')) 189 - ->setName('status') 190 - ->setOptions($this->getStatusOptions()) 191 - ->setValue($saved->getParameter('status'))); 192 - 193 - if ($this->requireViewer()->isLoggedIn()) { 194 - $form 195 - ->appendChild( 196 - id(new AphrontFormCheckboxControl()) 197 - ->addCheckbox( 198 - 'draft', 199 - 1, 200 - pht('Show only revisions with a draft comment.'), 201 - $only_draft)); 202 - } 203 - 204 - $form 205 - ->appendChild( 206 - id(new AphrontFormSelectControl()) 207 - ->setLabel(pht('Order')) 208 - ->setName('order') 209 - ->setOptions($this->getOrderOptions()) 210 - ->setValue($saved->getParameter('order'))); 55 + protected function buildCustomSearchFields() { 56 + return array( 57 + id(new PhabricatorUsersSearchField()) 58 + ->setLabel(pht('Responsible Users')) 59 + ->setKey('responsiblePHIDs') 60 + ->setAliases(array('responsiblePHID', 'responsibles', 'responsible')) 61 + ->setDescription( 62 + pht('Find revisions that a given user is responsible for.')), 63 + id(new PhabricatorUsersSearchField()) 64 + ->setLabel(pht('Authors')) 65 + ->setKey('authorPHIDs') 66 + ->setAliases(array('author', 'authors', 'authorPHID')) 67 + ->setDescription( 68 + pht('Find revisions with specific authors.')), 69 + id(new PhabricatorSearchDatasourceField()) 70 + ->setLabel(pht('Reviewers')) 71 + ->setKey('reviewerPHIDs') 72 + ->setAliases(array('reviewer', 'reviewers', 'reviewerPHID')) 73 + ->setDatasource(new DiffusionAuditorDatasource()) 74 + ->setDescription( 75 + pht('Find revisions with specific reviewers.')), 76 + id(new PhabricatorSearchDatasourceField()) 77 + ->setLabel(pht('Repositories')) 78 + ->setKey('repositoryPHIDs') 79 + ->setAliases(array('repository', 'repositories', 'repositoryPHID')) 80 + ->setDatasource(new DiffusionRepositoryDatasource()) 81 + ->setDescription( 82 + pht('Find revisions from specific repositories.')), 83 + id(new PhabricatorSearchSelectField()) 84 + ->setLabel(pht('Status')) 85 + ->setKey('status') 86 + ->setOptions($this->getStatusOptions()) 87 + ->setDescription( 88 + pht('Find revisions with particular statuses.')), 89 + ); 211 90 } 212 91 213 92 protected function getURI($path) {
+1 -2
src/applications/maniphest/query/ManiphestTaskSearchEngine.php
··· 148 148 } 149 149 150 150 protected function buildQueryFromParameters(array $map) { 151 - $query = id(new ManiphestTaskQuery()) 152 - ->needProjectPHIDs(true); 151 + $query = $this->newQuery(); 153 152 154 153 if ($map['assignedPHIDs']) { 155 154 $query->withOwners($map['assignedPHIDs']);