service = $service; } /** * GET /api/v1/browse * Public browse feed powered by authoritative artworks table. */ public function index(Request $request) { $perPage = $this->resolvePerPage($request); $sort = (string) $request->get('sort', 'latest'); $paginator = $this->service->browsePublicArtworks($perPage, $sort); $paginator->appends([ 'limit' => $perPage, 'sort' => $sort, ]); return ArtworkListResource::collection($paginator); } /** * GET /api/v1/browse/{content_type} * Browse by content type slug. */ public function byContentType(Request $request, string $contentTypeSlug) { $perPage = $this->resolvePerPage($request); $sort = (string) $request->get('sort', 'latest'); try { $paginator = $this->service->getArtworksByContentType($contentTypeSlug, $perPage, $sort); } catch (ModelNotFoundException $e) { abort(404); } $paginator->appends([ 'limit' => $perPage, 'sort' => $sort, ]); if ($paginator->count() === 0) { return response()->json(['message' => 'Gone'], 410); } return ArtworkListResource::collection($paginator); } /** * GET /api/v1/browse/{content_type}/{category_path} * Browse by content type + category path (slug segments). */ public function byCategoryPath(Request $request, string $contentTypeSlug, string $categoryPath) { $perPage = $this->resolvePerPage($request); $sort = (string) $request->get('sort', 'latest'); $slugs = array_merge([ strtolower($contentTypeSlug), ], array_values(array_filter(explode('/', trim($categoryPath, '/'))))); try { $paginator = $this->service->getArtworksByCategoryPath($slugs, $perPage, $sort); } catch (ModelNotFoundException $e) { abort(404); } $paginator->appends([ 'limit' => $perPage, 'sort' => $sort, ]); if ($paginator->count() === 0) { return response()->json(['message' => 'Gone'], 410); } return ArtworkListResource::collection($paginator); } private function resolvePerPage(Request $request): int { $limit = (int) $request->query('limit', 0); $perPage = (int) $request->query('per_page', 0); $value = $limit > 0 ? $limit : ($perPage > 0 ? $perPage : 24); return min(max($value, 1), 100); } }