mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 00:42:41 +01:00
Introduce search result buckets
Summary: Ref T10939. Currently, Differential hard-codes some behaviors for the "active" filter. This introduces "buckets" to make this grouping behavior more general/flexible. The buckets don't actually do any grouping yet, this just gets rid of the `$query === 'active'` stuff so far. These buckets change the page size to a large value, becuase pagination won't currently work with bucketing. The problem is that we normally paginate by selecting one more result than we need: so if we're building a page of size 10, we'll select 11 results. This is fast, and if we get 11 back, we know there's a next page with at least one result on it. With buckets, we can't do this, since our 11 results might come back in these buckets: - A, B, C, A, C, C, A, A, B, B, (B) So we know there are more results, and we know that bucket B has more results, but we have no clue if bucket A and bucket C have more results or not (or if there's anything in bucket D, etc). We might need to select a thousand more results to get the first (D) or the next (A). So we could render something like "Some buckets have more results, click here to go to the next page", but users would normally expect to be able to see "This specific bucket, A, has more results.", and we can't do that without a lot more work. It doesn't really matter for revisions, because almost no one has 1K of them, but this may need to be resolved eventually. (I have some OK-ish ideas for resolving it but nothing I'm particularly happy with.) Test Plan: {F1376542} Reviewers: chad Reviewed By: chad Maniphest Tasks: T10939 Differential Revision: https://secure.phabricator.com/D15923
This commit is contained in:
parent
3a727c31e2
commit
eade206625
6 changed files with 111 additions and 17 deletions
|
@ -533,6 +533,8 @@ phutil_register_library_map(array(
|
|||
'DifferentialRevisionQuery' => 'applications/differential/query/DifferentialRevisionQuery.php',
|
||||
'DifferentialRevisionRepositoryHeraldField' => 'applications/differential/herald/DifferentialRevisionRepositoryHeraldField.php',
|
||||
'DifferentialRevisionRepositoryProjectsHeraldField' => 'applications/differential/herald/DifferentialRevisionRepositoryProjectsHeraldField.php',
|
||||
'DifferentialRevisionRequiredActionResultBucket' => 'applications/differential/query/DifferentialRevisionRequiredActionResultBucket.php',
|
||||
'DifferentialRevisionResultBucket' => 'applications/differential/query/DifferentialRevisionResultBucket.php',
|
||||
'DifferentialRevisionReviewersHeraldField' => 'applications/differential/herald/DifferentialRevisionReviewersHeraldField.php',
|
||||
'DifferentialRevisionSearchEngine' => 'applications/differential/query/DifferentialRevisionSearchEngine.php',
|
||||
'DifferentialRevisionStatus' => 'applications/differential/constants/DifferentialRevisionStatus.php',
|
||||
|
@ -3317,6 +3319,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorSearchOrderField' => 'applications/search/field/PhabricatorSearchOrderField.php',
|
||||
'PhabricatorSearchPreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorSearchPreferencesSettingsPanel.php',
|
||||
'PhabricatorSearchRelationship' => 'applications/search/constants/PhabricatorSearchRelationship.php',
|
||||
'PhabricatorSearchResultBucket' => 'applications/search/buckets/PhabricatorSearchResultBucket.php',
|
||||
'PhabricatorSearchResultView' => 'applications/search/view/PhabricatorSearchResultView.php',
|
||||
'PhabricatorSearchSchemaSpec' => 'applications/search/storage/PhabricatorSearchSchemaSpec.php',
|
||||
'PhabricatorSearchSelectController' => 'applications/search/controller/PhabricatorSearchSelectController.php',
|
||||
|
@ -4758,6 +4761,8 @@ phutil_register_library_map(array(
|
|||
'DifferentialRevisionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'DifferentialRevisionRepositoryHeraldField' => 'DifferentialRevisionHeraldField',
|
||||
'DifferentialRevisionRepositoryProjectsHeraldField' => 'DifferentialRevisionHeraldField',
|
||||
'DifferentialRevisionRequiredActionResultBucket' => 'DifferentialRevisionResultBucket',
|
||||
'DifferentialRevisionResultBucket' => 'PhabricatorSearchResultBucket',
|
||||
'DifferentialRevisionReviewersHeraldField' => 'DifferentialRevisionHeraldField',
|
||||
'DifferentialRevisionSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'DifferentialRevisionStatus' => 'Phobject',
|
||||
|
@ -8009,6 +8014,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorSearchOrderField' => 'PhabricatorSearchField',
|
||||
'PhabricatorSearchPreferencesSettingsPanel' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorSearchRelationship' => 'Phobject',
|
||||
'PhabricatorSearchResultBucket' => 'Phobject',
|
||||
'PhabricatorSearchResultView' => 'AphrontView',
|
||||
'PhabricatorSearchSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
||||
'PhabricatorSearchSelectController' => 'PhabricatorSearchBaseController',
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialRevisionRequiredActionResultBucket
|
||||
extends DifferentialRevisionResultBucket {
|
||||
|
||||
const BUCKETKEY = 'action';
|
||||
|
||||
public function getResultBucketName() {
|
||||
return pht('Bucket by Required Action');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
abstract class DifferentialRevisionResultBucket
|
||||
extends PhabricatorSearchResultBucket {
|
||||
|
||||
public static function getAllResultBuckets() {
|
||||
return id(new PhutilClassMapQuery())
|
||||
->setAncestorClass(__CLASS__)
|
||||
->setUniqueMethod('getResultBucketKey')
|
||||
->execute();
|
||||
}
|
||||
|
||||
}
|
|
@ -11,6 +11,10 @@ final class DifferentialRevisionSearchEngine
|
|||
return 'PhabricatorDifferentialApplication';
|
||||
}
|
||||
|
||||
protected function newResultBuckets() {
|
||||
return DifferentialRevisionResultBucket::getAllResultBuckets();
|
||||
}
|
||||
|
||||
public function newQuery() {
|
||||
return id(new DifferentialRevisionQuery())
|
||||
->needFlags(true)
|
||||
|
@ -18,14 +22,6 @@ final class DifferentialRevisionSearchEngine
|
|||
->needRelationships(true);
|
||||
}
|
||||
|
||||
public function getPageSize(PhabricatorSavedQuery $saved) {
|
||||
if ($saved->getQueryKey() == 'active') {
|
||||
return 0xFFFF;
|
||||
}
|
||||
return parent::getPageSize($saved);
|
||||
}
|
||||
|
||||
|
||||
protected function buildQueryFromParameters(array $map) {
|
||||
$query = $this->newQuery();
|
||||
|
||||
|
@ -114,9 +110,12 @@ final class DifferentialRevisionSearchEngine
|
|||
|
||||
switch ($query_key) {
|
||||
case 'active':
|
||||
$bucket_key = DifferentialRevisionRequiredActionResultBucket::BUCKETKEY;
|
||||
|
||||
return $query
|
||||
->setParameter('responsiblePHIDs', array($viewer->getPHID()))
|
||||
->setParameter('status', DifferentialRevisionQuery::STATUS_OPEN);
|
||||
->setParameter('status', DifferentialRevisionQuery::STATUS_OPEN)
|
||||
->setParameter('bucket', $bucket_key);
|
||||
case 'authored':
|
||||
return $query
|
||||
->setParameter('authorPHIDs', array($viewer->getPHID()));
|
||||
|
@ -139,13 +138,6 @@ final class DifferentialRevisionSearchEngine
|
|||
);
|
||||
}
|
||||
|
||||
private function getOrderOptions() {
|
||||
return array(
|
||||
DifferentialRevisionQuery::ORDER_CREATED => pht('Created'),
|
||||
DifferentialRevisionQuery::ORDER_MODIFIED => pht('Updated'),
|
||||
);
|
||||
}
|
||||
|
||||
protected function renderResultList(
|
||||
array $revisions,
|
||||
PhabricatorSavedQuery $query,
|
||||
|
@ -157,8 +149,10 @@ final class DifferentialRevisionSearchEngine
|
|||
->setUser($viewer)
|
||||
->setNoBox($this->isPanelContext());
|
||||
|
||||
$bucket = $this->getResultBucket($query);
|
||||
|
||||
$views = array();
|
||||
if ($query->getQueryKey() == 'active') {
|
||||
if ($bucket) {
|
||||
$split = DifferentialRevisionQuery::splitResponsible(
|
||||
$revisions,
|
||||
$query->getParameter('responsiblePHIDs'));
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorSearchResultBucket
|
||||
extends Phobject {
|
||||
|
||||
private $pageSize;
|
||||
|
||||
final public function setPageSize($page_size) {
|
||||
$this->pageSize = $page_size;
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function getPageSize() {
|
||||
if ($this->pageSize === null) {
|
||||
return $this->getDefaultPageSize();
|
||||
}
|
||||
|
||||
return $this->pageSize;
|
||||
}
|
||||
|
||||
protected function getDefaultPageSize() {
|
||||
return 1000;
|
||||
}
|
||||
|
||||
abstract public function getResultBucketName();
|
||||
|
||||
final public function getResultBucketKey() {
|
||||
return $this->getPhobjectClassConstant('BUCKETKEY');
|
||||
}
|
||||
|
||||
}
|
|
@ -28,6 +28,8 @@ abstract class PhabricatorApplicationSearchEngine extends Phobject {
|
|||
const CONTEXT_LIST = 'list';
|
||||
const CONTEXT_PANEL = 'panel';
|
||||
|
||||
const BUCKET_NONE = 'none';
|
||||
|
||||
public function setController(PhabricatorController $controller) {
|
||||
$this->controller = $controller;
|
||||
return $this;
|
||||
|
@ -266,6 +268,18 @@ abstract class PhabricatorApplicationSearchEngine extends Phobject {
|
|||
->setOptions($orders);
|
||||
}
|
||||
|
||||
$buckets = $this->newResultBuckets();
|
||||
if ($query && $buckets) {
|
||||
$bucket_options = array(
|
||||
self::BUCKET_NONE => pht('No Bucketing'),
|
||||
) + mpull($buckets, 'getResultBucketName');
|
||||
|
||||
$fields[] = id(new PhabricatorSearchSelectField())
|
||||
->setLabel(pht('Bucket'))
|
||||
->setKey('bucket')
|
||||
->setOptions($bucket_options);
|
||||
}
|
||||
|
||||
$field_map = array();
|
||||
foreach ($fields as $field) {
|
||||
$key = $field->getKey();
|
||||
|
@ -944,13 +958,37 @@ abstract class PhabricatorApplicationSearchEngine extends Phobject {
|
|||
/* -( Paging and Executing Queries )--------------------------------------- */
|
||||
|
||||
|
||||
protected function newResultBuckets() {
|
||||
return array();
|
||||
}
|
||||
|
||||
protected function getResultBucket(PhabricatorSavedQuery $saved) {
|
||||
$key = $saved->getParameter('bucket');
|
||||
if ($key == self::BUCKET_NONE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$buckets = $this->newResultBuckets();
|
||||
return idx($buckets, $key);
|
||||
}
|
||||
|
||||
|
||||
public function getPageSize(PhabricatorSavedQuery $saved) {
|
||||
$bucket = $this->getResultBucket($saved);
|
||||
|
||||
$limit = (int)$saved->getParameter('limit');
|
||||
|
||||
if ($limit > 0) {
|
||||
if ($bucket) {
|
||||
$bucket->setPageSize($limit);
|
||||
}
|
||||
return $limit;
|
||||
}
|
||||
|
||||
if ($bucket) {
|
||||
return $bucket->getPageSize();
|
||||
}
|
||||
|
||||
return 100;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue