From 38df9bb91db175d6dc7df3fd41a11d6c45e7124b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Fri, 23 Sep 2016 12:28:26 +0200 Subject: [PATCH 1/3] adding a widget "add a person" on homepage, replacing the homepage menu We use the new widget api to add a widget "add a person" on homepage. The homepage menu is deprecated. --- .gitignore | 1 + DependencyInjection/ChillPersonExtension.php | 26 +++++++++++++++++ Resources/config/services/widgets.yml | 2 +- .../Widget/homepage_add_a_person.html.twig | 8 ++++++ Widget/AddAPersonWidget.php | 28 +++++++++++++++++++ 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 Resources/views/Widget/homepage_add_a_person.html.twig create mode 100644 Widget/AddAPersonWidget.php diff --git a/.gitignore b/.gitignore index f1b94a9ff..f69dfba9b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ parameters.yml Resources/node_modules/ Tests/Fixtures/App/app/config/parameters.yml +/nbproject/private/ \ No newline at end of file diff --git a/DependencyInjection/ChillPersonExtension.php b/DependencyInjection/ChillPersonExtension.php index 253948399..925aa940e 100644 --- a/DependencyInjection/ChillPersonExtension.php +++ b/DependencyInjection/ChillPersonExtension.php @@ -89,6 +89,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac public function prepend(ContainerBuilder $container) { $this->prependRoleHierarchy($container); + $this->prependHomepageWidget($container); $bundles = $container->getParameter('kernel.bundles'); //add ChillMain to assetic-enabled bundles @@ -125,6 +126,31 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac )); } + /** + * + * Add a widget "add a person" on the homepage, automatically + * + * @param \Chill\PersonBundle\DependencyInjection\containerBuilder $container + */ + protected function prependHomepageWidget(containerBuilder $container) + { + $container->prependExtensionConfig('chill_main', array( + 'widgets' => array( + 'homepage' => array( + array( + 'widget_alias' => 'add_person', + 'order' => 2 + ) + ) + ) + )); + } + + /** + * Add role hierarchy. + * + * @param ContainerBuilder $container + */ protected function prependRoleHierarchy(ContainerBuilder $container) { $container->prependExtensionConfig('security', array( diff --git a/Resources/config/services/widgets.yml b/Resources/config/services/widgets.yml index 9d0f126ae..1d7c3c0f5 100644 --- a/Resources/config/services/widgets.yml +++ b/Resources/config/services/widgets.yml @@ -8,6 +8,6 @@ services: # this widget is defined by the PersonListWidgetFactory chill_person.widget.add_person: - class: Chill\PersonBundle\Widget\AddPersonWidget + class: Chill\PersonBundle\Widget\AddAPersonWidget tags: - { name: chill_widget, alias: add_person, place: homepage } \ No newline at end of file diff --git a/Resources/views/Widget/homepage_add_a_person.html.twig b/Resources/views/Widget/homepage_add_a_person.html.twig new file mode 100644 index 000000000..6bdbbff04 --- /dev/null +++ b/Resources/views/Widget/homepage_add_a_person.html.twig @@ -0,0 +1,8 @@ +
+ +
+ {{ 'Add a person'|trans }} +
+
+
+ diff --git a/Widget/AddAPersonWidget.php b/Widget/AddAPersonWidget.php new file mode 100644 index 000000000..a7988ed2a --- /dev/null +++ b/Widget/AddAPersonWidget.php @@ -0,0 +1,28 @@ +render("ChillPersonBundle:Widget:homepage_add_a_person.html.twig"); + } +} From de4844fb9d13ffb4caf70fe9085df06aa0984397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Fri, 23 Sep 2016 12:33:20 +0200 Subject: [PATCH 2/3] removing homepage menu from routing --- Resources/config/routing.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Resources/config/routing.yml b/Resources/config/routing.yml index 7566c0e98..e377cf36c 100644 --- a/Resources/config/routing.yml +++ b/Resources/config/routing.yml @@ -20,9 +20,6 @@ chill_person_new: defaults: {_controller: ChillPersonBundle:Person:new } options: menus: - homepage: - order: 10 - label: Add a person section: order: 10 label: Add a person From 82c74348718eeb6f633ed204cc5eb193e6e52318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Thu, 6 Oct 2016 11:46:37 +0200 Subject: [PATCH 3/3] adding custom filtering on personListWidget --- Resources/config/services/widgets.yml | 1 + Widget/PersonListWidget.php | 30 ++++++- .../PersonFilteringInterface.php | 85 +++++++++++++++++++ Widget/PersonListWidgetFactory.php | 7 +- 4 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 Widget/PersonListWidget/PersonFilteringInterface.php 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(); }