1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-27 01:02:42 +01:00

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
This commit is contained in:
epriestley 2016-05-15 10:07:58 -07:00
parent 03a1deba23
commit 3a727c31e2
3 changed files with 81 additions and 215 deletions

View file

@ -91,18 +91,6 @@ final class DifferentialRevisionQuery
return $this;
}
/**
* Filter results to revisions with comments authored by the given PHIDs.
*
* @param array List of PHIDs of authors
* @return this
* @task config
*/
public function withDraftRepliesByAuthors(array $author_phids) {
$this->draftAuthors = $author_phids;
return $this;
}
/**
* Filter results to revisions which CC one of the listed people. Calling this
* function will clear anything set by previous calls to @{method:withCCs}.
@ -239,27 +227,6 @@ final class DifferentialRevisionQuery
}
/**
* Set result ordering. Provide a class constant, such as
* `DifferentialRevisionQuery::ORDER_CREATED`.
*
* @task config
*/
public function setOrder($order_constant) {
switch ($order_constant) {
case self::ORDER_CREATED:
$this->setOrderVector(array('id'));
break;
case self::ORDER_MODIFIED:
$this->setOrderVector(array('updated', 'id'));
break;
default:
throw new Exception(pht('Unknown order "%s".', $order_constant));
}
return $this;
}
/**
* Set whether or not the query will load and attach relationships.
@ -371,6 +338,11 @@ final class DifferentialRevisionQuery
/* -( Query Execution )---------------------------------------------------- */
public function newResultObject() {
return new DifferentialRevision();
}
/**
* Execute the query as configured, returning matching
* @{class:DifferentialRevision} objects.
@ -379,11 +351,9 @@ final class DifferentialRevisionQuery
* @task exec
*/
protected function loadPage() {
$table = new DifferentialRevision();
$conn_r = $table->establishConnection('r');
$data = $this->loadData();
$table = $this->newResultObject();
return $table->loadAllFromArray($data);
}
@ -519,7 +489,7 @@ final class DifferentialRevisionQuery
}
private function loadData() {
$table = new DifferentialRevision();
$table = $this->newResultObject();
$conn_r = $table->establishConnection('r');
$selects = array();
@ -605,7 +575,7 @@ final class DifferentialRevisionQuery
$joins = $this->buildJoinsClause($conn_r);
$where = $this->buildWhereClause($conn_r);
$group_by = $this->buildGroupByClause($conn_r);
$group_by = $this->buildGroupClause($conn_r);
$having = $this->buildHavingClause($conn_r);
$this->buildingGlobalOrder = false;
@ -849,19 +819,37 @@ final class DifferentialRevisionQuery
/**
* @task internal
*/
private function buildGroupByClause($conn_r) {
protected function shouldGroupQueryResultRows() {
$join_triggers = array_merge(
$this->pathIDs,
$this->ccs,
$this->reviewers);
$needs_distinct = (count($join_triggers) > 1);
if ($needs_distinct) {
return 'GROUP BY r.id';
} else {
return '';
if (count($join_triggers) > 1) {
return true;
}
return parent::shouldGroupQueryResultRows();
}
public function getBuiltinOrders() {
$orders = parent::getBuiltinOrders() + array(
'updated' => array(
'vector' => array('updated', 'id'),
'name' => pht('Date Updated (Latest First)'),
'aliases' => array(self::ORDER_MODIFIED),
),
'outdated' => array(
'vector' => array('-updated', '-id'),
'name' => pht('Date Updated (Oldest First)'),
),
);
// Alias the "newest" builtin to the historical key for it.
$orders['newest']['aliases'][] = self::ORDER_CREATED;
return $orders;
}
protected function getDefaultOrderVector() {

View file

@ -25,189 +25,68 @@ final class DifferentialRevisionSearchEngine
return parent::getPageSize($saved);
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
$saved->setParameter(
'responsiblePHIDs',
$this->readUsersFromRequest($request, 'responsibles'));
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
$saved->setParameter(
'authorPHIDs',
$this->readUsersFromRequest($request, 'authors'));
$saved->setParameter(
'reviewerPHIDs',
$this->readUsersFromRequest(
$request,
'reviewers',
array(
PhabricatorProjectProjectPHIDType::TYPECONST,
)));
$saved->setParameter(
'subscriberPHIDs',
$this->readSubscribersFromRequest($request, 'subscribers'));
$saved->setParameter(
'repositoryPHIDs',
$request->getArr('repositories'));
$saved->setParameter(
'projects',
$this->readProjectsFromRequest($request, 'projects'));
$saved->setParameter(
'draft',
$request->getBool('draft'));
$saved->setParameter(
'order',
$request->getStr('order'));
$saved->setParameter(
'status',
$request->getStr('status'));
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new DifferentialRevisionQuery())
->needFlags(true)
->needDrafts(true)
->needRelationships(true);
$user_datasource = id(new PhabricatorPeopleUserFunctionDatasource())
->setViewer($this->requireViewer());
$responsible_phids = $saved->getParameter('responsiblePHIDs', array());
$responsible_phids = $user_datasource->evaluateTokens($responsible_phids);
if ($responsible_phids) {
$query->withResponsibleUsers($responsible_phids);
if ($map['responsiblePHIDs']) {
$query->withResponsibleUsers($map['responsiblePHIDs']);
}
$this->setQueryProjects($query, $saved);
$author_phids = $saved->getParameter('authorPHIDs', array());
$author_phids = $user_datasource->evaluateTokens($author_phids);
if ($author_phids) {
$query->withAuthors($author_phids);
if ($map['authorPHIDs']) {
$query->withAuthors($map['authorPHIDs']);
}
$reviewer_phids = $saved->getParameter('reviewerPHIDs', array());
if ($reviewer_phids) {
$query->withReviewers($reviewer_phids);
if ($map['reviewerPHIDs']) {
$query->withReviewers($map['reviewerPHIDs']);
}
$sub_datasource = id(new PhabricatorMetaMTAMailableFunctionDatasource())
->setViewer($this->requireViewer());
$subscriber_phids = $saved->getParameter('subscriberPHIDs', array());
$subscriber_phids = $sub_datasource->evaluateTokens($subscriber_phids);
if ($subscriber_phids) {
$query->withCCs($subscriber_phids);
if ($map['repositoryPHIDs']) {
$query->withRepositoryPHIDs($map['repositoryPHIDs']);
}
$repository_phids = $saved->getParameter('repositoryPHIDs', array());
if ($repository_phids) {
$query->withRepositoryPHIDs($repository_phids);
}
$draft = $saved->getParameter('draft', false);
if ($draft && $this->requireViewer()->isLoggedIn()) {
$query->withDraftRepliesByAuthors(
array($this->requireViewer()->getPHID()));
}
$status = $saved->getParameter('status');
if (idx($this->getStatusOptions(), $status)) {
$query->withStatus($status);
}
$order = $saved->getParameter('order');
if (idx($this->getOrderOptions(), $order)) {
$query->setOrder($order);
} else {
$query->setOrder(DifferentialRevisionQuery::ORDER_CREATED);
if ($map['status']) {
$query->withStatus($map['status']);
}
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved) {
$responsible_phids = $saved->getParameter('responsiblePHIDs', array());
$author_phids = $saved->getParameter('authorPHIDs', array());
$reviewer_phids = $saved->getParameter('reviewerPHIDs', array());
$subscriber_phids = $saved->getParameter('subscriberPHIDs', array());
$repository_phids = $saved->getParameter('repositoryPHIDs', array());
$only_draft = $saved->getParameter('draft', false);
$projects = $saved->getParameter('projects', array());
$form
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Responsible Users'))
->setName('responsibles')
->setDatasource(new PhabricatorPeopleUserFunctionDatasource())
->setValue($responsible_phids))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Authors'))
->setName('authors')
->setDatasource(new PhabricatorPeopleUserFunctionDatasource())
->setValue($author_phids))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Reviewers'))
->setName('reviewers')
->setDatasource(new PhabricatorProjectOrUserDatasource())
->setValue($reviewer_phids))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Subscribers'))
->setName('subscribers')
->setDatasource(new PhabricatorMetaMTAMailableFunctionDatasource())
->setValue($subscriber_phids))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Repositories'))
->setName('repositories')
->setDatasource(new DiffusionRepositoryDatasource())
->setValue($repository_phids))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Tags'))
->setName('projects')
->setDatasource(new PhabricatorProjectLogicalDatasource())
->setValue($projects))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Status'))
->setName('status')
->setOptions($this->getStatusOptions())
->setValue($saved->getParameter('status')));
if ($this->requireViewer()->isLoggedIn()) {
$form
->appendChild(
id(new AphrontFormCheckboxControl())
->addCheckbox(
'draft',
1,
pht('Show only revisions with a draft comment.'),
$only_draft));
}
$form
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Order'))
->setName('order')
->setOptions($this->getOrderOptions())
->setValue($saved->getParameter('order')));
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setLabel(pht('Responsible Users'))
->setKey('responsiblePHIDs')
->setAliases(array('responsiblePHID', 'responsibles', 'responsible'))
->setDescription(
pht('Find revisions that a given user is responsible for.')),
id(new PhabricatorUsersSearchField())
->setLabel(pht('Authors'))
->setKey('authorPHIDs')
->setAliases(array('author', 'authors', 'authorPHID'))
->setDescription(
pht('Find revisions with specific authors.')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Reviewers'))
->setKey('reviewerPHIDs')
->setAliases(array('reviewer', 'reviewers', 'reviewerPHID'))
->setDatasource(new DiffusionAuditorDatasource())
->setDescription(
pht('Find revisions with specific reviewers.')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Repositories'))
->setKey('repositoryPHIDs')
->setAliases(array('repository', 'repositories', 'repositoryPHID'))
->setDatasource(new DiffusionRepositoryDatasource())
->setDescription(
pht('Find revisions from specific repositories.')),
id(new PhabricatorSearchSelectField())
->setLabel(pht('Status'))
->setKey('status')
->setOptions($this->getStatusOptions())
->setDescription(
pht('Find revisions with particular statuses.')),
);
}
protected function getURI($path) {

View file

@ -148,8 +148,7 @@ final class ManiphestTaskSearchEngine
}
protected function buildQueryFromParameters(array $map) {
$query = id(new ManiphestTaskQuery())
->needProjectPHIDs(true);
$query = $this->newQuery();
if ($map['assignedPHIDs']) {
$query->withOwners($map['assignedPHIDs']);