Differential D20634 Diff 49219 src/applications/project/controller/PhabricatorProjectBoardViewController.php
Changeset View
Changeset View
Standalone View
Standalone View
src/applications/project/controller/PhabricatorProjectBoardViewController.php
| <?php | <?php | ||||
| final class PhabricatorProjectBoardViewController | final class PhabricatorProjectBoardViewController | ||||
| extends PhabricatorProjectBoardController { | extends PhabricatorProjectBoardController { | ||||
| const BATCH_EDIT_ALL = 'all'; | |||||
epriestley: This removes some "edit all" stuff, I'll discuss that separately. | |||||
| public function shouldAllowPublic() { | public function shouldAllowPublic() { | ||||
| return true; | return true; | ||||
| } | } | ||||
| public function handleRequest(AphrontRequest $request) { | public function handleRequest(AphrontRequest $request) { | ||||
| $viewer = $request->getUser(); | $viewer = $request->getUser(); | ||||
| $response = $this->loadProject(); | $response = $this->loadProject(); | ||||
| Show All 13 Lines | public function handleRequest(AphrontRequest $request) { | ||||
| } | } | ||||
| if ($saved->getID()) { | if ($saved->getID()) { | ||||
| $custom_query = $saved; | $custom_query = $saved; | ||||
| } else { | } else { | ||||
| $custom_query = null; | $custom_query = null; | ||||
| } | } | ||||
| $task_query = $search_engine->buildQueryFromSavedQuery($saved); | $layout_engine = $state->getLayoutEngine(); | ||||
| $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'); | |||||
| $board_phid = $project->getPHID(); | $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); | $columns = $layout_engine->getColumns($board_phid); | ||||
| if (!$columns || !$project->getHasWorkboard()) { | if (!$columns || !$project->getHasWorkboard()) { | ||||
| $has_normal_columns = false; | $has_normal_columns = false; | ||||
| foreach ($columns as $column) { | foreach ($columns as $column) { | ||||
| if (!$column->getProxyPHID()) { | if (!$column->getProxyPHID()) { | ||||
| $has_normal_columns = true; | $has_normal_columns = true; | ||||
| break; | break; | ||||
| Show All 36 Lines | if (!$columns || !$project->getHasWorkboard()) { | ||||
| $project->getDisplayName(), | $project->getDisplayName(), | ||||
| pht('Workboard'), | pht('Workboard'), | ||||
| )) | )) | ||||
| ->setNavigation($nav) | ->setNavigation($nav) | ||||
| ->setCrumbs($crumbs) | ->setCrumbs($crumbs) | ||||
| ->appendChild($content); | ->appendChild($content); | ||||
| } | } | ||||
| $tasks = $state->getObjects(); | |||||
| $task_can_edit_map = id(new PhabricatorPolicyFilter()) | $task_can_edit_map = id(new PhabricatorPolicyFilter()) | ||||
| ->setViewer($viewer) | ->setViewer($viewer) | ||||
| ->requireCapabilities(array(PhabricatorPolicyCapability::CAN_EDIT)) | ->requireCapabilities(array(PhabricatorPolicyCapability::CAN_EDIT)) | ||||
| ->apply($tasks); | ->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'); | $move_id = $request->getStr('move'); | ||||
| if (strlen($move_id)) { | if (strlen($move_id)) { | ||||
| $column_id_map = mpull($columns, null, 'getID'); | $column_id_map = mpull($columns, null, 'getID'); | ||||
| $move_column = idx($column_id_map, $move_id); | $move_column = idx($column_id_map, $move_id); | ||||
| if (!$move_column) { | if (!$move_column) { | ||||
| return new Aphront404Response(); | return new Aphront404Response(); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 227 Lines • ▼ Show 20 Lines | foreach ($columns as $column) { | ||||
| $visible_columns[$column_phid] = $column; | $visible_columns[$column_phid] = $column; | ||||
| $column_phids[$column_phid] = $column_tasks; | $column_phids[$column_phid] = $column_tasks; | ||||
| foreach ($column_tasks as $phid => $task) { | foreach ($column_tasks as $phid => $task) { | ||||
| $visible_phids[$phid] = $phid; | $visible_phids[$phid] = $phid; | ||||
| } | } | ||||
| } | } | ||||
| $container_phids = $state->getBoardContainerPHIDs(); | |||||
| $rendering_engine = id(new PhabricatorBoardRenderingEngine()) | $rendering_engine = id(new PhabricatorBoardRenderingEngine()) | ||||
| ->setViewer($viewer) | ->setViewer($viewer) | ||||
| ->setObjects(array_select_keys($tasks, $visible_phids)) | ->setObjects(array_select_keys($tasks, $visible_phids)) | ||||
| ->setEditMap($task_can_edit_map) | ->setEditMap($task_can_edit_map) | ||||
| ->setExcludedProjectPHIDs($select_phids); | ->setExcludedProjectPHIDs($container_phids); | ||||
| $templates = array(); | $templates = array(); | ||||
| $all_tasks = array(); | $all_tasks = array(); | ||||
| $column_templates = array(); | $column_templates = array(); | ||||
| $sounds = array(); | $sounds = array(); | ||||
| foreach ($visible_columns as $column_phid => $column) { | foreach ($visible_columns as $column_phid => $column) { | ||||
| $column_tasks = $column_phids[$column_phid]; | $column_tasks = $column_phids[$column_phid]; | ||||
| ▲ Show 20 Lines • Show All 465 Lines • ▼ Show 20 Lines | $manage_items[] = id(new PhabricatorActionView()) | ||||
| ->setWorkflow(false); | ->setWorkflow(false); | ||||
| $manage_uri = $this->getApplicationURI("board/{$id}/manage/"); | $manage_uri = $this->getApplicationURI("board/{$id}/manage/"); | ||||
| $manage_items[] = id(new PhabricatorActionView()) | $manage_items[] = id(new PhabricatorActionView()) | ||||
| ->setIcon('fa-gear') | ->setIcon('fa-gear') | ||||
| ->setName(pht('Manage Workboard')) | ->setName(pht('Manage Workboard')) | ||||
| ->setHref($manage_uri); | ->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()) | $manage_menu = id(new PhabricatorActionListView()) | ||||
| ->setUser($viewer); | ->setUser($viewer); | ||||
| foreach ($manage_items as $item) { | foreach ($manage_items as $item) { | ||||
| $manage_menu->addAction($item); | $manage_menu->addAction($item); | ||||
| } | } | ||||
| $manage_button = id(new PHUIListItemView()) | $manage_button = id(new PHUIListItemView()) | ||||
| ->setIcon('fa-cog') | ->setIcon('fa-cog') | ||||
| ▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | foreach ($specs as $spec) { | ||||
| 'boardPHID' => $project->getPHID(), | 'boardPHID' => $project->getPHID(), | ||||
| 'projectPHID' => $default_phid, | 'projectPHID' => $default_phid, | ||||
| )); | )); | ||||
| } | } | ||||
| $column_items[] = id(new PhabricatorActionView()) | $column_items[] = id(new PhabricatorActionView()) | ||||
| ->setType(PhabricatorActionView::TYPE_DIVIDER); | ->setType(PhabricatorActionView::TYPE_DIVIDER); | ||||
| $batch_edit_uri = $request->getRequestURI(); | $bulk_edit_uri = $state->newWorkboardURI( | ||||
| $batch_edit_uri->replaceQueryParam('batch', $column->getID()); | urisprintf( | ||||
| $can_batch_edit = PhabricatorPolicyFilter::hasCapability( | 'bulk/%d/', | ||||
| $column->getID())); | |||||
| $can_bulk_edit = PhabricatorPolicyFilter::hasCapability( | |||||
| $viewer, | $viewer, | ||||
| PhabricatorApplication::getByClass('PhabricatorManiphestApplication'), | PhabricatorApplication::getByClass('PhabricatorManiphestApplication'), | ||||
| ManiphestBulkEditCapability::CAPABILITY); | ManiphestBulkEditCapability::CAPABILITY); | ||||
| $column_items[] = id(new PhabricatorActionView()) | $column_items[] = id(new PhabricatorActionView()) | ||||
| ->setIcon('fa-list-ul') | ->setIcon('fa-list-ul') | ||||
| ->setName(pht('Bulk Edit Tasks...')) | ->setName(pht('Bulk Edit Tasks...')) | ||||
| ->setHref($batch_edit_uri) | ->setHref($bulk_edit_uri) | ||||
| ->setDisabled(!$can_batch_edit); | ->setDisabled(!$can_bulk_edit); | ||||
| $batch_move_uri = $request->getRequestURI(); | $batch_move_uri = $request->getRequestURI(); | ||||
| $batch_move_uri->replaceQueryParam('move', $column->getID()); | $batch_move_uri->replaceQueryParam('move', $column->getID()); | ||||
| $column_items[] = id(new PhabricatorActionView()) | $column_items[] = id(new PhabricatorActionView()) | ||||
| ->setIcon('fa-arrow-right') | ->setIcon('fa-arrow-right') | ||||
| ->setName(pht('Move Tasks to Column...')) | ->setName(pht('Move Tasks to Column...')) | ||||
| ->setHref($batch_move_uri) | ->setHref($batch_move_uri) | ||||
| ->setWorkflow(true); | ->setWorkflow(true); | ||||
| ▲ Show 20 Lines • Show All 312 Lines • Show Last 20 Lines | |||||
This removes some "edit all" stuff, I'll discuss that separately.