getElement->execute( new GetElementRequest(id: $id) ); } catch (BadRequestException $exception) { return new JsonResponse([ 'error' => $exception->getMessage(), ], 400); } catch (NotFoundException $exception) { return new JsonResponse([ 'error' => $exception->getMessage(), ], 404); } $element = $result->getElement(); $childElements = []; foreach ($result->getChildElements() as $childElement) { $childElements[] = [ 'id' => $childElement->getId(), 'title' => $childElement->getTitle(), 'description' => $childElement->getDescription(), ]; } return new JsonResponse([ 'childElements' => $childElements, 'element' => $this->buildElementPayload($element), ], 200); } public function update(?int $id, Request $request): JsonResponse { try { $element = $this->updateElement->execute( new UpdateElementRequest( id: $id, title: $this->stringInput($request, 'title'), description: $this->stringInput($request, 'description'), iconImageUrl: $this->stringInput( $request, 'iconImageUrl', ), richText: $this->stringInput($request, 'richText'), pdfPath: $this->stringInput($request, 'pdfPath'), youtubeUrl: $this->stringInput($request, 'youtubeUrl'), ) ); } catch (BadRequestException $exception) { return new JsonResponse([ 'error' => $exception->getMessage(), ], 400); } catch (NotFoundException $exception) { return new JsonResponse([ 'error' => $exception->getMessage(), ], 404); } return new JsonResponse([ 'element' => $this->buildElementPayload($element), ], 200); } public function uploadIconImage(?int $id, Request $request): JsonResponse { $iconImage = $this->uploadedFileInput($request, 'iconImage'); try { $element = $this->updateElementIconImage->execute( new UpdateElementIconImageRequest( id: $id, iconImageContents: $iconImage['contents'], iconImageOriginalName: $iconImage['originalName'], iconImageMimeType: $iconImage['mimeType'], iconImageSizeBytes: $iconImage['sizeBytes'], ) ); } catch (BadRequestException $exception) { return new JsonResponse([ 'error' => $exception->getMessage(), ], 400); } catch (NotFoundException $exception) { return new JsonResponse([ 'error' => $exception->getMessage(), ], 404); } return new JsonResponse([ 'element' => $this->buildElementPayload($element), ], 200); } private function stringInput(Request $request, string $key): ?string { $value = $request->input($key); if (! is_string($value)) { return null; } return $value; } /** * @return array{ * contents: string|null, * originalName: string|null, * mimeType: string|null, * sizeBytes: int|null * } */ private function uploadedFileInput(Request $request, string $key): array { $emptyFileInput = [ 'contents' => null, 'originalName' => null, 'mimeType' => null, 'sizeBytes' => null, ]; if (! $request->hasFile($key)) { return $emptyFileInput; } $file = $request->file($key); if (! $file instanceof UploadedFile) { return $emptyFileInput; } $realPath = $file->getRealPath(); if ($realPath === false) { return $emptyFileInput; } return [ 'contents' => (string) file_get_contents($realPath), 'originalName' => $file->getClientOriginalName(), 'mimeType' => (string) $file->getMimeType(), 'sizeBytes' => (int) $file->getSize(), ]; } /** * @return array{ * id: int, * title: string, * description: string, * iconImageUrl: string|null, * richText: string, * pdfPath: string|null, * youtubeUrl: string|null, * } */ private function buildElementPayload(Element $element): array { return [ 'id' => $element->getId(), 'title' => $element->getTitle(), 'description' => $element->getDescription(), 'iconImageUrl' => $this->storageUrl( $element->getIconImageUrl(), 'element-icons/', ), 'richText' => $element->getRichText(), 'pdfPath' => $element->getPdfPath(), 'youtubeUrl' => $element->getYoutubeUrl(), ]; } private function storageUrl(?string $path, string $folderPrefix): ?string { if ($path === null) { return null; } if (str_starts_with($path, $folderPrefix)) { return $this->fileUploader->url($path); } return $path; } }