$this->buildSetPayloads( $this->setRepository->getAll(), ), ], 200); } public function reorder(Request $request): JsonResponse { try { $sets = $this->reorderSets->execute(new ReorderSetsRequest( setIds: $this->intArrayInput($request, 'setIds'), )); } catch (BadRequestException $exception) { return new JsonResponse([ 'error' => $exception->getMessage(), ], 400); } return new JsonResponse([ 'sets' => $this->buildSetPayloads($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(), ]; } /** * @param DomainSet[] $sets * @return array */ private function buildSetPayloads(array $sets): array { $setPayloads = []; foreach ($sets as $set) { $setPayloads[] = $this->buildSetPayload($set); } return $setPayloads; } /** * @return int[]|null */ private function intArrayInput(Request $request, string $key): ?array { if (! $request->exists($key)) { return null; } $value = $request->input($key); if (! is_array($value)) { return null; } $integerValues = []; foreach ($value as $item) { if (is_int($item)) { $integerValues[] = $item; continue; } if (is_string($item) && ctype_digit($item)) { $integerValues[] = (int) $item; continue; } return null; } return $integerValues; } 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; } }