feat: controller liens avec validation et export json

This commit is contained in:
devcodetools committed 2026-09-14 14:39:09 +02:00
1 parent a2324d2307
commit a7003886da
1 file changed
+185
+185
View File
@@ -0,0 +1,185 @@
<?php
declare(strict_types=1);
final class LinkController
{
public function __construct(
private readonly LinkRepository $repository,
private readonly JsonExporter $exporter,
) {
}
public function handle(string $method, string $path): void
{
if ($path === '/links' || $path === '/links/') {
match ($method) {
'GET' => $this->listLinks(),
'POST' => $this->createLink(),
default => $this->methodNotAllowed(),
};
return;
}
if (preg_match('#^/links/(\d+)$#', $path, $matches)) {
$id = (int) $matches[1];
match ($method) {
'GET' => $this->showLink($id),
'PUT' => $this->updateLink($id),
'DELETE' => $this->deleteLink($id),
default => $this->methodNotAllowed(),
};
return;
}
$this->routeNotFound();
}
private function listLinks(): void
{
$this->json($this->repository->all());
}
private function showLink(int $id): void
{
$link = $this->repository->find($id);
if ($link === null) {
$this->json(['error' => 'Lien introuvable.'], 404);
return;
}
$this->json($link);
}
private function createLink(): void
{
$data = $this->body();
$errors = $this->validate($data);
if ($errors !== []) {
$this->json(['errors' => $errors], 422);
return;
}
try {
$id = $this->repository->create(
trim($data['title']),
trim((string) ($data['description'] ?? '')),
trim($data['link_url']),
$this->nullable($data['thumbnail'] ?? null),
);
} catch (PDOException) {
$this->json(['error' => 'Cette URL de vidéo existe déjà.'], 409);
return;
}
$this->exporter->export();
$this->json($this->repository->find($id), 201);
}
private function updateLink(int $id): void
{
if ($this->repository->find($id) === null) {
$this->json(['error' => 'Lien introuvable.'], 404);
return;
}
$data = $this->body();
$errors = $this->validate($data);
if ($errors !== []) {
$this->json(['errors' => $errors], 422);
return;
}
try {
$this->repository->update(
$id,
trim($data['title']),
trim((string) ($data['description'] ?? '')),
trim($data['link_url']),
$this->nullable($data['thumbnail'] ?? null),
);
} catch (PDOException) {
$this->json(['error' => 'Cette URL de vidéo existe déjà.'], 409);
return;
}
$this->exporter->export();
$this->json($this->repository->find($id));
}
private function deleteLink(int $id): void
{
if ($this->repository->find($id) === null) {
$this->json(['error' => 'Lien introuvable.'], 404);
return;
}
$this->repository->delete($id);
$this->exporter->export();
http_response_code(204);
}
private function body(): array
{
$decoded = json_decode(file_get_contents('php://input'), true);
return is_array($decoded) ? $decoded : [];
}
private function validate(array $data): array
{
$errors = [];
$title = trim((string) ($data['title'] ?? ''));
$linkUrl = trim((string) ($data['link_url'] ?? ''));
if ($title === '') {
$errors[] = 'Le champ title est requis.';
}
if ($linkUrl === '') {
$errors[] = 'Le champ link_url est requis.';
} elseif (!filter_var($linkUrl, FILTER_VALIDATE_URL)) {
$errors[] = 'Le champ link_url doit être une URL valide.';
}
return $errors;
}
private function nullable(?string $value): ?string
{
$value = trim((string) $value);
return $value === '' ? null : $value;
}
private function json(mixed $data, int $status = 200): void
{
http_response_code($status);
header('Content-Type: application/json; charset=utf-8');
echo json_encode($data, JSON_UNESCAPED_UNICODE);
}
private function routeNotFound(): void
{
$this->json(['error' => 'Route introuvable.'], 404);
}
private function methodNotAllowed(): void
{
$this->json(['error' => 'Méthode non autorisée.'], 405);
}
}