feat: controller liens avec validation et export json
This commit is contained in:
1 parent
a2324d2307
commit
a7003886da
1 file changed
+185
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user