From 912fdd63499826f2365317f716f74b693bb29511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Tue, 16 Apr 2024 14:41:55 +0200 Subject: [PATCH] Add phone number search function to PersonACLAwareRepository A new function, findByPhone, has been added to the PersonACLAwareRepository. This function allows searching for people based on their phone numbers. Changes also reflect in the PersonACLAwareRepositoryInterface, and new test cases have been added to the PersonACLAwareRepositoryTest. --- .../Repository/PersonACLAwareRepository.php | 25 +++++++ .../PersonACLAwareRepositoryInterface.php | 10 +++ .../PersonACLAwareRepositoryTest.php | 66 +++++++++++++++++++ 3 files changed, 101 insertions(+) diff --git a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php index 303773c3e..3eaa1d989 100644 --- a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php @@ -21,6 +21,8 @@ use Chill\PersonBundle\Security\Authorization\PersonVoter; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\NonUniqueResultException; use Doctrine\ORM\Query; +use libphonenumber\PhoneNumber; +use libphonenumber\PhoneNumberFormat; use Symfony\Component\Security\Core\Security; final readonly class PersonACLAwareRepository implements PersonACLAwareRepositoryInterface @@ -298,4 +300,27 @@ final readonly class PersonACLAwareRepository implements PersonACLAwareRepositor \array_map(static fn (Center $c) => $c->getId(), $authorizedCenters) ); } + + public function findByPhone(PhoneNumber $phoneNumber, int $start = 0, int $limit = 20): array + { + $authorizedCenters = $this->authorizationHelper + ->getReachableCenters($this->security->getUser(), PersonVoter::SEE); + + if ([] === $authorizedCenters) { + return []; + } + + $util = \libphonenumber\PhoneNumberUtil::getInstance(); + + return $this->em->createQuery( + 'SELECT p FROM '.Person::class.' p LEFT JOIN p.otherPhoneNumbers opn JOIN p.centerCurrent pcc '. + 'WHERE (p.phonenumber LIKE :phone OR p.mobilenumber LIKE :phone OR opn.phonenumber LIKE :phone) '. + 'AND pcc.center IN (:centers)' + ) + ->setMaxResults($limit) + ->setFirstResult($start) + ->setParameter('phone', $util->format($phoneNumber, PhoneNumberFormat::E164)) + ->setParameter('centers', $authorizedCenters) + ->getResult(); + } } diff --git a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepositoryInterface.php b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepositoryInterface.php index c327ecd40..42e61bf21 100644 --- a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepositoryInterface.php +++ b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepositoryInterface.php @@ -13,6 +13,7 @@ namespace Chill\PersonBundle\Repository; use Chill\MainBundle\Search\SearchApiQuery; use Chill\PersonBundle\Entity\Person; +use libphonenumber\PhoneNumber; interface PersonACLAwareRepositoryInterface { @@ -60,4 +61,13 @@ interface PersonACLAwareRepositoryInterface ?string $phonenumber = null, ?string $city = null ): array; + + /** + * @return list + */ + public function findByPhone( + PhoneNumber $phoneNumber, + int $start = 0, + int $limit = 20 + ): array; } diff --git a/src/Bundle/ChillPersonBundle/Tests/Repository/PersonACLAwareRepositoryTest.php b/src/Bundle/ChillPersonBundle/Tests/Repository/PersonACLAwareRepositoryTest.php index 94df35d88..667242111 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Repository/PersonACLAwareRepositoryTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Repository/PersonACLAwareRepositoryTest.php @@ -11,14 +11,17 @@ declare(strict_types=1); namespace Chill\PersonBundle\Tests\Repository; +use Chill\MainBundle\Entity\Center; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Repository\CenterRepositoryInterface; use Chill\MainBundle\Repository\CountryRepository; use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface; use Chill\PersonBundle\Entity\Person; +use Chill\PersonBundle\Entity\PersonPhone; use Chill\PersonBundle\Repository\PersonACLAwareRepository; use Chill\PersonBundle\Security\Authorization\PersonVoter; use Doctrine\ORM\EntityManagerInterface; +use PHPUnit\Framework\Attributes\DataProvider; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; @@ -98,4 +101,67 @@ final class PersonACLAwareRepositoryTest extends KernelTestCase $this->assertStringContainsString('diallo', strtolower($person->getFirstName().' '.$person->getLastName())); } } + + /** + * @dataProvider providePersonsWithPhoneNumbers + */ + public function testFindByPhonenumber(\libphonenumber\PhoneNumber $phoneNumber, ?int $expectedId): void + { + $user = new User(); + + $authorizationHelper = $this->prophesize(AuthorizationHelperInterface::class); + $authorizationHelper->getReachableCenters(Argument::exact($user), Argument::exact(PersonVoter::SEE)) + ->willReturn($this->centerRepository->findAll()); + + $security = $this->prophesize(Security::class); + $security->getUser()->willReturn($user); + + $repository = new PersonACLAwareRepository( + $security->reveal(), + $this->entityManager, + $this->countryRepository, + $authorizationHelper->reveal() + ); + + $actual = $repository->findByPhone($phoneNumber, 0, 10); + + if (null === $expectedId) { + self::assertCount(0, $actual); + } else { + $actualIds = array_map(fn (Person $person) => $person->getId(), $actual); + + self::assertContains($expectedId, $actualIds); + } + } + + public static function providePersonsWithPhoneNumbers(): iterable + { + self::bootKernel(); + $em = self::getContainer()->get(EntityManagerInterface::class); + $center = $em->createQuery('SELECT c FROM '.Center::class.' c ')->setMaxResults(1) + ->getSingleResult(); + $util = \libphonenumber\PhoneNumberUtil::getInstance(); + + $mobile = $util->parse('+32486123456'); + $fixed = $util->parse('+3281136917'); + $anotherMobile = $util->parse('+32486123478'); + $person = (new Person())->setFirstName('diallo')->setLastName('diallo')->setCenter($center); + $person->setMobilenumber($mobile)->setPhonenumber($fixed); + $otherPhone = new PersonPhone(); + $otherPhone->setPerson($person); + $otherPhone->setPhonenumber($anotherMobile); + $otherPhone->setType('mobile'); + + $em->persist($person); + $em->persist($otherPhone); + + $em->flush(); + + self::ensureKernelShutdown(); + + yield [$mobile, $person->getId()]; + yield [$anotherMobile, $person->getId()]; + yield [$fixed, $person->getId()]; + yield [$util->parse('+331234567890'), null]; + } }