diff --git a/src/Builder/CapsuleBuilder.php b/src/Builder/CapsuleBuilder.php index ae2e0aecd1816c4ec3507ae7a71dc6003a6e8110..b219d3bcab024d36e363d369c50fbf8a9c5f7d95 100644 --- a/src/Builder/CapsuleBuilder.php +++ b/src/Builder/CapsuleBuilder.php @@ -33,6 +33,7 @@ class CapsuleBuilder { $this->capsule->setCreationAuthor($creation_author); $this->hasRequiredCreationAuthor = true; + $this->capsule->addEditor($creation_author); return $this; } diff --git a/src/Controller/CapsuleController.php b/src/Controller/CapsuleController.php index f9333fd58268332e6698c77e4c6ff48597739b8c..2a7357f09f4d110362af5f315b266d0a29cdab18 100644 --- a/src/Controller/CapsuleController.php +++ b/src/Controller/CapsuleController.php @@ -287,7 +287,6 @@ class CapsuleController extends AbstractController ->withPassword($password) ->createCapsule(); - $capsule->addEditor($current_user); $entityManager->persist($capsule); $entityManager->flush(); diff --git a/src/Controller/CapsuleEditorController.php b/src/Controller/CapsuleEditorController.php index a10dc17bbf9fc055579b29e8c9fd095b54d63eb0..370fb90060781528305e90bbc31380bfd32bc63e 100644 --- a/src/Controller/CapsuleEditorController.php +++ b/src/Controller/CapsuleEditorController.php @@ -177,10 +177,9 @@ class CapsuleEditorController extends AbstractController ); return; } - $capsule_editor = new CapsuleEditor(); - $capsule_editor->setUserId($user_associated_with_email_address->getId()); - $capsule_editor->setCapsuleId($capsule->getId()); - $this->entity_manager->persist($capsule_editor); + + $capsule->addEditor($user_associated_with_email_address); + $this->entity_manager->persist($capsule); $this->entity_manager->flush(); $email = (new TemplatedEmail()) diff --git a/src/DataFixtures/CapsuleFixtures.php b/src/DataFixtures/CapsuleFixtures.php index c95b19e2c784c20fc50b2a0ee689f7d4dba9dc05..7f5c90a41ec7a19a8a826ae6060fa9ea95a92b8d 100644 --- a/src/DataFixtures/CapsuleFixtures.php +++ b/src/DataFixtures/CapsuleFixtures.php @@ -3,6 +3,7 @@ namespace App\DataFixtures; use App\Builder\CapsuleBuilder; +use App\Entity\CapsuleEditor; use App\Entity\User; use DateTime; use Doctrine\Bundle\FixturesBundle\Fixture; @@ -66,6 +67,11 @@ class CapsuleFixtures extends Fixture implements DependentFixtureInterface } ); +// $editor = new CapsuleEditor(); +// $editor->setCapsuleId(1); +// $editor->setUserId(3); +// $manager->persist($editor); + $manager->flush(); } diff --git a/src/Entity/CapsuleEditor.php b/src/Entity/CapsuleEditor.php deleted file mode 100644 index 4834b54a2ed69cfed557797743b9dd43786053d6..0000000000000000000000000000000000000000 --- a/src/Entity/CapsuleEditor.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -namespace App\Entity; - -use App\Repository\CapsuleEditorRepository; -use Doctrine\ORM\Mapping as ORM; - -/** - * @ORM\Table(name="editeur_capsule") - * @ORM\Entity(repositoryClass=CapsuleEditorRepository::class) - */ -class CapsuleEditor -{ - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ - private int $id; - - /** - * @ORM\Column(type="integer") - */ - private int $user_id; - - /** - * @ORM\Column(type="integer") - */ - private int $capsule_id; - - public function getId(): int - { - return $this->id; - } - - public function getUserId(): int - { - return $this->user_id; - } - - public function setUserId(int $user_id): self - { - $this->user_id = $user_id; - - return $this; - } - - public function getCapsuleId(): int - { - return $this->capsule_id; - } - - public function setCapsuleId(int $capsule_id): self - { - $this->capsule_id = $capsule_id; - - return $this; - } -} diff --git a/src/Repository/CapsuleEditorRepository.php b/src/Repository/CapsuleEditorRepository.php deleted file mode 100644 index 06146b7e5fe8cf1ccf2608956dcc7cb86be39ddc..0000000000000000000000000000000000000000 --- a/src/Repository/CapsuleEditorRepository.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -namespace App\Repository; - -use App\Entity\CapsuleEditor; -use App\Entity\User; -use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; -use Doctrine\Persistence\ManagerRegistry; - -/** - * @method CapsuleEditor|null find($id, $lockMode = null, $lockVersion = null) - * @method CapsuleEditor|null findOneBy(array $criteria, array $orderBy = null) - * @method CapsuleEditor[] findAll() - * @method CapsuleEditor[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class CapsuleEditorRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, CapsuleEditor::class); - } - - /** - * @return array<int> - */ - public function findEditorIdsByCapsuleId(int $capsule_id): array - { - $editors = $this->findBy(['capsule_id' => $capsule_id]); - - $editor_ids = []; - foreach ($editors as $editor) { - $editor_ids[] = $editor->getUserId(); - } - - return $editor_ids; - } - - // /** - // * @return CapsuleEditor[] Returns an array of CapsuleEditor objects - // */ - /* - public function findByExampleField($value) - { - return $this->createQueryBuilder('c') - ->andWhere('c.exampleField = :val') - ->setParameter('val', $value) - ->orderBy('c.id', 'ASC') - ->setMaxResults(10) - ->getQuery() - ->getResult() - ; - } - */ - - /* - public function findOneBySomeField($value): ?CapsuleEditor - { - return $this->createQueryBuilder('c') - ->andWhere('c.exampleField = :val') - ->setParameter('val', $value) - ->getQuery() - ->getOneOrNullResult() - ; - } - */ -} diff --git a/templates/capsule/editors/email_editor.html.twig b/templates/capsule/editors/email_editor.html.twig index a4125b0cf15cb6d0478a9e2021557733fb5d23e3..ef64e5be89a35cd85bc57c4254381fa102bc6eaa 100644 --- a/templates/capsule/editors/email_editor.html.twig +++ b/templates/capsule/editors/email_editor.html.twig @@ -13,7 +13,7 @@ <p class="alert"> {{ 'editors.add.user.email.text'|trans({'%user_name%': user.getFullName(), '%capsule_name%': capsule.getName()}) }} <a href="{{ member_url_external }}{{ capsule.getEditionLink() }}"> - {{ editors.add.user.email.link }} + {{ 'editors.add.user.email.link'|trans }} </a> </p> diff --git a/tests/functional/CapsuleControllerTest.php b/tests/functional/CapsuleControllerTest.php index 829b95310ee6c89478e601472e62bacc31dfbe87..96c813689e90cac2d62731df13d7defe7f4e2ce2 100644 --- a/tests/functional/CapsuleControllerTest.php +++ b/tests/functional/CapsuleControllerTest.php @@ -106,8 +106,6 @@ class CapsuleControllerTest extends WebTestCase $client = static::createClient(); $client->loginUser($this->verified_user); - - $client->request('GET', '/capsule/preview/' . $this->created_capsule->getLinkPath()); $this->assertResponseIsSuccessful('The preview should be allowed for none authenticated user'); } @@ -128,8 +126,11 @@ class CapsuleControllerTest extends WebTestCase $client = static::createClient(); $client->request('GET', '/capsule/edit/' . $this->created_capsule->getLinkPath()); - $this->assertResponseRedirects('/login', 302, 'An unauthenticated user ' - . 'should no access to capsule edition and should be redirected to the login page'); + $this->assertResponseRedirects( + '/login', + 302, + 'An unauthenticated user should no access to capsule edition and should be redirected to the login page' + ); } public function testLoggedUserShouldAccessToItsCapsuleEdition(): void @@ -138,7 +139,8 @@ class CapsuleControllerTest extends WebTestCase $client->loginUser($this->verified_user); $client->request('GET', '/capsule/edit/' . $this->created_capsule->getLinkPath()); - $this->assertResponseIsSuccessful('An authenticated user should be able to access to the edition of its ' - . ' capsules'); + $this->assertResponseIsSuccessful( + 'An authenticated user should be able to access to the edition of its capsules' + ); } } diff --git a/tests/functional/CapsuleEditorControllerTest.php b/tests/functional/CapsuleEditorControllerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2be2f65302c2b9a781fe24ccd080fe31dbc97f08 --- /dev/null +++ b/tests/functional/CapsuleEditorControllerTest.php @@ -0,0 +1,225 @@ +<?php + +namespace App\Tests\functional; + +use App\Entity\Capsule; +use App\Entity\User; +use App\Repository\CapsuleRepository; +use App\Repository\UserRepository; +use Doctrine\Persistence\ObjectManager; +use Symfony\Bundle\FrameworkBundle\KernelBrowser; +use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; + +class CapsuleEditorControllerTest extends WebTestCase +{ + private KernelBrowser $client; + private ObjectManager $object_manager; + private User $user_author; + private User $editor_non_author; + private UserRepository $user_repository; /** @phpstan-ignore-line */ + private CapsuleRepository $capsule_repository; /** @phpstan-ignore-line */ + private Capsule $capsule; + + protected function setUp(): void + { + self::ensureKernelShutdown(); + + $this->client = static::createClient(); + + $this->object_manager = $this->client->getContainer() + ->get('doctrine') + ->getManager(); + + + $this->user_repository = $this->object_manager->getRepository(User::class); + $this->capsule_repository = $this->object_manager->getRepository(Capsule::class); + + $this->setUsers(); + $this->setCapsule(); + } + + protected function tearDown(): void + { + parent::tearDown(); + self::ensureKernelShutdown(); + } + + public function testAuthorShouldBeAbleToDeleteACapsule(): void + { + $this->client->loginUser($this->user_author); + $this->client->request('GET', '/capsule/delete/' . $this->capsule->getId()); + + $this->assertResponseIsSuccessful(); + } + + public function testEditorNonAuthorShouldNotBeAbleToDeleteACapsule(): void + { + $this->client->loginUser($this->editor_non_author); + $this->client->request('GET', '/capsule/delete/' . $this->capsule->getId()); + + $this->assertResponseRedirects('/my_capsules', 302); + } + + public function testAuthorShouldBeAbleToAddANewEditorForACapsule(): void + { + $uri = '/capsule/' . $this->capsule->getId() . '/editors'; + $this->client->loginUser($this->user_author); + $crawler = $this->client->request('GET', $uri); + + $this->assertResponseIsSuccessful(); + + $this->client->enableProfiler(); + $submit_button = $crawler->selectButton('Validate'); + $form = $submit_button->form(); + $form['capsule_editors_form[email]'] = $this->editor_non_author->getEmail(); + $this->client->submit($form); + + $this->assertResponseRedirects($uri, 302); + $this->client->followRedirect(); + $this->assertResponseIsSuccessful($uri); + + $capsule_refreshed = $this->capsule_repository->findOneBy(['id' => $this->capsule->getId()]); + if (! $capsule_refreshed instanceof Capsule) { + throw new \Exception("Capsule does not exist."); + } + + $editor = $this->user_repository->findOneBy(['id' => $this->editor_non_author->getId()]); + $this->assertSame($editor, $capsule_refreshed->getEditors()->last()); + } + + public function testEditorShouldBeAbleToAccessTheCapsuleEditorsPage(): void + { + $this->capsule->addEditor($this->editor_non_author); + $uri = '/capsule/' . $this->capsule->getId() . '/editors'; + $this->client->loginUser($this->editor_non_author); + + $this->client->request('GET', $uri); + + $this->assertResponseIsSuccessful(); + } + + public function testNonRegisteredUserAddedAsEditorShouldReceiveAnEmail(): void + { + $uri = '/capsule/' . $this->capsule->getId() . '/editors'; + $this->client->loginUser($this->user_author); + $crawler = $this->client->request('GET', $uri); + + $this->assertResponseIsSuccessful(); + + $this->client->enableProfiler(); + $submit_button = $crawler->selectButton('Validate'); + $non_registered_user_email = "non_registered_user@email.fr"; + $form = $submit_button->form(); + $form['capsule_editors_form[email]'] = $non_registered_user_email; + $this->client->submit($form); + + $this->assertResponseRedirects($uri, 302); + + $this->assertEmailCount(1); + $emailMessage = $this->getMailerMessage(0); + + if (null === $emailMessage) { + throw new \Exception("Email message could not be found"); + } + + $this->assertEmailAddressContains( + $emailMessage, + 'To', + $non_registered_user_email + ); + + $this->client->followRedirect(); + $this->assertResponseIsSuccessful($uri); + } + + public function testRegisteredUserShouldReceiveAnEmailWithCapsuleEditionLink(): void + { + $uri = '/capsule/' . $this->capsule->getId() . '/editors'; + $this->client->loginUser($this->user_author); + $crawler = $this->client->request('GET', $uri); + + $this->assertResponseIsSuccessful(); + + $this->client->enableProfiler(); + $submit_button = $crawler->selectButton('Validate'); + $form = $submit_button->form(); + $form['capsule_editors_form[email]'] = $this->editor_non_author->getEmail(); + $this->client->submit($form); + + $this->assertResponseRedirects($uri, 302); + + $this->assertEmailCount(1); + $emailMessage = $this->getMailerMessage(0); + + if (null === $emailMessage) { + throw new \Exception("Email message could not be found"); + } + + $this->assertEmailAddressContains( + $emailMessage, + 'To', + $this->editor_non_author->getEmail() + ); + + $this->client->followRedirect(); + $this->assertResponseIsSuccessful($uri); + } + + public function testAlreadyAddedEditorShouldNotReceiveAnEmail(): void + { + $this->capsule->addEditor($this->editor_non_author); + $this->object_manager->persist($this->capsule); + $this->object_manager->flush(); + + $this->assertContains($this->editor_non_author, $this->capsule->getEditors()->toArray()); + $uri = '/capsule/' . $this->capsule->getId() . '/editors'; + $this->client->loginUser($this->user_author); + $crawler = $this->client->request('GET', $uri); + + $this->assertResponseIsSuccessful(); + + $this->client->enableProfiler(); + $submit_button = $crawler->selectButton('Validate'); + $form = $submit_button->form(); + $form['capsule_editors_form[email]'] = $this->editor_non_author->getEmail(); + $this->client->submit($form); + + $this->assertEmailCount(0); + $this->assertResponseRedirects($uri, 302); + + $this->client->followRedirect(); + $this->assertResponseIsSuccessful($uri); + } + + private function setUsers(): void + { + $verified_user_1 = $this->user_repository + ->findOneBy(['email' => 'defaultUser@localhost.com']); + + if (! $verified_user_1 instanceof User) { + throw new \Exception("User does not exist."); + } + + $this->user_author = $verified_user_1; + + $verified_user_2 = $this->user_repository + ->findOneBy(['email' => 'defaultUser2@localhost.com']); + + if (! $verified_user_2 instanceof User) { + throw new \Exception("User does not exist."); + } + + $this->editor_non_author = $verified_user_2; + } + + private function setCapsule(): void + { + $capsule = $this->capsule_repository->findOneBy(['name' => 'Pomme']); + + if (! $capsule instanceof Capsule) { + throw new \Exception("Capsule does not exist."); + } + + $this->capsule = $capsule; + } +}