complete homemade, terrible, CRUD for entities

This commit is contained in:
dece 2024-02-25 20:19:03 +01:00
parent d5609f63d3
commit be579da23c
6 changed files with 92 additions and 79 deletions

View file

@ -2,6 +2,7 @@
namespace App\Controller;
use App\Constants;
use App\Entity\Episode;
use App\Form\EpisodeType;
use App\Repository\EpisodeRepository;
@ -20,25 +21,25 @@ use Symfony\Component\String\Slugger\SluggerInterface;
#[Route('/manage/episodes')]
class EpisodeController extends AbstractController
{
public function __construct(protected LoggerInterface $logger)
{}
public function __construct(
protected EpisodeRepository $episodeRepo,
protected PodcastRepository $podcastRepo,
protected EntityManagerInterface $em,
protected LoggerInterface $logger,
protected SluggerInterface $slugger
) {
}
#[Route('/', name: 'app_episode_index', methods: ['GET'])]
public function index(EpisodeRepository $episodeRepository): Response
public function index(): Response
{
return $this->render('episode/index.html.twig', [
'episodes' => $episodeRepository->findAll(),
'episodes' => $this->episodeRepo->findAll(),
]);
}
#[Route('/new', name: 'app_episode_new', methods: ['GET', 'POST'])]
public function new(
Request $request,
EntityManagerInterface $entityManager,
PodcastRepository $podcastRepository,
SluggerInterface $slugger,
): Response
{
public function new(Request $request): Response {
$queryPodcastId = $request->query->getInt('podcast', 0);
$episode = new Episode();
@ -53,28 +54,29 @@ class EpisodeController extends AbstractController
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->logger->info("FLUMZO " . json_encode($form->getData()));
// Check that the user is the owner of the podcast this episode should belong to.
$podcastId = $form->get('podcast')->getData();
$podcast = $podcastRepository->find($podcastId ?? $queryPodcastId);
$podcast = $this->podcastRepo->find($podcastId ?? $queryPodcastId);
if (
$podcast === null
|| $podcast->getOwner()->getId() !== $this->getUser()->getId()
null === $podcast
|| $podcast->getOwner()?->getId() !== $this->getUser()?->getId()
) {
$form->get('podcast')->addError(new FormError('Invalid podcast.'));
return $this->render('episode/new.html.twig', ['episode' => $episode, 'form' => $form]);
}
$episode->setPodcast($podcast);
// Ensure the uploaded audio file is saved properly.
if (!$this->handleAudioChange($form, $episode, $slugger)) {
$form->get('logo')->addError(new FormError('Could not upload audio.'));
if (!$this->handleAudioChange($form, $episode)) {
$form->get('audio')->addError(new FormError('Could not upload audio.'));
return $this->render('episode/new.html.twig', ['episode' => $episode, 'form' => $form]);
}
$entityManager->persist($episode);
$entityManager->flush();
$this->em->persist($episode);
$this->em->flush();
return $this->redirectToRoute('app_episode_index', [], Response::HTTP_SEE_OTHER);
}
@ -89,11 +91,12 @@ class EpisodeController extends AbstractController
{
return $this->render('episode/show.html.twig', [
'episode' => $episode,
'files_path' => Constants::FILES_BASE_PATH
]);
}
#[Route('/{id}/edit', name: 'app_episode_edit', methods: ['GET', 'POST'])]
public function edit(Request $request, Episode $episode, EntityManagerInterface $entityManager): Response
public function edit(Episode $episode, Request $request): Response
{
$form = $this->createForm(
EpisodeType::class,
@ -103,7 +106,17 @@ class EpisodeController extends AbstractController
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->flush();
$data = $form->getData();
$this->logger->notice(json_encode($data));
// Ensure the uploaded audio file is saved properly.
if (!$this->handleAudioChange($form, $episode)) {
$form->get('audio')->addError(new FormError('Could not upload audio.'));
return $this->render('episode/edit.html.twig', ['episode' => $episode, 'form' => $form]);
}
$this->em->persist($episode);
$this->em->flush();
return $this->redirectToRoute('app_episode_index', [], Response::HTTP_SEE_OTHER);
}
@ -115,31 +128,32 @@ class EpisodeController extends AbstractController
}
#[Route('/{id}', name: 'app_episode_delete', methods: ['POST'])]
public function delete(Request $request, Episode $episode, EntityManagerInterface $entityManager): Response
public function delete(Episode $episode, Request $request): Response
{
if ($this->isCsrfTokenValid('delete'.$episode->getId(), $request->request->get('_token'))) {
$entityManager->remove($episode);
$entityManager->flush();
if ($this->isCsrfTokenValid('delete'.$episode->getId(), strval($request->request->get('_token')))) {
$this->em->remove($episode);
$this->em->flush();
}
return $this->redirectToRoute('app_episode_index', [], Response::HTTP_SEE_OTHER);
}
protected function handleAudioChange(
FormInterface $form,
Episode $episode,
SluggerInterface $slugger
): bool
protected function handleAudioChange(FormInterface $form, Episode $episode): bool
{
$audioFile = $form->get('audio')->getData();
if ($audioFile) {
$originalFilename = pathinfo($audioFile->getClientOriginalName(), PATHINFO_FILENAME);
$safeFilename = $slugger->slug($originalFilename);
$safeFilename = $this->slugger->slug($originalFilename);
$newFilename = $safeFilename.'-'.uniqid().'.'.$audioFile->guessExtension();
try {
$audioFile->move($this->getParameter('audio_directory'), $newFilename);
} catch (FileException $e) {
} catch (FileException $exc) {
$this->logger->error(
'Failed to move audio file to audio directory: {msg}',
['msg' => $exc->getMessage()]
);
return false;
}

View file

@ -7,6 +7,7 @@ use App\Form\PodcastType;
use App\Repository\EpisodeRepository;
use App\Repository\PodcastRepository;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormInterface;
@ -19,28 +20,35 @@ use Symfony\Component\String\Slugger\SluggerInterface;
#[Route('/manage/podcasts')]
class PodcastController extends AbstractController
{
public function __construct(
protected PodcastRepository $podcastRepo,
protected EntityManagerInterface $em,
protected LoggerInterface $logger,
protected SluggerInterface $slugger
) {
}
#[Route('/', name: 'app_podcast_index', methods: ['GET'])]
public function index(PodcastRepository $podcastRepository): Response
public function index(): Response
{
$user = $this->getUser();
return $this->render('podcast/index.html.twig', [
'podcasts' => $podcastRepository->findOwnedBy($this->getUser())
'podcasts' => $user ? $this->podcastRepo->findOwnedBy($user) : [],
]);
}
#[Route('/new', name: 'app_podcast_new', methods: ['GET', 'POST'])]
public function new(
Request $request,
EntityManagerInterface $entityManager,
SluggerInterface $slugger,
): Response
public function new(Request $request): Response
{
$podcast = new Podcast();
$form = $this->createForm(PodcastType::class, $podcast);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if (!$this->handleLogoChange($form, $podcast, $slugger)) {
if (!$this->handleLogoChange($form, $podcast)) {
$form->get('logo')->addError(new FormError('Could not upload logo.'));
return $this->render('podcast/new.html.twig', [
'podcast' => $podcast,
'form' => $form,
@ -52,8 +60,9 @@ class PodcastController extends AbstractController
}
$podcast->setOwner($owner);
$entityManager->persist($podcast);
$entityManager->flush();
$this->em->persist($podcast);
$this->em->flush();
return $this->redirectToRoute('app_podcast_index', [], Response::HTTP_SEE_OTHER);
}
@ -72,21 +81,19 @@ class PodcastController extends AbstractController
}
#[Route('/{id}/edit', name: 'app_podcast_edit', methods: ['GET', 'POST'])]
public function edit(
Request $request,
Podcast $podcast,
EntityManagerInterface $entityManager,
SluggerInterface $slugger,
): Response
public function edit(Podcast $podcast, Request $request): Response
{
$form = $this->createForm(PodcastType::class, $podcast);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if (!$this->handleLogoChange($form, $podcast, $slugger)) {
$data = $form->getData();
$this->logger->notice(json_encode($data));
if (!$this->handleLogoChange($form, $podcast)) {
$form->get('logo')->addError(new FormError('Could not upload logo.'));
} else {
$entityManager->flush();
$this->em->flush();
return $this->redirectToRoute('app_podcast_index', [], Response::HTTP_SEE_OTHER);
}
}
@ -98,30 +105,22 @@ class PodcastController extends AbstractController
}
#[Route('/{id}', name: 'app_podcast_delete', methods: ['POST'])]
public function delete(
Request $request,
Podcast $podcast,
EntityManagerInterface $entityManager
): Response
public function delete(Podcast $podcast, Request $request): Response
{
if ($this->isCsrfTokenValid('delete'.$podcast->getId(), $request->request->get('_token'))) {
$entityManager->remove($podcast);
$entityManager->flush();
$this->em->remove($podcast);
$this->em->flush();
}
return $this->redirectToRoute('app_podcast_index', [], Response::HTTP_SEE_OTHER);
}
protected function handleLogoChange(
FormInterface $form,
Podcast $podcast,
SluggerInterface $slugger
): bool
protected function handleLogoChange(FormInterface $form, Podcast $podcast): bool
{
$logoFile = $form->get('logo')->getData();
if ($logoFile) {
$originalFilename = pathinfo($logoFile->getClientOriginalName(), PATHINFO_FILENAME);
$safeFilename = $slugger->slug($originalFilename);
$safeFilename = $this->slugger->slug($originalFilename);
$newFilename = $safeFilename.'-'.uniqid().'.'.$logoFile->guessExtension();
try {
@ -137,10 +136,7 @@ class PodcastController extends AbstractController
}
#[Route('/{id}/episodes', name: 'app_podcast_episodes_index', methods: ['GET'])]
public function episodes_index(
Podcast $podcast,
EpisodeRepository $episodeRepository
): Response
public function episodes_index(Podcast $podcast, EpisodeRepository $episodeRepository): Response
{
return $this->render('episode/index.html.twig', [
'podcast' => $podcast,

View file

@ -9,6 +9,7 @@ use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\File;
@ -28,7 +29,7 @@ class EpisodeType extends AbstractType
'mapped' => false,
'required' => false,
'constraints' => new File([
'maxSize' => '4m',
'maxSize' => '512m',
'mimeTypes' => ['audio/mpeg', 'audio/ogg', 'audio/opus', 'audio/aac', 'audio/flac', 'audio/webm'],
'mimeTypesMessage' => 'Please select an audio file (MP3, OGG audio, Opus, AAC, FLAC, WebM audio).',
]),
@ -54,8 +55,12 @@ class EpisodeType extends AbstractType
},
'placeholder' => false,
'disabled' => $podcastId !== null,
'empty_data' => "$podcastId",
'empty_data' => strval($podcastId),
])
->add('submit', SubmitType::class, [
'label' => 'Save',
'attr' => ['class' => 'btn btn-primary']
]);
;
}

View file

@ -3,7 +3,7 @@
namespace App\Repository;
use App\Entity\Podcast;
use App\Entity\User;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
@ -40,7 +40,8 @@ class PodcastRepository extends ServiceEntityRepository
}
}
public function findOwnedBy(User $user): array
/** @return Podcast[] */
public function findOwnedBy(UserInterface $user): array
{
return $this->findBy(['owner' => $user], ['id' => 'ASC']);
}

View file

@ -1,4 +1 @@
{{ form_start(form) }}
{{ form_widget(form) }}
<button class="btn">{{ button_label|default('Save') }}</button>
{{ form_end(form) }}
{{ form(form) }}

View file

@ -32,7 +32,7 @@
</tr>
<tr>
<th>Audio</th>
<td><mark>TODO</mark></td>
<td><audio controls src="{{ files_path }}{{ episode.audioFilename }}"></audio></td>
</tr>
<tr>
<th>Publication date</th>