$uriVariables * @param array $context */ public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed { $request = $this->requestStack->getCurrentRequest(); if (null === $request) { throw new BadRequestHttpException('No request available.'); } $contentType = $request->headers->get('Content-Type', ''); // Multipart/form-data → file upload if (str_contains($contentType, 'multipart/form-data')) { return $this->handleMultipartUpload($operation, $uriVariables, $context, $request); } // Fallback to default processor for legacy JSON/Base64 requests if (!$data instanceof Document) { return $this->decorated->process($data, $operation, $uriVariables, $context); } return $this->decorated->process($data, $operation, $uriVariables, $context); } private function handleMultipartUpload( Operation $operation, array $uriVariables, array $context, Request $request, ): Document { /** @var null|UploadedFile $file */ $file = $request->files->get('file'); if (null === $file || !$file->isValid()) { throw new BadRequestHttpException('A valid file is required in the "file" field.'); } $document = new Document(); // Metadata from form fields $name = $request->request->get('name', $file->getClientOriginalName()); $filename = $file->getClientOriginalName(); $mimeType = $file->getMimeType() ?: $request->request->get('mimeType', 'application/octet-stream'); $size = $file->getSize(); $document->setName($name); $document->setFilename($filename); $document->setMimeType($mimeType); $document->setSize((int) $size); // Handle entity relations from form fields $this->setRelationsFromRequest($document, $request); // Generate CUID early so we can use it for the filename on disk $documentId = 'cl'.bin2hex(random_bytes(12)); $document->setId($documentId); // Store file on disk $extension = $this->storageService->extensionFromFilename($filename); $relativePath = $this->storageService->storeFromPath( $file->getPathname(), $documentId, $extension, ); $document->setPath($relativePath); // Persist via decorated processor (triggers prePersist for timestamps) return $this->decorated->process($document, $operation, $uriVariables, $context); } private function setRelationsFromRequest(Document $document, Request $request): void { $relationMap = [ 'machineId' => 'Machine', 'composantId' => 'Composant', 'pieceId' => 'Piece', 'productId' => 'Product', 'siteId' => 'Site', ]; foreach ($relationMap as $field => $entityName) { $value = $request->request->get($field); if (!$value) { continue; } // Accept both raw ID and IRI format $id = $value; if (str_contains($value, '/')) { $parts = explode('/', rtrim($value, '/')); $id = end($parts); } $entityClass = 'App\Entity\\'.$entityName; $entity = $this->em->getReference($entityClass, $id); $setter = 'set'.$entityName; $document->{$setter}($entity); } } }