From 983ed7a50d2d3ea661b4ab47421cd50c562cf10e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 14 May 2018 17:58:00 +0200 Subject: [PATCH] delegate person matching detection to service `SimilarPersonMatcher` --- Controller/PersonController.php | 43 +++------- DependencyInjection/ChillPersonExtension.php | 2 + Resources/config/services.yml | 11 --- Resources/config/services/controller.yml | 5 ++ Resources/config/services/search.yml | 18 ++++ Search/SimilarPersonMatcher.php | 89 ++++++++++++++++++++ 6 files changed, 128 insertions(+), 40 deletions(-) create mode 100644 Resources/config/services/controller.yml create mode 100644 Resources/config/services/search.yml create mode 100644 Search/SimilarPersonMatcher.php diff --git a/Controller/PersonController.php b/Controller/PersonController.php index 449fe3e47..1f5ef01d4 100644 --- a/Controller/PersonController.php +++ b/Controller/PersonController.php @@ -30,9 +30,21 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Role\Role; use Chill\PersonBundle\Security\Authorization\PersonVoter; +use Chill\PersonBundle\Search\SimilarPersonMatcher; class PersonController extends Controller { + /** + * + * @var SimilarPersonMatcher + */ + protected $similarPersonMatcher; + + public function __construct(SimilarPersonMatcher $similarPersonMatcher) + { + $this->similarPersonMatcher = $similarPersonMatcher; + } + public function getCFGroup() { $cFGroup = null; @@ -266,35 +278,8 @@ class PersonController extends Controller $this->get('logger')->info('Person created without errors'); } - $em = $this->getDoctrine()->getManager(); - - $query = $em->createQuery(); - - $dql = 'SELECT p from ChillPersonBundle:Person p WHERE ' - . 'LOWER(p.firstName) LIKE LOWER(:firstName)' - . ' OR LOWER(p.lastName) LIKE LOWER(:lastName)' - . ' OR LOWER(p.firstName) LIKE LOWER(:lastName)' - . ' OR LOWER(p.lastName) LIKE LOWER(:firstName)'; - - $query->setParameter('firstName', $form['firstName']->getData()) - ->setParameter('lastName', $form['lastName']->getData()); - - if ($this->container - ->getParameter('cl_chill_person.search.use_double_metaphone')) { - $dql .= ' OR DOUBLEMETAPHONE(p.lastName) LIKE DOUBLEMETAPHONE(:lastName) '; - } - - // add authorized centers - $centers = $this->get('chill.main.security.authorization.helper') - ->getReachableCenters($this->getUser(), new Role(PersonVoter::SEE)); - - $dql.=' and p.center IN (:centers) '; - $query->setParameter('centers', $centers); - - // run query - $query->setDql($dql); - - $alternatePersons = $query->getResult(); + $alternatePersons = $this->similarPersonMatcher + ->matchPerson($person); if (count($alternatePersons) === 0) { return $this->forward('ChillPersonBundle:Person:create'); diff --git a/DependencyInjection/ChillPersonExtension.php b/DependencyInjection/ChillPersonExtension.php index 51406153c..31d68701c 100644 --- a/DependencyInjection/ChillPersonExtension.php +++ b/DependencyInjection/ChillPersonExtension.php @@ -58,6 +58,8 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac $loader->load('services/widgets.yml'); $loader->load('services/exports.yml'); $loader->load('services/fixtures.yml'); + $loader->load('services/controller.yml'); + $loader->load('services/search.yml'); } private function handlePersonFieldsParameters(ContainerBuilder $container, $config) diff --git a/Resources/config/services.yml b/Resources/config/services.yml index cfa5c618b..5a61e8378 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -16,17 +16,6 @@ services: tags: - { name: form.type, alias: closing_motive } - chill.person.search_person: - class: Chill\PersonBundle\Search\PersonSearch - arguments: - - "@doctrine.orm.entity_manager" - - "@security.token_storage" - - "@chill.main.security.authorization.helper" - - "@chill_main.paginator_factory" - calls: - - ['setContainer', ["@service_container"]] - tags: - - { name: chill.search, alias: 'person_regular' } chill.person.form.type.select2maritalstatus: class: Chill\PersonBundle\Form\Type\Select2MaritalStatusType arguments: diff --git a/Resources/config/services/controller.yml b/Resources/config/services/controller.yml new file mode 100644 index 000000000..174edbf0a --- /dev/null +++ b/Resources/config/services/controller.yml @@ -0,0 +1,5 @@ +services: + Chill\PersonBundle\Controller\PersonController: + arguments: + $similarPersonMatcher: '@Chill\PersonBundle\Search\SimilarPersonMatcher' + tags: ['controller.service_arguments'] diff --git a/Resources/config/services/search.yml b/Resources/config/services/search.yml new file mode 100644 index 000000000..2abffbea5 --- /dev/null +++ b/Resources/config/services/search.yml @@ -0,0 +1,18 @@ +services: + chill.person.search_person: + class: Chill\PersonBundle\Search\PersonSearch + arguments: + - "@doctrine.orm.entity_manager" + - "@security.token_storage" + - "@chill.main.security.authorization.helper" + - "@chill_main.paginator_factory" + calls: + - ['setContainer', ["@service_container"]] + tags: + - { name: chill.search, alias: 'person_regular' } + + Chill\PersonBundle\Search\SimilarPersonMatcher: + arguments: + $em: '@Doctrine\ORM\EntityManagerInterface' + $tokenStorage: '@Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface' + $authorizationHelper: '@Chill\MainBundle\Security\Authorization\AuthorizationHelper' diff --git a/Search/SimilarPersonMatcher.php b/Search/SimilarPersonMatcher.php new file mode 100644 index 000000000..7d672d4df --- /dev/null +++ b/Search/SimilarPersonMatcher.php @@ -0,0 +1,89 @@ + + * + * 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 . + */ +namespace Chill\PersonBundle\Search; + +use Doctrine\ORM\EntityManagerInterface; +use Chill\PersonBundle\Entity\Person; +use Chill\MainBundle\Security\Authorization\AuthorizationHelper; +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é + */ +class SimilarPersonMatcher +{ + /** + * + * @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) + { + $centers = $this->authorizationHelper + ->getReachableCenters( + $this->tokenStorage->getToken()->getUser(), + new Role(PersonVoter::SEE) + ); + + $dql = 'SELECT p from ChillPersonBundle:Person p WHERE' + . ' UNACCENT(LOWER(p.firstName)) LIKE UNACCENT(LOWER(:firstName))' + . ' OR UNACCENT(LOWER(p.lastName)) LIKE UNACCENT(LOWER(:lastName))' + . ' OR UNACCENT(LOWER(p.firstName)) LIKE UNACCENT(LOWER(:lastName))' + . ' OR UNACCENT(LOWER(p.lastName)) LIKE UNACCENT(LOWER(:firstName))' + . ' AND p.center IN (:centers)'; + + $query = + $this->em + ->createQuery($dql) + ->setParameter('firstName', $person->getFirstName()) + ->setParameter('lastName', $person->getLastName()) + ->setParameter('centers', $centers) + ; + + return $query->getResult(); + } +}