Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15487837
D19366.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Referenced Files
None
Subscribers
None
D19366.id.diff
View Options
diff --git a/src/applications/maniphest/query/ManiphestTaskQuery.php b/src/applications/maniphest/query/ManiphestTaskQuery.php
--- a/src/applications/maniphest/query/ManiphestTaskQuery.php
+++ b/src/applications/maniphest/query/ManiphestTaskQuery.php
@@ -26,6 +26,7 @@
private $closedEpochMin;
private $closedEpochMax;
private $closerPHIDs;
+ private $columnPHIDs;
private $status = 'status-any';
const STATUS_ANY = 'status-any';
@@ -213,6 +214,11 @@
return $this;
}
+ public function withColumnPHIDs(array $column_phids) {
+ $this->columnPHIDs = $column_phids;
+ return $this;
+ }
+
public function newResultObject() {
return new ManiphestTask();
}
@@ -442,6 +448,91 @@
$this->subtypes);
}
+
+ if ($this->columnPHIDs !== null) {
+ $viewer = $this->getViewer();
+
+ $columns = id(new PhabricatorProjectColumnQuery())
+ ->setParentQuery($this)
+ ->setViewer($viewer)
+ ->withPHIDs($this->columnPHIDs)
+ ->execute();
+ if (!$columns) {
+ throw new PhabricatorEmptyQueryException();
+ }
+
+ // We must do board layout before we move forward because the column
+ // positions may not yet exist otherwise. An example is that newly
+ // created tasks may not yet be positioned in the backlog column.
+
+ $projects = mpull($columns, 'getProject');
+ $projects = mpull($projects, null, 'getPHID');
+
+ // The board layout engine needs to know about every object that it's
+ // going to be asked to do layout for. For now, we're just doing layout
+ // on every object on the boards. In the future, we could do layout on a
+ // smaller set of objects by using the constraints on this Query. For
+ // example, if the caller is only asking for open tasks, we only need
+ // to do layout on open tasks.
+
+ // This fetches too many objects (every type of object tagged with the
+ // project, not just tasks). We could narrow it by querying the edge
+ // table on the Maniphest side, but there's currently no way to build
+ // that query with EdgeQuery.
+ $edge_query = id(new PhabricatorEdgeQuery())
+ ->withSourcePHIDs(array_keys($projects))
+ ->withEdgeTypes(
+ array(
+ PhabricatorProjectProjectHasObjectEdgeType::EDGECONST,
+ ));
+
+ $edge_query->execute();
+ $all_phids = $edge_query->getDestinationPHIDs();
+
+ // Since we overfetched PHIDs, filter out any non-tasks we got back.
+ foreach ($all_phids as $key => $phid) {
+ if (phid_get_type($phid) !== ManiphestTaskPHIDType::TYPECONST) {
+ unset($all_phids[$key]);
+ }
+ }
+
+ // If there are no tasks on the relevant boards, this query can't
+ // possibly hit anything so we're all done.
+ $task_phids = array_fuse($all_phids);
+ if (!$task_phids) {
+ throw new PhabricatorEmptyQueryException();
+ }
+
+ // We know everything we need to know, so perform board layout.
+ $engine = id(new PhabricatorBoardLayoutEngine())
+ ->setViewer($viewer)
+ ->setFetchAllBoards(true)
+ ->setBoardPHIDs(array_keys($projects))
+ ->setObjectPHIDs($task_phids)
+ ->executeLayout();
+
+ // Find the tasks that are in the constraint columns after board layout
+ // completes.
+ $select_phids = array();
+ foreach ($columns as $column) {
+ $in_column = $engine->getColumnObjectPHIDs(
+ $column->getProjectPHID(),
+ $column->getPHID());
+ foreach ($in_column as $phid) {
+ $select_phids[$phid] = $phid;
+ }
+ }
+
+ if (!$select_phids) {
+ throw new PhabricatorEmptyQueryException();
+ }
+
+ $where[] = qsprintf(
+ $conn,
+ 'task.phid IN (%Ls)',
+ $select_phids);
+ }
+
return $where;
}
diff --git a/src/applications/maniphest/query/ManiphestTaskSearchEngine.php b/src/applications/maniphest/query/ManiphestTaskSearchEngine.php
--- a/src/applications/maniphest/query/ManiphestTaskSearchEngine.php
+++ b/src/applications/maniphest/query/ManiphestTaskSearchEngine.php
@@ -86,6 +86,10 @@
pht('Search for tasks with given subtypes.'))
->setDatasource(new ManiphestTaskSubtypeDatasource())
->setIsHidden($hide_subtypes),
+ id(new PhabricatorPHIDsSearchField())
+ ->setLabel(pht('Columns'))
+ ->setKey('columnPHIDs')
+ ->setAliases(array('column', 'columnPHID', 'columns')),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Open Parents'))
->setKey('hasParents')
@@ -246,6 +250,10 @@
$query->withSubtaskIDs($map['subtaskIDs']);
}
+ if ($map['columnPHIDs']) {
+ $query->withColumnPHIDs($map['columnPHIDs']);
+ }
+
$group = idx($map, 'group');
$group = idx($this->getGroupValues(), $group);
if ($group) {
diff --git a/src/applications/project/controller/PhabricatorProjectBoardViewController.php b/src/applications/project/controller/PhabricatorProjectBoardViewController.php
--- a/src/applications/project/controller/PhabricatorProjectBoardViewController.php
+++ b/src/applications/project/controller/PhabricatorProjectBoardViewController.php
@@ -36,7 +36,8 @@
if ($request->isFormPost()
&& !$request->getBool('initialize')
- && !$request->getStr('move')) {
+ && !$request->getStr('move')
+ && !$request->getStr('queryColumnID')) {
$saved = $search_engine->buildSavedQueryFromRequest($request);
$search_engine->saveQuery($saved);
$filter_form = id(new AphrontFormView())
@@ -188,6 +189,46 @@
->appendChild($content);
}
+ // If the user wants to turn a particular column into a query, build an
+ // apropriate filter and redirect them to the query results page.
+ $query_column_id = $request->getInt('queryColumnID');
+ if ($query_column_id) {
+ $column_id_map = mpull($columns, null, 'getID');
+ $query_column = idx($column_id_map, $query_column_id);
+ if (!$query_column) {
+ return new Aphront404Response();
+ }
+
+ // Create a saved query to combine the active filter on the workboard
+ // with the column filter. If the user currently has constraints on the
+ // board, we want to add a new column or project constraint, not
+ // completely replace the constraints.
+ $saved_query = clone $saved;
+
+ if ($query_column->getProxyPHID()) {
+ $project_phids = $saved_query->getParameter('projectPHIDs');
+ if (!$project_phids) {
+ $project_phids = array();
+ }
+ $project_phids[] = $query_column->getProxyPHID();
+ $saved_query->setParameter('projectPHIDs', $project_phids);
+ } else {
+ $saved_query->setParameter(
+ 'columnPHIDs',
+ array($query_column->getPHID()));
+ }
+
+ $search_engine = id(new ManiphestTaskSearchEngine())
+ ->setViewer($viewer);
+ $search_engine->saveQuery($saved_query);
+
+ $query_key = $saved_query->getQueryKey();
+ $query_uri = new PhutilURI("/maniphest/query/{$query_key}/#R");
+
+ return id(new AphrontRedirectResponse())
+ ->setURI($query_uri);
+ }
+
$task_can_edit_map = id(new PhabricatorPolicyFilter())
->setViewer($viewer)
->requireCapabilities(array(PhabricatorPolicyCapability::CAN_EDIT))
@@ -1069,8 +1110,14 @@
->setHref($batch_move_uri)
->setWorkflow(true);
- // Column Related Actions Below
- //
+ $query_uri = $request->getRequestURI();
+ $query_uri->setQueryParam('queryColumnID', $column->getID());
+
+ $column_items[] = id(new PhabricatorActionView())
+ ->setName(pht('View as Query'))
+ ->setIcon('fa-search')
+ ->setHref($query_uri);
+
$edit_uri = 'board/'.$this->id.'/edit/'.$column->getID().'/';
$column_items[] = id(new PhabricatorActionView())
->setName(pht('Edit Column'))
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Apr 11, 5:14 PM (2 w, 17 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7391403
Default Alt Text
D19366.id.diff (7 KB)
Attached To
Mode
D19366: Allow Maniphest tasks to be queried by workboard Column PHID via SearchEngine
Attached
Detach File
Event Timeline
Log In to Comment