From 25d7fc36a4c02937578baf0bd2d76ca9a4076371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 19 May 2021 16:14:36 +0200 Subject: [PATCH] action to create an accompanyinig period --- .../AccompanyingCourseController.php | 115 ++++++------------ .../Entity/AccompanyingPeriod.php | 4 +- .../Authorization/AccompanyingPeriodVoter.php | 3 + .../AccompanyingCourseControllerTest.php | 88 ++++++++++++++ .../ChillPersonBundle/config/services.yaml | 2 + 5 files changed, 131 insertions(+), 81 deletions(-) create mode 100644 src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingCourseControllerTest.php diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php index 8134f6938..6786cb05f 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php @@ -6,6 +6,7 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; use Chill\PersonBundle\Privacy\AccompanyingPeriodPrivacyEvent; use Chill\PersonBundle\Entity\Person; +use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter; use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\JsonResponse; @@ -42,6 +43,41 @@ class AccompanyingCourseController extends Controller $this->dispatcher = $dispatcher; $this->validator = $validator; } + + /** + * @Route("/{_locale}/person/parcours/new", name="chill_person_accompanying_course_new") + */ + public function newAction(Request $request): Response + { + $period = new AccompanyingPeriod(); + $em = $this->getDoctrine()->getManager(); + + if ($request->query->has('person_id')) { + $personIds = $request->query->get('person_id'); + + if (FALSE === \is_array($personIds)) { + throw new BadRequestException("person_id parameter should be an array"); + } + + foreach ($personIds as $personId) { + $person = $em->getRepository(Person::class)->find($personId); + if (NULL !== $person) { + $period->addPerson($person); + } + } + } + + $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $period); + + $em->persist($period); + $em->flush(); + + return $this->redirectToRoute('chill_person_accompanying_course_show', [ + 'accompanying_period_id' => $period->getId() + ]); + + } + /** * Homepage of Accompanying Course section * @@ -86,83 +122,4 @@ class AccompanyingCourseController extends Controller ]); } - /** - * Get API Data for showing endpoint - * - * @Route( - * "/{_locale}/person/api/1.0/accompanying-course/{accompanying_period_id}/show.{_format}", - * name="chill_person_accompanying_course_api_show" - * ) - * @ParamConverter("accompanyingCourse", options={"id": "accompanying_period_id"}) - */ - public function showAPI(AccompanyingPeriod $accompanyingCourse, $_format): Response - { - // TODO check ACL on AccompanyingPeriod - - $this->dispatcher->dispatch( - AccompanyingPeriodPrivacyEvent::ACCOMPANYING_PERIOD_PRIVACY_EVENT, - new AccompanyingPeriodPrivacyEvent($accompanyingCourse, [ - 'action' => 'showApi' - ]) - ); - - //$accompanyingCourse->getRequestorPerson(); - //$accompanyingCourse->getRequestorThirdParty(); - //$accompanyingCourse->isRequestorAnonymous(); - //dump($accompanyingCourse); die; - - switch ($_format) { - case 'json': - return $this->json($accompanyingCourse); - default: - throw new BadRequestException('Unsupported format'); - } - - } - - /** - * Get API Data for showing endpoint - * - * @Route( - * "/{_locale}/person/api/1.0/accompanying-course/{accompanying_period_id}/participation.{_format}", - * name="chill_person_accompanying_course_api_add_participation", - * methods={"POST","DELETE"}, - * format="json", - * requirements={ - * "_format": "json", - * } - * ) - * @ParamConverter("accompanyingCourse", options={"id": "accompanying_period_id"}) - */ - public function participationAPI(Request $request, AccompanyingPeriod $accompanyingCourse, $_format): Response - { - switch ($_format) { - case 'json': - $person = $this->serializer->deserialize($request->getContent(), Person::class, $_format, [ - - ]); - break; - default: - throw new BadRequestException('Unsupported format'); - } - - if (NULL === $person) { - throw new BadRequestException('person id not found'); - } - - // TODO add acl - $participation = ($request->getMethod() === 'POST') ? - $accompanyingCourse->addPerson($person) : $accompanyingCourse->removePerson($person); - - $errors = $this->validator->validate($accompanyingCourse); - - if ($errors->count() > 0) { - // only format accepted - return $this->json($errors); - } - - $this->getDoctrine()->getManager()->flush(); - - return $this->json($participation); - } } diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php index 716edd118..69d461319 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php @@ -266,8 +266,8 @@ class AccompanyingPeriod * @param \DateTime $dateOpening * @uses AccompanyingPeriod::setClosingDate() */ - public function __construct(\DateTime $dateOpening) { - $this->setOpeningDate($dateOpening); + public function __construct(\DateTime $dateOpening = null) { + $this->setOpeningDate($dateOpening ?? new \DateTime('now')); $this->participations = new ArrayCollection(); $this->scopes = new ArrayCollection(); $this->socialIssues = new ArrayCollection(); diff --git a/src/Bundle/ChillPersonBundle/Security/Authorization/AccompanyingPeriodVoter.php b/src/Bundle/ChillPersonBundle/Security/Authorization/AccompanyingPeriodVoter.php index ca92c6d7c..2801cb8f7 100644 --- a/src/Bundle/ChillPersonBundle/Security/Authorization/AccompanyingPeriodVoter.php +++ b/src/Bundle/ChillPersonBundle/Security/Authorization/AccompanyingPeriodVoter.php @@ -38,6 +38,9 @@ class AccompanyingPeriodVoter extends AbstractChillVoter implements ProvideRole } // TODO take scopes into account + if (count($subject->getPersons()) === 0) { + return true; + } foreach ($subject->getPersons() as $person) { // give access as soon as on center is reachable if ($this->helper->userHasAccess($token->getUser(), $person->getCenter(), $attribute)) { diff --git a/src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingCourseControllerTest.php b/src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingCourseControllerTest.php new file mode 100644 index 000000000..0143a70ed --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingCourseControllerTest.php @@ -0,0 +1,88 @@ +client = $this->getClientAuthenticated(); + } + + public function testNewWithoutUsers() + { + $this->client->request('GET', '/fr/person/parcours/new'); + + $this->assertResponseRedirects(); + $location = $this->client->getResponse()->headers->get('Location'); + + $this->assertEquals(1, \preg_match("|^\/[^\/]+\/parcours/([\d]+)/show$|", $location)); + + } + + /** + * @dataProvider dataGenerateRandomUsers + */ + public function testWithNewUsers($personId0, $personId1) + { + $this->client->request('GET', '/fr/person/parcours/new', [ + 'person_id' => [ + $personId0, + $personId1 + ] + ]); + + $this->assertResponseRedirects(); + $location = $this->client->getResponse()->headers->get('Location'); + $matches = []; + + $this->assertEquals(1, \preg_match("|^\/[^\/]+\/parcours/([\d]+)/show$|", $location, $matches)); + $id = $matches[1]; + + $period = self::$container->get(EntityManagerInterface::class) + ->getRepository(AccompanyingPeriod::class) + ->find($id); + + $this->assertNotNull($period); + + $this->assertEquals(2, count($period->getParticipations())); + } + + public function dataGenerateRandomUsers(): \Iterator + { + self::bootKernel(); + $em = self::$container->get(EntityManagerInterface::class); + + $period = new AccompanyingPeriod(new \DateTime('1 week ago')); + $user = $em->getRepository(User::class) + ->findOneByUsernameCanonical('center a_social'); + $period->setCreatedBy($user); + //$period->setCreatedAt(new \DateTime('yesterday')); + + $center = $em->getRepository(Center::class) + ->findOneBy(array('name' => 'Center A')); + + $personIds = $em->createQuery("SELECT p.id FROM ". + Person::class." p ". + " WHERE p.center = :center") + ->setParameter('center', $center) + ->setMaxResults(100) + ->getScalarResult(); + + yield [ \array_pop($personIds), \array_pop($personIds) ]; + } + + +} diff --git a/src/Bundle/ChillPersonBundle/config/services.yaml b/src/Bundle/ChillPersonBundle/config/services.yaml index 1c1a3a29b..523545900 100644 --- a/src/Bundle/ChillPersonBundle/config/services.yaml +++ b/src/Bundle/ChillPersonBundle/config/services.yaml @@ -44,5 +44,7 @@ services: - { name: validator.constraint_validator, alias: birthdate_not_before } Chill\PersonBundle\Repository\: + autowire: true + autoconfigure: true resource: '../Repository/' tags: ['doctrine.repository_service']