*/ final readonly class TaskDocumentProcessor implements ProcessorInterface { private const MAX_FILE_SIZE = 50 * 1024 * 1024; // 50 MB public function __construct( private EntityManagerInterface $entityManager, private Security $security, private RequestStack $requestStack, private string $uploadDir, ) {} /** * @param TaskDocument $data */ public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): TaskDocument { $request = $this->requestStack->getCurrentRequest(); if (null === $request) { throw new BadRequestHttpException('No request available.'); } $file = $request->files->get('file'); if (null === $file || !$file->isValid()) { throw new BadRequestHttpException('No valid file uploaded.'); } if ($file->getSize() > self::MAX_FILE_SIZE) { throw new BadRequestHttpException('File size exceeds 50 MB limit.'); } $taskIri = $request->request->get('task'); if (null === $taskIri || '' === $taskIri) { throw new BadRequestHttpException('Task IRI is required.'); } // Extract task ID from IRI (e.g., "/api/tasks/42" -> 42) $taskId = (int) basename((string) $taskIri); $task = $this->entityManager->getRepository(Task::class)->find($taskId); if (null === $task) { throw new BadRequestHttpException('Task not found.'); } // Capture file metadata BEFORE move() — move invalidates the temp file $originalName = $file->getClientOriginalName(); $extension = $file->getClientOriginalExtension() ?: 'bin'; $mimeType = $file->getClientMimeType() ?? 'application/octet-stream'; $fileSize = $file->getSize(); $uuid = Uuid::v4()->toRfc4122(); $fileName = $uuid.'.'.$extension; if (!is_dir($this->uploadDir)) { mkdir($this->uploadDir, 0o775, true); } $file->move($this->uploadDir, $fileName); $document = new TaskDocument(); $document->setTask($task); $document->setOriginalName($originalName); $document->setFileName($fileName); $document->setMimeType($mimeType); $document->setSize($fileSize); $document->setCreatedAt(new DateTimeImmutable()); $document->setUploadedBy($this->security->getUser()); $this->entityManager->persist($document); $this->entityManager->flush(); return $document; } }