diff --git a/assets/styles/app.scss b/assets/styles/app.scss index a35eb1cd9ccfe7afe7b691c2d6d0c2c53a2c4191..f1349795614fa1f72aa9dded9d17d5c9946574c1 100644 --- a/assets/styles/app.scss +++ b/assets/styles/app.scss @@ -151,4 +151,8 @@ button[type=submit]{ text-decoration: none; text-transform: uppercase; font-size: 18px; +} + +.remove-link { + font-size: 0.9rem; } \ No newline at end of file diff --git a/src/Controller/CapsuleEditorController.php b/src/Controller/CapsuleEditorController.php index 39af5fe0d9eed11481ea796bcce07d88f0320f19..a0d047b3ba9a96eef673f608ef438c878339adef 100644 --- a/src/Controller/CapsuleEditorController.php +++ b/src/Controller/CapsuleEditorController.php @@ -3,15 +3,13 @@ namespace App\Controller; use App\Entity\Capsule; -use App\Entity\CapsuleEditor; -use App\Entity\CapsulePendingEditor; +use App\Entity\PendingEditorInvitation; use App\Entity\User; use App\Form\CapsuleEditorsFormType; -use App\Repository\CapsulePendingEditorRepository; use App\Repository\CapsuleRepository; +use App\Repository\PendingEditorInvitationRepository; use App\Repository\UserRepository; use Doctrine\ORM\EntityManagerInterface; -use http\Env; use Symfony\Bridge\Twig\Mime\TemplatedEmail; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; @@ -26,22 +24,28 @@ class CapsuleEditorController extends AbstractController { private TranslatorInterface $translator; private MailerInterface $mailer; - private CapsulePendingEditorRepository $capsule_pending_editor_repository; + private PendingEditorInvitationRepository $capsule_pending_editor_invitation_repository; private EntityManagerInterface $entity_manager; private UrlGeneratorInterface $urlGenerator; + private CapsuleRepository $capsule_repository; + private UserRepository $user_repository; public function __construct( MailerInterface $mailer, TranslatorInterface $translator, - CapsulePendingEditorRepository $capsule_pending_editor_repository, + PendingEditorInvitationRepository $capsule_pending_editor_invitation_repository, EntityManagerInterface $entity_manager, - UrlGeneratorInterface $urlGenerator + UrlGeneratorInterface $urlGenerator, + CapsuleRepository $capsule_repository, + UserRepository $user_repository ) { $this->mailer = $mailer; $this->translator = $translator; - $this->capsule_pending_editor_repository = $capsule_pending_editor_repository; + $this->capsule_pending_editor_invitation_repository = $capsule_pending_editor_invitation_repository; $this->entity_manager = $entity_manager; $this->urlGenerator = $urlGenerator; + $this->capsule_repository = $capsule_repository; + $this->user_repository = $user_repository; } /** @@ -49,16 +53,14 @@ class CapsuleEditorController extends AbstractController */ public function editCapsuleEditors( Request $request, - int $capsule_id, - CapsuleRepository $capsule_repository, - UserRepository $user_repository + int $capsule_id ): Response { $current_user = $this->getUser(); if (! $current_user instanceof User) { return $this->redirectToRoute('app_logout'); } - $capsule = $capsule_repository->find($capsule_id); + $capsule = $this->capsule_repository->find($capsule_id); if (! $capsule) { throw $this->createNotFoundException( 'No capsule found for id ' . $capsule_id @@ -67,7 +69,6 @@ class CapsuleEditorController extends AbstractController $current_capsule_editors_users = $capsule->getEditors()->toArray(); if (! $capsule->getEditors()->contains($current_user)) { -// in_array($current_user, $current_capsule_editors_users)) { $this->addFlash( 'warning', $this->translator->trans( @@ -86,7 +87,7 @@ class CapsuleEditorController extends AbstractController if ($form->isSubmitted() && $form->isValid()) { $editor_email = $form->get('email')->getData(); - $user_associated_with_email_address = $user_repository + $user_associated_with_email_address = $this->user_repository ->findOneBy(['email' => $editor_email]); if (! $user_associated_with_email_address instanceof User) { @@ -106,19 +107,21 @@ class CapsuleEditorController extends AbstractController ]); } - $pending_editors = $this->capsule_pending_editor_repository->findBy(['capsule_id' => $capsule_id]); + $pending_editors = $this->capsule_pending_editor_invitation_repository->findBy(['capsule_id' => $capsule_id]); return $this->render('capsule/editors/list_editors.html.twig', [ 'userPermissionsCapsuleForm' => $form->createView(), - 'capsule_name' => $capsule->getName(), + 'capsule' => $capsule, 'editors' => $current_capsule_editors_users, - 'pending_editors' => $pending_editors + 'pending_editors' => $pending_editors, + 'current_user' => $current_user ]); } private function addPendingEditor(string $editor_email, Capsule $capsule, User $current_user): void { - $pending_editors_emails = $this->capsule_pending_editor_repository->getPendingEditorsEmails($capsule->getId()); + $pending_editors_emails = $this->capsule_pending_editor_invitation_repository + ->getPendingEditorsEmails($capsule->getId()); if (in_array($editor_email, $pending_editors_emails)) { $this->addFlash( @@ -133,10 +136,10 @@ class CapsuleEditorController extends AbstractController return; } - $pending_editor = new CapsulePendingEditor(); - $pending_editor->setCapsuleId($capsule->getId()); - $pending_editor->setEmail($editor_email); - $this->entity_manager->persist($pending_editor); + $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()) @@ -216,4 +219,112 @@ class CapsuleEditorController extends AbstractController ) ); } + + /** + * @Route("/capsule/{capsule_id}/editors/{editor_id}/remove", name="remove_editor") + */ + public function removeEditor( + int $capsule_id, + int $editor_id + ): 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.'); + } + + $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 === $current_user) { + $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() + ]); + } + + $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() + ]); + } + + /** + * @Route("/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 + ): 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]); + + 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 + ]); + } + + $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 + ]); + } } diff --git a/src/Entity/CapsulePendingEditor.php b/src/Entity/CapsulePendingEditor.php deleted file mode 100644 index 6dd010a96f837a03da48c7a80119c096cfd35d9e..0000000000000000000000000000000000000000 --- a/src/Entity/CapsulePendingEditor.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -namespace App\Entity; - -use App\Repository\CapsulePendingEditorRepository; -use Doctrine\ORM\Mapping as ORM; - -/** - * @ORM\Table(name="invitation_editeur_capsule") - * @ORM\Entity(repositoryClass=CapsulePendingEditorRepository::class) - */ -class CapsulePendingEditor -{ - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ - private int $id; - - /** - * @ORM\Column(type="integer") - * @ORM\Column(name="capsule_id", type="integer", nullable=false) - * @ORM\ManyToOne(targetEntity="App\Entity\Capsule", inversedBy="id") - * @ORM\JoinColumn(name="capsule_id", referencedColumnName="id") - */ - private int $capsule_id; - - /** - * @ORM\Column(name="email", type="string", length=255, nullable=false) - */ - private string $email; - - public function getId(): int - { - return $this->id; - } - - public function getCapsuleId(): int - { - return $this->capsule_id; - } - - public function setCapsuleId(int $capsule_id): self - { - $this->capsule_id = $capsule_id; - - return $this; - } - - public function getEmail(): string - { - return $this->email; - } - - public function setEmail(string $email): self - { - $this->email = $email; - - return $this; - } -} diff --git a/src/Repository/CapsulePendingEditorRepository.php b/src/Repository/CapsulePendingEditorRepository.php deleted file mode 100644 index 1504d2e8f9065246a327cfc2069f9abf50a34080..0000000000000000000000000000000000000000 --- a/src/Repository/CapsulePendingEditorRepository.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -namespace App\Repository; - -use App\Entity\CapsulePendingEditor; -use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; -use Doctrine\Persistence\ManagerRegistry; - -/** - * @method CapsulePendingEditor|null find($id, $lockMode = null, $lockVersion = null) - * @method CapsulePendingEditor|null findOneBy(array $criteria, array $orderBy = null) - * @method CapsulePendingEditor[] findAll() - * @method CapsulePendingEditor[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class CapsulePendingEditorRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, CapsulePendingEditor::class); - } - - /** - * @return array<string> - */ - public function getPendingEditorsEmails(int $capsule_id): array - { - $editors_emails_result = $this->createQueryBuilder('c') - ->select('c.email') - ->andWhere('c.capsule_id = :val') - ->setParameter('val', $capsule_id) - ->getQuery() - ->getResult() - ; - - $editors_emails = []; - - foreach ($editors_emails_result as $editor_email_result) { - $editors_emails[] = $editor_email_result['email']; - } - - return $editors_emails; - } -} diff --git a/src/Repository/PendingEditorInvitationRepository.php b/src/Repository/PendingEditorInvitationRepository.php index e891144dd03e5b31229c3707ea86c82f6bca48a8..fcfe7281c1580be5c2f8760bf65a398bbe39383b 100644 --- a/src/Repository/PendingEditorInvitationRepository.php +++ b/src/Repository/PendingEditorInvitationRepository.php @@ -19,6 +19,28 @@ class PendingEditorInvitationRepository extends ServiceEntityRepository parent::__construct($registry, PendingEditorInvitation::class); } + /** + * @return array<string> + */ + public function getPendingEditorsEmails(int $capsule_id): array + { + $editors_emails_result = $this->createQueryBuilder('c') + ->select('c.email') + ->andWhere('c.capsule_id = :val') + ->setParameter('val', $capsule_id) + ->getQuery() + ->getResult() + ; + + $editors_emails = []; + + foreach ($editors_emails_result as $editor_email_result) { + $editors_emails[] = $editor_email_result['email']; + } + + return $editors_emails; + } + /** * @return array<PendingEditorInvitation> */ diff --git a/templates/capsule/editors/list_editors.html.twig b/templates/capsule/editors/list_editors.html.twig index 31e7e6627efd798d1b19c863bac93ea06d7584cd..de7ba00e0000f6e181ec74c4773fbd4eea8f12b3 100644 --- a/templates/capsule/editors/list_editors.html.twig +++ b/templates/capsule/editors/list_editors.html.twig @@ -12,7 +12,7 @@ <div class="row w-100 gx-0"> <div class="row-title-box"> <h3 class="row-title"> - {{ 'editors.title_name'|trans({'%capsule_name%': capsule_name}) }} + {{ 'editors.title_name'|trans({'%capsule_name%': capsule.getName()}) }} </h3> </div> </div> @@ -46,6 +46,12 @@ {% for editor in editors %} <li class="text-capitalize text-secondary list-unstyled p-1"> {{ editor.getFirstName() }} {{ editor.getLastName() }} + {% if editor is not same as current_user %} + - + <a href="/capsule/{{ capsule.getId() }}/editors/{{ editor.getId() }}/remove" class="remove-link"> + {{ 'editors.remove.editor.link'|trans }} + </a> + {% endif %} </li> {% endfor %} </ul> @@ -56,6 +62,9 @@ {% for pending_editor in pending_editors %} <li class="text-secondary list-unstyled p-1"> {{ pending_editor.getEmail() }} + <a href="/capsule/{{ capsule.getId() }}/pending_editor/{{ pending_editor.getId() }}/remove" class="remove-link"> + {{ 'editors.remove.pending_editor.link'|trans }} + </a> </li> {% endfor %} </ul> diff --git a/translations/messages.en.yaml b/translations/messages.en.yaml index 7e70101b17d492bd2f9a35ec93529ef8a64f811c..1205a7bd25504c9a18efec26349f7bb3fb33cc17 100644 --- a/translations/messages.en.yaml +++ b/translations/messages.en.yaml @@ -136,3 +136,13 @@ editors: text: You have been add by %user_name% as editor of the capsule "%capsule_name%". You can now access and edit it. You will find the capsule in your capsule list. link: Go to capsule edition page + remove: + pending_editor: + link: Remove pending editor + error: The email address has already been removed from pending editors of the capsule capsule_name + success: The email address pending_editor_email has been successfully removed from pending editors of the capsule capsule_name + editor: + link: Remove editor + success: User editor_email is no longer and editor of the capsule capsule_name + error: You can't remove yourself as editor of your own capsule. + If you want to remove the capsule from your list, go to the capsule list page and click on "delete capsule" \ No newline at end of file diff --git a/translations/messages.fr.yaml b/translations/messages.fr.yaml index 3745a308579bd51b55da0808b7aa80e92e1c7468..43706c863bff25dd6acf715b1437b28c36fb9ab9 100644 --- a/translations/messages.fr.yaml +++ b/translations/messages.fr.yaml @@ -133,4 +133,14 @@ editors: title: Nouvelle capsule dans votre liste text: Vous avez été ajouté par %user_name% en tant qu'éditeur de la capsule "%capsule_name%". Vous pouvez maintenant y accéder et l'éditer. Vous la retrouverez dans la liste de vos capsules. - link: Se rendre sur la page d'édition de la capsule \ No newline at end of file + link: Se rendre sur la page d'édition de la capsule + remove: + pending_editor: + link: Supprimer l'éditeur en attente + error: L'adresse email pending_editor_email a déjà été supprimée de la liste des éditeurs en attente de la capsule capsule_name + success: L'adresse email pending_editor_email a bien été supprimée de la liste des éditeurs en attente de la capsule capsule_name + editor: + link: Supprimer l'éditeur + success: L'utilisateur editor_email ne peut plus éditer la capsule capsule_name + error: You can't remove yourself as editor of your own capsule. + If you want to remove the capsule from your list, go to the capsule list page and click on "delete capsule" \ No newline at end of file