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

Allow construction of ApplicationSearch queries with GET

Summary:
Ref T3775 (discussion here). Ref T2625.

T3775 presents two problems:

# Existing tools which linked to `/differential/active/epriestley/` (that is, put a username in the URL) can't generate search links now.
# Humans can't edit the URL anymore, either.

I think (1) is an actual issue, and this fixes it. I think (2) is pretty fluff, and this doesn't really try to fix it, although it probably improves it.

The fix for (1) is:

- Provide a helper to read a parameter containing either a list of user PHIDs or a list of usernames, so `/?users[]=PHID-USER-xyz` (from a tokenizer) and `/?users=alincoln,htaft` (from an external program) are equivalent inputs.
- Rename all the form parameters to be more digestable (`authorPHIDs` -> `authors`). Almost all of them were in this form already anyway. This just gives us `?users=alincoln` instead of `userPHIDs=alincoln`.
- Inside ApplicationSearch, if a request has no query associated with it but does have query parameters, build a query from the request instead of issuing the user's default query. Basically, this means that `/differential/` runs the default query, while `/differential/?users=x` runs a custom query.

Test Plan: {F56612}

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2625, T3775

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

+98 -27
+5 -1
src/aphront/AphrontRequest.php
··· 168 168 (idx($_FILES[$name], 'error') !== UPLOAD_ERR_NO_FILE); 169 169 } 170 170 171 + final public function isHTTPGet() { 172 + return ($_SERVER['REQUEST_METHOD'] == 'GET'); 173 + } 174 + 171 175 final public function isHTTPPost() { 172 176 return ($_SERVER['REQUEST_METHOD'] == 'POST'); 173 177 } ··· 416 420 417 421 // Remove magic parameters like __dialog__ and __ajax__. 418 422 foreach ($data as $key => $value) { 419 - if (strncmp($key, '__', 2)) { 423 + if (!strncmp($key, '__', 2)) { 420 424 unset($data[$key]); 421 425 } 422 426 }
+1 -1
src/applications/countdown/query/PhabricatorCountdownSearchEngine.php
··· 7 7 $saved = new PhabricatorSavedQuery(); 8 8 $saved->setParameter( 9 9 'authorPHIDs', 10 - array_values($request->getArr('authors'))); 10 + $this->readUsersFromRequest($request, 'authors')); 11 11 12 12 $saved->setParameter('upcoming', $request->getBool('upcoming')); 13 13
+8 -8
src/applications/differential/query/DifferentialRevisionSearchEngine.php
··· 15 15 16 16 $saved->setParameter( 17 17 'responsiblePHIDs', 18 - $request->getArr('responsiblePHIDs')); 18 + $this->readUsersFromRequest($request, 'responsibles')); 19 19 20 20 $saved->setParameter( 21 21 'authorPHIDs', 22 - $request->getArr('authorPHIDs')); 22 + $this->readUsersFromRequest($request, 'authors')); 23 23 24 24 $saved->setParameter( 25 25 'reviewerPHIDs', 26 - $request->getArr('reviewerPHIDs')); 26 + $this->readUsersFromRequest($request, 'reviewers')); 27 27 28 28 $saved->setParameter( 29 29 'subscriberPHIDs', 30 - $request->getArr('subscriberPHIDs')); 30 + $this->readUsersFromRequest($request, 'subscribers')); 31 31 32 32 $saved->setParameter( 33 33 'draft', ··· 115 115 ->appendChild( 116 116 id(new AphrontFormTokenizerControl()) 117 117 ->setLabel(pht('Responsible Users')) 118 - ->setName('responsiblePHIDs') 118 + ->setName('responsibles') 119 119 ->setDatasource('/typeahead/common/accounts/') 120 120 ->setValue(array_select_keys($tokens, $responsible_phids))) 121 121 ->appendChild( 122 122 id(new AphrontFormTokenizerControl()) 123 123 ->setLabel(pht('Authors')) 124 - ->setName('authorPHIDs') 124 + ->setName('authors') 125 125 ->setDatasource('/typeahead/common/accounts/') 126 126 ->setValue(array_select_keys($tokens, $author_phids))) 127 127 ->appendChild( 128 128 id(new AphrontFormTokenizerControl()) 129 129 ->setLabel(pht('Reviewers')) 130 - ->setName('reviewerPHIDs') 130 + ->setName('reviewers') 131 131 ->setDatasource('/typeahead/common/accounts/') 132 132 ->setValue(array_select_keys($tokens, $reviewer_phids))) 133 133 ->appendChild( 134 134 id(new AphrontFormTokenizerControl()) 135 135 ->setLabel(pht('Subscribers')) 136 - ->setName('subscriberPHIDs') 136 + ->setName('subscribers') 137 137 ->setDatasource('/typeahead/common/allmailable/') 138 138 ->setValue(array_select_keys($tokens, $subscriber_phids))) 139 139 ->appendChild(
+2 -2
src/applications/feed/query/PhabricatorFeedSearchEngine.php
··· 8 8 9 9 $saved->setParameter( 10 10 'userPHIDs', 11 - array_values($request->getArr('userPHIDs'))); 11 + $this->readUsersFromRequest($request, 'users')); 12 12 13 13 $saved->setParameter( 14 14 'projectPHIDs', ··· 76 76 ->appendChild( 77 77 id(new AphrontFormTokenizerControl()) 78 78 ->setDatasource('/typeahead/common/users/') 79 - ->setName('userPHIDs') 79 + ->setName('users') 80 80 ->setLabel(pht('Include Users')) 81 81 ->setValue($user_tokens)) 82 82 ->appendChild(
+1 -1
src/applications/files/query/PhabricatorFileSearchEngine.php
··· 7 7 $saved = new PhabricatorSavedQuery(); 8 8 $saved->setParameter( 9 9 'authorPHIDs', 10 - array_values($request->getArr('authors'))); 10 + $this->readUsersFromRequest($request, 'authors')); 11 11 12 12 $saved->setParameter('explicit', $request->getBool('explicit')); 13 13 $saved->setParameter('createdStart', $request->getStr('createdStart'));
+1 -1
src/applications/herald/query/HeraldRuleSearchEngine.php
··· 8 8 9 9 $saved->setParameter( 10 10 'authorPHIDs', 11 - array_values($request->getArr('authors'))); 11 + $this->readUsersFromRequest($request, 'authors')); 12 12 13 13 $saved->setParameter('contentType', $request->getStr('contentType')); 14 14 $saved->setParameter('ruleType', $request->getStr('ruleType'));
+2 -2
src/applications/legalpad/query/LegalpadDocumentSearchEngine.php
··· 10 10 $saved = new PhabricatorSavedQuery(); 11 11 $saved->setParameter( 12 12 'creatorPHIDs', 13 - array_values($request->getArr('creators'))); 13 + $this->readUsersFromRequest($request, 'creators')); 14 14 15 15 $saved->setParameter( 16 16 'contributorPHIDs', 17 - array_values($request->getArr('contributors'))); 17 + $this->readUsersFromRequest($request, 'contributors')); 18 18 19 19 $saved->setParameter('createdStart', $request->getStr('createdStart')); 20 20 $saved->setParameter('createdEnd', $request->getStr('createdEnd'));
+1 -1
src/applications/macro/query/PhabricatorMacroSearchEngine.php
··· 7 7 $saved = new PhabricatorSavedQuery(); 8 8 $saved->setParameter( 9 9 'authorPHIDs', 10 - array_values($request->getArr('authors'))); 10 + $this->readUsersFromRequest($request, 'authors')); 11 11 12 12 $saved->setParameter('status', $request->getStr('status')); 13 13 $saved->setParameter('names', $request->getStrList('names'));
+1 -1
src/applications/paste/query/PhabricatorPasteSearchEngine.php
··· 10 10 $saved = new PhabricatorSavedQuery(); 11 11 $saved->setParameter( 12 12 'authorPHIDs', 13 - array_values($request->getArr('authors'))); 13 + $this->readUsersFromRequest($request, 'authors')); 14 14 15 15 $languages = $request->getStrList('languages'); 16 16 if ($request->getBool('noLanguage')) {
+1 -1
src/applications/pholio/query/PholioMockSearchEngine.php
··· 7 7 $saved = new PhabricatorSavedQuery(); 8 8 $saved->setParameter( 9 9 'authorPHIDs', 10 - array_values($request->getArr('authors'))); 10 + $this->readUsersFromRequest($request, 'authors')); 11 11 12 12 return $saved; 13 13 }
+2 -2
src/applications/ponder/query/PonderQuestionSearchEngine.php
··· 8 8 9 9 $saved->setParameter( 10 10 'authorPHIDs', 11 - array_values($request->getArr('authors'))); 11 + $this->readUsersFromRequest($request, 'authors')); 12 12 13 13 $saved->setParameter( 14 14 'answererPHIDs', 15 - array_values($request->getArr('answerers'))); 15 + $this->readUsersFromRequest($request, 'answerers')); 16 16 17 17 $saved->setParameter('status', $request->getStr('status')); 18 18
+4 -2
src/applications/project/query/PhabricatorProjectSearchEngine.php
··· 6 6 public function buildSavedQueryFromRequest(AphrontRequest $request) { 7 7 $saved = new PhabricatorSavedQuery(); 8 8 9 - $saved->setParameter('memberPHIDs', $request->getArr('memberPHIDs')); 9 + $saved->setParameter( 10 + 'memberPHIDs', 11 + $this->readUsersFromRequest($request, 'members')); 10 12 $saved->setParameter('status', $request->getStr('status')); 11 13 12 14 return $saved; ··· 45 47 ->appendChild( 46 48 id(new AphrontFormTokenizerControl()) 47 49 ->setDatasource('/typeahead/common/users/') 48 - ->setName('memberPHIDs') 50 + ->setName('members') 49 51 ->setLabel(pht('Members')) 50 52 ->setValue($member_tokens)) 51 53 ->appendChild(
+4 -2
src/applications/releeph/query/ReleephRequestSearchEngine.php
··· 25 25 26 26 $saved->setParameter('status', $request->getStr('status')); 27 27 $saved->setParameter('severity', $request->getStr('severity')); 28 - $saved->setParameter('requestorPHIDs', $request->getArr('requestorPHIDs')); 28 + $saved->setParameter( 29 + 'requestorPHIDs', 30 + $this->readUsersFromRequest($request, 'requestors')); 29 31 30 32 return $saved; 31 33 } ··· 79 81 ->appendChild( 80 82 id(new AphrontFormTokenizerControl()) 81 83 ->setDatasource('/typeahead/common/users/') 82 - ->setName('requestorPHIDs') 84 + ->setName('requestors') 83 85 ->setLabel(pht('Requestors')) 84 86 ->setValue($requestor_tokens)); 85 87 }
+9 -1
src/applications/search/controller/PhabricatorApplicationSearchController.php
··· 107 107 $run_query = false; 108 108 $query_key = $request->getStr('query'); 109 109 } else if (!strlen($this->queryKey)) { 110 - $query_key = head_key($engine->loadEnabledNamedQueries()); 110 + if ($request->isHTTPGet() && $request->getPassthroughRequestData()) { 111 + // If this is a GET request and it has some query data, don't 112 + // do anything. We'll build and execute a query from it below. 113 + // This allows external tools to build URIs like "/query/?users=a,b". 114 + } else { 115 + // Otherwise, there's no query data so just run the user's default 116 + // query for this application. 117 + $query_key = head_key($engine->loadEnabledNamedQueries()); 118 + } 111 119 } 112 120 113 121 if ($engine->isBuiltinQuery($query_key)) {
+55
src/applications/search/engine/PhabricatorApplicationSearchEngine.php
··· 7 7 * @task builtin Builtin Queries 8 8 * @task uri Query URIs 9 9 * @task dates Date Filters 10 + * @task read Reading Utilities 10 11 * 11 12 * @group search 12 13 */ ··· 231 232 */ 232 233 public function buildSavedQueryFromBuiltin($query_key) { 233 234 throw new Exception("Builtin '{$query_key}' is not supported!"); 235 + } 236 + 237 + 238 + /* -( Reading Utilities )--------------------------------------------------- */ 239 + 240 + 241 + /** 242 + * Read a list of user PHIDs from a request in a flexible way. This method 243 + * supports either of these forms: 244 + * 245 + * users[]=alincoln&users[]=htaft 246 + * users=alincoln,htaft 247 + * 248 + * Additionally, users can be specified either by PHID or by name. 249 + * 250 + * The main goal of this flexibility is to allow external programs to generate 251 + * links to pages (like "alincoln's open revisions") without needing to make 252 + * API calls. 253 + * 254 + * @param AphrontRequest Request to read user PHIDs from. 255 + * @param string Key to read in the request. 256 + * @return list<phid> List of user PHIDs. 257 + * 258 + * @task read 259 + */ 260 + protected function readUsersFromRequest(AphrontRequest $request, $key) { 261 + $list = $request->getArr($key, null); 262 + if ($list === null) { 263 + $list = $request->getStrList($key); 264 + } 265 + 266 + $phids = array(); 267 + $names = array(); 268 + $user_type = PhabricatorPHIDConstants::PHID_TYPE_USER; 269 + foreach ($list as $item) { 270 + if (phid_get_type($item) == $user_type) { 271 + $phids[] = $item; 272 + } else { 273 + $names[] = $item; 274 + } 275 + } 276 + 277 + if ($names) { 278 + $users = id(new PhabricatorPeopleQuery()) 279 + ->setViewer($this->requireViewer()) 280 + ->withUsernames($names) 281 + ->execute(); 282 + foreach ($users as $user) { 283 + $phids[] = $user->getPHID(); 284 + } 285 + $phids = array_unique($phids); 286 + } 287 + 288 + return $phids; 234 289 } 235 290 236 291
+1 -1
src/applications/slowvote/query/PhabricatorSlowvoteSearchEngine.php
··· 7 7 $saved = new PhabricatorSavedQuery(); 8 8 $saved->setParameter( 9 9 'authorPHIDs', 10 - array_values($request->getArr('authors'))); 10 + $this->readUsersFromRequest($request, 'authors')); 11 11 12 12 $saved->setParameter('voted', $request->getBool('voted')); 13 13