Manage redirects, missing URLs, repositories and settings through the API

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-30 19:51:00 +02:00
parent 4c65604f04
commit 8d0f2e3639
20 changed files with 1581 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
<?php
declare(strict_types=1);
namespace App\Http\Controllers\Api\V1;
use App\Enums\MissingUrlStatus;
use App\Http\Controllers\Controller;
use App\Http\Requests\Api\V1\MissingUrlRedirectRequest;
use App\Http\Resources\MissingUrlResource;
use App\Http\Resources\RedirectResource;
use App\Models\MissingUrl;
use App\Models\Redirect;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Validation\Rule;
/**
* Addresses the public site was asked for and could not find, reported by the
* frontend. What can be done with one is what the panel does: ignore it, or
* give it a destination.
*/
class MissingUrlController extends Controller
{
/**
* Filters: status (pending by default), locale, search (path).
*/
public function index(Request $request): AnonymousResourceCollection
{
$this->authorize('viewAny', MissingUrl::class);
$missing = MissingUrl::query()
->where('status', $request->string('status', MissingUrlStatus::Pending->value))
->when($request->filled('locale'), fn ($q) => $q->where('locale', $request->string('locale')))
->when($request->filled('search'), fn ($q) => $q->where('path', 'like', '%'.$request->string('search').'%'))
->orderByDesc('hits')
->orderByDesc('last_seen_at')
->paginate(perPage: min($request->integer('per_page', 25), 100))
->withQueryString();
return MissingUrlResource::collection($missing);
}
public function show(MissingUrl $missingUrl): MissingUrlResource
{
$this->authorize('view', $missingUrl);
return MissingUrlResource::make($missingUrl);
}
/**
* Only between pending and ignored: `resolved` is what writing a redirect
* makes it, and claiming it without one would be a lie the next sighting
* undoes anyway.
*/
public function update(Request $request, MissingUrl $missingUrl): MissingUrlResource
{
$this->authorize('update', $missingUrl);
$data = $request->validate([
'status' => ['required', Rule::in([MissingUrlStatus::Pending->value, MissingUrlStatus::Ignored->value])],
]);
$missingUrl->update($data);
return MissingUrlResource::make($missingUrl);
}
public function destroy(MissingUrl $missingUrl): JsonResponse
{
$this->authorize('delete', $missingUrl);
$missingUrl->delete();
return response()->json(status: 204);
}
/**
* Give the address a destination. The report is marked resolved by the
* redirect being created, as from anywhere else.
*/
public function redirect(MissingUrlRedirectRequest $request, MissingUrl $missingUrl): JsonResponse
{
$this->authorize('redirect', $missingUrl);
$redirect = Redirect::create([
'from' => $missingUrl->path,
'is_enabled' => true,
...$request->validated(),
])->refresh();
return RedirectResource::make($redirect)->response()->setStatusCode(201);
}
}