mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-18 16:24:24 +00:00
Add functionality to find a caller by phone number
Added a new method in PersonRepository to allow querying people by phone number. Also, a new REST API endpoint "/public/api/1.0/ticket/find-caller" was introduced and it can find a caller by their phone number. Accompanied this feature addition with corresponding test cases.
This commit is contained in:
parent
66dc603c85
commit
78d1776733
@ -12,10 +12,12 @@ declare(strict_types=1);
|
|||||||
namespace Chill\PersonBundle\Repository;
|
namespace Chill\PersonBundle\Repository;
|
||||||
|
|
||||||
use Chill\PersonBundle\Entity\Person;
|
use Chill\PersonBundle\Entity\Person;
|
||||||
|
use Chill\PersonBundle\Entity\PersonPhone;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Doctrine\ORM\EntityRepository;
|
use Doctrine\ORM\EntityRepository;
|
||||||
use Doctrine\ORM\QueryBuilder;
|
use Doctrine\ORM\QueryBuilder;
|
||||||
use Doctrine\Persistence\ObjectRepository;
|
use Doctrine\Persistence\ObjectRepository;
|
||||||
|
use libphonenumber\PhoneNumber;
|
||||||
|
|
||||||
class PersonRepository implements ObjectRepository
|
class PersonRepository implements ObjectRepository
|
||||||
{
|
{
|
||||||
@ -29,6 +31,8 @@ class PersonRepository implements ObjectRepository
|
|||||||
/**
|
/**
|
||||||
* @throws \Doctrine\ORM\NoResultException
|
* @throws \Doctrine\ORM\NoResultException
|
||||||
* @throws \Doctrine\ORM\NonUniqueResultException
|
* @throws \Doctrine\ORM\NonUniqueResultException
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public function countByPhone(
|
public function countByPhone(
|
||||||
string $phonenumber,
|
string $phonenumber,
|
||||||
@ -71,6 +75,8 @@ class PersonRepository implements ObjectRepository
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
|
*
|
||||||
|
* @deprecated Use @see{self::findByPhoneNumber} or use a dedicated method in PersonACLAwareRepository
|
||||||
*/
|
*/
|
||||||
public function findByPhone(
|
public function findByPhone(
|
||||||
string $phonenumber,
|
string $phonenumber,
|
||||||
@ -91,6 +97,25 @@ class PersonRepository implements ObjectRepository
|
|||||||
return $qb->getQuery()->getResult();
|
return $qb->getQuery()->getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a person which is associated to the given phonenumber, without restrictions
|
||||||
|
* on any.
|
||||||
|
*
|
||||||
|
* @return list<Person
|
||||||
|
*/
|
||||||
|
public function findByPhoneNumber(PhoneNumber $phoneNumber, int $firstResult = 0, int $maxResults = 50): array
|
||||||
|
{
|
||||||
|
$qb = $this->repository->createQueryBuilder('p');
|
||||||
|
$qb->select('p');
|
||||||
|
|
||||||
|
$this->searchByPhoneNumbers($qb, $phoneNumber);
|
||||||
|
|
||||||
|
$qb->setFirstResult($firstResult)
|
||||||
|
->setMaxResults($maxResults);
|
||||||
|
|
||||||
|
return $qb->getQuery()->getResult();
|
||||||
|
}
|
||||||
|
|
||||||
public function findOneBy(array $criteria)
|
public function findOneBy(array $criteria)
|
||||||
{
|
{
|
||||||
return $this->repository->findOneBy($criteria);
|
return $this->repository->findOneBy($criteria);
|
||||||
@ -109,6 +134,20 @@ class PersonRepository implements ObjectRepository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function searchByPhoneNumbers(QueryBuilder $qb, PhoneNumber $phoneNumber): void
|
||||||
|
{
|
||||||
|
$qb->setParameter('number', $phoneNumber, 'phone_number');
|
||||||
|
|
||||||
|
$orX = $qb->expr()->orX();
|
||||||
|
$orX->add($qb->expr()->eq('p.mobilenumber', ':number'));
|
||||||
|
$orX->add($qb->expr()->eq('p.phonenumber', ':number'));
|
||||||
|
$orX->add(
|
||||||
|
$qb->expr()->exists('SELECT 1 FROM '.PersonPhone::class.' k WHERE k.phonenumber = :number AND k.person = p')
|
||||||
|
);
|
||||||
|
|
||||||
|
$qb->andWhere($orX);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\TicketBundle\Controller;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Phonenumber\PhonenumberHelper;
|
||||||
|
use Chill\PersonBundle\Repository\PersonRepository;
|
||||||
|
use Chill\PersonBundle\Templating\Entity\PersonRenderInterface;
|
||||||
|
use libphonenumber\NumberParseException;
|
||||||
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller for a rest api to find a caller for a given phonenumber.
|
||||||
|
*
|
||||||
|
* TODO: currently, this rest api is not secured
|
||||||
|
*/
|
||||||
|
class FindCallerController
|
||||||
|
{
|
||||||
|
public function __construct(private PhonenumberHelper $phonenumberHelper, private PersonRepository $personRepository, private PersonRenderInterface $personRender) {}
|
||||||
|
|
||||||
|
#[Route('/public/api/1.0/ticket/find-caller', name: 'find-caller', methods: ['GET'])]
|
||||||
|
public function findCaller(Request $request): Response
|
||||||
|
{
|
||||||
|
$caller = $request->query->get('caller', '');
|
||||||
|
|
||||||
|
if ('' === $caller) {
|
||||||
|
throw new BadRequestHttpException('Missing "caller" query parameter');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$phoneNumber = $this->phonenumberHelper->parse($caller);
|
||||||
|
} catch (NumberParseException $e) {
|
||||||
|
throw new BadRequestHttpException('Unable to parse number', $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
$persons = $this->personRepository->findByPhoneNumber($phoneNumber, 0, 2);
|
||||||
|
|
||||||
|
$asArray = match (count($persons)) {
|
||||||
|
0 => ['found' => false, 'name' => null],
|
||||||
|
1 => ['found' => true, 'name' => $this->personRender->renderString($persons[0], ['addAge' => false])],
|
||||||
|
default => ['found' => true, 'name' => 'multiple'],
|
||||||
|
};
|
||||||
|
|
||||||
|
return new JsonResponse($asArray);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,128 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\TicketBundle\Tests\Controller;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Phonenumber\PhonenumberHelper;
|
||||||
|
use Chill\PersonBundle\Entity\Person;
|
||||||
|
use Chill\PersonBundle\Repository\PersonRepository;
|
||||||
|
use Chill\PersonBundle\Templating\Entity\PersonRenderInterface;
|
||||||
|
use Chill\TicketBundle\Controller\FindCallerController;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Prophecy\Argument;
|
||||||
|
use Prophecy\PhpUnit\ProphecyTrait;
|
||||||
|
use Psr\Log\NullLogger;
|
||||||
|
use Symfony\Component\Cache\Adapter\ArrayAdapter;
|
||||||
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
class FindCallerControllerTest extends TestCase
|
||||||
|
{
|
||||||
|
use ProphecyTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideFindCaller
|
||||||
|
*/
|
||||||
|
public function testFindCaller(string $caller, array $persons, array $expected): void
|
||||||
|
{
|
||||||
|
$controller = $this->buildController($persons);
|
||||||
|
|
||||||
|
$request = new Request(query: ['caller' => $caller]);
|
||||||
|
|
||||||
|
$response = $controller->findCaller($request);
|
||||||
|
|
||||||
|
$actual = json_decode($response->getContent(), true);
|
||||||
|
|
||||||
|
self::assertEqualsCanonicalizing($expected, $actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindCallerWithoutCallerArgument(): void
|
||||||
|
{
|
||||||
|
self::expectException(BadRequestHttpException::class);
|
||||||
|
|
||||||
|
$controller = $this->buildController([]);
|
||||||
|
|
||||||
|
$request = new Request(query: []);
|
||||||
|
|
||||||
|
$controller->findCaller($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindCallerWithEmptyCallerArgument(): void
|
||||||
|
{
|
||||||
|
self::expectException(BadRequestHttpException::class);
|
||||||
|
|
||||||
|
$controller = $this->buildController([]);
|
||||||
|
|
||||||
|
$request = new Request(query: ['caller' => '']);
|
||||||
|
|
||||||
|
$controller->findCaller($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindCallerWithInvalidCaller(): void
|
||||||
|
{
|
||||||
|
self::expectException(BadRequestHttpException::class);
|
||||||
|
|
||||||
|
$controller = $this->buildController([]);
|
||||||
|
|
||||||
|
$request = new Request(query: ['caller' => 'abcde']);
|
||||||
|
|
||||||
|
$controller->findCaller($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function provideFindCaller(): iterable
|
||||||
|
{
|
||||||
|
yield [
|
||||||
|
'32486540600',
|
||||||
|
[],
|
||||||
|
['found' => false, 'name' => null],
|
||||||
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
'32486540600',
|
||||||
|
[new Person()],
|
||||||
|
['found' => true, 'name' => 'pppp'],
|
||||||
|
]
|
||||||
|
;
|
||||||
|
yield [
|
||||||
|
'32486540600',
|
||||||
|
[new Person(), new Person()],
|
||||||
|
['found' => true, 'name' => 'multiple'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildController(array $personsFound): FindCallerController
|
||||||
|
{
|
||||||
|
$phonenumberHelper =
|
||||||
|
$subject = new PhonenumberHelper(
|
||||||
|
new ArrayAdapter(),
|
||||||
|
new ParameterBag([
|
||||||
|
'chill_main.phone_helper' => [
|
||||||
|
'default_carrier_code' => 'BE',
|
||||||
|
],
|
||||||
|
]),
|
||||||
|
new NullLogger()
|
||||||
|
);
|
||||||
|
|
||||||
|
$personRepository = $this->prophesize(PersonRepository::class);
|
||||||
|
$personRepository->findByPhoneNumber(Argument::any(), Argument::type('int'), Argument::type('int'))->willReturn($personsFound);
|
||||||
|
|
||||||
|
$personRender = $this->prophesize(PersonRenderInterface::class);
|
||||||
|
$personRender->renderString(Argument::type(Person::class), Argument::type('array'))->willReturn('pppp');
|
||||||
|
|
||||||
|
return new FindCallerController($phonenumberHelper, $personRepository->reveal(), $personRender->reveal());
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user