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
This commit is contained in:
epriestley
2013-08-29 11:52:29 -07:00
parent 5a11f08ba4
commit f1c75a6382
16 changed files with 98 additions and 27 deletions

View File

@@ -107,7 +107,15 @@ final class PhabricatorApplicationSearchController
$run_query = false;
$query_key = $request->getStr('query');
} else if (!strlen($this->queryKey)) {
$query_key = head_key($engine->loadEnabledNamedQueries());
if ($request->isHTTPGet() && $request->getPassthroughRequestData()) {
// If this is a GET request and it has some query data, don't
// do anything. We'll build and execute a query from it below.
// This allows external tools to build URIs like "/query/?users=a,b".
} else {
// Otherwise, there's no query data so just run the user's default
// query for this application.
$query_key = head_key($engine->loadEnabledNamedQueries());
}
}
if ($engine->isBuiltinQuery($query_key)) {

View File

@@ -7,6 +7,7 @@
* @task builtin Builtin Queries
* @task uri Query URIs
* @task dates Date Filters
* @task read Reading Utilities
*
* @group search
*/
@@ -234,6 +235,60 @@ abstract class PhabricatorApplicationSearchEngine {
}
/* -( Reading Utilities )--------------------------------------------------- */
/**
* Read a list of user PHIDs from a request in a flexible way. This method
* supports either of these forms:
*
* users[]=alincoln&users[]=htaft
* users=alincoln,htaft
*
* Additionally, users can be specified either by PHID or by name.
*
* The main goal of this flexibility is to allow external programs to generate
* links to pages (like "alincoln's open revisions") without needing to make
* API calls.
*
* @param AphrontRequest Request to read user PHIDs from.
* @param string Key to read in the request.
* @return list<phid> List of user PHIDs.
*
* @task read
*/
protected function readUsersFromRequest(AphrontRequest $request, $key) {
$list = $request->getArr($key, null);
if ($list === null) {
$list = $request->getStrList($key);
}
$phids = array();
$names = array();
$user_type = PhabricatorPHIDConstants::PHID_TYPE_USER;
foreach ($list as $item) {
if (phid_get_type($item) == $user_type) {
$phids[] = $item;
} else {
$names[] = $item;
}
}
if ($names) {
$users = id(new PhabricatorPeopleQuery())
->setViewer($this->requireViewer())
->withUsernames($names)
->execute();
foreach ($users as $user) {
$phids[] = $user->getPHID();
}
$phids = array_unique($phids);
}
return $phids;
}
/* -( Dates )-------------------------------------------------------------- */