1
0
Fork 0
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:
Bob Trahan 2015-01-12 13:42:37 -08:00
parent 25167776dc
commit 1eb8b6a1b8
2 changed files with 114 additions and 1 deletions

View file

@ -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);

View file

@ -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