From 2f5efd50e887965e3b86304ad21b184ec1458e0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Sun, 18 Sep 2016 23:57:32 +0200 Subject: [PATCH] add a widget to display a person list on homepage --- ChillPersonBundle.php | 9 ++ DependencyInjection/ChillPersonExtension.php | 18 +++ Resources/config/services/widgets.yml | 13 ++ Resources/translations/messages.fr.yml | 5 + .../Widget/homepage_person_list.html.twig | 16 ++ Widget/PersonListWidget.php | 149 ++++++++++++++++++ Widget/PersonListWidgetFactory.php | 61 +++++++ 7 files changed, 271 insertions(+) create mode 100644 Resources/config/services/widgets.yml create mode 100644 Resources/views/Widget/homepage_person_list.html.twig create mode 100644 Widget/PersonListWidget.php create mode 100644 Widget/PersonListWidgetFactory.php diff --git a/ChillPersonBundle.php b/ChillPersonBundle.php index 847e46e3b..93576c0d4 100644 --- a/ChillPersonBundle.php +++ b/ChillPersonBundle.php @@ -3,7 +3,16 @@ namespace Chill\PersonBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Chill\PersonBundle\Widget\PersonListWidgetFactory; class ChillPersonBundle extends Bundle { + public function build(ContainerBuilder $container) + { + parent::build($container); + + $container->getExtension('chill_main') + ->addWidgetFactory(new PersonListWidgetFactory()); + } } diff --git a/DependencyInjection/ChillPersonExtension.php b/DependencyInjection/ChillPersonExtension.php index 733ff9e27..253948399 100644 --- a/DependencyInjection/ChillPersonExtension.php +++ b/DependencyInjection/ChillPersonExtension.php @@ -1,5 +1,22 @@ + * + * 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\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -37,6 +54,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('services.yml'); + $loader->load('services/widgets.yml'); } private function handlePersonFieldsParameters(ContainerBuilder $container, $config) diff --git a/Resources/config/services/widgets.yml b/Resources/config/services/widgets.yml new file mode 100644 index 000000000..9d0f126ae --- /dev/null +++ b/Resources/config/services/widgets.yml @@ -0,0 +1,13 @@ +services: + chill_person.widget.person_list: + class: Chill\PersonBundle\Widget\PersonListWidget + arguments: + - "@chill.person.repository.person" + - "@chill.main.security.authorization.helper" + - "@security.token_storage" + # this widget is defined by the PersonListWidgetFactory + + chill_person.widget.add_person: + class: Chill\PersonBundle\Widget\AddPersonWidget + tags: + - { name: chill_widget, alias: add_person, place: homepage } \ No newline at end of file diff --git a/Resources/translations/messages.fr.yml b/Resources/translations/messages.fr.yml index 58fa95d82..d1e42f534 100644 --- a/Resources/translations/messages.fr.yml +++ b/Resources/translations/messages.fr.yml @@ -117,3 +117,8 @@ CHILL_PERSON_CREATE: Ajouter des personnes #period Period closed!: Période clôturée! Pediod closing form is not valide: Le formulaire de fermeture n'est pas valide + +#widget + +## widget person_list +Accompanyied people: Personnes accompagnées \ No newline at end of file diff --git a/Resources/views/Widget/homepage_person_list.html.twig b/Resources/views/Widget/homepage_person_list.html.twig new file mode 100644 index 000000000..a57b5e8ff --- /dev/null +++ b/Resources/views/Widget/homepage_person_list.html.twig @@ -0,0 +1,16 @@ +{% import 'ChillPersonBundle:Person:macro.html.twig' as person %} +
+

{{ 'Accompanyied people'|trans }}

+ + + + {% for p in persons %} + {% if (loop.index - 1) % 3 == 0 %} + + {% endif %} + + {% endfor %} + + +
{{ person.render(p, true) }}
+
diff --git a/Widget/PersonListWidget.php b/Widget/PersonListWidget.php new file mode 100644 index 000000000..46a4a5361 --- /dev/null +++ b/Widget/PersonListWidget.php @@ -0,0 +1,149 @@ + + * + * 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; + +use Chill\MainBundle\Templating\Widget\WidgetInterface; +use Doctrine\ORM\EntityRepository; +use Doctrine\ORM\Query\Expr; +use Doctrine\DBAL\Types\Type; +use Chill\MainBundle\Security\Authorization\AuthorizationHelper; +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; + +/** + * add a widget with person list. + * + * The configuration is defined by `PersonListWidgetFactory` + */ +class PersonListWidget implements WidgetInterface +{ + + /** + * Repository for persons + * + * @var EntityRepository + */ + protected $personRepository; + + /** + * the authorization helper + * + * @var AuthorizationHelper; + */ + protected $authorizationHelper; + + /** + * + * @var TokenStorage + */ + protected $tokenStorage; + + /** + * + * @var UserInterface + */ + protected $user; + + public function __construct( + EntityRepository $personRepostory, + AuthorizationHelper $authorizationHelper, + TokenStorage $tokenStorage + ) { + $this->personRepository = $personRepostory; + $this->authorizationHelper = $authorizationHelper; + $this->tokenStorage = $tokenStorage; + + } + + /** + * + * @param type $place + * @param array $context + * @param array $config + * @return string + */ + public function render(\Twig_Environment $env, $place, array $context, array $config) + { + $qb = $this->personRepository + ->createQueryBuilder('person'); + + // show only the person from the authorized centers + $and = $qb->expr()->andX(); + $centers = $this->authorizationHelper + ->getReachableCenters($this->getUser(), new Role(PersonVoter::SEE)); + $and->add($qb->expr()->in('person.center', ':centers')); + $qb->setParameter('centers', $centers); + + + + if ($config['only_active'] === true) { + $qb->join('person.accompanyingPeriods', 'ap'); + $or = new Expr\Orx(); + // add the case where closingDate IS NULL + $andWhenClosingDateIsNull = new Expr\Andx(); + $andWhenClosingDateIsNull->add((new Expr())->isNull('ap.closingDate')); + $andWhenClosingDateIsNull->add ((new Expr())->gte(':now', 'ap.openingDate')); + $or->add($andWhenClosingDateIsNull); + // add the case when closingDate is in the future + $or->add( + (new Expr())->between(':now', 'ap.openingDate', 'ap.closingDate') + ); + $and->add($or); + $qb->setParameter('now', new \DateTime(), Type::DATE); + } + $qb->where($and); + + + $qb->setFirstResult(0)->setMaxResults($config['number_of_items']); + + $persons = $qb->getQuery()->getResult(); + + return $env->render( + 'ChillPersonBundle:Widget:homepage_person_list.html.twig', + array('persons' => $persons) + ); + } + + /** + * + * @return UserInterface + * @throws \RuntimeException + */ + private function getUser() + { + $token = $this->tokenStorage->getToken(); + + if ($token === null) { + throw new \RuntimeException("the token should not be null"); + } + + $user = $token->getUser(); + + if (!$user instanceof UserInterface || $user == null) { + throw new \RuntimeException("the user should implement UserInterface. " + . "Are you logged in ?"); + } + + return $user; + } + +} \ No newline at end of file diff --git a/Widget/PersonListWidgetFactory.php b/Widget/PersonListWidgetFactory.php new file mode 100644 index 000000000..98933a86d --- /dev/null +++ b/Widget/PersonListWidgetFactory.php @@ -0,0 +1,61 @@ + + * + * 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; + +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; + +/** + * add configuration for the person_list widget. + */ +class PersonListWidgetFactory extends AbstractWidgetFactory +{ + public function configureOptions($place, NodeBuilder $node) + { + $node->booleanNode('only_active') + ->defaultTrue() + ->end(); + $node->integerNode('number_of_items') + ->defaultValue(50) + ->end(); + + } + + public function getAllowedPlaces() + { + return array('homepage'); + } + + public function getWidgetAlias() + { + return 'person_list'; + } + + public function getServiceId(ContainerBuilder $containerBuilder, $place, $order, array $config) + { + return 'chill_person.widget.person_list'; + } + +}