parseLimit($request); $page = $this->parsePage($request); $sortField = $this->parseSortField($request); $direction = $this->parseDirection($request); $cursor = $this->parseCursor($request); // Create pagination request if ($cursor !== null) { // Cursor-based pagination $paginationRequest = $this->paginationService->cursorRequest( limit: $limit, cursorValue: $cursor, sortField: $sortField, direction: $direction ); } else { // Offset-based pagination $offset = ($page - 1) * $limit; $paginationRequest = $this->paginationService->offsetRequest( limit: $limit, offset: $offset, sortField: $sortField, direction: $direction ); } // Get paginated results $paginator = $this->paginationService->forEntity(Image::class); $paginationResponse = $paginator->paginate($paginationRequest); // Transform images to API format $transformedData = array_map([$this, 'transformImage'], $paginationResponse->data); // Create response with transformed data $responseData = [ 'data' => $transformedData, 'meta' => $paginationResponse->meta->toArray(), ]; return new JsonResponse($responseData, Status::OK); } /** * Parse limit parameter with validation */ private function parseLimit(HttpRequest $request): int { $limit = $request->query->getInt('limit', 20); // Validate limit bounds if ($limit < 1) { $limit = 1; } elseif ($limit > 100) { $limit = 100; } return $limit; } /** * Parse page parameter with validation */ private function parsePage(HttpRequest $request): int { $page = $request->query->getInt('page', 1); return max(1, $page); } /** * Parse sort field parameter */ private function parseSortField(HttpRequest $request): ?string { $sortField = $request->query->getString('sort'); // Allow only specific fields for security $allowedFields = ['ulid', 'filename', 'width', 'height', 'fileSize']; if ($sortField && in_array($sortField, $allowedFields)) { return $sortField; } // Default sort by creation time (via ULID) return 'ulid'; } /** * Parse direction parameter */ private function parseDirection(HttpRequest $request): string { $direction = $request->query->getString('direction', 'desc'); return in_array($direction, ['asc', 'desc']) ? $direction : 'desc'; } /** * Parse cursor parameter */ private function parseCursor(HttpRequest $request): ?string { return $request->query->getString('cursor'); } /** * Transform Image entity to API representation */ private function transformImage(Image $image): array { return [ 'ulid' => $image->getUlidString(), 'filename' => $image->filename, 'original_filename' => $image->originalFilename, 'url' => '/images/' . $image->filename, 'thumbnail_url' => '/images/' . str_replace('_original.', '_thumbnail.', $image->filename), 'alt_text' => $image->altText, 'dimensions' => [ 'width' => $image->width, 'height' => $image->height, 'aspect_ratio' => $image->getAspectRatio(), 'orientation' => $image->getDimensions()->getOrientation()->value, ], 'mime_type' => $image->mimeType->value, 'file_size' => [ 'bytes' => $image->fileSize->toBytes(), 'human_readable' => $image->getHumanReadableFileSize(), ], 'hash' => $image->hash->toString(), 'is_image' => $image->isImageFile(), 'created_at' => $image->ulid->getDateTime()->format('c'), 'variants' => array_map(fn ($variant) => [ 'type' => $variant->variantType, 'width' => $variant->width, 'height' => $variant->height, 'path' => $variant->path, 'url' => '/images/' . $variant->filename, ], $image->variants ?? []), ]; } }