implement new episode route in the API
This commit is contained in:
parent
e97bbc1bc1
commit
a1ba12a938
|
@ -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.*",
|
||||
|
|
2
composer.lock
generated
2
composer.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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:
|
||||
|
|
64
src/Controller/ApiController.php
Normal file
64
src/Controller/ApiController.php
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Message\DownloadRequest;
|
||||
use App\Repository\PodcastRepository;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Messenger\MessageBusInterface;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
|
||||
#[Route('/api')]
|
||||
class ApiController extends AbstractController
|
||||
{
|
||||
#[Route('/podcasts', name: 'app_api_list_podcasts')]
|
||||
public function listPodcasts(PodcastRepository $podcastRepo): JsonResponse
|
||||
{
|
||||
$data = array_map(fn ($p) => $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.']);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
13
src/Message/DownloadRequest.php
Normal file
13
src/Message/DownloadRequest.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace App\Message;
|
||||
|
||||
class DownloadRequest
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string $url,
|
||||
public readonly string $podcastSlug,
|
||||
public readonly ?string $description = null,
|
||||
) {
|
||||
}
|
||||
}
|
40
src/MessageHandler/DownloadRequestHandler.php
Normal file
40
src/MessageHandler/DownloadRequestHandler.php
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace App\MessageHandler;
|
||||
|
||||
use App\Message\DownloadRequest;
|
||||
use App\Repository\PodcastRepository;
|
||||
use App\Service\DownloadService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
|
||||
|
||||
#[AsMessageHandler]
|
||||
class DownloadRequestHandler
|
||||
{
|
||||
public function __construct(
|
||||
protected LoggerInterface $logger,
|
||||
protected EntityManagerInterface $em,
|
||||
protected DownloadService $service,
|
||||
protected PodcastRepository $podcastRepo,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(DownloadRequest $request): void
|
||||
{
|
||||
$this->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();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue