diff --git a/Resources/config/services/widgets.yml b/Resources/config/services/widgets.yml index 1d7c3c0f5..7ea920cc2 100644 --- a/Resources/config/services/widgets.yml +++ b/Resources/config/services/widgets.yml @@ -3,6 +3,7 @@ services: class: Chill\PersonBundle\Widget\PersonListWidget arguments: - "@chill.person.repository.person" + - "@doctrine.orm.entity_manager" - "@chill.main.security.authorization.helper" - "@security.token_storage" # this widget is defined by the PersonListWidgetFactory diff --git a/Widget/PersonListWidget.php b/Widget/PersonListWidget.php index 46a4a5361..18e55a017 100644 --- a/Widget/PersonListWidget.php +++ b/Widget/PersonListWidget.php @@ -28,6 +28,7 @@ use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; use Chill\PersonBundle\Security\Authorization\PersonVoter; use Symfony\Component\Security\Core\Role\Role; +use Doctrine\ORM\EntityManager; /** * add a widget with person list. @@ -44,6 +45,13 @@ class PersonListWidget implements WidgetInterface */ protected $personRepository; + /** + * The entity manager + * + * @var EntityManager + */ + protected $entityManager; + /** * the authorization helper * @@ -65,13 +73,14 @@ class PersonListWidget implements WidgetInterface public function __construct( EntityRepository $personRepostory, + EntityManager $em, AuthorizationHelper $authorizationHelper, TokenStorage $tokenStorage ) { $this->personRepository = $personRepostory; $this->authorizationHelper = $authorizationHelper; $this->tokenStorage = $tokenStorage; - + $this->entityManager = $em; } /** @@ -94,7 +103,7 @@ class PersonListWidget implements WidgetInterface $qb->setParameter('centers', $centers); - + // add the "only active" query if ($config['only_active'] === true) { $qb->join('person.accompanyingPeriods', 'ap'); $or = new Expr\Orx(); @@ -110,6 +119,23 @@ class PersonListWidget implements WidgetInterface $and->add($or); $qb->setParameter('now', new \DateTime(), Type::DATE); } + + + if ($config['filtering_class'] !== NULL) { + $filteringClass = new $config['filtering_class']; + if ( ! $filteringClass instanceof PersonListWidget\PersonFilteringInterface) { + throw new \UnexpectedValueException(sprintf("the class %s does not " + . "implements %s", $config['filtering_class'], + PersonListWidget\PersonFilteringInterface::class)); + } + $ids = $filteringClass->getPersonIds($this->entityManager, + $this->getUser()); + $in = (new Expr())->in('person.id', ':ids'); + $and->add($in); + $qb->setParameter('ids', $ids); + } + + // adding the where clause to the query $qb->where($and); diff --git a/Widget/PersonListWidget/PersonFilteringInterface.php b/Widget/PersonListWidget/PersonFilteringInterface.php new file mode 100644 index 000000000..555884cc1 --- /dev/null +++ b/Widget/PersonListWidget/PersonFilteringInterface.php @@ -0,0 +1,85 @@ + + * + * 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\Widget\PersonListWidget; + +use Doctrine\ORM\EntityManager; +use Chill\MainBundle\Entity\User; + + +/** + * Interface to implement on classes called in configuration for + * PersonListWidget (`person_list`), under the key `filtering_class` : + * + * ``` + * widgets: + * homepage: + * person_list: + * # where \FQDN\To\Class implements PersonFiltering + * class_filtering: \FQDN\To\Class + * ``` + * + */ +interface PersonFilteringInterface +{ + /** + * Return an array of persons id to show. + * + * Those ids are inserted into the query like this (where ids is the array + * returned by this class) : + * + * ``` + * SELECT p FROM ChillPersonBundle:Persons p + * WHERE p.id IN (:ids) + * AND + * -- security/authorization statement: restraint person to authorized centers + * p.center in :authorized_centers + * ``` + * + * Example of use : filtering based on custom field data : + * ``` + + class HomepagePersonFiltering implements PersonFilteringInterface { + + public function getPersonIds(EntityManager $em, User $user) + { + $rsmBuilder = new ResultSetMappingBuilder($em); + $rsmBuilder->addScalarResult('id', 'id', Type::BIGINT); + + $personTable = $em->getClassMetadata('ChillPersonBundle:Person') + ->getTableName(); + $personIdColumn = $em->getClassMetadata('ChillPersonBundle:Person') + ->getColumnName('id'); + $personCfDataColumn = $em->getClassMetadata('ChillPersonBundle:Person') + ->getColumnName('cfData'); + + return $em->createNativeQuery(sprintf("SELECT %s FROM %s WHERE " + . "jsonb_exists(%s, 'school-2fb5440e-192c-11e6-b2fd-74d02b0c9b55')", + $personIdColumn, $personTable, $personCfDataColumn), $rsmBuilder) + ->getScalarResult(); + } +} + * ``` + * + * @param EntityManager $em + * @return int[] an array of persons id to show + */ + public function getPersonIds(EntityManager $em, User $user); +} diff --git a/Widget/PersonListWidgetFactory.php b/Widget/PersonListWidgetFactory.php index 98933a86d..760764fcb 100644 --- a/Widget/PersonListWidgetFactory.php +++ b/Widget/PersonListWidgetFactory.php @@ -19,12 +19,8 @@ namespace Chill\PersonBundle\Widget; -use Chill\MainBundle\DependencyInjection\Widget\Factory\WidgetFactoryInterface; use Chill\MainBundle\DependencyInjection\Widget\Factory\AbstractWidgetFactory; -use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; use Symfony\Component\Config\Definition\Builder\NodeBuilder; /** @@ -40,6 +36,9 @@ class PersonListWidgetFactory extends AbstractWidgetFactory $node->integerNode('number_of_items') ->defaultValue(50) ->end(); + $node->scalarNode('filtering_class') + ->defaultNull() + ->end(); }