<?php namespace App\Controller; use App\Entity\Capsule; use App\Entity\PendingEditorInvitation; use App\Entity\User; use App\Form\CapsuleEditorsFormType; use App\Form\RemoveEditorFormType; use App\Repository\CapsuleRepository; use App\Repository\PendingEditorInvitationRepository; use App\Repository\UserRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bridge\Twig\Mime\TemplatedEmail; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use Symfony\Component\Mailer\MailerInterface; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Contracts\Translation\TranslatorInterface; class CapsuleEditorController extends AbstractController { public function __construct( private MailerInterface $mailer, private TranslatorInterface $translator, private PendingEditorInvitationRepository $capsule_pending_editor_invitation_repository, private EntityManagerInterface $entity_manager, private UrlGeneratorInterface $urlGenerator, private CapsuleRepository $capsule_repository, private UserRepository $user_repository ) { } #[Route('/{_locale<%app.supported_locales%>}/capsule/{capsule_id}/editors', name:'edit_capsule_editors')] public function editCapsuleEditors( Request $request, int $capsule_id ): Response { $current_user = $this->getUser(); if (! $current_user instanceof User) { return $this->redirectToRoute('app_logout'); } $capsule = $this->capsule_repository->find($capsule_id); if (! $capsule) { throw $this->createNotFoundException( 'No capsule found for id ' . $capsule_id ); } $current_capsule_editors_users = $capsule->getEditors()->toArray(); if (! $capsule->getEditors()->contains($current_user)) { $this->addFlash( 'warning', $this->translator->trans( 'editors.user_not_editor_error', [ 'capsule_name' => $capsule->getName() ] ) ); return $this->redirectToRoute('capsule_list'); } $form = $this->createForm(CapsuleEditorsFormType::class); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $editor_email = $form->get('email')->getData(); $user_associated_with_email_address = $this->user_repository ->findOneBy(['email' => $editor_email]); if (! $user_associated_with_email_address instanceof User) { $this->addPendingEditor($editor_email, $capsule, $current_user); } else { $this->addEditor( $editor_email, $capsule, $current_user, $user_associated_with_email_address, $current_capsule_editors_users ); } return $this->redirectToRoute('edit_capsule_editors', [ 'capsule_id' => $capsule_id ]); } $pending_editors = $this->capsule_pending_editor_invitation_repository->findBy(['capsule_id' => $capsule_id]); return $this->renderForm('capsule/editors/list_editors.html.twig', [ 'userPermissionsCapsuleForm' => $form, 'capsule' => $capsule, 'editors' => $current_capsule_editors_users, 'pending_editors' => $pending_editors, 'current_user' => $current_user ]); } #[Route( '/{_locale<%app.supported_locales%>}/capsule/{capsule_id}/editors/{editor_id}/remove', name:'remove_editor' )] public function removeEditor( int $capsule_id, int $editor_id, Request $request ): Response { $form = $this->createForm(RemoveEditorFormType::class); $form->handleRequest($request); $capsule = $this->capsule_repository->findOneBy(['id' => $capsule_id]); if (! $capsule instanceof Capsule) { throw new \Exception('The retrieved capsule is not an instance of Capsule.'); } $editor = $this->user_repository->findOneBy(['id' => $editor_id]); if (! $editor instanceof User) { throw new \Exception('The retrieved user is not an instance of User.'); } $current_user = $this->getUser(); if (! $current_user instanceof User) { return $this->redirectToRoute('app_logout'); } if ($editor_id === $capsule->getCreationAuthor()->getId()) { $this->addFlash( 'warning', $this->translator->trans( 'editors.remove.editor.error', [ 'editor_email' => $editor->getEmail(), 'capsule_name' => $capsule->getName() ] ) ); return $this->redirectToRoute('edit_capsule_editors', [ 'capsule_id' => $capsule->getId() ]); } if ($form->isSubmitted() && $form->isValid()) { $capsule->removeEditor($editor); $this->entity_manager->flush(); $this->addFlash( 'success', $this->translator->trans( 'editors.remove.editor.success', [ 'editor_email' => $editor->getEmail(), 'capsule_name' => $capsule->getName() ] ) ); return $this->redirectToRoute('edit_capsule_editors', [ 'capsule_id' => $capsule->getId() ]); } return $this->renderForm('capsule/editors/remove_editor.html.twig', [ 'removeEditorForm' => $form, 'editor_email' => $editor->getEmail(), 'capsule_id' => $capsule_id ]); } #[Route( '/{_locale<%app.supported_locales%>}/capsule/{capsule_id}/pending_editor/{pending_editor_invitation_id}/remove', name:'remove_pending_editor' )] public function removePendingEditor( int $pending_editor_invitation_id, int $capsule_id, Request $request ): Response { $capsule = $this->capsule_repository->findOneBy(['id' => $capsule_id]); if (! $capsule instanceof Capsule) { throw new \Exception('The retrieved capsule is not an instance of Capsule.'); } $pending_editor_invitation = $this->capsule_pending_editor_invitation_repository ->findOneBy(['id' => $pending_editor_invitation_id]); $form = $this->createForm(RemoveEditorFormType::class); $form->handleRequest($request); if (! $pending_editor_invitation instanceof PendingEditorInvitation) { $this->addFlash( 'warning', $this->translator->trans( 'editors.remove.pending_editor.error', [ 'capsule_name' => $capsule->getName() ] ) ); return $this->redirectToRoute('edit_capsule_editors', [ 'capsule_id' => $capsule_id ]); } if ($form->isSubmitted() && $form->isValid()) { $this->entity_manager->remove($pending_editor_invitation); $this->entity_manager->flush(); $this->addFlash( 'success', $this->translator->trans( 'editors.remove.pending_editor.success', [ 'pending_editor_email' => $pending_editor_invitation->getEmail(), 'capsule_name' => $capsule->getName() ] ) ); return $this->redirectToRoute('edit_capsule_editors', [ 'capsule_id' => $capsule_id ]); } return $this->renderForm('capsule/editors/remove_pending_editor.html.twig', [ 'removeEditorForm' => $form, 'editor_email' => $pending_editor_invitation->getEmail(), 'capsule_id' => $capsule_id ]); } private function addPendingEditor(string $editor_email, Capsule $capsule, User $current_user): void { $pending_editors_emails = $this->capsule_pending_editor_invitation_repository ->getPendingEditorsEmails($capsule->getId()); if (in_array($editor_email, $pending_editors_emails)) { $this->addFlash( 'warning', $this->translator->trans( 'editors.add.pending_editor.already_added', [ 'user_email' => $editor_email ] ) ); return; } $pending_editor_invitation = new PendingEditorInvitation(); $pending_editor_invitation->setCapsuleId($capsule->getId()); $pending_editor_invitation->setEmail($editor_email); $this->entity_manager->persist($pending_editor_invitation); $this->entity_manager->flush(); $email = (new TemplatedEmail()) ->to($editor_email) ->subject($this->translator->trans('editors.add.pending_editor.email.title')) ->htmlTemplate('capsule/editors/email_pending_editor.html.twig') ->context([ 'user' => $current_user, 'capsule' => $capsule ]); $this->mailer->send($email); $this->addFlash( 'success', $this->translator->trans( 'editors.add.pending_editor.success', [ 'user_email' => $editor_email ] ) ); } /** * @param array<User> $current_capsule_editors_users * @throws TransportExceptionInterface */ private function addEditor( string $editor_email, Capsule $capsule, User $current_user, User $user_associated_with_email_address, array $current_capsule_editors_users ): void { if (in_array($user_associated_with_email_address, $current_capsule_editors_users)) { $this->addFlash( 'warning', $this->translator->trans( 'editors.add.user.already_added', [ 'user_email' => $editor_email ] ) ); $link = null; } else { $link = $this->urlGenerator->generate( 'edit_capsule', [ 'path' => $capsule->getLinkPath() ], UrlGeneratorInterface::ABSOLUTE_URL ); $capsule->addEditor($user_associated_with_email_address); $this->entity_manager->persist($capsule); $this->entity_manager->flush(); $this->addFlash( 'success', $this->translator->trans( 'editors.add.user.success', [ 'capsule_name' => $capsule->getName(), 'user_email' => $editor_email ] ) ); } $email = (new TemplatedEmail()) ->to($editor_email) ->subject($this->translator->trans('editors.add.user.email.title')) ->htmlTemplate('capsule/editors/email_editor.html.twig') ->context([ 'user' => $current_user, 'capsule' => $capsule, 'capsule_edit_link' => $link ]); $this->mailer->send($email); } }