File: /home/timetracker.panomity.com/tm.old/Controller/TaskController.php
<?php
/*
* This file is part of the TaskManagementBundle for Kimai 2.
* All rights reserved by Kevin Papst (www.kevinpapst.de).
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace KimaiPlugin\TaskManagementBundle\Controller;
use App\Constants;
use App\Controller\AbstractController;
use App\Entity\Activity;
use App\Export\Spreadsheet\AnnotatedObjectExporter;
use App\Export\Spreadsheet\Writer\BinaryFileResponseWriter;
use App\Export\Spreadsheet\Writer\XlsxWriter;
use Exception;
use KimaiPlugin\TaskManagementBundle\Entity\Task;
use KimaiPlugin\TaskManagementBundle\Entity\TaskComment;
use KimaiPlugin\TaskManagementBundle\Form\TaskCommentForm;
use KimaiPlugin\TaskManagementBundle\Form\TaskForm;
use KimaiPlugin\TaskManagementBundle\Form\TaskToolbarForm;
use KimaiPlugin\TaskManagementBundle\Repository\Query\TaskQuery;
use KimaiPlugin\TaskManagementBundle\Repository\TaskRepository;
use Pagerfanta\Doctrine\Collections\CollectionAdapter;
use Pagerfanta\Pagerfanta;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
/**
* @Route(path="/tasks")
*/
final class TaskController extends AbstractController
{
/**
* @var TaskRepository
*/
private $repository;
public function __construct(TaskRepository $repository)
{
$this->repository = $repository;
}
/**
* @Route(path="/", defaults={"page": 1}, name="tasks", methods={"GET"})
* @Route(path="/page/{page}", requirements={"page": "[1-9]\d*"}, name="tasks_paginated", methods={"GET"})
* @Security("is_granted('task_view')")
*/
public function index(int $page, Request $request): Response
{
$viewTeamTasks = $this->isGranted('task_team_view');
$query = new TaskQuery();
$query->setCurrentUser($this->getUser());
$query->setWithUnassigned($this->isGranted('task_assign'));
$query->setWithTeamTasks($viewTeamTasks);
if (!$viewTeamTasks) {
$query->setUser($this->getUser());
}
$query->setStatus([Task::STATUS_PENDING, Task::STATUS_IN_PROGRESS]);
$query->setPage($page);
$form = $this->getToolbarForm($query, $viewTeamTasks);
if ($this->handleSearch($form, $request)) {
return $this->redirectToRoute('tasks');
}
$pager = $this->repository->getPagerfantaForQuery($query);
return $this->render('@TaskManagement/index.html.twig', [
'entries' => $pager,
'page' => $query->getPage(),
'query' => $query,
'toolbarForm' => $form->createView(),
]);
}
/**
* @Route(path="/{id}/edit", name="tasks_edit", methods={"GET", "POST"})
* @Security("is_granted('task_edit', task)")
*/
public function editAction(Task $task, Request $request): Response
{
$assign = $this->isGranted('task_edit_other');
$form = $this->createForm(TaskForm::class, $task, [
'action' => $this->generateUrl('tasks_edit', ['id' => $task->getId()]),
'include_user' => $assign,
'include_team' => $assign,
'timezone' => $this->getUser()->getTimezone(),
]);
return $this->renderEditForm($task, $request, $form);
}
/**
* @Route(path="/create", name="tasks_create", methods={"GET", "POST"})
* @Security("is_granted('task_edit_other')")
*/
public function createAction(Request $request): Response
{
return $this->renderCreateForm($this->generateUrl('tasks_create'), new Task(), $request);
}
private function renderCreateForm(string $action, Task $task, Request $request): Response
{
$assign = $this->isGranted('task_edit_other');
$form = $this->createForm(TaskForm::class, $task, [
'action' => $action,
'include_user' => $assign,
'include_team' => $assign,
'timezone' => $this->getUser()->getTimezone(),
'attr' => [
'data-form-event' => 'kimai.taskUpdate kimai.taskCreate',
],
]);
return $this->renderEditForm($task, $request, $form);
}
/**
* @Route(path="/{id}/duplicate", name="tasks_duplicate", methods={"GET", "POST"})
* @Security("is_granted('task_edit', task)")
*/
public function duplicateAction(Task $task, Request $request): Response
{
$newTask = clone $task;
$newTask->setTitle($task->getTitle() . ' [COPY]');
return $this->renderCreateForm($this->generateUrl('tasks_duplicate', ['id' => $task->getId()]), $newTask, $request);
}
/**
* @Route(path="/export", name="tasks_export", methods={"GET"})
*/
public function exportAction(Request $request, AnnotatedObjectExporter $exporter): Response
{
$query = new TaskQuery();
$query->setCurrentUser($this->getUser());
$viewOtherUser = $this->isGranted('view_other_timesheet');
$form = $this->getToolbarForm($query, $viewOtherUser);
$form->setData($query);
$form->submit($request->query->all(), false);
if (!$form->isValid()) {
$query->resetByFormError($form->getErrors());
}
$entries = $this->repository->getTasksForQuery($query);
$spreadsheet = $exporter->export(Task::class, $entries);
$writer = new BinaryFileResponseWriter(new XlsxWriter(), 'kimai-tasks');
return $writer->getFileResponse($spreadsheet);
}
/**
* @Route(path="/create_my", name="tasks_create_my", methods={"GET", "POST"})
* @Security("is_granted('task_edit_own')")
*/
public function createMyTaskAction(Request $request): Response
{
$task = new Task();
$task->setUser($this->getUser());
$assign = $this->isGranted('task_edit_other');
$form = $this->createForm(TaskForm::class, $task, [
'action' => $this->generateUrl('tasks_create_my'),
'include_user' => $assign,
'include_team' => $assign,
'timezone' => $this->getUser()->getTimezone(),
'attr' => [
'data-form-event' => 'kimai.taskUpdate kimai.myTaskCreate',
],
]);
return $this->renderEditForm($task, $request, $form);
}
/**
* @Route(path="/create_activity/{id}", name="tasks_create_activity", methods={"GET", "POST"})
* @Security("is_granted('task_edit_other')")
*/
public function createFromActivity(Activity $activity, Request $request): Response
{
$task = new Task();
$task->setTitle($activity->getName());
$task->setActivity($activity);
if (null !== ($project = $activity->getProject())) {
$task->setTodo($project->getComment());
$task->setDescription($project->getComment());
$task->setEstimation($project->getTimeBudget());
$task->setEnd($project->getEnd());
$task->setProject($project);
if ($project->getTeams()->count() === 1) {
$task->setTeam($project->getTeams()->first());
}
}
if ($activity->getTimeBudget() > 0) {
$task->setEstimation($activity->getTimeBudget());
}
if ($activity->getTeams()->count() === 1) {
$task->setTeam($activity->getTeams()->first());
}
if (!empty($activity->getComment())) {
$task->setTodo($activity->getComment());
$task->setDescription($activity->getComment());
}
$form = $this->createForm(TaskForm::class, $task, [
'action' => $this->generateUrl('tasks_create_activity', ['id' => $activity->getId()]),
'include_user' => true,
'include_team' => true,
'timezone' => $this->getUser()->getTimezone(),
'attr' => [
'data-form-event' => 'kimai.taskUpdate kimai.taskCreate',
],
]);
return $this->renderEditForm($task, $request, $form);
}
/**
* @Route(path="/my", defaults={"page": 1}, name="tasks_my", methods={"GET", "POST"})
* @Route(path="/my/{page}", requirements={"page": "[1-9]\d*"}, name="tasks_my_paginated", methods={"GET"})
* @Security("is_granted('task_start')")
*/
public function myTaskAction(int $page): Response
{
return $this->render('@TaskManagement/user-tasks.html.twig', [
'user' => $this->getUser(),
'page' => $page,
]);
}
/**
* @Route(path="/pending", defaults={"page": 1}, name="tasks_pending", methods={"GET", "POST"})
* @Route(path="/pending/{page}", requirements={"page": "[1-9]\d*"}, name="tasks_pending_paginated", methods={"GET"})
* @Security("is_granted('task_assign')")
*/
public function pendingTaskAction(int $page): Response
{
return $this->render('@TaskManagement/pending-tasks.html.twig', [
'user' => $this->getUser(),
'page' => $page,
]);
}
/**
* @Route(path="/{id}/details/{page}", defaults={"page": 1}, name="tasks_detail", methods={"GET", "POST"})
* @Security("is_granted('task_details', task)")
*/
public function detailsAction(Task $task, int $page): Response
{
$paginator = new Pagerfanta(new CollectionAdapter($task->getTimesheets()));
$paginator->setMaxPerPage(10);
$paginator->setCurrentPage($page);
return $this->render('@TaskManagement/details.html.twig', [
'task' => $task,
'timesheets' => $paginator,
'comments' => $this->repository->getComments($task),
'commentForm' => $this->getCommentForm($task, new TaskComment())->createView(),
'now' => $this->getDateTimeFactory()->createDateTime(),
]);
}
/**
* @Route(path="/{id}/comment_delete", name="tasks_comment_delete", methods={"GET"})
* @Security("is_granted('task_details', comment.getTask())")
*/
public function deleteCommentAction(TaskComment $comment, Request $request, CsrfTokenManagerInterface $csrfTokenManager): Response
{
$taskId = $comment->getTask()->getId();
// this should be mandatory at a later point
if (Constants::VERSION_ID >= 11600) {
$token = $request->query->get('token');
if ($token === null || !$csrfTokenManager->isTokenValid(new CsrfToken('comment.delete', $token))) {
$this->flashError('action.csrf.error');
return $this->redirectToRoute('tasks_detail', ['id' => $taskId]);
}
$csrfTokenManager->refreshToken($token);
}
try {
$this->repository->deleteComment($comment);
} catch (\Exception $ex) {
$this->flashDeleteException($ex);
}
return $this->redirectToRoute('tasks_detail', ['id' => $taskId]);
}
/**
* @Route(path="/{id}/comment_add", name="tasks_comment_add", methods={"POST"})
* @Security("is_granted('task_details', task)")
*/
public function addCommentAction(Task $task, Request $request): Response
{
$comment = new TaskComment();
$form = $this->getCommentForm($task, $comment);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
try {
$this->repository->saveComment($comment);
} catch (\Exception $ex) {
$this->flashUpdateException($ex);
}
}
return $this->redirectToRoute('tasks_detail', ['id' => $task->getId()]);
}
private function getCommentForm(Task $task, TaskComment $comment): FormInterface
{
if (null === $comment->getId()) {
$comment->setTask($task);
$comment->setCreatedBy($this->getUser());
}
return $this->createForm(TaskCommentForm::class, $comment, [
'action' => $this->generateUrl('tasks_comment_add', ['id' => $task->getId()]),
'method' => 'POST',
]);
}
private function getToolbarForm(TaskQuery $query, bool $viewOtherUser): FormInterface
{
return $this->createForm(TaskToolbarForm::class, $query, [
'action' => $this->generateUrl('tasks', [
'page' => $query->getPage(),
]),
'method' => 'GET',
'include_user' => $viewOtherUser,
'include_team' => $viewOtherUser,
]);
}
private function renderEditForm(Task $task, Request $request, FormInterface $editForm): Response
{
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
try {
$this->repository->saveTask($task);
$this->flashSuccess('action.update.success');
if ($this->isGranted('task_view')) {
return $this->redirectToRoute('tasks');
} elseif ($this->isGranted('task_details')) {
return $this->redirectToRoute('tasks_detail', ['id' => $task->getId()]);
} else {
return $this->redirectToRoute('tasks_edit', ['id' => $task->getId()]);
}
} catch (Exception $ex) {
$this->flashError('action.update.error', ['%reason%' => $ex->getMessage()]);
}
}
return $this->render(
'@TaskManagement/edit.html.twig',
[
'task' => $task,
'form' => $editForm->createView(),
]
);
}
}