eventDispatcher = $eventDispatcher; $this->timelineBuilder = $timelineBuilder; $this->logger = $logger; $this->translator = $translator; $this->centerResolverDispatcher = $centerResolverDispatcher; $this->paginatorFactory = $paginatorFactory; $this->singleTaskAclAwareRepository = $singleTaskAclAwareRepository; $this->filterOrderHelperFactory = $filterOrderHelperFactory; } private function getEntityContext(Request $request) { if ($request->query->has('person_id')) { return 'person'; } else if ($request->query->has('course_id')) { return 'course'; } else { return null; } } /** * @Route( * "/{_locale}/task/single-task/new", * name="chill_task_single_task_new" * ) */ public function newAction(Request $request) { $task = (new SingleTask()) ->setAssignee($this->getUser()) ->setType('task_default') ; $entityType = $this->getEntityContext($request); if (NULL === $entityType) { throw new BadRequestHttpException("You must provide a entity_type"); } $entityId = $request->query->getInt("{$entityType}_id", 0); if ($entityId === null) { return new BadRequestHttpException("You must provide a {$entityType}_id"); } switch ($entityType) { case 'person': $person = $this->getDoctrine()->getManager() ->getRepository(Person::class) ->find($entityId); if ($person === null) { $this->createNotFoundException("Invalid person id"); } $task->setPerson($person); $role = TaskVoter::CREATE_PERSON; break; case 'course': $course = $this->getDoctrine()->getManager() ->getRepository(AccompanyingPeriod::class) ->find($entityId); if ($course === null) { $this->createNotFoundException("Invalid accompanying course id"); } $task->setCourse($course); $role = TaskVoter::CREATE_COURSE; break; default: return new BadRequestHttpException("context with {$entityType} is not supported"); } $this->denyAccessUnlessGranted($role, $task, 'You are not ' . 'allowed to create this task'); $form = $this->setCreateForm($task, new Role($role)); $form->handleRequest($request); if ($form->isSubmitted()) { if ($form->isValid()) { $em = $this->getDoctrine()->getManager(); $em->persist($task); $this->eventDispatcher->dispatch(TaskEvent::PERSIST, new TaskEvent($task)); $em->flush(); $this->addFlash('success', $this->translator->trans("The task is created")); if ($request->query->has('returnPath')) { return $this->redirect($request->query->get('returnPath')); } if ($entityType === 'person') { return $this->redirectToRoute('chill_task_singletask_by-person_list', [ 'id' => $task->getPerson()->getId() ]); } elseif ($entityType === 'course') { return $this->redirectToRoute('chill_task_singletask_by-course_list', [ 'id' => $task->getCourse()->getId() ]); } } else { $this->addFlash('error', $this->translator->trans("This form contains errors")); } } switch ($entityType) { case 'person': return $this->render('@ChillTask/SingleTask/Person/new.html.twig', array( 'form' => $form->createView(), 'task' => $task, 'person' => $task->getPerson(), )); case 'course': return $this->render('@ChillTask/SingleTask/AccompanyingCourse/new.html.twig', array( 'form' => $form->createView(), 'task' => $task, 'accompanyingCourse' => $task->getCourse(), )); default: throw new \LogicException("entity context not supported"); } } /** * @Route( * "/{_locale}/task/single-task/{id}/show", * name="chill_task_single_task_show" * ) */ public function showAction(SingleTask $task, Request $request) { $this->denyAccessUnlessGranted(TaskVoter::SHOW, $task); if ($person = $task->getContext() instanceof Person) { $event = new PrivacyEvent($person, array( 'element_class' => SingleTask::class, 'element_id' => $task->getId(), 'action' => 'show' )); $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); } $timeline = $this->timelineBuilder ->getTimelineHTML('task', array('task' => $task)); if ($task->getContext() instanceof Person) { return $this->render('@ChillTask/SingleTask/Person/show.html.twig', array( 'task' => $task, 'timeline' => $timeline )); } else { return $this->render('@ChillTask/SingleTask/AccompanyingCourse/show.html.twig', array( 'task' => $task, 'timeline' => $timeline )); } } /** * @Route( * "/{_locale}/task/single-task/{id}/edit", * name="chill_task_single_task_edit" * ) */ public function editAction( SingleTask $task, Request $request ) { $this->denyAccessUnlessGranted(TaskVoter::UPDATE, $task, 'You are not ' . 'allowed to edit this task'); $event = (new UIEvent('single-task', $task)) ->setForm($this->setCreateForm($task, new Role(TaskVoter::UPDATE))) ; $this->eventDispatcher->dispatch(UIEvent::EDIT_FORM, $event); $form = $event->getForm(); $form->handleRequest($request); if ($form->isSubmitted()) { if ($form->isValid()) { $em = $this->getDoctrine()->getManager(); $em->persist($task); $em->flush(); $this->addFlash('success', $this->translator ->trans("The task has been updated")); if ($task->getContext() instanceof Person) { $event = new PrivacyEvent($task->getPerson(), array( 'element_class' => SingleTask::class, 'element_id' => $task->getId(), 'action' => 'update' )); $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); if ($request->query->has('returnPath')) { return $this->redirect($request->query->get('returnPath')); } return $this->redirectToRoute( 'chill_task_singletask_list', ); } else { if ($request->query->has('returnPath')) { return $this->redirect($request->query->get('returnPath')); } return $this->redirectToRoute( 'chill_task_singletask_by-course_list', ['id' => $task->getCourse()->getId()] ); } } else { $this->addFlash('error', $this->translator->trans("This form contains errors")); } } $this->eventDispatcher->dispatch(UIEvent::EDIT_PAGE, $event); if ($event->hasResponse()) { return $event->getResponse(); } if ($task->getContext() instanceof Person) { $event = new PrivacyEvent($task->getPerson(), array( 'element_class' => SingleTask::class, 'element_id' => $task->getId(), 'action' => 'edit' )); $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); return $this->render('@ChillTask/SingleTask/Person/edit.html.twig', array( 'task' => $task, 'form' => $form->createView() )); } else { return $this->render('@ChillTask/SingleTask/AccompanyingCourse/edit.html.twig', array( 'task' => $task, 'form' => $form->createView(), 'accompanyingCourse' => $task->getCourse() )); } } /** * @Route( * "/{_locale}/task/single-task/{id}/delete", * name="chill_task_single_task_delete" * ) */ public function deleteAction( Request $request, $id ) { $em = $this->getDoctrine()->getManager(); $task = $em->getRepository(SingleTask::class)->find($id); if (!$task) { throw $this->createNotFoundException('Unable to find Task entity.'); } if ($task->getPerson() !== null) { $personId = $task->getPerson()->getId(); if ($personId === null) { return new Response("You must provide a person_id", Response::HTTP_BAD_REQUEST); } $person = $this->getDoctrine()->getManager() ->getRepository(Person::class) ->find($personId); if ($person === null) { throw $this->createNotFoundException("Invalid person id"); } } else { $courseId = $task->getCourse()->getId(); if ($courseId === null){ return new Response("You must provide a course_id", Response::HTTP_BAD_REQUEST); } $course = $this->getDoctrine()->getManager() ->getRepository(AccompanyingPeriod::class) ->find($courseId); if($course === null){ throw $this->createNotFoundException("Invalid accompanying period id"); } } // TODO: reactivate right to delete // $this->denyAccessUnlessGranted(TaskVoter::DELETE, $task, 'You are not ' // . 'allowed to delete this task'); $form = $this->createDeleteForm($id); if ($request->getMethod() === Request::METHOD_DELETE) { $form->handleRequest($request); if ($form->isValid()) { $this->logger->notice("A task has been removed", array( 'by_user' => $this->getUser()->getUsername(), 'task_id' => $task->getId(), 'description' => $task->getDescription(), 'assignee' => $task->getAssignee(), // TODO reimplement scope // 'scope_id' => $task->getScope()->getId(), )); $em = $this->getDoctrine()->getManager(); $em->remove($task); $em->flush(); $this->addFlash('success', $this->translator ->trans("The task has been successfully removed.")); if ($task->getContext() instanceof Person) { return $this->redirect($this->generateUrl( 'chill_task_singletask_by-person_list', [ 'id' => $task->getPerson()->getId() ] )); } else { return $this->redirect($this->generateUrl( 'chill_task_singletask_by-course_list', ['id' => $task->getCourse()->getId()] )); } } } if($task->getContext() instanceof Person){ return $this->render('@ChillTask/SingleTask/Person/confirm_delete.html.twig', array( 'task' => $task, 'delete_form' => $form->createView() )); } else { return $this->render('@ChillTask/SingleTask/AccompanyingCourse/confirm_delete.html.twig', array( 'task' => $task, 'delete_form' => $form->createView(), 'accompanyingCourse' => $course )); } } /** * * @param SingleTask $task * @param Role $role * @return \Symfony\Component\Form\FormInterface */ protected function setCreateForm(SingleTask $task, Role $role) { $form = $this->createForm(SingleTaskType::class, $task, [ 'role' => $role, ]); $form->add('submit', SubmitType::class); return $form; } /** * * @return Response * @Route( * "/{_locale}/task/single-task/list/my", * name="chill_task_singletask_my_tasks" * ) */ public function myTasksAction() { $this->denyAccessUnlessGranted('ROLE_USER'); $filterOrder = $this->buildFilterOrder(); $flags = \array_merge( $filterOrder->getCheckboxData('status'), \array_map(fn ($i) => 'state_'.$i, $filterOrder->getCheckboxData('states')) ); $nb = $this->singleTaskAclAwareRepository->countByCurrentUsersTasks( $filterOrder->getQueryString(), $flags ); $paginator = $this->paginatorFactory->create($nb); $tasks = $this->singleTaskAclAwareRepository->findByCurrentUsersTasks( $filterOrder->getQueryString(), $flags, $paginator->getCurrentPageFirstItemNumber(), $paginator->getItemsPerPage(), [ 'startDate' => 'DESC', 'endDate' => 'DESC', ] ); return $this->render('@ChillTask/SingleTask/List/index_my_tasks.html.twig', [ 'tasks' => $tasks, 'paginator' => $paginator, 'filter_order' => $filterOrder, ]); } private function buildFilterOrder(): FilterOrderHelper { $statuses = ['no-alert', 'warning', 'alert']; $statusTrans = [ 'Tasks without alert', 'Tasks near deadline', 'Tasks over deadline', ]; $states = [ // todo: get a list of possible states dynamically 'new', 'in_progress', 'closed', 'canceled' ]; return $this->filterOrderHelperFactory ->create(self::class) ->addSearchBox() ->addCheckbox('status', $statuses, $statuses, $statusTrans) ->addCheckbox('states', $states, ['new', 'in_progress']) ->build() ; } /** * * Arguments: * - user_id * - scope_id * - s * - person_id * - hide_form (hide the form to filter the tasks) * - status: date state, amongst SingleTaskRepository::DATE_STATUSES, or 'closed' * * @Route( * "/{_locale}/task/single-task/list", * name="chill_task_singletask_list" * ) */ public function listAction( Request $request ) { $this->denyAccessUnlessGranted(TaskVoter::SHOW, null); $filterOrder = $this->buildFilterOrder(); $flags = \array_merge( $filterOrder->getCheckboxData('status'), \array_map(fn ($i) => 'state_'.$i, $filterOrder->getCheckboxData('states')) ); $nb = $this->singleTaskAclAwareRepository->countByAllViewable( $filterOrder->getQueryString(), $flags ); $paginator = $this->paginatorFactory->create($nb); if (0 < $nb) { $tasks = $this->singleTaskAclAwareRepository->findByAllViewable( $filterOrder->getQueryString(), $flags, $paginator->getCurrentPageFirstItemNumber(), $paginator->getItemsPerPage(), [ 'startDate' => 'DESC', 'endDate' => 'DESC', ] ); } else { $tasks = []; } return $this->render('@ChillTask/SingleTask/List/index.html.twig', [ 'tasks' => $tasks, 'paginator' => $paginator, 'filter_order' => $filterOrder ]); } /** * Creates a form to delete a Task entity by id. * * @param mixed $id The entity id * * @return \Symfony\Component\Form\Form The form */ private function createDeleteForm($id) { return $this->createFormBuilder() ->setAction($this->generateUrl( 'chill_task_single_task_delete', array('id' => $id))) ->setMethod('DELETE') ->add('submit', SubmitType::class, array('label' => 'Delete')) ->getForm() ; } /** * @Route( * "/{_locale}/task/single-task/by-course/{id}", * name="chill_task_singletask_by-course_list") */ public function listCourseTasks( AccompanyingPeriod $course, FormFactoryInterface $formFactory, Request $request ): Response { $this->denyAccessUnlessGranted(TaskVoter::SHOW, $course); $filterOrder = $this->buildFilterOrder(); $flags = \array_merge( $filterOrder->getCheckboxData('status'), \array_map(fn ($i) => 'state_'.$i, $filterOrder->getCheckboxData('states')) ); $nb = $this->singleTaskAclAwareRepository->countByCourse( $course, $filterOrder->getQueryString(), $flags ); $paginator = $this->paginatorFactory->create($nb); if (0 < $nb) { $tasks = $this->singleTaskAclAwareRepository->findByCourse( $course, $filterOrder->getQueryString(), $flags, $paginator->getCurrentPageFirstItemNumber(), $paginator->getItemsPerPage(), [ 'startDate' => 'DESC', 'endDate' => 'DESC', ] ); } else { $tasks = []; } return $this->render( '@ChillTask/SingleTask/AccompanyingCourse/list.html.twig', [ 'tasks' => $tasks, 'accompanyingCourse' => $course, 'paginator' => $paginator, 'filter_order' => $filterOrder ]); } /** * @Route( * "/{_locale}/task/single-task/by-person/{id}", * name="chill_task_singletask_by-person_list") */ public function listPersonTasks( Person $person ): Response { $this->denyAccessUnlessGranted(TaskVoter::SHOW, $person); $filterOrder = $this->buildFilterOrder(); $flags = \array_merge( $filterOrder->getCheckboxData('status'), \array_map(fn ($i) => 'state_'.$i, $filterOrder->getCheckboxData('states')) ); $nb = $this->singleTaskAclAwareRepository->countByPerson( $person, $filterOrder->getQueryString(), $flags ); $paginator = $this->paginatorFactory->create($nb); if (0 < $nb) { $tasks = $this->singleTaskAclAwareRepository->findByPerson( $person, $filterOrder->getQueryString(), $flags, $paginator->getCurrentPageFirstItemNumber(), $paginator->getItemsPerPage(), [ 'startDate' => 'DESC', 'endDate' => 'DESC', ] ); } else { $tasks = []; } return $this->render( '@ChillTask/SingleTask/Person/list.html.twig', [ 'tasks' => $tasks, 'person' => $person, 'paginator' => $paginator, 'filter_order' => $filterOrder ]); } }