mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-22 12:41:19 +01:00
Maniphest - allow for searching for tasks based on dependency relationships
Summary: Fixes T5352. This is very useful for finding things that should be easy to do ("not blocked") as well as things that are important to do ("blocking"). I have wanted to check out the latter case in our installation, though no promises on what I would end up actually doing from that search result list. =D I also think supporting something like T6638 is reasonable but the UI seems trickier to me; its some sort of task tokenizer, which I don't think we've done before? Test Plan: toggled various search options and got reasonable results. When i clicked conflicting things like "blocking" and "not blocking" verified it was like I had not clicked anything at all. Reviewers: chad, epriestley Reviewed By: epriestley Subscribers: Korvin, epriestley Maniphest Tasks: T5352 Differential Revision: https://secure.phabricator.com/D11306
This commit is contained in:
parent
25167776dc
commit
1eb8b6a1b8
2 changed files with 114 additions and 1 deletions
|
@ -53,6 +53,9 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
private $needSubscriberPHIDs;
|
||||
private $needProjectPHIDs;
|
||||
|
||||
private $blockingTasks;
|
||||
private $blockedTasks;
|
||||
|
||||
const DEFAULT_PAGE_SIZE = 1000;
|
||||
|
||||
public function withAuthors(array $authors) {
|
||||
|
@ -161,6 +164,34 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* True returns tasks that are blocking other tasks only.
|
||||
* False returns tasks that are not blocking other tasks only.
|
||||
* Null returns tasks regardless of blocking status.
|
||||
*/
|
||||
public function withBlockingTasks($mode) {
|
||||
$this->blockingTasks = $mode;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function shouldJoinBlockingTasks() {
|
||||
return $this->blockingTasks !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* True returns tasks that are blocked by other tasks only.
|
||||
* False returns tasks that are not blocked by other tasks only.
|
||||
* Null returns tasks regardless of blocked by status.
|
||||
*/
|
||||
public function withBlockedTasks($mode) {
|
||||
$this->blockedTasks = $mode;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function shouldJoinBlockedTasks() {
|
||||
return $this->blockedTasks !== null;
|
||||
}
|
||||
|
||||
public function withDateCreatedBefore($date_created_before) {
|
||||
$this->dateCreatedBefore = $date_created_before;
|
||||
return $this;
|
||||
|
@ -207,6 +238,7 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
$where[] = $this->buildStatusWhereClause($conn);
|
||||
$where[] = $this->buildStatusesWhereClause($conn);
|
||||
$where[] = $this->buildPrioritiesWhereClause($conn);
|
||||
$where[] = $this->buildDependenciesWhereClause($conn);
|
||||
$where[] = $this->buildAuthorWhereClause($conn);
|
||||
$where[] = $this->buildOwnerWhereClause($conn);
|
||||
$where[] = $this->buildProjectWhereClause($conn);
|
||||
|
@ -520,6 +552,38 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
$fulltext_results);
|
||||
}
|
||||
|
||||
private function buildDependenciesWhereClause(
|
||||
AphrontDatabaseConnection $conn) {
|
||||
|
||||
if (!$this->shouldJoinBlockedTasks() &&
|
||||
!$this->shouldJoinBlockingTasks()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$parts = array();
|
||||
if ($this->blockingTasks === true) {
|
||||
$parts[] = qsprintf(
|
||||
$conn,
|
||||
'blocking.dst IS NOT NULL');
|
||||
} else if ($this->blockingTasks === false) {
|
||||
$parts[] = qsprintf(
|
||||
$conn,
|
||||
'blocking.dst IS NULL');
|
||||
}
|
||||
|
||||
if ($this->blockedTasks === true) {
|
||||
$parts[] = qsprintf(
|
||||
$conn,
|
||||
'blocked.dst IS NOT NULL');
|
||||
} else if ($this->blockedTasks === false) {
|
||||
$parts[] = qsprintf(
|
||||
$conn,
|
||||
'blocked.dst IS NULL');
|
||||
}
|
||||
|
||||
return '('.implode(') OR (', $parts).')';
|
||||
}
|
||||
|
||||
private function buildProjectWhereClause(AphrontDatabaseConnection $conn) {
|
||||
if (!$this->projectPHIDs && !$this->includeNoProject) {
|
||||
return null;
|
||||
|
@ -699,6 +763,23 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
|
||||
}
|
||||
|
||||
if ($this->shouldJoinBlockingTasks()) {
|
||||
$joins[] = qsprintf(
|
||||
$conn_r,
|
||||
'LEFT JOIN %T blocking ON blocking.src = task.phid '.
|
||||
'AND blocking.type = %d',
|
||||
$edge_table,
|
||||
ManiphestTaskDependedOnByTaskEdgeType::EDGECONST);
|
||||
}
|
||||
if ($this->shouldJoinBlockedTasks()) {
|
||||
$joins[] = qsprintf(
|
||||
$conn_r,
|
||||
'LEFT JOIN %T blocked ON blocked.src = task.phid '.
|
||||
'AND blocked.type = %d',
|
||||
$edge_table,
|
||||
ManiphestTaskDependsOnTaskEdgeType::EDGECONST);
|
||||
}
|
||||
|
||||
if ($this->anyProjectPHIDs || $this->anyUserProjectPHIDs) {
|
||||
$joins[] = qsprintf(
|
||||
$conn_r,
|
||||
|
@ -766,6 +847,8 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
private function buildGroupClause(AphrontDatabaseConnection $conn_r) {
|
||||
$joined_multiple_rows = (count($this->projectPHIDs) > 1) ||
|
||||
(count($this->anyProjectPHIDs) > 1) ||
|
||||
$this->shouldJoinBlockingTasks() ||
|
||||
$this->shouldJoinBlockedTasks() ||
|
||||
($this->getApplicationSearchMayJoinMultipleRows());
|
||||
|
||||
$joined_project_name = ($this->groupBy == self::GROUP_PROJECT);
|
||||
|
|
|
@ -67,6 +67,13 @@ final class ManiphestTaskSearchEngine
|
|||
'priorities',
|
||||
$this->readListFromRequest($request, 'priorities'));
|
||||
|
||||
$saved->setParameter(
|
||||
'blocking',
|
||||
$this->readBoolFromRequest($request, 'blocking'));
|
||||
$saved->setParameter(
|
||||
'blocked',
|
||||
$this->readBoolFromRequest($request, 'blocked'));
|
||||
|
||||
$saved->setParameter('group', $request->getStr('group'));
|
||||
$saved->setParameter('order', $request->getStr('order'));
|
||||
|
||||
|
@ -152,6 +159,10 @@ final class ManiphestTaskSearchEngine
|
|||
$query->withPriorities($priorities);
|
||||
}
|
||||
|
||||
|
||||
$query->withBlockingTasks($saved->getParameter('blocking'));
|
||||
$query->withBlockedTasks($saved->getParameter('blocked'));
|
||||
|
||||
$this->applyOrderByToQuery(
|
||||
$query,
|
||||
$this->getOrderValues(),
|
||||
|
@ -302,6 +313,23 @@ final class ManiphestTaskSearchEngine
|
|||
isset($priorities[$pri]));
|
||||
}
|
||||
|
||||
$blocking_control = id(new AphrontFormSelectControl())
|
||||
->setLabel(pht('Blocking'))
|
||||
->setName('blocking')
|
||||
->setValue($this->getBoolFromQuery($saved, 'blocking'))
|
||||
->setOptions(array(
|
||||
'' => pht('Show All Tasks'),
|
||||
'true' => pht('Show Tasks Blocking Other Tasks'),
|
||||
'false' => pht('Show Tasks Not Blocking Other Tasks'),));
|
||||
$blocked_control = id(new AphrontFormSelectControl())
|
||||
->setLabel(pht('Blocked'))
|
||||
->setName('blocked')
|
||||
->setValue($this->getBoolFromQuery($saved, 'blocked'))
|
||||
->setOptions(array(
|
||||
'' => pht('Show All Tasks'),
|
||||
'true' => pht('Show Tasks Blocked By Other Tasks'),
|
||||
'false' => pht('Show Tasks Not Blocked By Other Tasks'),));
|
||||
|
||||
$ids = $saved->getParameter('ids', array());
|
||||
|
||||
$builtin_orders = $this->getOrderOptions();
|
||||
|
@ -377,7 +405,9 @@ final class ManiphestTaskSearchEngine
|
|||
->setLabel(pht('Contains Words'))
|
||||
->setValue($saved->getParameter('fulltext')))
|
||||
->appendChild($status_control)
|
||||
->appendChild($priority_control);
|
||||
->appendChild($priority_control)
|
||||
->appendChild($blocking_control)
|
||||
->appendChild($blocked_control);
|
||||
|
||||
if (!$this->getIsBoardView()) {
|
||||
$form
|
||||
|
|
Loading…
Reference in a new issue