diff --git a/src/Bundle/ChillPersonBundle/Controller/HouseholdApiController.php b/src/Bundle/ChillPersonBundle/Controller/HouseholdApiController.php index 67f70db40..1e15490dc 100644 --- a/src/Bundle/ChillPersonBundle/Controller/HouseholdApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/HouseholdApiController.php @@ -4,15 +4,50 @@ namespace Chill\PersonBundle\Controller; use Chill\MainBundle\CRUD\Controller\ApiController; use Chill\MainBundle\Entity\Address; +use Chill\MainBundle\Serializer\Model\Collection; +use Chill\PersonBundle\Entity\Person; +use Chill\PersonBundle\Repository\Household\HouseholdRepository; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; class HouseholdApiController extends ApiController { + private HouseholdRepository $householdRepository; + + public function __construct(HouseholdRepository $householdRepository) + { + $this->householdRepository = $householdRepository; + } + public function householdAddressApi($id, Request $request, string $_format): Response { return $this->addRemoveSomething('address', $id, $request, $_format, 'address', Address::class, [ 'groups' => [ 'read' ] ]); } + /** + * Find Household of people participating to the same AccompanyingPeriod + * + * @ParamConverter("person", options={"id" = "person_id"}) + */ + public function suggestHouseholdByAccompanyingPeriodParticipationApi(Person $person, string $_format) + { + // TODO add acl + + $count = $this->householdRepository->countByAccompanyingPeriodParticipation($person); + $paginator = $this->getPaginatorFactory()->create($count); + + if ($count === 0) { + $households = []; + } else { + $households = $this->householdRepository->findByAccompanyingPeriodParticipation($person, + $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber()); + } + + $collection = new Collection($households, $paginator); + + return $this->json($collection, Response::HTTP_OK, [], + [ "groups" => ["read"]]); + } } diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php index 733579acb..03b05bbc8 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php @@ -565,6 +565,13 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac ], 'controller_action' => 'householdAddressApi' ], + 'suggestHouseholdByAccompanyingPeriodParticipation' => [ + 'path' => '/suggest/by-person/{person_id}/through-accompanying-period-participation.{_format}', + 'methods' => [ + Request::METHOD_GET => true, + Request::METHOD_HEAD => true, + ] + ] ] ], [ diff --git a/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdRepository.php b/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdRepository.php index b7a8816b3..d9ec6c35e 100644 --- a/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdRepository.php @@ -3,15 +3,102 @@ namespace Chill\PersonBundle\Repository\Household; use Chill\PersonBundle\Entity\Household\Household; +use Chill\PersonBundle\Entity\Person; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; +use Doctrine\ORM\Query\ResultSetMappingBuilder; +use Doctrine\Persistence\ObjectRepository; -final class HouseholdRepository +final class HouseholdRepository implements ObjectRepository { private EntityRepository $repository; + private EntityManagerInterface $em; public function __construct(EntityManagerInterface $entityManager) { $this->repository = $entityManager->getRepository(Household::class); + $this->em = $entityManager; } + + public function find($id) + { + return $this->repository->find($id); + } + + public function findAll() + { + return $this->repository->findAll(); + } + + public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null) + { + return $this->repository->findBy($criteria, $orderBy, $limit, $offset); + } + + public function findOneBy(array $criteria) + { + return $this->findOneBy($criteria); + } + + public function getClassName() + { + return Household::class; + } + + public function countByAccompanyingPeriodParticipation(Person $person) + { + return $this->buildQueryByAccompanyingPeriodParticipation($person, true); + } + + public function findByAccompanyingPeriodParticipation(Person $person, int $limit, int $offset) + { + return $this->buildQueryByAccompanyingPeriodParticipation($person, false, $limit, $offset); + } + + private function buildQueryByAccompanyingPeriodParticipation(Person $person, bool $isCount = false, int $limit = 50, int $offset = 0) + { + $rsm = new ResultSetMappingBuilder($this->em); + $rsm->addRootEntityFromClassMetadata(Household::class, 'h'); + + if ($isCount) { + $rsm->addScalarResult('count', 'count'); + $sql = \strtr(self::SQL_BY_ACCOMPANYING_PERIOD_PARTICIPATION, [ + '{select}' => 'COUNT(households.*) AS count', + '{limits}' => '' + ]); + } else { + $sql = \strtr(self::SQL_BY_ACCOMPANYING_PERIOD_PARTICIPATION, [ + '{select}' => $rsm->generateSelectClause(['h' => 'households']), + '{limits}' => "OFFSET {$offset} LIMIT {$limit}" + ]); + } + $native = $this->em->createNativeQuery($sql, $rsm); + $native->setParameters([0 => $person->getId(), 1 => $person->getId()]); + + if ($isCount) { + return $native->getSingleScalarResult(); + } else { + return $native->getResult(); + } + } + + private CONST SQL_BY_ACCOMPANYING_PERIOD_PARTICIPATION = <<