diff --git a/Controller/BulkMoveController.php b/Controller/BulkMoveController.php new file mode 100644 index 0000000..b0ec250 --- /dev/null +++ b/Controller/BulkMoveController.php @@ -0,0 +1,103 @@ +getProject(); + $this->checkAccess($project['id']); + + $column_id = $this->request->getIntegerParam('column_id'); + $swimlane_id = $this->request->getIntegerParam('swimlane_id'); + + // Offer every column of the project except the source one as a destination. + $columns = $this->columnModel->getList($project['id']); + unset($columns[$column_id]); + + $this->response->html($this->template->render('bulkMoveTasks:board/move_all_tasks', array( + 'project' => $project, + 'nb_tasks' => $this->taskFinderModel->countByColumnAndSwimlaneId($project['id'], $column_id, $swimlane_id), + 'column' => $this->columnModel->getColumnTitleById($column_id), + 'swimlane' => $this->swimlaneModel->getNameById($swimlane_id), + 'columns_list' => $columns, + 'values' => array( + 'column_id' => $column_id, + 'swimlane_id' => $swimlane_id, + ), + ))); + } + + /** + * Perform the move and return to the board. + */ + public function move() + { + $project = $this->getProject(); + $this->checkAccess($project['id']); + + $values = $this->request->getValues(); + $src_column_id = isset($values['column_id']) ? (int) $values['column_id'] : 0; + $dst_column_id = isset($values['dst_column_id']) ? (int) $values['dst_column_id'] : 0; + $swimlane_id = isset($values['swimlane_id']) ? (int) $values['swimlane_id'] : 0; + + $columns = $this->columnModel->getList($project['id']); + + if ($src_column_id === 0 || $dst_column_id === 0 || $src_column_id === $dst_column_id || ! isset($columns[$dst_column_id])) { + $this->flash->failure(t('Please choose a different destination column.')); + } else { + $moved = $this->moveAllTasks($project['id'], $src_column_id, $dst_column_id, $swimlane_id); + $this->flash->success(t('%d task(s) moved from "%s" to "%s".', $moved, $this->columnModel->getColumnTitleById($src_column_id), $this->columnModel->getColumnTitleById($dst_column_id))); + } + + $this->response->redirect($this->helper->url->to('BoardViewController', 'show', array('project_id' => $project['id']))); + } + + /** + * Move every open task of (source column, swimlane) to the end of the + * destination column, keeping their relative order. Returns the count moved. + */ + private function moveAllTasks($project_id, $src_column_id, $dst_column_id, $swimlane_id) + { + $task_ids = $this->db->table(TaskModel::TABLE) + ->eq('project_id', $project_id) + ->eq('column_id', $src_column_id) + ->eq('swimlane_id', $swimlane_id) + ->eq('is_active', TaskModel::STATUS_OPEN) + ->asc('position') + ->findAllByColumn('id'); + + $position = $this->taskFinderModel->countByColumnAndSwimlaneId($project_id, $dst_column_id, $swimlane_id) + 1; + $moved = 0; + + foreach ($task_ids as $task_id) { + if ($this->taskPositionModel->movePosition($project_id, $task_id, $dst_column_id, $position, $swimlane_id)) { + $position++; + $moved++; + } + } + + return $moved; + } + + /** + * Allow only users who can modify tasks in this project. + */ + private function checkAccess($project_id) + { + if (! $this->helper->user->hasProjectAccess('TaskModificationController', 'update', $project_id)) { + throw new AccessForbiddenException(); + } + } +}