Add Person's external identifiers to creation and edit form

This commit is contained in:
2025-12-05 17:02:26 +00:00
parent d21d03d407
commit 6d93b2b1b6
131 changed files with 9015 additions and 4954 deletions

View File

@@ -0,0 +1,42 @@
<?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\PersonBundle\Repository\Identifier;
use Chill\PersonBundle\Entity\Identifier\PersonIdentifier;
use Chill\PersonBundle\Entity\Identifier\PersonIdentifierDefinition;
use Chill\PersonBundle\PersonIdentifier\PersonIdentifierManagerInterface;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
class PersonIdentifierRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry, private readonly PersonIdentifierManagerInterface $personIdentifierManager)
{
parent::__construct($registry, PersonIdentifier::class);
}
public function findByDefinitionAndCanonical(PersonIdentifierDefinition $definition, array|string $valueOrCanonical): array
{
return $this->createQueryBuilder('p')
->where('p.definition = :definition')
->andWhere('p.canonical = :canonical')
->setParameter('definition', $definition)
->setParameter(
'canonical',
is_string($valueOrCanonical) ?
$valueOrCanonical :
$this->personIdentifierManager->buildWorkerByPersonIdentifierDefinition($definition)->canonicalizeValue($valueOrCanonical),
)
->getQuery()
->getResult();
}
}

View File

@@ -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,20 +141,53 @@ 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 * 1000000";
$qArguments = [...$qArguments, $str, ...$idDefinitionWorkers];
$pertinenceArgs = [...$pertinenceArgs, $str, ...$idDefinitionWorkers];
}
$andWhereSearchClause[] = '('.implode(' OR ', $q).')';
$andWhereSearchClauseArgs = [...$andWhereSearchClauseArgs, ...$qArguments];
}
$query->andWhereClause(
\implode(' AND ', $andWhereSearchClause),
$andWhereSearchClauseArgs
);
} else {
$pertinence = ['1'];
$pertinenceArgs = [];
}
if (null !== $phonenumber) {
$personPhoneClause = "person.phonenumber LIKE '%' || ? || '%' OR person.mobilenumber LIKE '%' || ? || '%' OR EXISTS (SELECT 1 FROM chill_person_phone where person_id = person.id AND phonenumber LIKE '%' || ? || '%')";
if (count($andWhereSearchClauseArgs) > 0) {
$initialSearchClause = '(('.\implode(' AND ', $andWhereSearchClause).') OR '.$personPhoneClause.')';
}
$andWhereSearchClauseArgs = [...$andWhereSearchClauseArgs, $phonenumber, $phonenumber, $phonenumber];
// drastically increase pertinence
$pertinence[] = "(person.phonenumber LIKE '%' || ? || '%' OR person.mobilenumber LIKE '%' || ? || '%' OR EXISTS (SELECT 1 FROM chill_person_phone where person_id = person.id AND phonenumber LIKE '%' || ? || '%'))::int * 1000000";
$pertinenceArgs = [...$pertinenceArgs, $phonenumber, $phonenumber, $phonenumber];
} else {
$initialSearchClause = \implode(' AND ', $andWhereSearchClause);
}
if (isset($initialSearchClause)) {
$query->andWhereClause(
$initialSearchClause,
$andWhereSearchClauseArgs
);
}
$query
->setSelectPertinence(\implode(' + ', $pertinence), $pertinenceArgs);
@@ -176,14 +226,6 @@ final readonly class PersonACLAwareRepository implements PersonACLAwareRepositor
);
}
if (null !== $phonenumber) {
$query->andWhereClause(
"person.phonenumber LIKE '%' || ? || '%' OR person.mobilenumber LIKE '%' || ? || '%' OR pp.phonenumber LIKE '%' || ? || '%'",
[$phonenumber, $phonenumber, $phonenumber]
);
$query->setFromClause($query->getFromClause().' LEFT JOIN chill_person_phone pp ON pp.person_id = person.id');
}
if (null !== $city) {
$query->setFromClause($query->getFromClause().' '.
'JOIN view_chill_person_current_address vcpca ON vcpca.person_id = person.id '.