From a1ba12a938849e573bbdb49caf3ab936f27a6147 Mon Sep 17 00:00:00 2001 From: dece Date: Sun, 1 Sep 2024 16:17:39 +0200 Subject: [PATCH] implement new episode route in the API --- composer.json | 1 + composer.lock | 2 +- config/packages/security.yaml | 3 + src/Controller/ApiController.php | 64 +++++++++++++++++++ src/Entity/Podcast.php | 3 + src/Message/DownloadRequest.php | 13 ++++ src/MessageHandler/DownloadRequestHandler.php | 40 ++++++++++++ 7 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 src/Controller/ApiController.php create mode 100644 src/Message/DownloadRequest.php create mode 100644 src/MessageHandler/DownloadRequestHandler.php diff --git a/composer.json b/composer.json index 3c88610..509452b 100644 --- a/composer.json +++ b/composer.json @@ -26,6 +26,7 @@ "symfony/http-client": "7.1.*", "symfony/intl": "7.1.*", "symfony/mailer": "7.1.*", + "symfony/messenger": "7.1.*", "symfony/mime": "7.1.*", "symfony/monolog-bundle": "^3.0", "symfony/notifier": "7.1.*", diff --git a/composer.lock b/composer.lock index 3d5e4fa..7165660 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "856f163b5bcd6da7dc6bc4b1953eb4a0", + "content-hash": "7889f2e58c2d416ef961044023f570be", "packages": [ { "name": "doctrine/annotations", diff --git a/config/packages/security.yaml b/config/packages/security.yaml index bb1c2c4..efad643 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -22,6 +22,9 @@ security: logout: path: app_logout target: app_index + http_basic: + realm: Secured Area + entry_point: form_login role_hierarchy: ROLE_ADMIN: ROLE_USER access_control: diff --git a/src/Controller/ApiController.php b/src/Controller/ApiController.php new file mode 100644 index 0000000..20b3ccc --- /dev/null +++ b/src/Controller/ApiController.php @@ -0,0 +1,64 @@ + $p->getSlug(), $podcastRepo->findAll()); + + return new JsonResponse(['slugs' => $data]); + } + + #[Route('/podcasts/{slug}', name: 'app_api_show_podcast')] + public function getPodcast(string $slug, PodcastRepository $podcastRepo, SerializerInterface $serializer): JsonResponse + { + $podcast = $podcastRepo->findOneBy(['slug' => $slug]); + if (null === $podcast) { + return new JsonResponse(['error' => 'No podcast with that slug.'], 404); + } + + return (new JsonResponse())->setContent($serializer->serialize($podcast, 'json')); + } + + #[IsGranted('ROLE_USER')] + #[Route('/podcasts/{slug}/add', name: 'app_api_add_podcast_episode', methods: ['POST'])] + public function addPodcastEpisode( + string $slug, + Request $request, + PodcastRepository $podcastRepo, + MessageBusInterface $bus, + ): JsonResponse { + $podcast = $podcastRepo->findOneBy(['slug' => $slug]); + if (null === $podcast) { + return new JsonResponse(['error' => 'No podcast with that slug.'], 404); + } + + if ($podcast->getOwner() !== $this->getUser()) { + return new JsonResponse(['error' => 'Only the podcast owner can add an episode.'], 403); + } + + $payload = $request->getPayload(); + $url = $payload->getString('url'); + if (empty($url)) { + return new JsonResponse(['error' => '"url" is a required parameter.'], 400); + } + $description = $payload->getString('description'); + $bus->dispatch(new DownloadRequest($url, $slug, $description ?: null)); + + return new JsonResponse(['message' => 'Request dispatched.']); + } +} diff --git a/src/Entity/Podcast.php b/src/Entity/Podcast.php index 2d742e5..5ac02df 100644 --- a/src/Entity/Podcast.php +++ b/src/Entity/Podcast.php @@ -9,6 +9,7 @@ use Doctrine\Common\Collections\Collection; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; +use Symfony\Component\Serializer\Attribute\Ignore; use Symfony\Component\String\Slugger\SluggerInterface; #[ORM\Entity(repositoryClass: PodcastRepository::class)] @@ -26,6 +27,7 @@ class Podcast #[ORM\Column(length: 255, unique: true)] private string $slug; + #[Ignore] #[ORM\OneToMany(mappedBy: 'podcast', targetEntity: Episode::class)] private Collection $episodes; @@ -44,6 +46,7 @@ class Podcast #[ORM\Column(length: 255, nullable: true)] private ?string $logoFilename; + #[Ignore] #[ORM\ManyToOne(inversedBy: 'podcasts')] #[ORM\JoinColumn(nullable: true)] private ?User $owner = null; diff --git a/src/Message/DownloadRequest.php b/src/Message/DownloadRequest.php new file mode 100644 index 0000000..d5dc995 --- /dev/null +++ b/src/Message/DownloadRequest.php @@ -0,0 +1,13 @@ +logger->info('Processing download.', ['url' => $request->url]); + $episode = $this->service->download($request->url); + if ($episode === false) { + $this->logger->error('Episode download failed.'); + return; + } + + $episode->setPodcast($this->podcastRepo->findOneBy(['slug' => $request->podcastSlug])); + if ($request->description) { + $episode->setDescription($request->description); + } + + $this->em->persist($episode); + $this->em->flush(); + } +}