setRepository->getAll() as $set) { $sets[] = $this->buildSetPayload($set); } return new JsonResponse([ 'sets' => $sets, ], 200); } public function create(Request $request): JsonResponse { $iconImage = $this->uploadedFileInput($request, 'iconImage'); try { $set = $this->createSetWithRoot->execute( new CreateSetWithRootRequest( name: $this->stringInput($request, 'name'), description: $this->stringInput($request, 'description'), iconImageContents: $iconImage['contents'], iconImageOriginalName: $iconImage['originalName'], iconImageMimeType: $iconImage['mimeType'], iconImageSizeBytes: $iconImage['sizeBytes'], ) ); } catch (BadRequestException $exception) { return new JsonResponse([ 'error' => $exception->getMessage(), ], 400); } return new JsonResponse([ 'set' => $this->buildSetPayload($set), ], 201); } public function update(Request $request, ?int $id): JsonResponse { $iconImage = $this->uploadedFileInput($request, 'iconImage'); try { $set = $this->updateSet->execute( new UpdateSetRequest( id: $id, name: $this->stringInput($request, 'name'), description: $this->stringInput($request, 'description'), 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([ 'set' => $this->buildSetPayload($set), ], 200); } public function delete(?int $id): JsonResponse { try { $this->deleteSet->execute(new DeleteSetRequest(id: $id)); } catch (BadRequestException $exception) { return new JsonResponse([ 'error' => $exception->getMessage(), ], 400); } catch (NotFoundException $exception) { return new JsonResponse([ 'error' => $exception->getMessage(), ], 404); } return new JsonResponse(null, 204); } /** * @return array{ * id: int, * name: string, * description: string, * iconImageUrl: string, * rootElementId: int|null * } */ private function buildSetPayload(DomainSet $set): array { $rootElement = $this->elementRepository->findRootBySet($set); return [ 'id' => $set->getId(), 'name' => $set->getName(), 'description' => $set->getDescription(), 'iconImageUrl' => $this->storageUrl( $set->getIconImageUrl(), 'set-icons/', ), 'rootElementId' => $rootElement?->getId(), ]; } private function stringInput(Request $request, string $key): ?string { if (! $request->exists($key)) { return null; } $value = $request->input($key); if ($value === null) { return ''; } 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(), ]; } private function storageUrl(string $path, string $folderPrefix): string { if (str_starts_with($path, $folderPrefix)) { return $this->filesystem->url($path); } return $path; } }