You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

396 lines
14 KiB

<?php
namespace App\Controller;
use App\Entity\Comment;
use App\Entity\Project;
use App\Entity\Task;
use App\Form\CommentType;
use App\Form\TaskType;
use App\Service\GeoJsonManager;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Workflow\WorkflowInterface;
#[Route('/task')]
class TaskController extends AbstractController
{
#[Route('/create', name: 'app_task_create')]
public function create(Request $request, EntityManagerInterface $entityManager): Response
{
if (!$request->query->has('slug')) {
$this->addFlash( 'warning', 'Projet non spécifié !');
return $this->redirectToRoute('app_project');
}
$slug = $request->query->get('slug');
$repository = $entityManager->getRepository(Project::class);
$project = $repository->findOneBySlug($slug);
if (!$project) {
$this->addFlash( 'warning', 'Projet non trouvé !');
return $this->redirectToRoute('app_project');
}
$task = new Task();
$task->setProject($project);
$createForm = $this->createForm(TaskType::class, $task);
$createForm->add('submit', SubmitType::class, [
'label' => 'Créer',
]);
$createForm->handleRequest($request);
if ($createForm->isSubmitted() and $createForm->isValid()) {
$task = $createForm->getData();
try {
$task->setCreatedBy($this->getUser());
$entityManager->persist($task);
$entityManager->flush();
$this->addFlash(
'success',
'Tâche créée !'
);
return $this->redirectToRoute('app_project_show', ['slug' => $slug]);
} catch (\Exception $exception) {
$this->addFlash('danger', 'Impossible de créer la tâche !');
}
}
return $this->render('task/create.html.twig', [
'project' => $project,
'create_form' => $createForm,
]);
}
#[Route('/{slug}', name: 'app_task_show')]
public function show(Request $request, EntityManagerInterface $entityManager, GeoJsonManager $geoJsonManager, $slug): Response
{
$repository = $entityManager->getRepository(Task::class);
$task = $repository->findOneBySlug($slug);
if (!$task) {
$this->addFlash(
'warning',
'Tâche non trouvée !'
);
if (!$request->headers->has('Referer')) {
throw $this->createNotFoundException('Task not found');
}
return $this->redirect($request->headers->get('Referer'));
}
$nextTask = $repository->findNextOne($task);
$comment = new Comment();
$commentForm = $this->createForm(CommentType::class, $comment, [
'action' => $this->generateUrl('app_task_comment', ['slug' => $slug]),
]);
$commentForm->add('submit', SubmitType::class, [
'label' => 'Commenter',
]);
$geom = \geoPHP::load($task->getGeojson(), 'json');
$bbox = $geom->getBBox();
return $this->render('task/show.html.twig', [
'task' => $task,
'project' => $task->getProject(),
'commentForm' => $commentForm,
'nextTask' => $nextTask,
'bbox' => $bbox,
]);
}
#[Route('/{slug}/comment', name: 'app_task_comment')]
public function comment(Request $request, EntityManagerInterface $entityManager, $slug): Response
{
$repository = $entityManager->getRepository(Task::class);
$task = $repository->findOneBySlug($slug);
if (!$task) {
$this->addFlash(
'warning',
'Tâche non trouvée !'
);
return $this->redirect($request->headers->get('Referer'));
}
$comment = new Comment();
$comment->setCreatedBy($this->getUser());
$comment->setTask($task);
$commentForm = $this->createForm(CommentType::class, $comment);
$commentForm->add('submit', SubmitType::class, [
'label' => 'Commenter',
]);
$commentForm->handleRequest($request);
if ($commentForm->isSubmitted() and $commentForm->isValid()) {
$comment = $commentForm->getData();
try {
$entityManager->persist($comment);
$entityManager->flush();
} catch (\Exception $exception) {
$this->addFlash(
'danger',
'Impossible de commenter ! ' . $exception->getMessage()
);
}
}
return $this->redirectToRoute('app_task_show', ['slug' => $slug]);
}
#[Route('/{slug}/update', name: 'app_task_update')]
public function update(Request $request, EntityManagerInterface $entityManager, $slug): Response
{
$repository = $entityManager->getRepository(Task::class);
$task = $repository->findOneBySlug($slug);
if (!$task) {
$this->addFlash(
'warning',
'Tâche non trouvée !'
);
return $this->redirect($request->headers->get('Referer'));
}
$updateForm = $this->createForm(TaskType::class, $task);
$updateForm->add('submit', SubmitType::class, [
'label' => 'Modifier',
]);
$updateForm->handleRequest($request);
if ($updateForm->isSubmitted() and $updateForm->isValid()) {
$task = $updateForm->getData();
try {
$entityManager->persist($task);
$entityManager->flush();
return $this->redirectToRoute('app_task_show', ['slug' => $slug]);
} catch (\Exception $exception) {
$this->addFlash(
'danger',
'Impossible de modifier la tâche !'
);
}
}
return $this->render('task/update.html.twig', [
'project' => $task->getProject(),
'task' => $task,
'update_form' => $updateForm,
]);
}
#[Route('/{slug}/remove', name: 'app_task_remove')]
public function remove(Request $request, EntityManagerInterface $entityManager, $slug): Response
{
$repository = $entityManager->getRepository(Task::class);
$task = $repository->findOneBySlug($slug);
if (!$task) {
$this->addFlash(
'warning',
'Tâche non trouvée !'
);
return $this->redirect($request->headers->get('Referer'));
}
$project = $task->getProject();
try {
$entityManager->remove($task);
$entityManager->flush();
return $this->redirectToRoute('app_project_show', ['slug' => $project->getSlug()]);
} catch (\Exception $exception) {
$this->addFlash(
'danger',
'Impossible de supprimer la tâche !'
);
}
return $this->redirectToRoute('app_project_show', ['slug' => $slug]);
}
private function transition(WorkflowInterface $taskLifecycleStateMachine, EntityManagerInterface $entityManager, $slug, $transitionName, $commentTemplate): Response
{
$repository = $entityManager->getRepository(Task::class);
$task = $repository->findOneBySlug($slug);
if (!$task) {
$this->addFlash(
'warning',
'Tâche non trouvée !'
);
return $this->redirectToRoute('app_project');
}
try {
// TODO on doit pouvoir faire mieux pour le verrouillage, notamment au niveau des règles de tansition du workflow…
$transitions = array_filter(
$taskLifecycleStateMachine->getDefinition()->getTransitions(),
function ($transition) use ($transitionName) {
return $transitionName === $transition->getName();
}
);
$transition = reset($transitions);
$shouldTransitionLock = $taskLifecycleStateMachine->getMetadataStore()->getTransitionMetadata($transition)['lock'];
$shouldTransitionUnlock = $taskLifecycleStateMachine->getMetadataStore()->getTransitionMetadata($transition)['unlock'];
$taskLifecycleStateMachine->apply($task, $transitionName);
if ($shouldTransitionLock) {
$task->lock($this->getUser());
} elseif ($shouldTransitionUnlock) {
$task->unlock();
}
$entityManager->persist($task);
$comment = new Comment();
$comment->setTask($task);
$comment->setCreatedBy($this->getUser());
$comment->setContent($this->renderView($commentTemplate, [
'user' => $this->getUser(),
'task' => $task,
]));
$entityManager->persist($comment);
$entityManager->flush();
} catch (Exception $exception) {
$this->addFlash(
'warning',
'Impossible de modifier la tâche !'
);
}
return $this->redirectToRoute('app_task_show', ['slug' => $slug]);
}
#[Route('/{slug}/start', name: 'app_task_start')]
public function start(WorkflowInterface $taskLifecycleStateMachine, EntityManagerInterface $entityManager, $slug): Response
{
return $this->transition($taskLifecycleStateMachine, $entityManager, $slug, Task::TRANSITION_START, 'comment/start.md.twig');
}
#[Route('/{slug}/finish', name: 'app_task_finish')]
public function finish(WorkflowInterface $taskLifecycleStateMachine, EntityManagerInterface $entityManager, $slug): Response
{
return $this->transition($taskLifecycleStateMachine, $entityManager, $slug, Task::TRANSITION_FINISH, 'comment/finish.md.twig');
}
#[Route('/{slug}/cancel', name: 'app_task_cancel')]
public function cancel(WorkflowInterface $taskLifecycleStateMachine, EntityManagerInterface $entityManager, $slug): Response
{
return $this->transition($taskLifecycleStateMachine, $entityManager, $slug, Task::TRANSITION_CANCEL, 'comment/cancel.md.twig');
}
#[Route('/{slug}/reset', name: 'app_task_reset')]
public function reset(WorkflowInterface $taskLifecycleStateMachine, EntityManagerInterface $entityManager, $slug): Response
{
return $this->transition($taskLifecycleStateMachine, $entityManager, $slug, Task::TRANSITION_RESET, 'comment/reset.md.twig');
}
#[Route('/download/{slug}.geojson', name: 'app_task_geojson')]
public function geojson(Request $request, EntityManagerInterface $entityManager, $slug): Response
{
$repository = $entityManager->getRepository(Task::class);
$task = $repository->findOneBySlug($slug);
if (!$task) {
$this->addFlash(
'warning',
'Tâche non trouvée !'
);
// TODO faire pareil ailleurs où il y a des referer
if (!$request->headers->has('Referer')) {
throw $this->createNotFoundException('Task not found');
}
return $this->redirect($request->headers->get('Referer'));
}
$response = JsonResponse::fromJsonString($task->getGeojson());
$response->headers->set('Content-Disposition', HeaderUtils::makeDisposition(
HeaderUtils::DISPOSITION_ATTACHMENT,
sprintf('%s.geojson', $task->getSlug())
));
return $response;
}
#[Route('/download/{slug}.gpx', name: 'app_task_gpx')]
public function gpx(Request $request, EntityManagerInterface $entityManager, $slug): Response
{
$repository = $entityManager->getRepository(Task::class);
$task = $repository->findOneBySlug($slug);
if (!$task) {
$this->addFlash('warning', 'Tâche non trouvée !');
if (!$request->headers->has('Referer')) {
throw $this->createNotFoundException('Task not found');
}
return $this->redirect($request->headers->get('Referer'));
}
$geom = \geoPHP::load($task->getGeojson(), 'json');
$gpx = $geom->out('gpx');
$response = new Response($gpx);
$response->headers->set('Content-Type', 'application/xml');
$response->headers->set('Content-Disposition', HeaderUtils::makeDisposition(
HeaderUtils::DISPOSITION_ATTACHMENT,
sprintf('%s.gpx', $task->getSlug())
));
return $response;
}
#[Route('/download/{slug}.osm', name: 'app_task_osm')]
public function osm(Request $request, EntityManagerInterface $entityManager, $slug): Response
{
$repository = $entityManager->getRepository(Task::class);
$task = $repository->findOneBySlug($slug);
if (!$task) {
$this->addFlash(
'warning',
'Tâche non trouvée !'
);
return $this->redirect($request->headers->get('referer'));
}
$xml = new \DOMDocument();
$xml->loadXml($task->getOsm());
$response = new Response($xml->saveXML());
$response->headers->set('Content-Type', 'application/xml');
$response->headers->set('Content-Disposition', HeaderUtils::makeDisposition(
HeaderUtils::DISPOSITION_ATTACHMENT,
sprintf('%s.osm', $task->getSlug())
));
return $response;
}
}