diff --git a/src/LinkController.php b/src/LinkController.php new file mode 100644 index 0000000..d64a2fc --- /dev/null +++ b/src/LinkController.php @@ -0,0 +1,185 @@ + $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); + } +} \ No newline at end of file