action to create an accompanyinig period

This commit is contained in:
Julien Fastré 2021-05-19 16:14:36 +02:00
parent 03bd1674e1
commit 25d7fc36a4
5 changed files with 131 additions and 81 deletions

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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)) {

View File

@ -0,0 +1,88 @@
<?php
namespace Chill\PersonBundle\Tests\Controller;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Test\PrepareClientTrait;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class AccompanyingCourseControllerTest extends WebTestCase
{
use PrepareClientTrait;
public function setUp()
{
parent::setUp();
self::bootKernel();
$this->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) ];
}
}

View File

@ -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']