chill-bundles/src/Bundle/ChillPersonBundle/Search/SimilarPersonMatcher.php
2021-05-18 12:02:00 +02:00

111 lines
3.7 KiB
PHP

<?php
/*
*
* Copyright (C) 2018, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Chill\PersonBundle\Search;
use Chill\PersonBundle\Entity\PersonNotDuplicate;
use Doctrine\ORM\EntityManagerInterface;
use Chill\PersonBundle\Entity\Person;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\PersonBundle\Repository\PersonNotDuplicateRepository;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Role\Role;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class SimilarPersonMatcher
{
CONST SIMILAR_SEARCH_ORDER_BY_ALPHABETICAL = 'alphabetical';
CONST SIMILAR_SEARCH_ORDER_BY_SIMILARITY = 'similarity';
/**
* @var EntityManagerInterface
*/
protected $em;
/**
* @var AuthorizationHelper
*/
protected $authorizationHelper;
/**
* @var TokenStorageInterface
*/
protected $tokenStorage;
public function __construct(
EntityManagerInterface $em,
AuthorizationHelper $authorizationHelper,
TokenStorageInterface $tokenStorage
) {
$this->em = $em;
$this->authorizationHelper = $authorizationHelper;
$this->tokenStorage = $tokenStorage;
}
public function matchPerson(Person $person, PersonNotDuplicateRepository $personNotDuplicateRepository, $precision = 0.15, $orderBy = self::SIMILAR_SEARCH_ORDER_BY_SIMILARITY)
{
$centers = $this->authorizationHelper->getReachableCenters(
$this->tokenStorage->getToken()->getUser(),
new Role(PersonVoter::SEE)
);
$dql = 'SELECT p from ChillPersonBundle:Person p '
. ' WHERE ('
. ' SIMILARITY(p.fullnameCanonical, UNACCENT(LOWER(:fullName))) >= :precision '
. ' ) '
. ' AND p.center IN (:centers)'
. ' AND p.id != :personId '
;
$notDuplicatePersons = $personNotDuplicateRepository->findNotDuplicatePerson($person);
if (count($notDuplicatePersons)) {
$dql .= ' AND p.id not in (:notDuplicatePersons)';
}
switch ($orderBy) {
case self::SIMILAR_SEARCH_ORDER_BY_ALPHABETICAL:
$dql .= ' ORDER BY p.fullnameCanonical ASC ';
break;
case self::SIMILAR_SEARCH_ORDER_BY_SIMILARITY:
default :
$dql .= ' ORDER BY SIMILARITY(p.fullnameCanonical, UNACCENT(LOWER(:fullName))) DESC ';
}
$query = $this->em
->createQuery($dql)
->setParameter('fullName', $person->getFirstName() . ' ' . $person->getLastName())
->setParameter('centers', $centers)
->setParameter('personId', $person->getId())
->setParameter('precision', $precision)
;
if (count($notDuplicatePersons)) {
$query->setParameter('notDuplicatePersons', $notDuplicatePersons);
}
return $query->getResult();
}
}