Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13982849
D20634.id49219.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
13 KB
Referenced Files
None
Subscribers
None
D20634.id49219.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -4172,6 +4172,7 @@
'PhabricatorProjectColorsConfigType' => 'applications/project/config/PhabricatorProjectColorsConfigType.php',
'PhabricatorProjectColumn' => 'applications/project/storage/PhabricatorProjectColumn.php',
'PhabricatorProjectColumnAuthorOrder' => 'applications/project/order/PhabricatorProjectColumnAuthorOrder.php',
+ 'PhabricatorProjectColumnBulkEditController' => 'applications/project/controller/PhabricatorProjectColumnBulkEditController.php',
'PhabricatorProjectColumnCreatedOrder' => 'applications/project/order/PhabricatorProjectColumnCreatedOrder.php',
'PhabricatorProjectColumnDetailController' => 'applications/project/controller/PhabricatorProjectColumnDetailController.php',
'PhabricatorProjectColumnEditController' => 'applications/project/controller/PhabricatorProjectColumnEditController.php',
@@ -10445,6 +10446,7 @@
'PhabricatorConduitResultInterface',
),
'PhabricatorProjectColumnAuthorOrder' => 'PhabricatorProjectColumnOrder',
+ 'PhabricatorProjectColumnBulkEditController' => 'PhabricatorProjectBoardController',
'PhabricatorProjectColumnCreatedOrder' => 'PhabricatorProjectColumnOrder',
'PhabricatorProjectColumnDetailController' => 'PhabricatorProjectBoardController',
'PhabricatorProjectColumnEditController' => 'PhabricatorProjectBoardController',
diff --git a/src/applications/project/application/PhabricatorProjectApplication.php b/src/applications/project/application/PhabricatorProjectApplication.php
--- a/src/applications/project/application/PhabricatorProjectApplication.php
+++ b/src/applications/project/application/PhabricatorProjectApplication.php
@@ -81,6 +81,8 @@
=> 'PhabricatorProjectColumnDetailController',
'viewquery/(?P<columnID>\d+)/'
=> 'PhabricatorProjectColumnViewQueryController',
+ 'bulk/(?P<columnID>\d+)/'
+ => 'PhabricatorProjectColumnBulkEditController',
'import/'
=> 'PhabricatorProjectBoardImportController',
'reorder/'
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
@@ -3,8 +3,6 @@
final class PhabricatorProjectBoardViewController
extends PhabricatorProjectBoardController {
- const BATCH_EDIT_ALL = 'all';
-
public function shouldAllowPublic() {
return true;
}
@@ -34,42 +32,9 @@
$custom_query = null;
}
- $task_query = $search_engine->buildQueryFromSavedQuery($saved);
-
- $select_phids = array($project->getPHID());
- if ($project->getHasSubprojects() || $project->getHasMilestones()) {
- $descendants = id(new PhabricatorProjectQuery())
- ->setViewer($viewer)
- ->withAncestorProjectPHIDs($select_phids)
- ->execute();
- foreach ($descendants as $descendant) {
- $select_phids[] = $descendant->getPHID();
- }
- }
-
- $tasks = $task_query
- ->withEdgeLogicPHIDs(
- PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
- PhabricatorQueryConstraint::OPERATOR_ANCESTOR,
- array($select_phids))
- ->setOrder(ManiphestTaskQuery::ORDER_PRIORITY)
- ->setViewer($viewer)
- ->execute();
- $tasks = mpull($tasks, null, 'getPHID');
+ $layout_engine = $state->getLayoutEngine();
$board_phid = $project->getPHID();
-
- // Regardless of display order, pass tasks to the layout engine in ID order
- // so layout is consistent.
- $board_tasks = msort($tasks, 'getID');
-
- $layout_engine = id(new PhabricatorBoardLayoutEngine())
- ->setViewer($viewer)
- ->setBoardPHIDs(array($board_phid))
- ->setObjectPHIDs(array_keys($board_tasks))
- ->setFetchAllBoards(true)
- ->executeLayout();
-
$columns = $layout_engine->getColumns($board_phid);
if (!$columns || !$project->getHasWorkboard()) {
$has_normal_columns = false;
@@ -122,67 +87,13 @@
->appendChild($content);
}
+ $tasks = $state->getObjects();
+
$task_can_edit_map = id(new PhabricatorPolicyFilter())
->setViewer($viewer)
->requireCapabilities(array(PhabricatorPolicyCapability::CAN_EDIT))
->apply($tasks);
- // If this is a batch edit, select the editable tasks in the chosen column
- // and ship the user into the batch editor.
- $batch_edit = $request->getStr('batch');
- if ($batch_edit) {
- if ($batch_edit !== self::BATCH_EDIT_ALL) {
- $column_id_map = mpull($columns, null, 'getID');
- $batch_column = idx($column_id_map, $batch_edit);
- if (!$batch_column) {
- return new Aphront404Response();
- }
-
- $batch_task_phids = $layout_engine->getColumnObjectPHIDs(
- $board_phid,
- $batch_column->getPHID());
-
- foreach ($batch_task_phids as $key => $batch_task_phid) {
- if (empty($task_can_edit_map[$batch_task_phid])) {
- unset($batch_task_phids[$key]);
- }
- }
-
- $batch_tasks = array_select_keys($tasks, $batch_task_phids);
- } else {
- $batch_tasks = $task_can_edit_map;
- }
-
- if (!$batch_tasks) {
- $cancel_uri = $state->newWorkboardURI();
- return $this->newDialog()
- ->setTitle(pht('No Editable Tasks'))
- ->appendParagraph(
- pht(
- 'The selected column contains no visible tasks which you '.
- 'have permission to edit.'))
- ->addCancelButton($board_uri);
- }
-
- // Create a saved query to hold the working set. This allows us to get
- // around URI length limitations with a long "?ids=..." query string.
- // For details, see T10268.
- $search_engine = id(new ManiphestTaskSearchEngine())
- ->setViewer($viewer);
-
- $saved_query = $search_engine->newSavedQuery();
- $saved_query->setParameter('ids', mpull($batch_tasks, 'getID'));
- $search_engine->saveQuery($saved_query);
-
- $query_key = $saved_query->getQueryKey();
-
- $bulk_uri = new PhutilURI("/maniphest/bulk/query/{$query_key}/");
- $bulk_uri->replaceQueryParam('board', $project->getID());
-
- return id(new AphrontRedirectResponse())
- ->setURI($bulk_uri);
- }
-
$move_id = $request->getStr('move');
if (strlen($move_id)) {
$column_id_map = mpull($columns, null, 'getID');
@@ -426,11 +337,13 @@
}
}
+ $container_phids = $state->getBoardContainerPHIDs();
+
$rendering_engine = id(new PhabricatorBoardRenderingEngine())
->setViewer($viewer)
->setObjects(array_select_keys($tasks, $visible_phids))
->setEditMap($task_can_edit_map)
- ->setExcludedProjectPHIDs($select_phids);
+ ->setExcludedProjectPHIDs($container_phids);
$templates = array();
$all_tasks = array();
@@ -912,13 +825,6 @@
->setName(pht('Manage Workboard'))
->setHref($manage_uri);
- $batch_edit_uri = $request->getRequestURI();
- $batch_edit_uri->replaceQueryParam('batch', self::BATCH_EDIT_ALL);
- $can_batch_edit = PhabricatorPolicyFilter::hasCapability(
- $viewer,
- PhabricatorApplication::getByClass('PhabricatorManiphestApplication'),
- ManiphestBulkEditCapability::CAPABILITY);
-
$manage_menu = id(new PhabricatorActionListView())
->setUser($viewer);
foreach ($manage_items as $item) {
@@ -1002,9 +908,12 @@
$column_items[] = id(new PhabricatorActionView())
->setType(PhabricatorActionView::TYPE_DIVIDER);
- $batch_edit_uri = $request->getRequestURI();
- $batch_edit_uri->replaceQueryParam('batch', $column->getID());
- $can_batch_edit = PhabricatorPolicyFilter::hasCapability(
+ $bulk_edit_uri = $state->newWorkboardURI(
+ urisprintf(
+ 'bulk/%d/',
+ $column->getID()));
+
+ $can_bulk_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
PhabricatorApplication::getByClass('PhabricatorManiphestApplication'),
ManiphestBulkEditCapability::CAPABILITY);
@@ -1012,8 +921,8 @@
$column_items[] = id(new PhabricatorActionView())
->setIcon('fa-list-ul')
->setName(pht('Bulk Edit Tasks...'))
- ->setHref($batch_edit_uri)
- ->setDisabled(!$can_batch_edit);
+ ->setHref($bulk_edit_uri)
+ ->setDisabled(!$can_bulk_edit);
$batch_move_uri = $request->getRequestURI();
$batch_move_uri->replaceQueryParam('move', $column->getID());
diff --git a/src/applications/project/controller/PhabricatorProjectColumnBulkEditController.php b/src/applications/project/controller/PhabricatorProjectColumnBulkEditController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/controller/PhabricatorProjectColumnBulkEditController.php
@@ -0,0 +1,72 @@
+<?php
+
+final class PhabricatorProjectColumnBulkEditController
+ extends PhabricatorProjectBoardController {
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $request->getViewer();
+
+ $response = $this->loadProject();
+ if ($response) {
+ return $response;
+ }
+
+ $project = $this->getProject();
+ $state = $this->getViewState();
+ $board_uri = $state->newWorkboardURI();
+
+ $layout_engine = $state->getLayoutEngine();
+
+ $board_phid = $project->getPHID();
+ $columns = $layout_engine->getColumns($board_phid);
+ $columns = mpull($columns, null, 'getID');
+
+ $column_id = $request->getURIData('columnID');
+ $bulk_column = idx($columns, $column_id);
+ if (!$bulk_column) {
+ return new Aphront404Response();
+ }
+
+ $bulk_task_phids = $layout_engine->getColumnObjectPHIDs(
+ $board_phid,
+ $bulk_column->getPHID());
+
+ $tasks = $state->getObjects();
+
+ $bulk_tasks = array_select_keys($tasks, $bulk_task_phids);
+
+ $bulk_tasks = id(new PhabricatorPolicyFilter())
+ ->setViewer($viewer)
+ ->requireCapabilities(array(PhabricatorPolicyCapability::CAN_EDIT))
+ ->apply($bulk_tasks);
+
+ if (!$bulk_tasks) {
+ return $this->newDialog()
+ ->setTitle(pht('No Editable Tasks'))
+ ->appendParagraph(
+ pht(
+ 'The selected column contains no visible tasks which you '.
+ 'have permission to edit.'))
+ ->addCancelButton($board_uri);
+ }
+
+ // Create a saved query to hold the working set. This allows us to get
+ // around URI length limitations with a long "?ids=..." query string.
+ // For details, see T10268.
+ $search_engine = id(new ManiphestTaskSearchEngine())
+ ->setViewer($viewer);
+
+ $saved_query = $search_engine->newSavedQuery();
+ $saved_query->setParameter('ids', mpull($bulk_tasks, 'getID'));
+ $search_engine->saveQuery($saved_query);
+
+ $query_key = $saved_query->getQueryKey();
+
+ $bulk_uri = new PhutilURI("/maniphest/bulk/query/{$query_key}/");
+ $bulk_uri->replaceQueryParam('board', $project->getID());
+
+ return id(new AphrontRedirectResponse())
+ ->setURI($bulk_uri);
+ }
+
+}
diff --git a/src/applications/project/state/PhabricatorWorkboardViewState.php b/src/applications/project/state/PhabricatorWorkboardViewState.php
--- a/src/applications/project/state/PhabricatorWorkboardViewState.php
+++ b/src/applications/project/state/PhabricatorWorkboardViewState.php
@@ -8,6 +8,8 @@
private $requestState = array();
private $savedQuery;
private $searchEngine;
+ private $layoutEngine;
+ private $objects;
public function setProject(PhabricatorProject $project) {
$this->project = $project;
@@ -212,4 +214,78 @@
return $this->requestState;
}
+ public function getLayoutEngine() {
+ if ($this->layoutEngine === null) {
+ $this->layoutEngine = $this->newLayoutEngine();
+ }
+ return $this->layoutEngine;
+ }
+
+ private function newLayoutEngine() {
+ $project = $this->getProject();
+ $viewer = $this->getViewer();
+
+ $board_phid = $project->getPHID();
+ $objects = $this->getObjects();
+
+ // Regardless of display order, pass tasks to the layout engine in ID order
+ // so layout is consistent.
+ $objects = msort($objects, 'getID');
+
+ $layout_engine = id(new PhabricatorBoardLayoutEngine())
+ ->setViewer($viewer)
+ ->setObjectPHIDs(array_keys($objects))
+ ->setBoardPHIDs(array($board_phid))
+ ->setFetchAllBoards(true)
+ ->executeLayout();
+
+ return $layout_engine;
+ }
+
+ public function getBoardContainerPHIDs() {
+ $project = $this->getProject();
+ $viewer = $this->getViewer();
+
+ $container_phids = array($project->getPHID());
+ if ($project->getHasSubprojects() || $project->getHasMilestones()) {
+ $descendants = id(new PhabricatorProjectQuery())
+ ->setViewer($viewer)
+ ->withAncestorProjectPHIDs($container_phids)
+ ->execute();
+ foreach ($descendants as $descendant) {
+ $container_phids[] = $descendant->getPHID();
+ }
+ }
+
+ return $container_phids;
+ }
+
+ public function getObjects() {
+ if ($this->objects === null) {
+ $this->objects = $this->newObjects();
+ }
+
+ return $this->objects;
+ }
+
+ private function newObjects() {
+ $viewer = $this->getViewer();
+ $saved_query = $this->getSavedQuery();
+ $search_engine = $this->getSearchEngine();
+
+ $container_phids = $this->getBoardContainerPHIDs();
+
+ $task_query = $search_engine->buildQueryFromSavedQuery($saved_query)
+ ->setViewer($viewer)
+ ->withEdgeLogicPHIDs(
+ PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
+ PhabricatorQueryConstraint::OPERATOR_ANCESTOR,
+ array($container_phids));
+
+ $tasks = $task_query->execute();
+ $tasks = mpull($tasks, null, 'getPHID');
+
+ return $tasks;
+ }
+
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Oct 21, 2:24 AM (3 w, 6 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6737821
Default Alt Text
D20634.id49219.diff (13 KB)
Attached To
Mode
D20634: Move workboard "Bulk Edit Tasks" workflow to a separate controller
Attached
Detach File
Event Timeline
Log In to Comment