2013-09-10 19:04:26 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
final class ManiphestTaskSearchEngine
|
|
|
|
extends PhabricatorApplicationSearchEngine {
|
|
|
|
|
2014-05-16 04:17:38 +02:00
|
|
|
private $showBatchControls;
|
2014-05-20 20:42:05 +02:00
|
|
|
private $baseURI;
|
|
|
|
private $isBoardView;
|
|
|
|
|
|
|
|
public function setIsBoardView($is_board_view) {
|
|
|
|
$this->isBoardView = $is_board_view;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getIsBoardView() {
|
|
|
|
return $this->isBoardView;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setBaseURI($base_uri) {
|
|
|
|
$this->baseURI = $base_uri;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getBaseURI() {
|
|
|
|
return $this->baseURI;
|
|
|
|
}
|
2014-05-16 04:17:38 +02:00
|
|
|
|
|
|
|
public function setShowBatchControls($show_batch_controls) {
|
|
|
|
$this->showBatchControls = $show_batch_controls;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2014-06-12 22:22:20 +02:00
|
|
|
public function getResultTypeDescription() {
|
|
|
|
return pht('Tasks');
|
|
|
|
}
|
|
|
|
|
2015-02-05 00:47:48 +01:00
|
|
|
public function getApplicationClassName() {
|
2014-07-23 02:03:09 +02:00
|
|
|
return 'PhabricatorManiphestApplication';
|
2014-05-16 04:17:38 +02:00
|
|
|
}
|
|
|
|
|
2015-06-08 21:23:13 +02:00
|
|
|
public function newQuery() {
|
|
|
|
return id(new ManiphestTaskQuery())
|
|
|
|
->needProjectPHIDs(true);
|
2013-09-17 01:03:09 +02:00
|
|
|
}
|
|
|
|
|
2015-06-14 23:34:14 +02:00
|
|
|
protected function buildCustomSearchFields() {
|
2015-06-09 22:17:31 +02:00
|
|
|
return array(
|
2015-07-06 14:52:04 +02:00
|
|
|
id(new PhabricatorOwnersSearchField())
|
2015-06-09 22:17:31 +02:00
|
|
|
->setLabel(pht('Assigned To'))
|
|
|
|
->setKey('assignedPHIDs')
|
2015-12-13 16:43:02 +01:00
|
|
|
->setConduitKey('assigned')
|
|
|
|
->setAliases(array('assigned'))
|
|
|
|
->setDescription(
|
|
|
|
pht('Search for tasks owned by a user from a list.')),
|
2015-07-06 14:52:04 +02:00
|
|
|
id(new PhabricatorUsersSearchField())
|
2015-06-09 22:17:31 +02:00
|
|
|
->setLabel(pht('Authors'))
|
|
|
|
->setKey('authorPHIDs')
|
2015-12-13 16:43:02 +01:00
|
|
|
->setAliases(array('author', 'authors'))
|
|
|
|
->setDescription(
|
|
|
|
pht('Search for tasks with given authors.')),
|
2015-06-09 22:17:31 +02:00
|
|
|
id(new PhabricatorSearchDatasourceField())
|
|
|
|
->setLabel(pht('Statuses'))
|
|
|
|
->setKey('statuses')
|
|
|
|
->setAliases(array('status'))
|
2015-12-13 16:43:02 +01:00
|
|
|
->setDescription(
|
|
|
|
pht('Search for tasks with given statuses.'))
|
2015-06-09 22:17:31 +02:00
|
|
|
->setDatasource(new ManiphestTaskStatusFunctionDatasource()),
|
|
|
|
id(new PhabricatorSearchDatasourceField())
|
|
|
|
->setLabel(pht('Priorities'))
|
|
|
|
->setKey('priorities')
|
|
|
|
->setAliases(array('priority'))
|
2015-12-13 16:43:02 +01:00
|
|
|
->setDescription(
|
|
|
|
pht('Search for tasks with given priorities.'))
|
|
|
|
->setConduitParameterType(new ConduitIntListParameterType())
|
2015-06-09 22:17:31 +02:00
|
|
|
->setDatasource(new ManiphestTaskPriorityDatasource()),
|
|
|
|
id(new PhabricatorSearchTextField())
|
|
|
|
->setLabel(pht('Contains Words'))
|
|
|
|
->setKey('fulltext'),
|
|
|
|
id(new PhabricatorSearchThreeStateField())
|
|
|
|
->setLabel(pht('Blocking'))
|
|
|
|
->setKey('blocking')
|
|
|
|
->setOptions(
|
|
|
|
pht('(Show All)'),
|
|
|
|
pht('Show Only Tasks Blocking Other Tasks'),
|
|
|
|
pht('Hide Tasks Blocking Other Tasks')),
|
|
|
|
id(new PhabricatorSearchThreeStateField())
|
|
|
|
->setLabel(pht('Blocked'))
|
|
|
|
->setKey('blocked')
|
|
|
|
->setOptions(
|
|
|
|
pht('(Show All)'),
|
|
|
|
pht('Show Only Task Blocked By Other Tasks'),
|
|
|
|
pht('Hide Tasks Blocked By Other Tasks')),
|
|
|
|
id(new PhabricatorSearchSelectField())
|
|
|
|
->setLabel(pht('Group By'))
|
|
|
|
->setKey('group')
|
|
|
|
->setOptions($this->getGroupOptions()),
|
|
|
|
id(new PhabricatorSearchDateField())
|
|
|
|
->setLabel(pht('Created After'))
|
|
|
|
->setKey('createdStart'),
|
|
|
|
id(new PhabricatorSearchDateField())
|
|
|
|
->setLabel(pht('Created Before'))
|
|
|
|
->setKey('createdEnd'),
|
|
|
|
id(new PhabricatorSearchDateField())
|
|
|
|
->setLabel(pht('Updated After'))
|
|
|
|
->setKey('modifiedStart'),
|
|
|
|
id(new PhabricatorSearchDateField())
|
|
|
|
->setLabel(pht('Updated Before'))
|
|
|
|
->setKey('modifiedEnd'),
|
|
|
|
id(new PhabricatorSearchTextField())
|
|
|
|
->setLabel(pht('Page Size'))
|
|
|
|
->setKey('limit'),
|
|
|
|
);
|
|
|
|
}
|
2013-09-10 19:04:26 +02:00
|
|
|
|
2015-06-14 23:34:14 +02:00
|
|
|
protected function getDefaultFieldOrder() {
|
2015-06-09 22:17:31 +02:00
|
|
|
return array(
|
2013-09-10 19:44:42 +02:00
|
|
|
'assignedPHIDs',
|
2015-06-09 22:17:31 +02:00
|
|
|
'projectPHIDs',
|
2013-09-10 19:44:42 +02:00
|
|
|
'authorPHIDs',
|
2013-09-28 01:02:08 +02:00
|
|
|
'subscriberPHIDs',
|
2014-04-24 19:35:28 +02:00
|
|
|
'statuses',
|
|
|
|
'priorities',
|
2015-06-09 22:17:31 +02:00
|
|
|
'fulltext',
|
2015-01-12 22:42:37 +01:00
|
|
|
'blocking',
|
|
|
|
'blocked',
|
2015-06-09 22:17:31 +02:00
|
|
|
'group',
|
|
|
|
'order',
|
|
|
|
'ids',
|
|
|
|
'...',
|
|
|
|
'createdStart',
|
|
|
|
'createdEnd',
|
|
|
|
'modifiedStart',
|
|
|
|
'modifiedEnd',
|
|
|
|
'limit',
|
|
|
|
);
|
|
|
|
}
|
2013-09-12 22:03:14 +02:00
|
|
|
|
2015-06-14 23:34:14 +02:00
|
|
|
protected function getHiddenFields() {
|
2015-06-09 22:17:31 +02:00
|
|
|
$keys = array();
|
2013-09-12 22:03:39 +02:00
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
if ($this->getIsBoardView()) {
|
|
|
|
$keys[] = 'group';
|
|
|
|
$keys[] = 'order';
|
|
|
|
$keys[] = 'limit';
|
Allow Maniphest queries to have configurable page sizes
Summary:
Current page size is `1000`. This is nice to have in some cases, but makes pages slower than necessary in others. Task lists are generally dominated by rendering costs.
For example, my default is "recent tasks", which just lists all tasks ordered by date created. Showing 100 tasks here instead of 1000 makes this several times faster without compromising utility.
I don't want to force the default to 100, though, since sometimes listing everything is quite useful and I think an advantage of Maniphest is that it generally deals reasonably well with large task sets.
(This `limit` property is actually read by the default implementation of `getPageSize()` in the parent class.)
Test Plan: Made queries with page sizes 1, 100, 12, 9, 3000, etc.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Differential Revision: https://secure.phabricator.com/D6976
2013-09-13 17:44:00 +02:00
|
|
|
}
|
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
return $keys;
|
2013-09-10 19:04:26 +02:00
|
|
|
}
|
|
|
|
|
2015-06-14 23:34:14 +02:00
|
|
|
protected function buildQueryFromParameters(array $map) {
|
2015-06-09 22:17:31 +02:00
|
|
|
$query = id(new ManiphestTaskQuery())
|
|
|
|
->needProjectPHIDs(true);
|
2013-09-10 19:04:26 +02:00
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
if ($map['assignedPHIDs']) {
|
|
|
|
$query->withOwners($map['assignedPHIDs']);
|
|
|
|
}
|
2015-04-23 14:13:12 +02:00
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
if ($map['authorPHIDs']) {
|
|
|
|
$query->withAuthors($map['authorPHIDs']);
|
|
|
|
}
|
2015-04-23 14:13:12 +02:00
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
if ($map['statuses']) {
|
|
|
|
$query->withStatuses($map['statuses']);
|
2013-09-10 19:44:42 +02:00
|
|
|
}
|
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
if ($map['priorities']) {
|
|
|
|
$query->withPriorities($map['priorities']);
|
2013-09-28 01:02:08 +02:00
|
|
|
}
|
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
if ($map['createdStart']) {
|
|
|
|
$query->withDateCreatedAfter($map['createdStart']);
|
|
|
|
}
|
2015-04-19 17:23:56 +02:00
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
if ($map['createdEnd']) {
|
|
|
|
$query->withDateCreatedBefore($map['createdEnd']);
|
2013-09-10 19:44:42 +02:00
|
|
|
}
|
2013-09-10 19:04:26 +02:00
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
if ($map['modifiedStart']) {
|
|
|
|
$query->withDateModifiedAfter($map['modifiedStart']);
|
2013-09-10 20:07:34 +02:00
|
|
|
}
|
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
if ($map['modifiedEnd']) {
|
|
|
|
$query->withDateModifiedBefore($map['modifiedEnd']);
|
2013-09-10 20:54:17 +02:00
|
|
|
}
|
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
if ($map['blocking'] !== null) {
|
|
|
|
$query->withBlockingTasks($map['blocking']);
|
|
|
|
}
|
2015-01-12 22:42:37 +01:00
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
if ($map['blocked'] !== null) {
|
|
|
|
$query->withBlockedTasks($map['blocked']);
|
|
|
|
}
|
2015-01-12 22:42:37 +01:00
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
if (strlen($map['fulltext'])) {
|
|
|
|
$query->withFullTextSearch($map['fulltext']);
|
2015-06-08 21:23:13 +02:00
|
|
|
}
|
2013-09-10 20:07:34 +02:00
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
$group = idx($map, 'group');
|
2013-09-12 23:48:52 +02:00
|
|
|
$group = idx($this->getGroupValues(), $group);
|
|
|
|
if ($group) {
|
|
|
|
$query->setGroupBy($group);
|
|
|
|
} else {
|
|
|
|
$query->setGroupBy(head($this->getGroupValues()));
|
|
|
|
}
|
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
if ($map['ids']) {
|
|
|
|
$ids = $map['ids'];
|
|
|
|
foreach ($ids as $key => $id) {
|
|
|
|
$id = trim($id, ' Tt');
|
|
|
|
if (!$id || !is_numeric($id)) {
|
|
|
|
unset($ids[$key]);
|
|
|
|
} else {
|
|
|
|
$ids[$key] = $id;
|
|
|
|
}
|
|
|
|
}
|
2014-03-17 23:53:07 +01:00
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
if ($ids) {
|
|
|
|
$query->withIDs($ids);
|
|
|
|
}
|
2014-03-17 23:53:07 +01:00
|
|
|
}
|
|
|
|
|
2013-09-10 19:04:26 +02:00
|
|
|
return $query;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getURI($path) {
|
2014-05-20 20:42:05 +02:00
|
|
|
if ($this->baseURI) {
|
|
|
|
return $this->baseURI.$path;
|
|
|
|
}
|
2013-09-10 19:04:26 +02:00
|
|
|
return '/maniphest/'.$path;
|
|
|
|
}
|
|
|
|
|
2015-01-06 21:34:51 +01:00
|
|
|
protected function getBuiltinQueryNames() {
|
2013-09-10 19:04:26 +02:00
|
|
|
$names = array();
|
|
|
|
|
|
|
|
if ($this->requireViewer()->isLoggedIn()) {
|
|
|
|
$names['assigned'] = pht('Assigned');
|
|
|
|
$names['authored'] = pht('Authored');
|
2013-11-14 19:13:20 +01:00
|
|
|
$names['subscribed'] = pht('Subscribed');
|
2013-09-10 19:04:26 +02:00
|
|
|
}
|
|
|
|
|
2013-09-10 20:07:34 +02:00
|
|
|
$names['open'] = pht('Open Tasks');
|
2013-09-10 19:04:26 +02:00
|
|
|
$names['all'] = pht('All Tasks');
|
|
|
|
|
|
|
|
return $names;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function buildSavedQueryFromBuiltin($query_key) {
|
|
|
|
|
|
|
|
$query = $this->newSavedQuery();
|
|
|
|
$query->setQueryKey($query_key);
|
|
|
|
|
2013-09-10 19:44:42 +02:00
|
|
|
$viewer_phid = $this->requireViewer()->getPHID();
|
|
|
|
|
2013-09-10 19:04:26 +02:00
|
|
|
switch ($query_key) {
|
|
|
|
case 'all':
|
|
|
|
return $query;
|
|
|
|
case 'assigned':
|
2013-09-10 20:07:34 +02:00
|
|
|
return $query
|
|
|
|
->setParameter('assignedPHIDs', array($viewer_phid))
|
2014-02-18 00:59:31 +01:00
|
|
|
->setParameter(
|
|
|
|
'statuses',
|
|
|
|
ManiphestTaskStatus::getOpenStatusConstants());
|
2013-11-14 19:13:20 +01:00
|
|
|
case 'subscribed':
|
|
|
|
return $query
|
|
|
|
->setParameter('subscriberPHIDs', array($viewer_phid))
|
2014-02-18 00:59:31 +01:00
|
|
|
->setParameter(
|
|
|
|
'statuses',
|
|
|
|
ManiphestTaskStatus::getOpenStatusConstants());
|
2013-09-10 20:07:34 +02:00
|
|
|
case 'open':
|
|
|
|
return $query
|
2014-02-18 00:59:31 +01:00
|
|
|
->setParameter(
|
|
|
|
'statuses',
|
|
|
|
ManiphestTaskStatus::getOpenStatusConstants());
|
2013-09-10 19:04:26 +02:00
|
|
|
case 'authored':
|
2013-09-10 20:07:34 +02:00
|
|
|
return $query
|
2013-09-13 01:58:09 +02:00
|
|
|
->setParameter('authorPHIDs', array($viewer_phid))
|
|
|
|
->setParameter('order', 'created')
|
|
|
|
->setParameter('group', 'none');
|
2013-09-10 19:04:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return parent::buildSavedQueryFromBuiltin($query_key);
|
|
|
|
}
|
|
|
|
|
2013-09-12 23:48:52 +02:00
|
|
|
private function getGroupOptions() {
|
|
|
|
return array(
|
|
|
|
'priority' => pht('Priority'),
|
|
|
|
'assigned' => pht('Assigned'),
|
2014-07-23 02:03:09 +02:00
|
|
|
'status' => pht('Status'),
|
|
|
|
'project' => pht('Project'),
|
|
|
|
'none' => pht('None'),
|
2013-09-12 23:48:52 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
private function getGroupValues() {
|
|
|
|
return array(
|
|
|
|
'priority' => ManiphestTaskQuery::GROUP_PRIORITY,
|
|
|
|
'assigned' => ManiphestTaskQuery::GROUP_OWNER,
|
2014-07-23 02:03:09 +02:00
|
|
|
'status' => ManiphestTaskQuery::GROUP_STATUS,
|
|
|
|
'project' => ManiphestTaskQuery::GROUP_PROJECT,
|
|
|
|
'none' => ManiphestTaskQuery::GROUP_NONE,
|
2013-09-12 23:48:52 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2014-05-16 04:17:38 +02:00
|
|
|
protected function renderResultList(
|
|
|
|
array $tasks,
|
|
|
|
PhabricatorSavedQuery $saved,
|
|
|
|
array $handles) {
|
|
|
|
|
|
|
|
$viewer = $this->requireViewer();
|
|
|
|
|
2014-06-25 00:59:06 +02:00
|
|
|
if ($this->isPanelContext()) {
|
|
|
|
$can_edit_priority = false;
|
|
|
|
$can_bulk_edit = false;
|
|
|
|
} else {
|
|
|
|
$can_edit_priority = PhabricatorPolicyFilter::hasCapability(
|
|
|
|
$viewer,
|
|
|
|
$this->getApplication(),
|
2014-07-25 00:20:39 +02:00
|
|
|
ManiphestEditPriorityCapability::CAPABILITY);
|
2014-06-25 00:59:06 +02:00
|
|
|
|
|
|
|
$can_bulk_edit = PhabricatorPolicyFilter::hasCapability(
|
|
|
|
$viewer,
|
|
|
|
$this->getApplication(),
|
2014-07-25 00:20:39 +02:00
|
|
|
ManiphestBulkEditCapability::CAPABILITY);
|
2014-06-25 00:59:06 +02:00
|
|
|
}
|
2014-05-16 04:17:38 +02:00
|
|
|
|
2015-06-19 12:46:20 +02:00
|
|
|
$list = id(new ManiphestTaskResultListView())
|
2014-05-16 04:17:38 +02:00
|
|
|
->setUser($viewer)
|
|
|
|
->setTasks($tasks)
|
|
|
|
->setSavedQuery($saved)
|
|
|
|
->setCanEditPriority($can_edit_priority)
|
|
|
|
->setCanBatchEdit($can_bulk_edit)
|
|
|
|
->setShowBatchControls($this->showBatchControls);
|
2015-06-19 12:46:20 +02:00
|
|
|
|
|
|
|
$result = new PhabricatorApplicationSearchResultView();
|
|
|
|
$result->setContent($list);
|
|
|
|
|
|
|
|
return $result;
|
2014-05-16 04:17:38 +02:00
|
|
|
}
|
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
protected function willUseSavedQuery(PhabricatorSavedQuery $saved) {
|
2015-04-19 17:23:56 +02:00
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
// The 'withUnassigned' parameter may be present in old saved queries from
|
|
|
|
// before parameterized typeaheads, and is retained for compatibility. We
|
|
|
|
// could remove it by migrating old saved queries.
|
|
|
|
$assigned_phids = $saved->getParameter('assignedPHIDs', array());
|
2015-04-19 17:23:56 +02:00
|
|
|
if ($saved->getParameter('withUnassigned')) {
|
2015-04-23 12:07:24 +02:00
|
|
|
$assigned_phids[] = PhabricatorPeopleNoOwnerDatasource::FUNCTION_TOKEN;
|
2015-04-19 17:23:56 +02:00
|
|
|
}
|
2015-06-09 22:17:31 +02:00
|
|
|
$saved->setParameter('assignedPHIDs', $assigned_phids);
|
2015-04-19 17:23:56 +02:00
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
// The 'projects' and other parameters may be present in old saved queries
|
|
|
|
// from before parameterized typeaheads.
|
|
|
|
$project_phids = $saved->getParameter('projectPHIDs', array());
|
2015-04-19 17:23:56 +02:00
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
$old = $saved->getParameter('projects', array());
|
|
|
|
foreach ($old as $phid) {
|
|
|
|
$project_phids[] = $phid;
|
|
|
|
}
|
2015-04-23 12:58:04 +02:00
|
|
|
|
|
|
|
$all = $saved->getParameter('allProjectPHIDs', array());
|
|
|
|
foreach ($all as $phid) {
|
2015-06-09 22:17:31 +02:00
|
|
|
$project_phids[] = $phid;
|
2015-04-23 12:58:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$any = $saved->getParameter('anyProjectPHIDs', array());
|
|
|
|
foreach ($any as $phid) {
|
2015-06-09 22:17:31 +02:00
|
|
|
$project_phids[] = 'any('.$phid.')';
|
2015-04-23 12:58:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$not = $saved->getParameter('excludeProjectPHIDs', array());
|
|
|
|
foreach ($not as $phid) {
|
2015-06-09 22:17:31 +02:00
|
|
|
$project_phids[] = 'not('.$phid.')';
|
2015-04-23 12:58:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$users = $saved->getParameter('userProjectPHIDs', array());
|
|
|
|
foreach ($users as $phid) {
|
2015-06-09 22:17:31 +02:00
|
|
|
$project_phids[] = 'projects('.$phid.')';
|
2015-04-23 12:58:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$no = $saved->getParameter('withNoProject');
|
|
|
|
if ($no) {
|
2015-06-09 22:17:31 +02:00
|
|
|
$project_phids[] = 'null()';
|
2015-04-23 12:58:04 +02:00
|
|
|
}
|
|
|
|
|
2015-06-09 22:17:31 +02:00
|
|
|
$saved->setParameter('projectPHIDs', $project_phids);
|
2015-04-23 12:58:04 +02:00
|
|
|
}
|
|
|
|
|
2013-09-10 19:04:26 +02:00
|
|
|
}
|