HEX
Server: LiteSpeed
System: Linux houston.panomity.com 6.8.0-100-generic #100-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 13 16:40:06 UTC 2026 x86_64
User: nudepix (1011)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
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(),
            ]
        );
    }
}