Laravel 13 + Filament 5 admin panel and REST API for a non-profit developer collective, backed by the Pireon OAuth identity server. The public site is a separate, server-rendered application consuming /api/public/v1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
75 lines
2.4 KiB
PHP
75 lines
2.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Api\V1;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\Api\V1\CategoryRequest;
|
|
use App\Http\Resources\CategoryResource;
|
|
use App\Models\Category;
|
|
use App\Support\TranslatablePayload;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
|
|
|
class CategoryController extends Controller
|
|
{
|
|
public function index(Request $request): AnonymousResourceCollection
|
|
{
|
|
$this->authorize('viewAny', Category::class);
|
|
|
|
$locale = app()->getLocale();
|
|
|
|
$categories = Category::query()
|
|
->withCount('pages')
|
|
->when($request->has('is_visible'), fn ($q) => $q->where('is_visible', $request->boolean('is_visible')))
|
|
->when($request->filled('search'), fn ($q) => $q->where("name->{$locale}", 'like', '%'.$request->string('search').'%'))
|
|
->orderBy('position')
|
|
->orderBy("name->{$locale}")
|
|
->paginate(perPage: min($request->integer('per_page', 25), 100))
|
|
->withQueryString();
|
|
|
|
return CategoryResource::collection($categories);
|
|
}
|
|
|
|
public function store(CategoryRequest $request): JsonResponse
|
|
{
|
|
$this->authorize('create', Category::class);
|
|
|
|
$category = new Category;
|
|
$category->fill(TranslatablePayload::merge($category, $request->validated(), $category->translatable));
|
|
$category->save();
|
|
|
|
return CategoryResource::make($category)->response()->setStatusCode(201);
|
|
}
|
|
|
|
public function show(Category $category): CategoryResource
|
|
{
|
|
$this->authorize('view', $category);
|
|
|
|
return CategoryResource::make($category->loadCount('pages'));
|
|
}
|
|
|
|
public function update(CategoryRequest $request, Category $category): CategoryResource
|
|
{
|
|
$this->authorize('update', $category);
|
|
|
|
$category->fill(TranslatablePayload::merge($category, $request->validated(), $category->translatable));
|
|
$category->save();
|
|
|
|
return CategoryResource::make($category->loadCount('pages'));
|
|
}
|
|
|
|
public function destroy(Category $category): JsonResponse
|
|
{
|
|
// CategoryPolicy refuses while the category still holds pages, so this
|
|
// answers 403 rather than orphaning content.
|
|
$this->authorize('delete', $category);
|
|
|
|
$category->delete();
|
|
|
|
return response()->json(status: 204);
|
|
}
|
|
}
|