From 0fd76d3fa8e0786a1f1b45148ccb465531be4ba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 24 Sep 2025 00:01:28 +0200 Subject: [PATCH] Add `PersonIdentifierManagerInterface` to `PersonACLAwareRepository` and enhance search logic for identifiers - Inject `PersonIdentifierManagerInterface` into `PersonACLAwareRepository` for improved identifier handling. - Update search queries to include logic for filtering and matching `PersonIdentifier` values. - Modify test cases to support the new dependency and ensure proper coverage. --- .../Repository/PersonACLAwareRepository.php | 42 ++++++++++++++++--- .../PersonACLAwareRepositoryTest.php | 14 +++++-- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php index 0d972914d..2947038a8 100644 --- a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php @@ -17,6 +17,8 @@ use Chill\MainBundle\Search\ParsingException; use Chill\MainBundle\Search\SearchApiQuery; use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface; use Chill\PersonBundle\Entity\Person; +use Chill\PersonBundle\PersonIdentifier\PersonIdentifierManagerInterface; +use Chill\PersonBundle\PersonIdentifier\PersonIdentifierWorker; use Chill\PersonBundle\Security\Authorization\PersonVoter; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\NonUniqueResultException; @@ -27,7 +29,13 @@ use Symfony\Component\Security\Core\Security; final readonly class PersonACLAwareRepository implements PersonACLAwareRepositoryInterface { - public function __construct(private Security $security, private EntityManagerInterface $em, private CountryRepository $countryRepository, private AuthorizationHelperInterface $authorizationHelper) {} + public function __construct( + private Security $security, + private EntityManagerInterface $em, + private CountryRepository $countryRepository, + private AuthorizationHelperInterface $authorizationHelper, + private PersonIdentifierManagerInterface $personIdentifierManager, + ) {} public function buildAuthorizedQuery( ?string $default = null, @@ -107,6 +115,15 @@ final readonly class PersonACLAwareRepository implements PersonACLAwareRepositor $query ->setFromClause('chill_person_person AS person'); + $idDefinitionWorkers = array_map( + fn (PersonIdentifierWorker $worker) => $worker->getDefinition()->getId(), + array_filter( + $this->personIdentifierManager->getWorkers(), + fn (PersonIdentifierWorker $worker) => $worker->getDefinition()->isSearchable() + ) + ); + $idDefinitionWorkerQuestionMarks = implode(', ', array_fill(0, count($idDefinitionWorkers), '?')); + $pertinence = []; $pertinenceArgs = []; $andWhereSearchClause = []; @@ -124,10 +141,25 @@ final readonly class PersonACLAwareRepository implements PersonACLAwareRepositor '(starts_with(LOWER(UNACCENT(lastname)), UNACCENT(LOWER(?))))::int'; \array_push($pertinenceArgs, $str, $str, $str, $str); - $andWhereSearchClause[] = - '(LOWER(UNACCENT(?)) <<% person.fullnamecanonical OR '. - "person.fullnamecanonical LIKE '%' || LOWER(UNACCENT(?)) || '%' )"; - \array_push($andWhereSearchClauseArgs, $str, $str); + $q = [ + 'LOWER(UNACCENT(?)) <<% person.fullnamecanonical', + "person.fullnamecanonical LIKE '%' || LOWER(UNACCENT(?)) || '%' ", + ]; + $qArguments = [$str, $str]; + + if (count($idDefinitionWorkers) > 0) { + $q[] = $mq = "EXISTS ( + SELECT 1 FROM chill_person_identifier AS identifier + WHERE identifier.canonical LIKE LOWER(UNACCENT(?)) || '%' AND identifier.definition_id IN ({$idDefinitionWorkerQuestionMarks}) + AND person.id = identifier.person_id + )"; + $pertinence[] = "({$mq})::int * 1_000_000"; + $qArguments = [...$qArguments, $str, ...$idDefinitionWorkers]; + $pertinenceArgs = [...$pertinenceArgs, $str, ...$idDefinitionWorkers]; + } + + $andWhereSearchClause[] = '('.implode(' OR ', $q).')'; + $andWhereSearchClauseArgs = [...$andWhereSearchClauseArgs, ...$qArguments]; } $query->andWhereClause( diff --git a/src/Bundle/ChillPersonBundle/Tests/Repository/PersonACLAwareRepositoryTest.php b/src/Bundle/ChillPersonBundle/Tests/Repository/PersonACLAwareRepositoryTest.php index 667242111..20401c1b1 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Repository/PersonACLAwareRepositoryTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Repository/PersonACLAwareRepositoryTest.php @@ -18,6 +18,7 @@ use Chill\MainBundle\Repository\CountryRepository; use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\PersonPhone; +use Chill\PersonBundle\PersonIdentifier\PersonIdentifierManagerInterface; use Chill\PersonBundle\Repository\PersonACLAwareRepository; use Chill\PersonBundle\Security\Authorization\PersonVoter; use Doctrine\ORM\EntityManagerInterface; @@ -42,6 +43,8 @@ final class PersonACLAwareRepositoryTest extends KernelTestCase private EntityManagerInterface $entityManager; + private PersonIdentifierManagerInterface $personIdentifierManager; + protected function setUp(): void { self::bootKernel(); @@ -49,6 +52,8 @@ final class PersonACLAwareRepositoryTest extends KernelTestCase $this->entityManager = self::getContainer()->get(EntityManagerInterface::class); $this->countryRepository = self::getContainer()->get(CountryRepository::class); $this->centerRepository = self::getContainer()->get(CenterRepositoryInterface::class); + $this->personIdentifierManager = self::getContainer()->get(PersonIdentifierManagerInterface::class); + } public function testCountByCriteria() @@ -66,7 +71,8 @@ final class PersonACLAwareRepositoryTest extends KernelTestCase $security->reveal(), $this->entityManager, $this->countryRepository, - $authorizationHelper->reveal() + $authorizationHelper->reveal(), + $this->personIdentifierManager, ); $number = $repository->countBySearchCriteria('diallo'); @@ -89,7 +95,8 @@ final class PersonACLAwareRepositoryTest extends KernelTestCase $security->reveal(), $this->entityManager, $this->countryRepository, - $authorizationHelper->reveal() + $authorizationHelper->reveal(), + $this->personIdentifierManager, ); $results = $repository->findBySearchCriteria(0, 5, false, 'diallo'); @@ -120,7 +127,8 @@ final class PersonACLAwareRepositoryTest extends KernelTestCase $security->reveal(), $this->entityManager, $this->countryRepository, - $authorizationHelper->reveal() + $authorizationHelper->reveal(), + $this->personIdentifierManager, ); $actual = $repository->findByPhone($phoneNumber, 0, 10);