add a widget to display a person list on homepage

This commit is contained in:
Julien Fastré 2016-09-18 23:57:32 +02:00
parent 52fb5f56be
commit 2f5efd50e8
7 changed files with 271 additions and 0 deletions

View File

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

View File

@ -1,5 +1,22 @@
<?php
/*
* Copyright (C) 2014-2016 Julien Fastré <julien.fastre@champs-libres.coop>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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)

View File

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

View File

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

View File

@ -0,0 +1,16 @@
{% import 'ChillPersonBundle:Person:macro.html.twig' as person %}
<div class="grid-8 centered">
<h2>{{ 'Accompanyied people'|trans }}</h2>
<table>
<tbody>
<tr>
{% for p in persons %}
{% if (loop.index - 1) % 3 == 0 %}
</tr><tr>
{% endif %}
<td>{{ person.render(p, true) }}</td>
{% endfor %}
</tr>
</tbody>
</table>
</div>

149
Widget/PersonListWidget.php Normal file
View File

@ -0,0 +1,149 @@
<?php
/*
* Copyright (C) 2016 Julien Fastré <julien.fastre@champs-libres.coop>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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;
}
}

View File

@ -0,0 +1,61 @@
<?php
/*
* Copyright (C) 2016 Julien Fastré <julien.fastre@champs-libres.coop>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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';
}
}