Files
Lesstime/src/Controller/Mail/MailLinkTaskController.php
matthieu 117175d4b1 feat(mail) : MailLinkTask + MailUnlinkTask + TaskMailsList controllers
- POST /api/mail/messages/{id}/link-task body {taskId} : cree TaskMailLink (idempotent)
- DELETE /api/mail/messages/{id}/link-task/{taskId} : supprime le lien (204)
- GET /api/tasks/{id}/mails : liste les mails lies a une tache
- securite via MailAccessChecker, tests fonctionnels 401/403

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 00:12:10 +02:00

70 lines
2.5 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Controller\Mail;
use App\Entity\Task;
use App\Entity\TaskMailLink;
use App\Repository\MailMessageRepository;
use App\Repository\TaskMailLinkRepository;
use App\Security\MailAccessChecker;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route('/api/mail/messages/{id}/link-task', name: 'mail_link_task', methods: ['POST'], priority: 1, requirements: ['id' => '\d+'])]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
class MailLinkTaskController extends AbstractController
{
public function __construct(
private readonly MailMessageRepository $messageRepository,
private readonly TaskMailLinkRepository $linkRepository,
private readonly EntityManagerInterface $em,
private readonly MailAccessChecker $accessChecker,
) {}
public function __invoke(Request $request, int $id): JsonResponse
{
$this->accessChecker->ensureCanAccessMail($this->getUser());
$message = $this->messageRepository->find($id);
if (null === $message) {
throw new NotFoundHttpException('Message not found');
}
$body = json_decode($request->getContent(), true);
$taskId = $body['taskId'] ?? null;
if (null === $taskId) {
throw new UnprocessableEntityHttpException('taskId is required');
}
$task = $this->em->getRepository(Task::class)->find($taskId);
if (null === $task) {
throw new NotFoundHttpException('Task not found');
}
$existing = $this->linkRepository->findByTaskAndMessage($task, $message);
if (null !== $existing) {
return $this->json(['message' => 'Already linked']);
}
$link = new TaskMailLink();
$link->setTask($task);
$link->setMailMessage($message);
$link->setLinkedAt(new DateTimeImmutable());
$link->setLinkedBy($this->getUser());
$this->em->persist($link);
$this->em->flush();
return $this->json(['linkId' => $link->getId(), 'taskId' => $task->getId(), 'messageId' => $message->getId()], 201);
}
}