Compare commits

..

5 Commits

25 changed files with 366 additions and 277 deletions

View File

@@ -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

View File

@@ -15,13 +15,19 @@ use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Translation\TranslatorInterface;
class PersonMenuBuilder implements LocalMenuBuilderInterface
{
protected AuthorizationCheckerInterface $authorizationChecker;
/**
* @var AuthorizationCheckerInterface
*/
protected $authorizationChecker;
protected TranslatorInterface $translator;
/**
* @var TranslatorInterface
*/
protected $translator;
public function __construct(
AuthorizationCheckerInterface $authorizationChecker,

View File

@@ -16,17 +16,29 @@ use Chill\TaskBundle\Templating\UI\CountNotificationTask;
use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Translation\TranslatorInterface;
class UserMenuBuilder implements LocalMenuBuilderInterface
{
public AuthorizationCheckerInterface $authorizationChecker;
/**
* @var AuthorizationCheckerInterface
*/
public $authorizationChecker;
public CountNotificationTask $counter;
/**
* @var CountNotificationTask
*/
public $counter;
public TokenStorageInterface $tokenStorage;
/**
* @var TokenStorageInterface
*/
public $tokenStorage;
public TranslatorInterface $translator;
/**
* @var TranslatorInterface
*/
public $translator;
public function __construct(
CountNotificationTask $counter,

View File

@@ -14,18 +14,14 @@ namespace Chill\CalendarBundle\Menu;
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\Translation\TranslatorInterface;
class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
{
protected AuthorizationHelper $authorizationHelper;
protected Security $security;
protected TokenStorageInterface $tokenStorage;
protected TranslatorInterface $translator;
@@ -33,13 +29,11 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
public function __construct(
TokenStorageInterface $tokenStorage,
AuthorizationHelper $authorizationHelper,
TranslatorInterface $translator,
Security $security
TranslatorInterface $translator
) {
$this->translator = $translator;
$this->authorizationHelper = $authorizationHelper;
$this->tokenStorage = $tokenStorage;
$this->security = $security;
}
public function buildMenu($menuId, MenuItem $menu, array $parameters)
@@ -47,14 +41,12 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
$period = $parameters['accompanyingCourse'];
if (AccompanyingPeriod::STEP_DRAFT !== $period->getStep()) {
if ($this->security->isGranted(AccompanyingPeriodVoter::SEE, $period)) {
$menu->addChild($this->translator->trans('Calendar'), [
'route' => 'chill_calendar_calendar_list',
'routeParameters' => [
'accompanying_period_id' => $period->getId(),
], ])
->setExtras(['order' => 35]);
}
$menu->addChild($this->translator->trans('Calendar'), [
'route' => 'chill_calendar_calendar_list',
'routeParameters' => [
'accompanying_period_id' => $period->getId(),
], ])
->setExtras(['order' => 35]);
}
}

View File

@@ -15,13 +15,19 @@ use Chill\AMLI\FamilyMembersBundle\Security\Voter\FamilyMemberVoter;
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Translation\TranslatorInterface;
class UserMenuBuilder implements LocalMenuBuilderInterface
{
protected AuthorizationCheckerInterface $authorizationChecker;
/**
* @var AuthorizationCheckerInterface
*/
protected $authorizationChecker;
protected TranslatorInterface $translator;
/**
* @var TranslatorInterface
*/
protected $translator;
public function __construct(
AuthorizationCheckerInterface $authorizationChecker,

View File

@@ -12,23 +12,11 @@ declare(strict_types=1);
namespace Chill\MainBundle\Routing\MenuBuilder;
use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
class LocationMenuBuilder implements \Chill\MainBundle\Routing\LocalMenuBuilderInterface
{
private AuthorizationCheckerInterface $authorizationChecker;
public function __construct(AuthorizationCheckerInterface $authorizationChecker)
{
$this->authorizationChecker = $authorizationChecker;
}
public function buildMenu($menuId, MenuItem $menu, array $parameters)
{
if (!$this->authorizationChecker->isGranted('ROLE_ADMIN')) {
return;
}
$menu->addChild('Location type list', [
'route' => 'chill_crud_main_location_type_index',
])->setExtras(['order' => 205]);

View File

@@ -12,23 +12,11 @@ declare(strict_types=1);
namespace Chill\MainBundle\Routing\MenuBuilder;
use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
class PermissionMenuBuilder implements \Chill\MainBundle\Routing\LocalMenuBuilderInterface
{
private AuthorizationCheckerInterface $authorizationChecker;
public function __construct(AuthorizationCheckerInterface $authorizationChecker)
{
$this->authorizationChecker = $authorizationChecker;
}
public function buildMenu($menuId, MenuItem $menu, array $parameters)
{
if (!$this->authorizationChecker->isGranted('ROLE_ADMIN')) {
return;
}
$menu->addChild('Permissions group list', [
'route' => 'admin_permissionsgroup',
])->setExtras([

View File

@@ -15,16 +15,22 @@ use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Chill\MainBundle\Security\Authorization\ChillExportVoter;
use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Translation\TranslatorInterface;
/**
* Class SectionMenuBuilder.
*/
class SectionMenuBuilder implements LocalMenuBuilderInterface
{
protected AuthorizationCheckerInterface $authorizationChecker;
/**
* @var AuthorizationCheckerInterface
*/
protected $authorizationChecker;
protected TranslatorInterface $translator;
/**
* @var TranslatorInterface
*/
protected $translator;
/**
* SectionMenuBuilder constructor.
@@ -40,24 +46,22 @@ class SectionMenuBuilder implements LocalMenuBuilderInterface
*/
public function buildMenu($menuId, MenuItem $menu, array $parameters)
{
if (!$this->authorizationChecker->isGranted('ROLE_USER')) {
$menu->addChild($this->translator->trans('Homepage'), [
'route' => 'chill_main_homepage',
])
->setExtras([
'icons' => ['home'],
'order' => 0,
]);
$menu->addChild($this->translator->trans('Homepage'), [
'route' => 'chill_main_homepage',
])
->setExtras([
'icons' => ['home'],
'order' => 0,
]);
$menu->addChild($this->translator->trans('Global timeline'), [
'route' => 'chill_center_timeline',
])
->setExtras(
[
'order' => 10,
]
);
}
$menu->addChild($this->translator->trans('Global timeline'), [
'route' => 'chill_center_timeline',
])
->setExtras(
[
'order' => 10,
]
);
if ($this->authorizationChecker->isGranted(ChillExportVoter::EXPORT)) {
$menu->addChild($this->translator->trans('Export Menu'), [

View File

@@ -15,14 +15,11 @@ use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Notification\Counter\NotificationByUserCounter;
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Chill\MainBundle\Workflow\Counter\WorkflowByUserCounter;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\Translation\TranslatorInterface;
class UserMenuBuilder implements LocalMenuBuilderInterface
{
private AuthorizationCheckerInterface $authorizationChecker;
private NotificationByUserCounter $notificationByUserCounter;
private Security $security;
@@ -35,22 +32,16 @@ class UserMenuBuilder implements LocalMenuBuilderInterface
NotificationByUserCounter $notificationByUserCounter,
WorkflowByUserCounter $workflowByUserCounter,
Security $security,
TranslatorInterface $translator,
AuthorizationCheckerInterface $authorizationChecker
TranslatorInterface $translator
) {
$this->notificationByUserCounter = $notificationByUserCounter;
$this->workflowByUserCounter = $workflowByUserCounter;
$this->security = $security;
$this->translator = $translator;
$this->authorizationChecker = $authorizationChecker;
}
public function buildMenu($menuId, \Knp\Menu\MenuItem $menu, array $parameters)
{
if (!$this->authorizationChecker->isGranted('ROLE_USER')) {
return;
}
$user = $this->security->getUser();
if ($user instanceof User) {

View File

@@ -19,7 +19,6 @@ use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Form\HouseholdMemberType;
use Chill\PersonBundle\Household\MembersEditor;
use Chill\PersonBundle\Repository\AccompanyingPeriodRepository;
use Chill\PersonBundle\Security\Authorization\HouseholdVoter;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
use Symfony\Component\HttpFoundation\Request;
@@ -27,7 +26,7 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Serializer\Exception;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Translation\TranslatorInterface;
use function count;
@@ -57,7 +56,7 @@ class HouseholdMemberController extends ApiController
*/
public function editMembership(Request $request, HouseholdMember $member): Response
{
$this->denyAccessUnlessGranted(HouseholdVoter::EDIT, $member);
// TODO ACL
$form = $this->createForm(HouseholdMemberType::class, $member, [
'validation_groups' => ['household_memberships'],

View File

@@ -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)

View File

@@ -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);

View File

@@ -29,7 +29,10 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
protected Security $security;
protected TranslatorInterface $translator;
/**
* @var TranslatorInterface
*/
protected $translator;
public function __construct(TranslatorInterface $translator, Registry $registry, Security $security)
{
@@ -43,14 +46,12 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
/** @var AccompanyingPeriod $period */
$period = $parameters['accompanyingCourse'];
if ($this->security->isGranted(AccompanyingPeriodVoter::SEE, $period)) {
$menu->addChild($this->translator->trans('Resume Accompanying Course'), [
'route' => 'chill_person_accompanying_course_index',
'routeParameters' => [
'accompanying_period_id' => $period->getId(),
], ])
->setExtras(['order' => 10]);
}
$menu->addChild($this->translator->trans('Resume Accompanying Course'), [
'route' => 'chill_person_accompanying_course_index',
'routeParameters' => [
'accompanying_period_id' => $period->getId(),
], ])
->setExtras(['order' => 10]);
if ($this->security->isGranted(AccompanyingPeriodVoter::EDIT, $period)) {
$menu->addChild($this->translator->trans('Edit Accompanying Course'), [
@@ -93,24 +94,22 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
$workflow = $this->registry->get($period, 'accompanying_period_lifecycle');
if ($this->security->isGranted(AccompanyingPeriodVoter::EDIT, $period)) {
if (null !== $period->getClosingDate()) {
$menu->addChild($this->translator->trans('Re-open accompanying course'), [
'route' => 'chill_person_accompanying_course_reopen',
'routeParameters' => [
'accompanying_period_id' => $period->getId(),
], ])
->setExtras(['order' => 99998]);
}
if (null !== $period->getClosingDate()) {
$menu->addChild($this->translator->trans('Re-open accompanying course'), [
'route' => 'chill_person_accompanying_course_reopen',
'routeParameters' => [
'accompanying_period_id' => $period->getId(),
], ])
->setExtras(['order' => 99998]);
}
if ($workflow->can($period, 'close')) {
$menu->addChild($this->translator->trans('Close Accompanying Course'), [
'route' => 'chill_person_accompanying_course_close',
'routeParameters' => [
'accompanying_period_id' => $period->getId(),
], ])
->setExtras(['order' => 99999]);
}
if ($workflow->can($period, 'close')) {
$menu->addChild($this->translator->trans('Close Accompanying Course'), [
'route' => 'chill_person_accompanying_course_close',
'routeParameters' => [
'accompanying_period_id' => $period->getId(),
], ])
->setExtras(['order' => 99999]);
}
}

View File

@@ -12,9 +12,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Menu;
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Chill\PersonBundle\Security\Authorization\HouseholdVoter;
use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\Translation\TranslatorInterface;
class HouseholdMenuBuilder implements LocalMenuBuilderInterface
@@ -24,12 +22,9 @@ class HouseholdMenuBuilder implements LocalMenuBuilderInterface
*/
protected $translator;
private $security;
public function __construct(TranslatorInterface $translator, Security $security)
public function __construct(TranslatorInterface $translator)
{
$this->translator = $translator;
$this->security = $security;
}
public function buildMenu($menuId, MenuItem $menu, array $parameters): void
@@ -37,46 +32,40 @@ class HouseholdMenuBuilder implements LocalMenuBuilderInterface
/** @var \Chill\PersonBundle\Entity\Household\Household $household */
$household = $parameters['household'];
if ($this->security->isGranted(HouseholdVoter::SEE, $household)) {
$menu->addChild($this->translator->trans('household.Household summary'), [
'route' => 'chill_person_household_summary',
'routeParameters' => [
'household_id' => $household->getId(),
], ])
->setExtras(['order' => 10]);
$menu->addChild($this->translator->trans('household.Household summary'), [
'route' => 'chill_person_household_summary',
'routeParameters' => [
'household_id' => $household->getId(),
], ])
->setExtras(['order' => 10]);
$menu->addChild($this->translator->trans('household.Relationship'), [
'route' => 'chill_person_household_relationship',
'routeParameters' => [
'household_id' => $household->getId(),
], ])
->setExtras(['order' => 15]);
}
$menu->addChild($this->translator->trans('household.Relationship'), [
'route' => 'chill_person_household_relationship',
'routeParameters' => [
'household_id' => $household->getId(),
], ])
->setExtras(['order' => 15]);
if ($this->security->isGranted(HouseholdVoter::EDIT, $household)) {
$menu->addChild($this->translator->trans('household_composition.Compositions'), [
'route' => 'chill_person_household_composition_index',
'routeParameters' => [
'id' => $household->getId(),
], ])
->setExtras(['order' => 17]);
}
$menu->addChild($this->translator->trans('household_composition.Compositions'), [
'route' => 'chill_person_household_composition_index',
'routeParameters' => [
'id' => $household->getId(),
], ])
->setExtras(['order' => 17]);
if ($this->security->isGranted(HouseholdVoter::SEE, $household)) {
$menu->addChild($this->translator->trans('household.Accompanying period'), [
'route' => 'chill_person_household_accompanying_period',
'routeParameters' => [
'household_id' => $household->getId(),
], ])
->setExtras(['order' => 20]);
$menu->addChild($this->translator->trans('household.Accompanying period'), [
'route' => 'chill_person_household_accompanying_period',
'routeParameters' => [
'household_id' => $household->getId(),
], ])
->setExtras(['order' => 20]);
$menu->addChild($this->translator->trans('household.Addresses'), [
'route' => 'chill_person_household_addresses',
'routeParameters' => [
'household_id' => $household->getId(),
], ])
->setExtras(['order' => 30]);
}
$menu->addChild($this->translator->trans('household.Addresses'), [
'route' => 'chill_person_household_addresses',
'routeParameters' => [
'household_id' => $household->getId(),
], ])
->setExtras(['order' => 30]);
}
public static function getMenuIds(): array

View File

@@ -13,7 +13,6 @@ namespace Chill\PersonBundle\Menu;
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Knp\Menu\MenuItem;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Security\Core\Security;
@@ -34,7 +33,10 @@ class PersonMenuBuilder implements LocalMenuBuilderInterface
*/
protected $showAccompanyingPeriod;
protected TranslatorInterface $translator;
/**
* @var TranslatorInterface
*/
protected $translator;
private Security $security;
@@ -50,46 +52,45 @@ class PersonMenuBuilder implements LocalMenuBuilderInterface
public function buildMenu($menuId, MenuItem $menu, array $parameters)
{
if ($this->security->isGranted(PersonVoter::SEE, $parameters['person'])) {
$menu->addChild($this->translator->trans('Person details'), [
'route' => 'chill_person_view',
'routeParameters' => [
'person_id' => $parameters['person']->getId(),
],
])
->setExtras([
'order' => 50,
]);
$menu->addChild($this->translator->trans('Residential addresses'), [
'route' => 'chill_person_residential_address_list',
'routeParameters' => [
'id' => $parameters['person']->getId(),
],
])
->setExtras([
'order' => 60,
]);
$menu->addChild($this->translator->trans('Person details'), [
'route' => 'chill_person_view',
'routeParameters' => [
'person_id' => $parameters['person']->getId(),
],
])
->setExtras([
'order' => 50,
]);
$menu->addChild($this->translator->trans('household.person history'), [
'route' => 'chill_person_household_person_history',
'routeParameters' => [
'person_id' => $parameters['person']->getId(),
],
])
->setExtras([
'order' => 99999,
]);
$menu->addChild($this->translator->trans('Residential addresses'), [
'route' => 'chill_person_residential_address_list',
'routeParameters' => [
'id' => $parameters['person']->getId(),
],
])
->setExtras([
'order' => 60,
]);
$menu->addChild($this->translator->trans('Person duplicate'), [
'route' => 'chill_person_duplicate_view',
'routeParameters' => [
'person_id' => $parameters['person']->getId(),
],
])
->setExtras([
'order' => 99999,
]);
}
$menu->addChild($this->translator->trans('household.person history'), [
'route' => 'chill_person_household_person_history',
'routeParameters' => [
'person_id' => $parameters['person']->getId(),
],
])
->setExtras([
'order' => 99999,
]);
$menu->addChild($this->translator->trans('Person duplicate'), [
'route' => 'chill_person_duplicate_view',
'routeParameters' => [
'person_id' => $parameters['person']->getId(),
],
])
->setExtras([
'order' => 99999,
]);
if (
'visible' === $this->showAccompanyingPeriod
@@ -106,17 +107,15 @@ class PersonMenuBuilder implements LocalMenuBuilderInterface
]);
}
if ($this->security->isGranted(PersonVoter::SEE, $parameters['person'])) {
$menu->addChild($this->translator->trans('person_resources_menu'), [
'route' => 'chill_person_resource_list',
'routeParameters' => [
'person_id' => $parameters['person']->getId(),
],
])
->setExtras([
'order' => 99999,
]);
}
$menu->addChild($this->translator->trans('person_resources_menu'), [
'route' => 'chill_person_resource_list',
'routeParameters' => [
'person_id' => $parameters['person']->getId(),
],
])
->setExtras([
'order' => 99999,
]);
}
public static function getMenuIds(): array

View File

@@ -12,7 +12,6 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Menu;
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
@@ -57,15 +56,13 @@ class SectionMenuBuilder implements LocalMenuBuilderInterface
]);
}
if ($this->authorizationChecker->isGranted(AccompanyingPeriodVoter::CREATE)) {
$menu->addChild($this->translator->trans('Create an accompanying course'), [
'route' => 'chill_person_accompanying_course_new',
])
->setExtras([
'order' => 11,
'icons' => ['plus'],
]);
}
$menu->addChild($this->translator->trans('Create an accompanying course'), [
'route' => 'chill_person_accompanying_course_new',
])
->setExtras([
'order' => 11,
'icons' => ['plus'],
]);
}
public static function getMenuIds(): array

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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 %}&nbsp;{% 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'}}) }}

View File

@@ -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';

View File

@@ -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'

View File

@@ -16,13 +16,19 @@ use Chill\TaskBundle\Security\Authorization\TaskVoter;
use Knp\Menu\MenuItem;
use LogicException;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Translation\TranslatorInterface;
class MenuBuilder implements LocalMenuBuilderInterface
{
protected AuthorizationCheckerInterface $authorizationChecker;
/**
* @var AuthorizationCheckerInterface
*/
protected $authorizationChecker;
protected TranslatorInterface $translator;
/**
* @var TranslatorInterface
*/
protected $translator;
public function __construct(
AuthorizationCheckerInterface $authorizationChecker,

View File

@@ -15,13 +15,19 @@ use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Chill\TaskBundle\Security\Authorization\TaskVoter;
use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Translation\TranslatorInterface;
class SectionMenuBuilder implements LocalMenuBuilderInterface
{
public AuthorizationCheckerInterface $authorizationChecker;
/**
* @var AuthorizationCheckerInterface
*/
public $authorizationChecker;
public TranslatorInterface $translator;
/**
* @var TranslatorInterface
*/
public $translator;
public function __construct(
AuthorizationCheckerInterface $authorizationChecker,

View File

@@ -17,17 +17,29 @@ use Chill\TaskBundle\Templating\UI\CountNotificationTask;
use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Translation\TranslatorInterface;
class UserMenuBuilder implements LocalMenuBuilderInterface
{
public AuthorizationCheckerInterface $authorizationChecker;
/**
* @var AuthorizationCheckerInterface
*/
public $authorizationChecker;
public CountNotificationTask $counter;
/**
* @var CountNotificationTask
*/
public $counter;
public TokenStorageInterface $tokenStorage;
/**
* @var TokenStorageInterface
*/
public $tokenStorage;
public TranslatorInterface $translator;
/**
* @var TranslatorInterface
*/
public $translator;
public function __construct(
CountNotificationTask $counter,

View File

@@ -15,16 +15,22 @@ use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Chill\ThirdPartyBundle\Security\Voter\ThirdPartyVoter;
use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Translation\TranslatorInterface;
/**
* Add an entry in section to go to third party index page.
*/
class MenuBuilder implements LocalMenuBuilderInterface
{
protected AuthorizationCheckerInterface $authorizationChecker;
/**
* @var AuthorizationCheckerInterface
*/
protected $authorizationChecker;
protected TranslatorInterface $translator;
/**
* @var TranslatorInterface
*/
protected $translator;
public function __construct(
AuthorizationCheckerInterface $authorizationChecker,