mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-15 19:24:57 +00:00
Compare commits
5 Commits
user_edit_
...
issue451_m
Author | SHA1 | Date | |
---|---|---|---|
|
bfb19d0670 | ||
|
574c3596d1 | ||
|
d7f5de6570 | ||
|
bc08719c0c | ||
|
a3ffd2709d |
@@ -11,7 +11,8 @@ and this project adheres to
|
||||
## Unreleased
|
||||
|
||||
<!-- write down unreleased development here -->
|
||||
|
||||
* [person] use the same rendering of person in similar person proposition (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/348)
|
||||
* [person] move similar person matcher to PersonACLAwareRepository and replace the SimilarPersonMatcher uses (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/451)
|
||||
## Test releases
|
||||
|
||||
### test release 2022-02-14
|
||||
@@ -22,7 +23,7 @@ and this project adheres to
|
||||
* [person] accompanying course work: fix on-the-fly update of thirdParty
|
||||
* fix normalisation of accompanying course requestor api (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/378)
|
||||
* [person] add a returnPath when clicking on some Person or ThirdParty badge (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/427)
|
||||
* [person] accompanying course work: fix on-the-fly update of thirdParty
|
||||
* [person] accompanying course work: fix on-the-fly update of thirdParty
|
||||
* [on-the-fly] close modal only after validation
|
||||
* [person] correct thirdparty PATCH url + add email and altnames in AddPerson and serializer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/433)
|
||||
* change order for accompanying course work list
|
||||
|
@@ -16,8 +16,8 @@ use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Form\CreationPersonType;
|
||||
use Chill\PersonBundle\Form\PersonType;
|
||||
use Chill\PersonBundle\Privacy\PrivacyEvent;
|
||||
use Chill\PersonBundle\Repository\PersonACLAwareRepositoryInterface;
|
||||
use Chill\PersonBundle\Repository\PersonRepository;
|
||||
use Chill\PersonBundle\Search\SimilarPersonMatcher;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||
@@ -56,11 +56,6 @@ final class PersonController extends AbstractController
|
||||
*/
|
||||
protected $personRepository;
|
||||
|
||||
/**
|
||||
* @var SimilarPersonMatcher
|
||||
*/
|
||||
protected $similarPersonMatcher;
|
||||
|
||||
/**
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
@@ -76,13 +71,14 @@ final class PersonController extends AbstractController
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
private PersonACLAwareRepositoryInterface $personACLAwareRepository;
|
||||
|
||||
/**
|
||||
* @var ValidatorInterface
|
||||
*/
|
||||
private $validator;
|
||||
|
||||
public function __construct(
|
||||
SimilarPersonMatcher $similarPersonMatcher,
|
||||
TranslatorInterface $translator,
|
||||
EventDispatcherInterface $eventDispatcher,
|
||||
PersonRepository $personRepository,
|
||||
@@ -90,9 +86,9 @@ final class PersonController extends AbstractController
|
||||
LoggerInterface $logger,
|
||||
ValidatorInterface $validator,
|
||||
EntityManagerInterface $em,
|
||||
Security $security
|
||||
Security $security,
|
||||
PersonACLAwareRepositoryInterface $personACLAwareRepository
|
||||
) {
|
||||
$this->similarPersonMatcher = $similarPersonMatcher;
|
||||
$this->translator = $translator;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->configPersonAltNameHelper = $configPersonAltNameHelper;
|
||||
@@ -101,6 +97,7 @@ final class PersonController extends AbstractController
|
||||
$this->validator = $validator;
|
||||
$this->em = $em;
|
||||
$this->security = $security;
|
||||
$this->personACLAwareRepository = $personACLAwareRepository;
|
||||
}
|
||||
|
||||
public function editAction($person_id, Request $request)
|
||||
@@ -236,8 +233,8 @@ final class PersonController extends AbstractController
|
||||
$request->getMethod() === Request::METHOD_POST
|
||||
&& $form->isValid()
|
||||
) {
|
||||
$alternatePersons = $this->similarPersonMatcher
|
||||
->matchPerson($person);
|
||||
$alternatePersons = $this->personACLAwareRepository
|
||||
->findMatchingPersons($person);
|
||||
|
||||
if (
|
||||
false === $this->isLastPostDataChanges($form, $request, true)
|
||||
|
@@ -20,9 +20,9 @@ use Chill\PersonBundle\Entity\PersonNotDuplicate;
|
||||
use Chill\PersonBundle\Form\PersonConfimDuplicateType;
|
||||
use Chill\PersonBundle\Form\PersonFindManuallyDuplicateType;
|
||||
use Chill\PersonBundle\Privacy\PrivacyEvent;
|
||||
use Chill\PersonBundle\Repository\PersonACLAwareRepositoryInterface;
|
||||
use Chill\PersonBundle\Repository\PersonNotDuplicateRepository;
|
||||
use Chill\PersonBundle\Repository\PersonRepository;
|
||||
use Chill\PersonBundle\Search\SimilarPersonMatcher;
|
||||
use Chill\TaskBundle\Entity\SingleTask;
|
||||
use http\Exception\InvalidArgumentException;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
@@ -39,6 +39,11 @@ class PersonDuplicateController extends Controller
|
||||
*/
|
||||
private $eventDispatcher;
|
||||
|
||||
/**
|
||||
* @var PersonACLAwareRepositoryInterface
|
||||
*/
|
||||
private $personACLAwareRepository;
|
||||
|
||||
/**
|
||||
* @var \Chill\PersonBundle\Actions\Remove\PersonMove
|
||||
*/
|
||||
@@ -49,24 +54,19 @@ class PersonDuplicateController extends Controller
|
||||
*/
|
||||
private $personRepository;
|
||||
|
||||
/**
|
||||
* @var \Chill\PersonBundle\Search\SimilarPersonMatcher
|
||||
*/
|
||||
private $similarPersonMatcher;
|
||||
|
||||
/**
|
||||
* @var \Symfony\Component\Translation\TranslatorInterface
|
||||
*/
|
||||
private $translator;
|
||||
|
||||
public function __construct(
|
||||
SimilarPersonMatcher $similarPersonMatcher,
|
||||
PersonACLAwareRepositoryInterface $personACLAwareRepository,
|
||||
TranslatorInterface $translator,
|
||||
PersonRepository $personRepository,
|
||||
PersonMove $personMove,
|
||||
EventDispatcherInterface $eventDispatcher
|
||||
) {
|
||||
$this->similarPersonMatcher = $similarPersonMatcher;
|
||||
$this->personACLAwareRepository = $personACLAwareRepository;
|
||||
$this->translator = $translator;
|
||||
$this->personRepository = $personRepository;
|
||||
$this->personMove = $personMove;
|
||||
@@ -246,8 +246,11 @@ class PersonDuplicateController extends Controller
|
||||
'You are not allowed to see this person.'
|
||||
);
|
||||
|
||||
$duplicatePersons = $this->similarPersonMatcher->
|
||||
matchPerson($person, $personNotDuplicateRepository, 0.5, SimilarPersonMatcher::SIMILAR_SEARCH_ORDER_BY_ALPHABETICAL);
|
||||
$duplicatePersons = $this->personACLAwareRepository->findMatchingPersons(
|
||||
$person,
|
||||
0.5,
|
||||
PersonACLAwareRepositoryInterface::SIMILAR_SEARCH_ORDER_BY_ALPHABETICAL
|
||||
);
|
||||
|
||||
$notDuplicatePersons = $personNotDuplicateRepository->findNotDuplicatePerson($person);
|
||||
|
||||
|
@@ -18,6 +18,7 @@ use Chill\MainBundle\Search\SearchApiQuery;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Chill\PersonBundle\Templating\Entity\PersonRender;
|
||||
use DateTimeInterface;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\NonUniqueResultException;
|
||||
@@ -40,18 +41,26 @@ final class PersonACLAwareRepository implements PersonACLAwareRepositoryInterfac
|
||||
|
||||
private EntityManagerInterface $em;
|
||||
|
||||
private PersonNotDuplicateRepository $personNotDuplicateRepository;
|
||||
|
||||
private PersonRender $personRender;
|
||||
|
||||
private Security $security;
|
||||
|
||||
public function __construct(
|
||||
Security $security,
|
||||
EntityManagerInterface $em,
|
||||
CountryRepository $countryRepository,
|
||||
AuthorizationHelper $authorizationHelper
|
||||
AuthorizationHelper $authorizationHelper,
|
||||
PersonRender $personRender,
|
||||
PersonNotDuplicateRepository $personNotDuplicateRepository
|
||||
) {
|
||||
$this->security = $security;
|
||||
$this->em = $em;
|
||||
$this->countryRepository = $countryRepository;
|
||||
$this->authorizationHelper = $authorizationHelper;
|
||||
$this->personRender = $personRender;
|
||||
$this->personNotDuplicateRepository = $personNotDuplicateRepository;
|
||||
}
|
||||
|
||||
public function buildAuthorizedQuery(
|
||||
@@ -297,6 +306,70 @@ final class PersonACLAwareRepository implements PersonACLAwareRepositoryInterfac
|
||||
return $this->fetchQueryPerson($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NonUniqueResultException
|
||||
* @throws ParsingException
|
||||
*
|
||||
* @return array|Person[]
|
||||
*/
|
||||
public function findMatchingPersons(
|
||||
Person $person,
|
||||
float $precision = 0.15,
|
||||
string $orderBy = self::SIMILAR_SEARCH_ORDER_BY_SIMILARITY
|
||||
): array {
|
||||
$query = $this->matchPerson($person, $precision, $orderBy);
|
||||
$authorizedQuery = $this->addAuthorizations($query);
|
||||
|
||||
return $this->fetchQueryPerson($authorizedQuery);
|
||||
}
|
||||
|
||||
public function matchPerson(
|
||||
Person $person,
|
||||
float $precision = 0.15,
|
||||
string $orderBy = self::SIMILAR_SEARCH_ORDER_BY_SIMILARITY
|
||||
): SearchApiQuery {
|
||||
$fullName = $this->personRender->renderString($person, []);
|
||||
|
||||
$query = new SearchApiQuery();
|
||||
$query->setFromClause('chill_person_person AS person');
|
||||
$query->andWhereClause(
|
||||
'SIMILARITY(person.fullnameCanonical, UNACCENT(LOWER(?))) >= ?',
|
||||
[$fullName, $precision]
|
||||
);
|
||||
|
||||
if (null !== $person->getId()) {
|
||||
$query->andWhereClause(
|
||||
'person.id != ?',
|
||||
[$person->getId()]
|
||||
);
|
||||
|
||||
$notDuplicatePersons = $this->personNotDuplicateRepository->findNotDuplicatePerson($person);
|
||||
|
||||
if (count($notDuplicatePersons)) {
|
||||
$query->andWhereClause(
|
||||
'person.id NOT IN (?)',
|
||||
[$notDuplicatePersons]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
switch ($orderBy) {
|
||||
case self::SIMILAR_SEARCH_ORDER_BY_ALPHABETICAL:
|
||||
$query->setSelectPertinence('person.fullnameCanonical');
|
||||
|
||||
break;
|
||||
|
||||
case self::SIMILAR_SEARCH_ORDER_BY_SIMILARITY:
|
||||
default:
|
||||
$query->setSelectPertinence(
|
||||
'SIMILARITY(person.fullnameCanonical, UNACCENT(LOWER(?)))',
|
||||
[$fullName]
|
||||
);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
private function addAuthorizations(SearchApiQuery $query): SearchApiQuery
|
||||
{
|
||||
$authorizedCenters = $this->authorizationHelper
|
||||
|
@@ -17,6 +17,10 @@ use DateTimeInterface;
|
||||
|
||||
interface PersonACLAwareRepositoryInterface
|
||||
{
|
||||
public const SIMILAR_SEARCH_ORDER_BY_ALPHABETICAL = 'alphabetical';
|
||||
|
||||
public const SIMILAR_SEARCH_ORDER_BY_SIMILARITY = 'similarity';
|
||||
|
||||
public function buildAuthorizedQuery(
|
||||
?string $default = null,
|
||||
?string $firstname = null,
|
||||
@@ -61,4 +65,13 @@ interface PersonACLAwareRepositoryInterface
|
||||
?string $phonenumber = null,
|
||||
?string $city = null
|
||||
): array;
|
||||
|
||||
/**
|
||||
* @return array|Person[]
|
||||
*/
|
||||
public function findMatchingPersons(
|
||||
Person $person,
|
||||
float $precision = 0.15,
|
||||
string $orderBy = self::SIMILAR_SEARCH_ORDER_BY_SIMILARITY
|
||||
): array;
|
||||
}
|
||||
|
@@ -17,6 +17,15 @@
|
||||
|
||||
{% block title %}{{ 'Add a person'|trans }}{% endblock title %}
|
||||
|
||||
{% macro button_person_after(person) %}
|
||||
{% set household = person.getCurrentHousehold %}
|
||||
{% if household is not null %}
|
||||
<li>
|
||||
<a href="{{ path('chill_person_household_summary', { 'household_id': household.id }) }}" class="btn btn-sm btn-chill-beige"><i class="fa fa-home"></i></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% block content %}
|
||||
<div class="col-md-10 col-xxl person-new">
|
||||
|
||||
@@ -31,34 +40,24 @@
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<table class="table table-bordered border-dark">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="chill-red">{{ 'Name'|trans }}</th>
|
||||
<th class="chill-green">{{ 'Date of birth'|trans }}</th>
|
||||
<th class="chill-orange">{{ 'Nationality'|trans }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<div class="flex-table">
|
||||
{% for person in alternatePersons %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ path('chill_person_view', {'person_id': person.id } ) }}">
|
||||
{{ person|chill_entity_render_string }}{% apply spaceless %}
|
||||
{% if person.isOpen == false %}
|
||||
<i class="icon-lock"></i>
|
||||
{% endif %}
|
||||
{% endapply %}
|
||||
</a>
|
||||
</td>
|
||||
<td>{% if person.birthdate is not null %}{{ person.birthdate|format_date('long') }}{% else %} {% endif %}</td>
|
||||
<td>
|
||||
{% if person.nationality is not null %}{{ person.nationality.name|localize_translatable_string }}{% else %}{{ 'Without nationality'|trans }}{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<div class="item-bloc">
|
||||
|
||||
{{ person|chill_entity_render_box({
|
||||
'render': 'bloc',
|
||||
'addLink': true,
|
||||
'addInfo': true,
|
||||
'addAge': true,
|
||||
'addAltNames': true,
|
||||
'addCenter': true,
|
||||
'address_multiline': false,
|
||||
'customButtons': { 'after': _self.button_person_after(person) }
|
||||
}) }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{{ form_start(form, {'attr' : {'id' : 'create-form'}}) }}
|
||||
|
@@ -21,6 +21,9 @@ use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInt
|
||||
|
||||
use function count;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
class SimilarPersonMatcher
|
||||
{
|
||||
public const SIMILAR_SEARCH_ORDER_BY_ALPHABETICAL = 'alphabetical';
|
||||
|
@@ -24,7 +24,7 @@ services:
|
||||
|
||||
Chill\PersonBundle\Controller\PersonDuplicateController:
|
||||
arguments:
|
||||
$similarPersonMatcher: '@Chill\PersonBundle\Search\SimilarPersonMatcher'
|
||||
$personACLAwareRepository: '@Chill\PersonBundle\Repository\PersonACLAwareRepositoryInterface'
|
||||
$translator: '@Symfony\Component\Translation\TranslatorInterface'
|
||||
$personRepository: '@Chill\PersonBundle\Repository\PersonRepository'
|
||||
$personMove: '@Chill\PersonBundle\Actions\Remove\PersonMove'
|
||||
|
Reference in New Issue
Block a user