From bc331982d59b53894cb724d9fbf234873e482e98 Mon Sep 17 00:00:00 2001 From: matthieu Date: Sun, 15 Mar 2026 18:10:24 +0100 Subject: [PATCH] feat(bookstack) : add BookStackLink API resource with CRUD operations Co-Authored-By: Claude Sonnet 4.6 --- src/ApiResource/BookStackLink.php | 58 ++++++++++++++++++++ src/State/BookStackLinkProcessor.php | 79 ++++++++++++++++++++++++++++ src/State/BookStackLinkProvider.php | 54 +++++++++++++++++++ 3 files changed, 191 insertions(+) create mode 100644 src/ApiResource/BookStackLink.php create mode 100644 src/State/BookStackLinkProcessor.php create mode 100644 src/State/BookStackLinkProvider.php diff --git a/src/ApiResource/BookStackLink.php b/src/ApiResource/BookStackLink.php new file mode 100644 index 0000000..edceecb --- /dev/null +++ b/src/ApiResource/BookStackLink.php @@ -0,0 +1,58 @@ + ['bookstack_link:read']], + provider: BookStackLinkProvider::class, + security: "is_granted('IS_AUTHENTICATED_FULLY')", + ), + new Post( + uriTemplate: '/tasks/{taskId}/bookstack/links', + denormalizationContext: ['groups' => ['bookstack_link:write']], + normalizationContext: ['groups' => ['bookstack_link:read']], + provider: BookStackLinkProvider::class, + processor: BookStackLinkProcessor::class, + security: "is_granted('IS_AUTHENTICATED_FULLY')", + ), + new Delete( + uriTemplate: '/tasks/{taskId}/bookstack/links/{id}', + provider: BookStackLinkProvider::class, + processor: BookStackLinkProcessor::class, + security: "is_granted('IS_AUTHENTICATED_FULLY')", + ), + ], +)] +final class BookStackLink +{ + #[Groups(['bookstack_link:read'])] + public ?int $id = null; + + #[Groups(['bookstack_link:read', 'bookstack_link:write'])] + public int $bookstackId = 0; + + #[Groups(['bookstack_link:read', 'bookstack_link:write'])] + public string $bookstackType = ''; + + #[Groups(['bookstack_link:read', 'bookstack_link:write'])] + public string $title = ''; + + #[Groups(['bookstack_link:read', 'bookstack_link:write'])] + public string $url = ''; + + #[Groups(['bookstack_link:read'])] + public ?string $createdAt = null; +} diff --git a/src/State/BookStackLinkProcessor.php b/src/State/BookStackLinkProcessor.php new file mode 100644 index 0000000..81809e0 --- /dev/null +++ b/src/State/BookStackLinkProcessor.php @@ -0,0 +1,79 @@ +handleDelete($uriVariables); + } + + return $this->handleCreate($data, $uriVariables); + } + + private function handleCreate(mixed $data, array $uriVariables): BookStackLink + { + assert($data instanceof BookStackLink); + + $taskId = $uriVariables['taskId'] ?? 0; + $task = $this->em->getRepository(Task::class)->find($taskId); + + if (null === $task) { + throw new NotFoundHttpException('Task not found.'); + } + + $link = new TaskBookStackLink(); + $link->setTask($task); + $link->setBookstackId($data->bookstackId); + $link->setBookstackType($data->bookstackType); + $link->setTitle($data->title); + $link->setUrl($data->url); + + $this->em->persist($link); + $this->em->flush(); + + $result = new BookStackLink(); + $result->id = $link->getId(); + $result->bookstackId = $link->getBookstackId(); + $result->bookstackType = $link->getBookstackType(); + $result->title = $link->getTitle(); + $result->url = $link->getUrl(); + $result->createdAt = $link->getCreatedAt()->format('c'); + + return $result; + } + + private function handleDelete(array $uriVariables): null + { + $linkId = $uriVariables['id'] ?? 0; + $link = $this->linkRepository->find($linkId); + + if (null === $link) { + throw new NotFoundHttpException('Link not found.'); + } + + $this->em->remove($link); + $this->em->flush(); + + return null; + } +} diff --git a/src/State/BookStackLinkProvider.php b/src/State/BookStackLinkProvider.php new file mode 100644 index 0000000..e7a0cdf --- /dev/null +++ b/src/State/BookStackLinkProvider.php @@ -0,0 +1,54 @@ +linkRepository->find($uriVariables['id'] ?? 0); + if (null === $link) { + throw new NotFoundHttpException('Link not found.'); + } + $dto = new BookStackLink(); + $dto->id = $link->getId(); + + return $dto; + } + + $taskId = $uriVariables['taskId'] ?? 0; + $links = $this->linkRepository->findByTaskId($taskId); + + return array_map(static function (TaskBookStackLink $link): BookStackLink { + $dto = new BookStackLink(); + $dto->id = $link->getId(); + $dto->bookstackId = $link->getBookstackId(); + $dto->bookstackType = $link->getBookstackType(); + $dto->title = $link->getTitle(); + $dto->url = $link->getUrl(); + $dto->createdAt = $link->getCreatedAt()->format('c'); + + return $dto; + }, $links); + } +}