cs: Fix code style (safe rules only).

This commit is contained in:
Pol Dellaiera 2021-11-23 14:06:38 +01:00
parent 149d7ce991
commit 8f96a1121d
No known key found for this signature in database
GPG Key ID: D476DFE9C67467CA
1223 changed files with 65199 additions and 64625 deletions

View File

@ -1,123 +1,124 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\PersonBundle\Export\Filter;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\MainBundle\Export\FilterInterface;
use DateTime;
use Doctrine\ORM\Query\Expr;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraints;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Doctrine\ORM\Query\Expr;
use Chill\MainBundle\Form\Type\Export\FilterType;
use Symfony\Component\Form\FormError;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
class BirthdateFilter implements FilterInterface, ExportElementValidatedInterface
{
// add specific role for this filter
// add specific role for this filter
public function addRole()
{
// we do not need any new role for this filter, so we return null
return null;
}
// here, we alter the query created by Export
public function alterQuery(\Doctrine\ORM\QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
// we create the clause here
$clause = $qb->expr()->between(
'person.birthdate',
':date_from',
':date_to'
);
// we have to take care **not to** remove previous clauses...
if ($where instanceof Expr\Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->add('where', $where);
// we add parameters from $data. $data contains the parameters from the form
$qb->setParameter('date_from', $data['date_from']);
$qb->setParameter('date_to', $data['date_to']);
}
// we give information on which type of export this filter applies
public function applyOn()
{
return 'person';
}
public function getTitle()
{
return 'Filter by person\'s birthdate';
}
// we build a form to collect some parameters from the users
public function buildForm(\Symfony\Component\Form\FormBuilderInterface $builder)
{
$builder->add('date_from', DateType::class, array(
'label' => "Born after this date",
'data' => new \DateTime(),
'attr' => array('class' => 'datepicker'),
'widget'=> 'single_text',
$builder->add('date_from', DateType::class, [
'label' => 'Born after this date',
'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
));
$builder->add('date_to', DateType::class, array(
'label' => "Born before this date",
'data' => new \DateTime(),
'attr' => array('class' => 'datepicker'),
'widget'=> 'single_text',
]);
$builder->add('date_to', DateType::class, [
'label' => 'Born before this date',
'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
));
}
// the form created above must be validated. The process of validation
// is executed here. This function is added by the interface
// `ExportElementValidatedInterface`, and can be ignore if there is
// no need for a validation
public function validateForm($data, ExecutionContextInterface $context)
{
$date_from = $data['date_from'];
$date_to = $data['date_to'];
if ($date_from === null) {
$context->buildViolation('The "date from" should not be empty')
//->atPath('date_from')
->addViolation();
}
if ($date_to === null) {
$context->buildViolation('The "date to" should not be empty')
//->atPath('date_to')
->addViolation();
}
if (
($date_from !== null && $date_to !== null)
&&
$date_from >= $date_to
) {
$context->buildViolation('The date "date to" should be after the '
. 'date given in "date from" field')
->addViolation();
}
}
// here, we alter the query created by Export
public function alterQuery(\Doctrine\ORM\QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
// we create the clause here
$clause = $qb->expr()->between('person.birthdate', ':date_from',
':date_to');
// we have to take care **not to** remove previous clauses...
if ($where instanceof Expr\Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->add('where', $where);
// we add parameters from $data. $data contains the parameters from the form
$qb->setParameter('date_from', $data['date_from']);
$qb->setParameter('date_to', $data['date_to']);
]);
}
// here, we create a simple string which will describe the action of
// the filter in the Response
public function describeAction($data, $format = 'string')
{
return array('Filtered by person\'s birtdate: '
. 'between %date_from% and %date_to%', array(
return ['Filtered by person\'s birtdate: '
. 'between %date_from% and %date_to%', [
'%date_from%' => $data['date_from']->format('d-m-Y'),
'%date_to%' => $data['date_to']->format('d-m-Y')
));
'%date_to%' => $data['date_to']->format('d-m-Y'),
], ];
}
public function getTitle()
{
return 'Filter by person\'s birthdate';
}
// the form created above must be validated. The process of validation
// is executed here. This function is added by the interface
// `ExportElementValidatedInterface`, and can be ignore if there is
// no need for a validation
public function validateForm($data, ExecutionContextInterface $context)
{
$date_from = $data['date_from'];
$date_to = $data['date_to'];
if (null === $date_from) {
$context->buildViolation('The "date from" should not be empty')
//->atPath('date_from')
->addViolation();
}
if (null === $date_to) {
$context->buildViolation('The "date to" should not be empty')
//->atPath('date_to')
->addViolation();
}
if (
(null !== $date_from && null !== $date_to)
&& $date_from >= $date_to
) {
$context->buildViolation('The date "date to" should be after the '
. 'date given in "date from" field')
->addViolation();
}
}
}

View File

@ -1,118 +1,115 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\PersonBundle\Export\Export;
use Chill\MainBundle\Export\ExportInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Doctrine\ORM\Query;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Symfony\Component\Security\Core\Role\Role;
use Chill\PersonBundle\Export\Declarations;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class CountPerson implements ExportInterface
{
/**
*
* @var EntityManagerInterface
*/
protected $entityManager;
public function __construct(
EntityManagerInterface $em
)
{
EntityManagerInterface $em
) {
$this->entityManager = $em;
}
public function getType()
public function buildForm(FormBuilderInterface $builder)
{
return Declarations::PERSON_TYPE;
// this export does not add any form
}
public function getAllowedFormattersTypes()
{
return [FormatterInterface::TYPE_TABULAR];
}
public function getDescription()
{
return "Count peoples by various parameters.";
return 'Count peoples by various parameters.';
}
public function getTitle()
public function getLabels($key, array $values, $data)
{
return "Count peoples";
// the Closure which will be executed by the formatter.
return function ($value) {
switch ($value) {
case '_header':
// we have to process specifically the '_header' string,
// which will be used by the formatter to show a column title
return $this->getTitle();
default:
// for all value, we do not process them and return them
// immediatly
return $value;
}
};
}
public function requiredRole()
{
return new Role(PersonVoter::STATS);
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = array())
{
// we gather all center the user choose.
$centers = array_map(function($el) { return $el['center']; }, $acl);
$qb = $this->entityManager->createQueryBuilder();
$qb->select('COUNT(person.id) AS export_result')
->from('ChillPersonBundle:Person', 'person')
->join('person.center', 'center')
->andWhere('center IN (:authorized_centers)')
->setParameter('authorized_centers', $centers);
;
return $qb;
}
public function getResult($qb, $data)
{
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getQueryKeys($data)
{
// this array match the result keys in the query. We have only
// one column.
return array('export_result');
return ['export_result'];
}
public function getLabels($key, array $values, $data)
public function getResult($qb, $data)
{
// the Closure which will be executed by the formatter.
return function($value) {
switch($value) {
case '_header':
// we have to process specifically the '_header' string,
// which will be used by the formatter to show a column title
return $this->getTitle();
default:
// for all value, we do not process them and return them
// immediatly
return $value;
};
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getAllowedFormattersTypes()
public function getTitle()
{
return array(FormatterInterface::TYPE_TABULAR);
return 'Count peoples';
}
public function buildForm(FormBuilderInterface $builder) {
// this export does not add any form
public function getType()
{
return Declarations::PERSON_TYPE;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
// we gather all center the user choose.
$centers = array_map(function ($el) { return $el['center']; }, $acl);
$qb = $this->entityManager->createQueryBuilder();
$qb->select('COUNT(person.id) AS export_result')
->from('ChillPersonBundle:Person', 'person')
->join('person.center', 'center')
->andWhere('center IN (:authorized_centers)')
->setParameter('authorized_centers', $centers);
return $qb;
}
public function requiredRole()
{
return new Role(PersonVoter::STATS);
}
public function supportsModifiers()
{
// explain the export manager which formatters and filters are allowed
return array(Declarations::PERSON_TYPE, Declarations::PERSON_IMPLIED_IN);
return [Declarations::PERSON_TYPE, Declarations::PERSON_IMPLIED_IN];
}
}

View File

@ -1,42 +1,47 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MyBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class ItemController extends Controller {
public function yourAction()
class ItemController extends Controller
{
public function yourAction()
{
$em = $this->getDoctrine()->getManager();
// first, get the number of total item are available
$total = $em
->createQuery("SELECT COUNT (item.id) FROM ChillMyBundle:Item item")
->getSingleScalarResult();
->createQuery('SELECT COUNT (item.id) FROM ChillMyBundle:Item item')
->getSingleScalarResult();
// get the PaginatorFactory
$paginatorFactory = $this->get('chill_main.paginator_factory');
// create a pagination instance. This instance is only valid for
// create a pagination instance. This instance is only valid for
// the current route and parameters
$paginator = $paginatorFactory->create($total);
// launch your query on item. Limit the query to the results
// for the current page using the paginator
$items = $em->createQuery("SELECT item FROM ChillMyBundle:Item item WHERE <your clause>")
$items = $em->createQuery('SELECT item FROM ChillMyBundle:Item item WHERE <your clause>')
// use the paginator to get the first item number
->setFirstResult($paginator->getCurrentPage()->getFirstItemNumber())
// use the paginator to get the number of items to display
->setMaxResults($paginator->getItemsPerPage());
return $this->render('ChillMyBundle:Item:list.html.twig', array(
return $this->render(
'ChillMyBundle:Item:list.html.twig',
[
'items' => $items,
'paginator' => $paginator
);
'paginator' => $paginator,
]
);
}
}

View File

@ -1,43 +1,51 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\HealthBundle\Controller;
use Chill\HealthBundle\Security\Authorization\ConsultationVoter;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\Role\Role;
class ConsultationController extends Controller
{
/**
*
* @param int $id personId
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws type
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function listAction($id)
{
/* @var $person \Chill\PersonBundle\Entity\Person */
$person = $this->get('chill.person.repository.person')
->find($id);
if ($person === null) {
throw $this->createNotFoundException("The person is not found");
if (null === $person) {
throw $this->createNotFoundException('The person is not found');
}
$this->denyAccessUnlessGranted(PersonVoter::SEE, $person);
/* @var $authorizationHelper \Chill\MainBundle\Security\Authorization\AuthorizationHelper */
$authorizationHelper = $this->get('chill.main.security.'
. 'authorization.helper');
$circles = $authorizationHelper->getReachableCircles(
$this->getUser(),
new Role(ConsultationVoter::SEE),
$this->getUser(),
new Role(ConsultationVoter::SEE),
$person->getCenter()
);
// create a query which take circles into account
);
// create a query which take circles into account
$consultations = $this->getDoctrine()->getManager()
->createQuery('SELECT c FROM ChillHealthBundle:Consultation c '
. 'WHERE c.patient = :person AND c.circle IN(:circles) '
@ -45,11 +53,10 @@ class ConsultationController extends Controller
->setParameter('person', $person)
->setParameter('circles', $circles)
->getResult();
return $this->render('ChillHealthBundle:Consultation:list.html.twig', array(
'person' => $person,
'consultations' => $consultations
));
return $this->render('ChillHealthBundle:Consultation:list.html.twig', [
'person' => $person,
'consultations' => $consultations,
]);
}
}

View File

@ -1,64 +1,62 @@
<?php
# Chill\MainBundle\DependencyInjection\Configuration.php
namespace Chill\MainBundle\DependencyInjection;
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\DependencyInjection;
use Chill\MainBundle\DependencyInjection\Widget\AddWidgetConfigurationTrait;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Chill\MainBundle\DependencyInjection\Widget\AddWidgetConfigurationTrait;
use Symfony\Component\DependencyInjection\ContainerBuilder;
/**
* Configure the main bundle
* Configure the main bundle.
*/
class Configuration implements ConfigurationInterface
{
use AddWidgetConfigurationTrait;
/**
*
* @var ContainerBuilder
*/
* @var ContainerBuilder
*/
private $containerBuilder;
public function __construct(array $widgetFactories = array(),
ContainerBuilder $containerBuilder)
public function __construct(
array $widgetFactories = [],
ContainerBuilder $containerBuilder
)
{
// we register here widget factories (see below)
$this->setWidgetFactories($widgetFactories);
$this->setWidgetFactories($widgetFactories);
// we will need the container builder later...
$this->containerBuilder = $containerBuilder;
$this->containerBuilder = $containerBuilder;
}
/**
* {@inheritDoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('chill_main');
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('chill_main');
$rootNode
->children()
$rootNode
->children()
// ...
->arrayNode('widgets')
->canBeDisabled()
->children()
->arrayNode('widgets')
->canBeDisabled()
->children()
// we declare here all configuration for homepage place
->append($this->addWidgetsConfiguration('homepage', $this->containerBuilder))
->end() // end of widgets/children
->end() // end of widgets
->end() // end of root/children
->end() // end of root
;
->append($this->addWidgetsConfiguration('homepage', $this->containerBuilder))
->end() // end of widgets/children
->end() // end of widgets
->end() // end of root/children
->end() // end of root
;
return $treeBuilder;
return $treeBuilder;
}
}

View File

@ -1,16 +1,17 @@
<?php
#Chill\MainBundle\DependencyInjection\ChillMainExtension.php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Chill\MainBundle\DependencyInjection\Widget\Factory\WidgetFactoryInterface;
use Chill\MainBundle\DependencyInjection\Configuration;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
/**
* This class load config for chillMainExtension.
@ -18,42 +19,42 @@ use Chill\MainBundle\DependencyInjection\Configuration;
class ChillMainExtension extends Extension implements Widget\HasWidgetFactoriesExtensionInterface
{
/**
* widget factory
*
* widget factory.
*
* @var WidgetFactoryInterface[]
*/
protected $widgetFactories = array();
protected $widgetFactories = [];
public function addWidgetFactory(WidgetFactoryInterface $factory)
{
$this->widgetFactories[] = $factory;
}
public function getConfiguration(array $config, ContainerBuilder $container)
{
return new Configuration($this->widgetFactories, $container);
}
/**
*
* @return WidgetFactoryInterface[]
*/
public function getWidgetFactories()
{
return $this->widgetFactories;
}
public function load(array $configs, ContainerBuilder $container)
{
// configuration for main bundle
$configuration = $this->getConfiguration($configs, $container);
$config = $this->processConfiguration($configuration, $configs);
// add the key 'widget' without the key 'enable'
$container->setParameter('chill_main.widgets',
array('homepage' => $config['widgets']['homepage']));
// ...
// add the key 'widget' without the key 'enable'
$container->setParameter(
'chill_main.widgets',
['homepage' => $config['widgets']['homepage']]
);
// ...
}
public function getConfiguration(array $config, ContainerBuilder $container)
{
return new Configuration($this->widgetFactories, $container);
}
}

View File

@ -1,69 +1,71 @@
<?php
# Chill/PersonBundle/Widget/PersonListWidgetFactory
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\PersonBundle\Widget;
use Chill\MainBundle\DependencyInjection\Widget\Factory\AbstractWidgetFactory;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\Definition\Builder\NodeBuilder;
use Symfony\Component\DependencyInjection\ContainerBuilder;
/**
* add configuration for the person_list widget.
*/
class PersonListWidgetFactory extends AbstractWidgetFactory
{
/*
* append the option to the configuration
* see http://symfony.com/doc/current/components/config/definition.html
*
*/
/*
* append the option to the configuration
* see http://symfony.com/doc/current/components/config/definition.html
*
*/
public function configureOptions($place, NodeBuilder $node)
{
$node->booleanNode('only_active')
->defaultTrue()
->end();
->defaultTrue()
->end();
$node->integerNode('number_of_items')
->defaultValue(50)
->end();
$node->scalarNode('filtering_class')
->defaultNull()
->end();
->defaultNull()
->end();
}
/*
* return an array with the allowed places where the widget can be rendered
*
* @return string[]
*/
/*
* return an array with the allowed places where the widget can be rendered
*
* @return string[]
*/
public function getAllowedPlaces()
{
return array('homepage');
return ['homepage'];
}
/*
* return the widget alias
*
* @return string
*/
public function getWidgetAlias()
{
return 'person_list';
}
/*
* return the service id for the service which will render the widget.
*
* this service must implements `Chill\MainBundle\Templating\Widget\WidgetInterface`
*
* the service must exists in the container, and it is not required that the service
*
* the service must exists in the container, and it is not required that the service
* has the `chill_main` tag.
*/
public function getServiceId(ContainerBuilder $containerBuilder, $place, $order, array $config)
{
return 'chill_person.widget.person_list';
}
}
/*
* return the widget alias
*
* @return string
*/
public function getWidgetAlias()
{
return 'person_list';
}
}

View File

@ -1,66 +1,71 @@
<?php
# Chill/PersonBundle/Widget/PersonListWidget.php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\PersonBundle\Widget;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Templating\Widget\WidgetInterface;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use DateTime;
use Doctrine\DBAL\Types\Type;
use Doctrine\ORM\EntityManager;
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;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Security\Core\User\UserInterface;
use Twig_Environment;
/**
* add a widget with person list.
*
* add a widget with person list.
*
* The configuration is defined by `PersonListWidgetFactory`
*/
class PersonListWidget implements WidgetInterface
{
/**
* Repository for persons
*
* @var EntityRepository
* the authorization helper.
*
* @var AuthorizationHelper;
*/
protected $personRepository;
protected $authorizationHelper;
/**
* The entity manager
* The entity manager.
*
* @var EntityManager
*/
protected $entityManager;
/**
* the authorization helper
*
* @var AuthorizationHelper;
*/
protected $authorizationHelper;
/**
* Repository for persons.
*
* @var EntityRepository
*/
protected $personRepository;
/**
* @var TokenStorage
*/
protected $tokenStorage;
/**
*
* @var UserInterface
*/
protected $user;
public function __construct(
EntityRepository $personRepostory,
EntityManager $em,
AuthorizationHelper $authorizationHelper,
TokenStorage $tokenStorage
) {
EntityRepository $personRepostory,
EntityManager $em,
AuthorizationHelper $authorizationHelper,
TokenStorage $tokenStorage
) {
$this->personRepository = $personRepostory;
$this->authorizationHelper = $authorizationHelper;
$this->tokenStorage = $tokenStorage;
@ -68,27 +73,24 @@ class PersonListWidget implements WidgetInterface
}
/**
*
* @param type $place
* @param array $context
* @param array $config
*
* @return string
*/
public function render(\Twig_Environment $env, $place, array $context, array $config)
{
public function render(Twig_Environment $env, $place, array $context, array $config)
{
$qb = $this->personRepository
->createQueryBuilder('person');
->createQueryBuilder('person');
// show only the person from the authorized centers
$and = $qb->expr()->andX();
$centers = $this->authorizationHelper
->getReachableCenters($this->getUser(), new Role(PersonVoter::SEE));
->getReachableCenters($this->getUser(), new Role(PersonVoter::SEE));
$and->add($qb->expr()->in('person.center', ':centers'));
$qb->setParameter('centers', $centers);
// add the "only active" where clause
if ($config['only_active'] === true) {
if (true === $config['only_active']) {
$qb->join('person.accompanyingPeriods', 'ap');
$or = new Expr\Orx();
// add the case where closingDate IS NULL
@ -98,32 +100,30 @@ class PersonListWidget implements WidgetInterface
$or->add($andWhenClosingDateIsNull);
// add the case when now is between opening date and closing date
$or->add(
(new Expr())->between(':now', 'ap.openingDate', 'ap.closingDate')
);
(new Expr())->between(':now', 'ap.openingDate', 'ap.closingDate')
);
$and->add($or);
$qb->setParameter('now', new \DateTime(), Type::DATE);
$qb->setParameter('now', new DateTime(), Type::DATE);
}
// adding the where clause to the query
$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)
);
['persons' => $persons]
);
}
/**
*
* @return UserInterface
*/
private function getUser()
{
// return a user
}
}

View File

@ -1,51 +1,46 @@
<?php
# Chill/PersonBundle/DependencyInjection/ChillPersonExtension.php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\PersonBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Chill\MainBundle\DependencyInjection\MissingBundleException;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
/**
* This is the class that loads and manages your bundle configuration
* This is the class that loads and manages your bundle configuration.
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
*/
class ChillPersonExtension extends Extension implements PrependExtensionInterface
{
/**
* {@inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
// ...
// ...
}
/**
*
* Add a widget "add a person" on the homepage, automatically
*
* Add a widget "add a person" on the homepage, automatically.
*
* @param \Chill\PersonBundle\DependencyInjection\containerBuilder $container
*/
public function prepend(ContainerBuilder $container)
public function prepend(ContainerBuilder $container)
{
$container->prependExtensionConfig('chill_main', array(
'widgets' => array(
'homepage' => array(
array(
$container->prependExtensionConfig('chill_main', [
'widgets' => [
'homepage' => [
[
'widget_alias' => 'add_person',
'order' => 2
)
)
)
));
'order' => 2,
],
],
],
]);
}
}

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;

View File

@ -1,15 +1,25 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Controller;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Form\ActivityType;
use Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface;
use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\ActivityBundle\Repository\ActivityTypeCategoryRepository;
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
use Chill\MainBundle\Repository\LocationRepository;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
@ -17,45 +27,44 @@ use Chill\PersonBundle\Privacy\PrivacyEvent;
use Chill\PersonBundle\Repository\AccompanyingPeriodRepository;
use Chill\PersonBundle\Repository\PersonRepository;
use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Form\ActivityType;
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
use Symfony\Component\Serializer\SerializerInterface;
final class ActivityController extends AbstractController
{
private EventDispatcherInterface $eventDispatcher;
private LoggerInterface $logger;
private SerializerInterface $serializer;
private AccompanyingPeriodRepository $accompanyingPeriodRepository;
private ActivityACLAwareRepositoryInterface $activityACLAwareRepository;
private ActivityRepository $activityRepository;
private ActivityTypeCategoryRepository $activityTypeCategoryRepository;
private ActivityTypeRepository $activityTypeRepository;
private ThirdPartyRepository $thirdPartyRepository;
private PersonRepository $personRepository;
private LocationRepository $locationRepository;
private EntityManagerInterface $entityManager;
private ActivityRepository $activityRepository;
private EventDispatcherInterface $eventDispatcher;
private AccompanyingPeriodRepository $accompanyingPeriodRepository;
private LocationRepository $locationRepository;
private ActivityTypeCategoryRepository $activityTypeCategoryRepository;
private LoggerInterface $logger;
private PersonRepository $personRepository;
private SerializerInterface $serializer;
private ThirdPartyRepository $thirdPartyRepository;
public function __construct(
ActivityACLAwareRepositoryInterface $activityACLAwareRepository,
@ -85,6 +94,150 @@ final class ActivityController extends AbstractController
$this->serializer = $serializer;
}
/**
* Deletes a Activity entity.
*
* @param mixed $id
*/
public function deleteAction(Request $request, $id)
{
$view = null;
[$person, $accompanyingPeriod] = $this->getEntity($request);
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:confirm_deleteAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:confirm_deletePerson.html.twig';
}
$activity = $this->activityRepository->find($id);
if (!$activity) {
throw $this->createNotFoundException('Unable to find Activity entity.');
}
// TODO
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_DELETE', $activity);
$form = $this->createDeleteForm($activity->getId(), $person, $accompanyingPeriod);
if ($request->getMethod() === Request::METHOD_DELETE) {
$form->handleRequest($request);
if ($form->isValid()) {
$this->logger->notice('An activity has been removed', [
'by_user' => $this->getUser()->getUsername(),
'activity_id' => $activity->getId(),
'person_id' => $activity->getPerson() ? $activity->getPerson()->getId() : null,
'comment' => $activity->getComment()->getComment(),
'scope_id' => $activity->getScope() ? $activity->getScope()->getId() : null,
'reasons_ids' => $activity->getReasons()
->map(
static fn (ActivityReason $ar): int => $ar->getId()
)
->toArray(),
'type_id' => $activity->getType()->getId(),
'duration' => $activity->getDurationTime() ? $activity->getDurationTime()->format('U') : null,
'date' => $activity->getDate()->format('Y-m-d'),
'attendee' => $activity->getAttendee(),
]);
$this->entityManager->remove($activity);
$this->entityManager->flush();
$this->addFlash('success', $this->get('translator')
->trans('The activity has been successfully removed.'));
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
return $this->redirectToRoute('chill_activity_activity_list', $params);
}
}
if (null === $view) {
throw $this->createNotFoundException('Template not found');
}
return $this->render($view, [
'activity' => $activity,
'delete_form' => $form->createView(),
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
]);
}
/**
* Displays a form to edit an existing Activity entity.
*/
public function editAction(int $id, Request $request): Response
{
$view = null;
[$person, $accompanyingPeriod] = $this->getEntity($request);
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:editAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:editPerson.html.twig';
}
$entity = $this->activityRepository->find($id);
if (null === $entity) {
throw $this->createNotFoundException('Unable to find Activity entity.');
}
// TODO
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity);
$form = $this->createForm(ActivityType::class, $entity, [
'center' => $entity->getCenter(),
'role' => new Role('CHILL_ACTIVITY_UPDATE'),
'activityType' => $entity->getType(),
'accompanyingPeriod' => $accompanyingPeriod,
])->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->persist($entity);
$this->entityManager->flush();
$this->addFlash('success', $this->get('translator')->trans('Success : activity updated!'));
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
$params['id'] = $entity->getId();
return $this->redirectToRoute('chill_activity_activity_show', $params);
}
$deleteForm = $this->createDeleteForm($entity->getId(), $person, $accompanyingPeriod);
/*
* TODO
$event = new PrivacyEvent($person, array(
'element_class' => Activity::class,
'element_id' => $entity->getId(),
'action' => 'edit'
));
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
*/
if (null === $view) {
throw $this->createNotFoundException('Template not found');
}
$activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']);
return $this->render($view, [
'entity' => $entity,
'edit_form' => $form->createView(),
'delete_form' => $deleteForm->createView(),
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
'activity_json' => $activity_array,
]);
}
/**
* Lists all Activity entities.
*/
@ -103,7 +256,7 @@ final class ActivityController extends AbstractController
$event = new PrivacyEvent($person, [
'element_class' => Activity::class,
'action' => 'list'
'action' => 'list',
]);
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
@ -121,12 +274,152 @@ final class ActivityController extends AbstractController
$view,
[
'activities' => $activities,
'person' => $person,
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
]
);
}
public function newAction(Request $request): Response
{
$view = null;
[$person, $accompanyingPeriod] = $this->getEntity($request);
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:newAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:newPerson.html.twig';
}
$activityType_id = $request->get('activityType_id', 0);
$activityType = $this->activityTypeRepository->find($activityType_id);
if (isset($activityType) && !$activityType->isActive()) {
throw new InvalidArgumentException('Activity type must be active');
}
$activityData = null;
if ($request->query->has('activityData')) {
$activityData = $request->query->get('activityData');
}
if (!$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType
|| !$activityType->isActive()) {
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
if (null !== $activityData) {
$params['activityData'] = $activityData;
}
return $this->redirectToRoute('chill_activity_activity_select_type', $params);
}
$entity = new Activity();
$entity->setUser($this->getUser());
if ($person instanceof Person) {
$entity->setPerson($person);
}
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$entity->setAccompanyingPeriod($accompanyingPeriod);
}
$entity->setType($activityType);
$entity->setDate(new DateTime('now'));
if ($request->query->has('activityData')) {
$activityData = $request->query->get('activityData');
if (array_key_exists('durationTime', $activityData)) {
$durationTimeInMinutes = $activityData['durationTime'];
$hours = floor($durationTimeInMinutes / 60);
$minutes = $durationTimeInMinutes % 60;
$duration = DateTime::createFromFormat('H:i', $hours . ':' . $minutes);
if ($duration) {
$entity->setDurationTime($duration);
}
}
if (array_key_exists('date', $activityData)) {
$date = DateTime::createFromFormat('Y-m-d', $activityData['date']);
if ($date) {
$entity->setDate($date);
}
}
if (array_key_exists('personsId', $activityData)) {
foreach ($activityData['personsId'] as $personId) {
$concernedPerson = $this->personRepository->find($personId);
$entity->addPerson($concernedPerson);
}
}
if (array_key_exists('professionalsId', $activityData)) {
foreach ($activityData['professionalsId'] as $professionalsId) {
$professional = $this->thirdPartyRepository->find($professionalsId);
$entity->addThirdParty($professional);
}
}
if (array_key_exists('location', $activityData)) {
$location = $this->locationRepository->find($activityData['location']);
$entity->setLocation($location);
}
if (array_key_exists('comment', $activityData)) {
$comment = new CommentEmbeddable();
$comment->setComment($activityData['comment']);
$comment->setUserId($this->getUser()->getid());
$comment->setDate(new DateTime('now'));
$entity->setComment($comment);
}
}
$this->denyAccessUnlessGranted(ActivityVoter::CREATE, $entity);
$form = $this->createForm(ActivityType::class, $entity, [
'center' => $entity->getCenter(),
'role' => new Role('CHILL_ACTIVITY_CREATE'),
'activityType' => $entity->getType(),
'accompanyingPeriod' => $accompanyingPeriod,
])->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->persist($entity);
$this->entityManager->flush();
$this->addFlash('success', $this->get('translator')->trans('Success : activity created!'));
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
$params['id'] = $entity->getId();
return $this->redirectToRoute('chill_activity_activity_show', $params);
}
if (null === $view) {
throw $this->createNotFoundException('Template not found');
}
$activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']);
$defaultLocationId = $this->getUser()->getCurrentLocation()->getId();
return $this->render($view, [
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
'entity' => $entity,
'form' => $form->createView(),
'activity_json' => $activity_array,
'default_location_id' => $defaultLocationId,
]);
}
public function selectTypeAction(Request $request): Response
{
$view = null;
@ -159,7 +452,7 @@ final class ActivityController extends AbstractController
];
}
if ($view === null) {
if (null === $view) {
throw $this->createNotFoundException('Template not found');
}
@ -171,144 +464,6 @@ final class ActivityController extends AbstractController
]);
}
public function newAction(Request $request): Response
{
$view = null;
[$person, $accompanyingPeriod] = $this->getEntity($request);
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:newAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:newPerson.html.twig';
}
$activityType_id = $request->get('activityType_id', 0);
$activityType = $this->activityTypeRepository->find($activityType_id);
if (isset($activityType) && !$activityType->isActive()) {
throw new \InvalidArgumentException('Activity type must be active');
}
$activityData = null;
if ($request->query->has('activityData')) {
$activityData = $request->query->get('activityData');
}
if (!$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType ||
!$activityType->isActive()) {
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
if (null !== $activityData) {
$params['activityData'] = $activityData;
}
return $this->redirectToRoute('chill_activity_activity_select_type', $params);
}
$entity = new Activity();
$entity->setUser($this->getUser());
if ($person instanceof Person) {
$entity->setPerson($person);
}
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$entity->setAccompanyingPeriod($accompanyingPeriod);
}
$entity->setType($activityType);
$entity->setDate(new \DateTime('now'));
if ($request->query->has('activityData')) {
$activityData = $request->query->get('activityData');
if (array_key_exists('durationTime', $activityData)) {
$durationTimeInMinutes = $activityData['durationTime'];
$hours = floor($durationTimeInMinutes / 60);
$minutes = $durationTimeInMinutes % 60;
$duration = \DateTime::createFromFormat("H:i", $hours.':'.$minutes);
if ($duration) {
$entity->setDurationTime($duration);
}
}
if (array_key_exists('date', $activityData)) {
$date = \DateTime::createFromFormat('Y-m-d', $activityData['date']);
if ($date) {
$entity->setDate($date);
}
}
if (array_key_exists('personsId', $activityData)) {
foreach($activityData['personsId'] as $personId){
$concernedPerson = $this->personRepository->find($personId);
$entity->addPerson($concernedPerson);
}
}
if (array_key_exists('professionalsId', $activityData)) {
foreach($activityData['professionalsId'] as $professionalsId){
$professional = $this->thirdPartyRepository->find($professionalsId);
$entity->addThirdParty($professional);
}
}
if (array_key_exists('location', $activityData)) {
$location = $this->locationRepository->find($activityData['location']);
$entity->setLocation($location);
}
if (array_key_exists('comment', $activityData)) {
$comment = new CommentEmbeddable();
$comment->setComment($activityData['comment']);
$comment->setUserId($this->getUser()->getid());
$comment->setDate(new \DateTime('now'));
$entity->setComment($comment);
}
}
$this->denyAccessUnlessGranted(ActivityVoter::CREATE, $entity);
$form = $this->createForm(ActivityType::class, $entity, [
'center' => $entity->getCenter(),
'role' => new Role('CHILL_ACTIVITY_CREATE'),
'activityType' => $entity->getType(),
'accompanyingPeriod' => $accompanyingPeriod,
])->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->persist($entity);
$this->entityManager->flush();
$this->addFlash('success', $this->get('translator')->trans('Success : activity created!'));
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
$params['id'] = $entity->getId();
return $this->redirectToRoute('chill_activity_activity_show', $params);
}
if ($view === null) {
throw $this->createNotFoundException('Template not found');
}
$activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']);
$defaultLocationId = $this->getUser()->getCurrentLocation()->getId();
return $this->render($view, [
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
'entity' => $entity,
'form' => $form->createView(),
'activity_json' => $activity_array,
'default_location_id' => $defaultLocationId
]);
}
public function showAction(Request $request, int $id): Response
{
$view = null;
@ -329,8 +484,8 @@ final class ActivityController extends AbstractController
if (null !== $accompanyingPeriod) {
// @TODO: Properties created dynamically.
$entity->personsAssociated = $entity->getPersonsAssociated();
$entity->personsNotAssociated = $entity->getPersonsNotAssociated();
$entity->personsAssociated = $entity->getPersonsAssociated();
$entity->personsNotAssociated = $entity->getPersonsNotAssociated();
}
// TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période
@ -346,160 +501,33 @@ final class ActivityController extends AbstractController
'action' => 'show'
));
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
*/
*/
if ($view === null) {
if (null === $view) {
throw $this->createNotFoundException('Template not found');
}
return $this->render($view, [
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
'entity' => $entity,
'delete_form' => $deleteForm->createView(),
]);
}
/**
* Displays a form to edit an existing Activity entity.
*/
public function editAction(int $id, Request $request): Response
{
$view = null;
[$person, $accompanyingPeriod] = $this->getEntity($request);
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:editAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:editPerson.html.twig';
}
$entity = $this->activityRepository->find($id);
if (null === $entity) {
throw $this->createNotFoundException('Unable to find Activity entity.');
}
// TODO
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity);
$form = $this->createForm(ActivityType::class, $entity, [
'center' => $entity->getCenter(),
'role' => new Role('CHILL_ACTIVITY_UPDATE'),
'activityType' => $entity->getType(),
'accompanyingPeriod' => $accompanyingPeriod,
])->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->persist($entity);
$this->entityManager->flush();
$this->addFlash('success', $this->get('translator')->trans('Success : activity updated!'));
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
$params['id'] = $entity->getId();
return $this->redirectToRoute('chill_activity_activity_show', $params);
}
$deleteForm = $this->createDeleteForm($entity->getId(), $person, $accompanyingPeriod);
/*
* TODO
$event = new PrivacyEvent($person, array(
'element_class' => Activity::class,
'element_id' => $entity->getId(),
'action' => 'edit'
));
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
*/
if ($view === null) {
throw $this->createNotFoundException('Template not found');
}
$activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']);
return $this->render($view, [
'entity' => $entity,
'edit_form' => $form->createView(),
'delete_form' => $deleteForm->createView(),
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
'activity_json' => $activity_array
'entity' => $entity,
'delete_form' => $deleteForm->createView(),
]);
}
/**
* Deletes a Activity entity.
*/
public function deleteAction(Request $request, $id)
private function buildParamsToUrl(?Person $person, ?AccompanyingPeriod $accompanyingPeriod): array
{
$view = null;
$params = [];
[$person, $accompanyingPeriod] = $this->getEntity($request);
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:confirm_deleteAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:confirm_deletePerson.html.twig';
if (null !== $person) {
$params['person_id'] = $person->getId();
}
$activity = $this->activityRepository->find($id);
if (!$activity) {
throw $this->createNotFoundException('Unable to find Activity entity.');
if (null !== $accompanyingPeriod) {
$params['accompanying_period_id'] = $accompanyingPeriod->getId();
}
// TODO
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_DELETE', $activity);
$form = $this->createDeleteForm($activity->getId(), $person, $accompanyingPeriod);
if ($request->getMethod() === Request::METHOD_DELETE) {
$form->handleRequest($request);
if ($form->isValid()) {
$this->logger->notice("An activity has been removed", [
'by_user' => $this->getUser()->getUsername(),
'activity_id' => $activity->getId(),
'person_id' => $activity->getPerson() ? $activity->getPerson()->getId() : null,
'comment' => $activity->getComment()->getComment(),
'scope_id' => $activity->getScope() ? $activity->getScope()->getId() : null,
'reasons_ids' => $activity->getReasons()
->map(
static fn (ActivityReason $ar): int => $ar->getId()
)
->toArray(),
'type_id' => $activity->getType()->getId(),
'duration' => $activity->getDurationTime() ? $activity->getDurationTime()->format('U') : null,
'date' => $activity->getDate()->format('Y-m-d'),
'attendee' => $activity->getAttendee()
]);
$this->entityManager->remove($activity);
$this->entityManager->flush();
$this->addFlash('success', $this->get('translator')
->trans("The activity has been successfully removed."));
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
return $this->redirectToRoute('chill_activity_activity_list', $params);
}
}
if ($view === null) {
throw $this->createNotFoundException('Template not found');
}
return $this->render($view, [
'activity' => $activity,
'delete_form' => $form->createView(),
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
]);
return $params;
}
/**
@ -519,13 +547,13 @@ final class ActivityController extends AbstractController
private function getEntity(Request $request): array
{
$person = $accompanyingPeriod = null;
$person = $accompanyingPeriod = null;
if ($request->query->has('person_id')) {
$person_id = $request->get('person_id');
$person = $this->personRepository->find($person_id);
if ($person === null) {
if (null === $person) {
throw $this->createNotFoundException('Person not found');
}
@ -534,34 +562,19 @@ final class ActivityController extends AbstractController
$accompanying_period_id = $request->get('accompanying_period_id');
$accompanyingPeriod = $this->accompanyingPeriodRepository->find($accompanying_period_id);
if ($accompanyingPeriod === null) {
if (null === $accompanyingPeriod) {
throw $this->createNotFoundException('Accompanying Period not found');
}
// TODO Add permission
// $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
} else {
throw $this->createNotFoundException("Person or Accompanying Period not found");
throw $this->createNotFoundException('Person or Accompanying Period not found');
}
return [
$person,
$accompanyingPeriod
$accompanyingPeriod,
];
}
private function buildParamsToUrl(?Person $person, ?AccompanyingPeriod $accompanyingPeriod): array
{
$params = [];
if (null !== $person) {
$params['person_id'] = $person->getId();
}
if (null !== $accompanyingPeriod) {
$params['accompanying_period_id'] = $accompanyingPeriod->getId();
}
return $params;
}
}

View File

@ -1,38 +1,28 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Chill\ActivityBundle\Entity\ActivityReasonCategory;
use Chill\ActivityBundle\Form\ActivityReasonCategoryType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
/**
* ActivityReasonCategory controller.
*
*/
class ActivityReasonCategoryController extends AbstractController
{
/**
* Lists all ActivityReasonCategory entities.
*
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('ChillActivityBundle:ActivityReasonCategory')->findAll();
return $this->render('ChillActivityBundle:ActivityReasonCategory:index.html.twig', array(
'entities' => $entities,
));
}
/**
* Creates a new ActivityReasonCategory entity.
*
*/
public function createAction(Request $request)
{
@ -45,71 +35,19 @@ class ActivityReasonCategoryController extends AbstractController
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('chill_activity_activityreasoncategory_show', array('id' => $entity->getId())));
return $this->redirect($this->generateUrl('chill_activity_activityreasoncategory_show', ['id' => $entity->getId()]));
}
return $this->render('ChillActivityBundle:ActivityReasonCategory:new.html.twig', array(
return $this->render('ChillActivityBundle:ActivityReasonCategory:new.html.twig', [
'entity' => $entity,
'form' => $form->createView(),
));
}
/**
* Creates a form to create a ActivityReasonCategory entity.
*
* @param ActivityReasonCategory $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(ActivityReasonCategory $entity)
{
$form = $this->createForm(ActivityReasonCategoryType::class, $entity, array(
'action' => $this->generateUrl('chill_activity_activityreasoncategory_create'),
'method' => 'POST',
));
$form->add('submit', SubmitType::class, array('label' => 'Create'));
return $form;
}
/**
* Displays a form to create a new ActivityReasonCategory entity.
*
*/
public function newAction()
{
$entity = new ActivityReasonCategory();
$form = $this->createCreateForm($entity);
return $this->render('ChillActivityBundle:ActivityReasonCategory:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}
/**
* Finds and displays a ActivityReasonCategory entity.
*
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ChillActivityBundle:ActivityReasonCategory')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityReasonCategory entity.');
}
return $this->render('ChillActivityBundle:ActivityReasonCategory:show.html.twig', array(
'entity' => $entity,
));
'form' => $form->createView(),
]);
}
/**
* Displays a form to edit an existing ActivityReasonCategory entity.
*
* @param mixed $id
*/
public function editAction($id)
{
@ -123,33 +61,64 @@ class ActivityReasonCategoryController extends AbstractController
$editForm = $this->createEditForm($entity);
return $this->render('ChillActivityBundle:ActivityReasonCategory:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
));
return $this->render('ChillActivityBundle:ActivityReasonCategory:edit.html.twig', [
'entity' => $entity,
'edit_form' => $editForm->createView(),
]);
}
/**
* Creates a form to edit a ActivityReasonCategory entity.
*
* @param ActivityReasonCategory $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createEditForm(ActivityReasonCategory $entity)
* Lists all ActivityReasonCategory entities.
*/
public function indexAction()
{
$form = $this->createForm(ActivityReasonCategoryType::class, $entity, array(
'action' => $this->generateUrl('chill_activity_activityreasoncategory_update', array('id' => $entity->getId())),
'method' => 'PUT',
));
$em = $this->getDoctrine()->getManager();
$form->add('submit', SubmitType::class, array('label' => 'Update'));
$entities = $em->getRepository('ChillActivityBundle:ActivityReasonCategory')->findAll();
return $form;
return $this->render('ChillActivityBundle:ActivityReasonCategory:index.html.twig', [
'entities' => $entities,
]);
}
/**
* Displays a form to create a new ActivityReasonCategory entity.
*/
public function newAction()
{
$entity = new ActivityReasonCategory();
$form = $this->createCreateForm($entity);
return $this->render('ChillActivityBundle:ActivityReasonCategory:new.html.twig', [
'entity' => $entity,
'form' => $form->createView(),
]);
}
/**
* Finds and displays a ActivityReasonCategory entity.
*
* @param mixed $id
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ChillActivityBundle:ActivityReasonCategory')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityReasonCategory entity.');
}
return $this->render('ChillActivityBundle:ActivityReasonCategory:show.html.twig', [
'entity' => $entity,
]);
}
/**
* Edits an existing ActivityReasonCategory entity.
*
* @param mixed $id
*/
public function updateAction(Request $request, $id)
{
@ -167,12 +136,50 @@ class ActivityReasonCategoryController extends AbstractController
if ($editForm->isValid()) {
$em->flush();
return $this->redirect($this->generateUrl('chill_activity_activityreasoncategory_edit', array('id' => $id)));
return $this->redirect($this->generateUrl('chill_activity_activityreasoncategory_edit', ['id' => $id]));
}
return $this->render('ChillActivityBundle:ActivityReasonCategory:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
));
return $this->render('ChillActivityBundle:ActivityReasonCategory:edit.html.twig', [
'entity' => $entity,
'edit_form' => $editForm->createView(),
]);
}
/**
* Creates a form to create a ActivityReasonCategory entity.
*
* @param ActivityReasonCategory $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(ActivityReasonCategory $entity)
{
$form = $this->createForm(ActivityReasonCategoryType::class, $entity, [
'action' => $this->generateUrl('chill_activity_activityreasoncategory_create'),
'method' => 'POST',
]);
$form->add('submit', SubmitType::class, ['label' => 'Create']);
return $form;
}
/**
* Creates a form to edit a ActivityReasonCategory entity.
*
* @param ActivityReasonCategory $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createEditForm(ActivityReasonCategory $entity)
{
$form = $this->createForm(ActivityReasonCategoryType::class, $entity, [
'action' => $this->generateUrl('chill_activity_activityreasoncategory_update', ['id' => $entity->getId()]),
'method' => 'PUT',
]);
$form->add('submit', SubmitType::class, ['label' => 'Update']);
return $form;
}
}

View File

@ -1,38 +1,28 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Form\ActivityReasonType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
/**
* ActivityReason controller.
*
*/
class ActivityReasonController extends AbstractController
{
/**
* Lists all ActivityReason entities.
*
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('ChillActivityBundle:ActivityReason')->findAll();
return $this->render('ChillActivityBundle:ActivityReason:index.html.twig', array(
'entities' => $entities,
));
}
/**
* Creates a new ActivityReason entity.
*
*/
public function createAction(Request $request)
{
@ -45,71 +35,19 @@ class ActivityReasonController extends AbstractController
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('chill_activity_activityreason', array('id' => $entity->getId())));
return $this->redirect($this->generateUrl('chill_activity_activityreason', ['id' => $entity->getId()]));
}
return $this->render('ChillActivityBundle:ActivityReason:new.html.twig', array(
return $this->render('ChillActivityBundle:ActivityReason:new.html.twig', [
'entity' => $entity,
'form' => $form->createView(),
));
}
/**
* Creates a form to create a ActivityReason entity.
*
* @param ActivityReason $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(ActivityReason $entity)
{
$form = $this->createForm(ActivityReasonType::class, $entity, array(
'action' => $this->generateUrl('chill_activity_activityreason_create'),
'method' => 'POST',
));
$form->add('submit', SubmitType::class, array('label' => 'Create'));
return $form;
}
/**
* Displays a form to create a new ActivityReason entity.
*
*/
public function newAction()
{
$entity = new ActivityReason();
$form = $this->createCreateForm($entity);
return $this->render('ChillActivityBundle:ActivityReason:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}
/**
* Finds and displays a ActivityReason entity.
*
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ChillActivityBundle:ActivityReason')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityReason entity.');
}
return $this->render('ChillActivityBundle:ActivityReason:show.html.twig', array(
'entity' => $entity,
));
'form' => $form->createView(),
]);
}
/**
* Displays a form to edit an existing ActivityReason entity.
*
* @param mixed $id
*/
public function editAction($id)
{
@ -123,33 +61,64 @@ class ActivityReasonController extends AbstractController
$editForm = $this->createEditForm($entity);
return $this->render('ChillActivityBundle:ActivityReason:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView()
));
return $this->render('ChillActivityBundle:ActivityReason:edit.html.twig', [
'entity' => $entity,
'edit_form' => $editForm->createView(),
]);
}
/**
* Creates a form to edit a ActivityReason entity.
*
* @param ActivityReason $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createEditForm(ActivityReason $entity)
* Lists all ActivityReason entities.
*/
public function indexAction()
{
$form = $this->createForm(ActivityReasonType::class, $entity, array(
'action' => $this->generateUrl('chill_activity_activityreason_update', array('id' => $entity->getId())),
'method' => 'PUT',
));
$em = $this->getDoctrine()->getManager();
$form->add('submit', SubmitType::class, array('label' => 'Update'));
$entities = $em->getRepository('ChillActivityBundle:ActivityReason')->findAll();
return $form;
return $this->render('ChillActivityBundle:ActivityReason:index.html.twig', [
'entities' => $entities,
]);
}
/**
* Displays a form to create a new ActivityReason entity.
*/
public function newAction()
{
$entity = new ActivityReason();
$form = $this->createCreateForm($entity);
return $this->render('ChillActivityBundle:ActivityReason:new.html.twig', [
'entity' => $entity,
'form' => $form->createView(),
]);
}
/**
* Finds and displays a ActivityReason entity.
*
* @param mixed $id
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ChillActivityBundle:ActivityReason')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityReason entity.');
}
return $this->render('ChillActivityBundle:ActivityReason:show.html.twig', [
'entity' => $entity,
]);
}
/**
* Edits an existing ActivityReason entity.
*
* @param mixed $id
*/
public function updateAction(Request $request, $id)
{
@ -167,12 +136,50 @@ class ActivityReasonController extends AbstractController
if ($editForm->isValid()) {
$em->flush();
return $this->redirect($this->generateUrl('chill_activity_activityreason', array('id' => $id)));
return $this->redirect($this->generateUrl('chill_activity_activityreason', ['id' => $id]));
}
return $this->render('ChillActivityBundle:ActivityReason:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView()
));
return $this->render('ChillActivityBundle:ActivityReason:edit.html.twig', [
'entity' => $entity,
'edit_form' => $editForm->createView(),
]);
}
/**
* Creates a form to create a ActivityReason entity.
*
* @param ActivityReason $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(ActivityReason $entity)
{
$form = $this->createForm(ActivityReasonType::class, $entity, [
'action' => $this->generateUrl('chill_activity_activityreason_create'),
'method' => 'POST',
]);
$form->add('submit', SubmitType::class, ['label' => 'Create']);
return $form;
}
/**
* Creates a form to edit a ActivityReason entity.
*
* @param ActivityReason $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createEditForm(ActivityReason $entity)
{
$form = $this->createForm(ActivityReasonType::class, $entity, [
'action' => $this->generateUrl('chill_activity_activityreason_update', ['id' => $entity->getId()]),
'method' => 'PUT',
]);
$form->add('submit', SubmitType::class, ['label' => 'Update']);
return $form;
}
}

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Controller;
use Chill\MainBundle\CRUD\Controller\CRUDController;
@ -9,10 +16,8 @@ use Symfony\Component\HttpFoundation\Request;
class AdminActivityPresenceController extends CRUDController
{
/**
* @param string $action
* @param \Doctrine\ORM\QueryBuilder|mixed $query
* @param Request $request
* @param PaginatorInterface $paginator
*
* @return \Doctrine\ORM\QueryBuilder|mixed
*/
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Controller;
use Chill\MainBundle\CRUD\Controller\CRUDController;
@ -9,10 +16,8 @@ use Symfony\Component\HttpFoundation\Request;
class AdminActivityTypeCategoryController extends CRUDController
{
/**
* @param string $action
* @param \Doctrine\ORM\QueryBuilder|mixed $query
* @param Request $request
* @param PaginatorInterface $paginator
*
* @return \Doctrine\ORM\QueryBuilder|mixed
*/
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Controller;
use Chill\MainBundle\CRUD\Controller\CRUDController;
@ -9,10 +16,8 @@ use Symfony\Component\HttpFoundation\Request;
class AdminActivityTypeController extends CRUDController
{
/**
* @param string $action
* @param \Doctrine\ORM\QueryBuilder|mixed $query
* @param Request $request
* @param PaginatorInterface $paginator
*
* @return \Doctrine\ORM\QueryBuilder|mixed
*/
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)

View File

@ -1,33 +1,18 @@
<?php
/*
/**
* Chill is a software for social workers
* Copyright (C) 2015 Champs Libres <info@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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
/**
* Controller for activity configuration
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @author Champs Libres <info@champs-libres.coop>
* Controller for activity configuration.
*/
class AdminController extends AbstractController
{
@ -35,7 +20,7 @@ class AdminController extends AbstractController
{
return $this->render('ChillActivityBundle:Admin:layout_activity.html.twig');
}
public function redirectToAdminIndexAction()
{
return $this->redirectToRoute('chill_main_admin_central');

View File

@ -1,48 +1,34 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\DataFixtures\ORM;
use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\DataFixtures\ORM\LoadScopes;
use Chill\MainBundle\DataFixtures\ORM\LoadUsers;
use Chill\PersonBundle\Entity\Person;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ObjectManager;
use Faker\Factory as FakerFactory;
use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\DataFixtures\ORM\LoadUsers;
use Chill\ActivityBundle\DataFixtures\ORM\LoadActivityReason;
use Chill\ActivityBundle\DataFixtures\ORM\LoadActivityType;
use Chill\MainBundle\DataFixtures\ORM\LoadScopes;
class LoadActivity extends AbstractFixture implements OrderedFixtureInterface
{
use \Symfony\Component\DependencyInjection\ContainerAwareTrait;
private EntityManagerInterface $em;
/**
* @var \Faker\Generator
*/
private $faker;
private EntityManagerInterface $em;
public function __construct(EntityManagerInterface $em)
{
@ -55,30 +41,53 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface
return 16400;
}
/**
* Return a random scope
*
* @return \Chill\MainBundle\Entity\Scope
*/
private function getRandomScope()
public function load(ObjectManager $manager)
{
$scopeRef = LoadScopes::$references[array_rand(LoadScopes::$references)];
return $this->getReference($scopeRef);
$persons = $this->em
->getRepository(Person::class)
->findAll();
foreach ($persons as $person) {
$activityNbr = rand(0, 3);
for ($i = 0; $i < $activityNbr; ++$i ) {
$activity = $this->newRandomActivity($person);
if (null !== $activity) {
$manager->persist($activity);
}
}
}
$manager->flush();
}
public function newRandomActivity($person): ?Activity
{
$activity = (new Activity())
->setUser($this->getRandomUser())
->setPerson($person)
->setDate($this->faker->dateTimeThisYear())
->setDurationTime($this->faker->dateTime(36000))
->setType($this->getRandomActivityType())
->setScope($this->getRandomScope());
// ->setAttendee($this->faker->boolean())
for ($i = 0; rand(0, 4) > $i; ++$i) {
$reason = $this->getRandomActivityReason();
if (null !== $reason) {
$activity->addReason($reason);
} else {
return null;
}
}
return $activity;
}
/**
* Return a random activityType
*
* @return \Chill\ActivityBundle\Entity\ActivityType
*/
private function getRandomActivityType()
{
$typeRef = LoadActivityType::$references[array_rand(LoadActivityType::$references)];
return $this->getReference($typeRef);
}
/**
* Return a random activityReason
* Return a random activityReason.
*
* @return \Chill\ActivityBundle\Entity\ActivityReason
*/
@ -90,57 +99,38 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface
}
/**
* Return a random user
* Return a random activityType.
*
* @return \Chill\ActivityBundle\Entity\ActivityType
*/
private function getRandomActivityType()
{
$typeRef = LoadActivityType::$references[array_rand(LoadActivityType::$references)];
return $this->getReference($typeRef);
}
/**
* Return a random scope.
*
* @return \Chill\MainBundle\Entity\Scope
*/
private function getRandomScope()
{
$scopeRef = LoadScopes::$references[array_rand(LoadScopes::$references)];
return $this->getReference($scopeRef);
}
/**
* Return a random user.
*
* @return \Chill\MainBundle\Entity\User
*/
private function getRandomUser()
{
$userRef = array_rand(LoadUsers::$refs);
return $this->getReference($userRef);
}
public function newRandomActivity($person): ?Activity
{
$activity = (new Activity())
->setUser($this->getRandomUser())
->setPerson($person)
->setDate($this->faker->dateTimeThisYear())
->setDurationTime($this->faker->dateTime(36000))
->setType($this->getRandomActivityType())
->setScope($this->getRandomScope())
;
// ->setAttendee($this->faker->boolean())
for ($i = 0; $i < rand(0, 4); $i++) {
$reason = $this->getRandomActivityReason();
if (null !== $reason) {
$activity->addReason($reason);
} else {
return null;
}
}
return $activity;
}
public function load(ObjectManager $manager)
{
$persons = $this->em
->getRepository(Person::class)
->findAll();
foreach ($persons as $person) {
$activityNbr = rand(0,3);
for ($i = 0; $i < $activityNbr; $i ++) {
$activity = $this->newRandomActivity($person);
if (null !== $activity) {
$manager->persist($activity);
}
}
}
$manager->flush();
}
}

View File

@ -1,15 +1,21 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\DataFixtures\ORM\LoadAbstractNotificationsTrait;
use Chill\ActivityBundle\DataFixtures\ORM\LoadActivity;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
/**
* Load notififications into database
* Load notififications into database.
*/
class LoadActivityNotifications extends AbstractFixture implements DependentFixtureInterface
{
@ -25,9 +31,9 @@ class LoadActivityNotifications extends AbstractFixture implements DependentFixt
'center a_social',
'center a_administrative',
'center a_direction',
'multi_center'
'multi_center',
],
]
],
];
public function getDependencies()

View File

@ -1,81 +1,66 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@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/>.
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\DataFixtures\ORM;
use Chill\ActivityBundle\Entity\ActivityReason;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Chill\ActivityBundle\Entity\ActivityReason;
/**
* Description of LoadActivityReason
*
* @author Champs-Libres Coop
* Description of LoadActivityReason.
*/
class LoadActivityReason extends AbstractFixture implements OrderedFixtureInterface
{
public static $references = [];
public function getOrder()
{
return 16300;
}
public static $references = array();
public function load(ObjectManager $manager)
{
$reasons = [
[
'name' => ['fr' => 'Recherche logement', 'en' => 'Housing research', 'nl' => 'Woning zoektoch'],
'category' => 'cat_Housing'],
'category' => 'cat_Housing', ],
[
'name' => ['fr' => 'Problème avec propriétaire', 'en' => 'Landlord problems', 'nl' => 'Huisbaas problemen'],
'category' => 'cat_Housing'],
'category' => 'cat_Housing', ],
[
'name' => ['fr' => 'Retard de payement', 'en' => 'Payement problems', 'nl' => 'Betalings vertragingen'],
'category' => 'cat_Housing'],
'category' => 'cat_Housing', ],
[
'name' => ['fr' => 'Explication législation', 'en' => 'Legislation explanation', 'nl' => 'Legislative uitleg'],
'category' => 'cat_Unemployment procedure'],
'category' => 'cat_Unemployment procedure', ],
[
'name' => ['fr' => 'Coaching entretien d\'activation', 'en' => 'Interview coaching', 'nl' => 'Interview coaching'],
'category' => 'cat_Unemployment procedure'],
'category' => 'cat_Unemployment procedure', ],
[
'name' => ['fr' => 'Récupération des allocations', 'en' => 'Allowance recovery', 'nl' => 'Terugwinning van de uitkeringen'],
'category' => 'cat_Unemployment procedure']
'category' => 'cat_Unemployment procedure', ],
];
foreach ($reasons as $r) {
print "Creating activity reason : " . $r['name']['en'] . "\n";
echo 'Creating activity reason : ' . $r['name']['en'] . "\n";
$activityReason = (new ActivityReason())
->setName(($r['name']))
->setActive(true)
->setCategory($this->getReference($r['category']));
$manager->persist($activityReason);
$reference = 'activity_reason_'.$r['name']['en'];
$reference = 'activity_reason_' . $r['name']['en'];
$this->addReference($reference, $activityReason);
static::$references[] = $reference;
}
$manager->flush();
}
}

View File

@ -1,35 +1,21 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@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/>.
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\DataFixtures\ORM;
use Chill\ActivityBundle\Entity\ActivityReasonCategory;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Chill\ActivityBundle\Entity\ActivityReasonCategory;
/**
* Description of LoadActivityReasonCategory
*
* @author Champs-Libres Coop
* Description of LoadActivityReasonCategory.
*/
class LoadActivityReasonCategory extends AbstractFixture implements OrderedFixtureInterface
{
@ -37,27 +23,26 @@ class LoadActivityReasonCategory extends AbstractFixture implements OrderedFixtu
{
return 16200;
}
public function load(ObjectManager $manager)
{
$categs = [
['name' =>
['fr' => 'Logement', 'en' => 'Housing', 'nl' => 'Woning']],
['name' =>
['fr' => 'Démarches chômage', 'en' => 'Unemployment procedure', 'nl' => 'Werkloosheid werkwijze']],
['name' => ['fr' => 'Logement', 'en' => 'Housing', 'nl' => 'Woning']],
['name' => ['fr' => 'Démarches chômage', 'en' => 'Unemployment procedure', 'nl' => 'Werkloosheid werkwijze']],
];
foreach ($categs as $c) {
print "Creating activity reason category : " . $c['name']['en'] . "\n";
echo 'Creating activity reason category : ' . $c['name']['en'] . "\n";
$activityReasonCategory = (new ActivityReasonCategory())
->setName(($c['name']))
->setActive(true);
$manager->persist($activityReasonCategory);
$this->addReference(
'cat_'.$c['name']['en'],
$activityReasonCategory);
'cat_' . $c['name']['en'],
$activityReasonCategory
);
}
$manager->flush();
}
}

View File

@ -1,86 +1,65 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\DataFixtures\ORM;
use Chill\ActivityBundle\Entity\ActivityType;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Chill\ActivityBundle\Entity\ActivityType;
/**
* Description of LoadActivityType
*
* @author Champs-Libres Coop
* Description of LoadActivityType.
*/
class LoadActivityType extends Fixture implements OrderedFixtureInterface
{
public static $references = [];
public function getOrder()
{
return 16100;
}
public static $references = array();
public function load(ObjectManager $manager)
{
$types = [
# Exange
// Exange
[
'name' =>
['fr' => 'Entretien physique avec l\'usager'],
'category' => 'exchange' ],
'name' => ['fr' => 'Entretien physique avec l\'usager'],
'category' => 'exchange', ],
[
'name' =>
['fr' => 'Appel téléphonique', 'en' => 'Telephone call', 'nl' => 'Telefoon appel'],
'category' => 'exchange' ],
'name' => ['fr' => 'Appel téléphonique', 'en' => 'Telephone call', 'nl' => 'Telefoon appel'],
'category' => 'exchange', ],
[
'name' =>
['fr' => 'Courriel', 'en' => 'Email', 'nl' => 'Email'],
'category' => 'exchange' ],
# Meeting
'name' => ['fr' => 'Courriel', 'en' => 'Email', 'nl' => 'Email'],
'category' => 'exchange', ],
// Meeting
[
'name' =>
['fr' => 'Point technique encadrant'],
'category' => 'meeting' ],
'name' => ['fr' => 'Point technique encadrant'],
'category' => 'meeting', ],
[
'name' =>
['fr' => 'Réunion avec des partenaires'],
'category' => 'meeting' ],
'name' => ['fr' => 'Réunion avec des partenaires'],
'category' => 'meeting', ],
[
'name' =>
['fr' => 'Commission pluridisciplinaire et pluri-institutionnelle'],
'category' => 'meeting' ],
'name' => ['fr' => 'Commission pluridisciplinaire et pluri-institutionnelle'],
'category' => 'meeting', ],
];
foreach ($types as $t) {
print "Creating activity type : " . $t['name']['fr'] . " (cat:". $t['category'] . " \n";
echo 'Creating activity type : ' . $t['name']['fr'] . ' (cat:' . $t['category'] . " \n";
$activityType = (new ActivityType())
->setName(($t['name']))
->setCategory($this->getReference('activity_type_cat_'.$t['category']))
->setCategory($this->getReference('activity_type_cat_' . $t['category']))
->setSocialIssuesVisible(1)
->setSocialActionsVisible(1);
$manager->persist($activityType);
$reference = 'activity_type_'.$t['name']['fr'];
$reference = 'activity_type_' . $t['name']['fr'];
$this->addReference($reference, $activityType);
static::$references[] = $reference;
}

View File

@ -1,40 +1,25 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2014-2021, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\DataFixtures\ORM;
use Chill\ActivityBundle\Entity\ActivityTypeCategory;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Chill\ActivityBundle\Entity\ActivityTypeCategory;
/**
* Fixtures for ActivityTypeCategory
*
* @author Champs-Libres Coop
* Fixtures for ActivityTypeCategory.
*/
class LoadActivityTypeCategory extends Fixture implements OrderedFixtureInterface
{
public static $references = array();
public static $references = [];
public function getOrder()
{
@ -55,13 +40,13 @@ class LoadActivityTypeCategory extends Fixture implements OrderedFixtureInterfac
];
foreach ($categories as $cat) {
print "Creating activity type category : " . $cat['ref'] . "\n";
echo 'Creating activity type category : ' . $cat['ref'] . "\n";
$newCat = (new ActivityTypeCategory())
->setName(($cat['name']));
$manager->persist($newCat);
$reference = 'activity_type_cat_'.$cat['ref'];
$reference = 'activity_type_cat_' . $cat['ref'];
$this->addReference($reference, $newCat);
static::$references[] = $reference;

View File

@ -1,38 +1,26 @@
<?php
/*
* Copyright (C) 2015 Julien Fastré <julien.fastre@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\DataFixtures\ORM;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Chill\MainBundle\DataFixtures\ORM\LoadPermissionsGroup;
use Chill\MainBundle\DataFixtures\ORM\LoadScopes;
use Chill\MainBundle\Entity\RoleScope;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Chill\MainBundle\DataFixtures\ORM\LoadPermissionsGroup;
use Chill\MainBundle\Entity\RoleScope;
use Chill\MainBundle\DataFixtures\ORM\LoadScopes;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
/**
* Add a role CHILL_ACTIVITY_UPDATE & CHILL_ACTIVITY_CREATE for all groups except administrative,
* and a role CHILL_ACTIVITY_SEE for administrative
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* and a role CHILL_ACTIVITY_SEE for administrative.
*/
class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterface
{
@ -41,12 +29,12 @@ class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterfac
return 16000;
}
public function load(ObjectManager $manager)
{
foreach (LoadPermissionsGroup::$refs as $permissionsGroupRef) {
$permissionsGroup = $this->getReference($permissionsGroupRef);
foreach (LoadScopes::$references as $scopeRef){
foreach (LoadScopes::$references as $scopeRef) {
$scope = $this->getReference($scopeRef);
//create permission group
switch ($permissionsGroup->getName()) {
@ -54,50 +42,52 @@ class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterfac
if ($scope->getName()['en'] === 'administrative') {
break 2; // we do not want any power on administrative
}
break;
case 'administrative':
case 'direction':
if (in_array($scope->getName()['en'], array('administrative', 'social'))) {
if (in_array($scope->getName()['en'], ['administrative', 'social'])) {
break 2; // we do not want any power on social or administrative
}
break;
}
printf("Adding CHILL_ACTIVITY_UPDATE & CHILL_ACTIVITY_CREATE & CHILL_ACTIVITY_DELETE, and stats and list permissions to %s "
printf(
'Adding CHILL_ACTIVITY_UPDATE & CHILL_ACTIVITY_CREATE & CHILL_ACTIVITY_DELETE, and stats and list permissions to %s '
. "permission group, scope '%s' \n",
$permissionsGroup->getName(), $scope->getName()['en']);
$permissionsGroup->getName(),
$scope->getName()['en']
);
$roleScopeUpdate = (new RoleScope())
->setRole('CHILL_ACTIVITY_UPDATE')
->setScope($scope);
->setRole('CHILL_ACTIVITY_UPDATE')
->setScope($scope);
$permissionsGroup->addRoleScope($roleScopeUpdate);
$roleScopeCreate = (new RoleScope())
->setRole(ActivityVoter::CREATE_ACCOMPANYING_COURSE)
->setScope($scope);
->setRole(ActivityVoter::CREATE_ACCOMPANYING_COURSE)
->setScope($scope);
$roleScopeCreate = (new RoleScope())
->setRole(ActivityVoter::CREATE_PERSON)
->setScope($scope);
$permissionsGroup->addRoleScope($roleScopeCreate);
$roleScopeDelete = (new RoleScope())
->setRole('CHILL_ACTIVITY_DELETE')
->setScope($scope);
->setRole('CHILL_ACTIVITY_DELETE')
->setScope($scope);
$permissionsGroup->addRoleScope($roleScopeDelete);
$roleScopeList = (new RoleScope())
->setRole(ActivityStatsVoter::LISTS)
;
->setRole(ActivityStatsVoter::LISTS);
$permissionsGroup->addRoleScope($roleScopeList);
$roleScopeStat = (new RoleScope())
->setRole(ActivityStatsVoter::STATS)
;
->setRole(ActivityStatsVoter::STATS);
$permissionsGroup->addRoleScope($roleScopeStat);
$manager->persist($roleScopeUpdate);
$manager->persist($roleScopeCreate);
$manager->persist($roleScopeDelete);
}
}
$manager->flush();
}
}

View File

@ -1,45 +1,28 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
/**
* This is the class that loads and manages your bundle configuration
* This is the class that loads and manages your bundle configuration.
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
*/
class ChillActivityExtension extends Extension implements PrependExtensionInterface
{
/**
* {@inheritdoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
@ -47,7 +30,7 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
$container->setParameter('chill_activity.form.time_duration', $config['form']['time_duration']);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config'));
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../config'));
$loader->load('services.yaml');
$loader->load('services/export.yaml');
$loader->load('services/repositories.yaml');
@ -65,38 +48,38 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
$this->prependCruds($container);
}
public function prependAuthorization(ContainerBuilder $container)
{
$container->prependExtensionConfig('security', [
'role_hierarchy' => [
ActivityVoter::UPDATE => [ActivityVoter::SEE_DETAILS],
ActivityVoter::CREATE_PERSON => [ActivityVoter::SEE_DETAILS],
ActivityVoter::CREATE_ACCOMPANYING_COURSE => [ActivityVoter::SEE_DETAILS],
ActivityVoter::DELETE => [ActivityVoter::SEE_DETAILS],
ActivityVoter::SEE_DETAILS => [ActivityVoter::SEE],
ActivityVoter::FULL => [
ActivityVoter::CREATE_PERSON,
ActivityVoter::CREATE_ACCOMPANYING_COURSE,
ActivityVoter::DELETE,
ActivityVoter::UPDATE,
],
],
]);
}
/* (non-PHPdoc)
* @see \Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface::prepend()
*/
public function prependRoutes(ContainerBuilder $container)
{
//add routes for custom bundle
$container->prependExtensionConfig('chill_main', array(
'routing' => array(
'resources' => array(
'@ChillActivityBundle/config/routes.yaml'
)
)
));
}
public function prependAuthorization(ContainerBuilder $container)
{
$container->prependExtensionConfig('security', array(
'role_hierarchy' => array(
ActivityVoter::UPDATE => array(ActivityVoter::SEE_DETAILS),
ActivityVoter::CREATE_PERSON => array(ActivityVoter::SEE_DETAILS),
ActivityVoter::CREATE_ACCOMPANYING_COURSE => array(ActivityVoter::SEE_DETAILS),
ActivityVoter::DELETE => array(ActivityVoter::SEE_DETAILS),
ActivityVoter::SEE_DETAILS => array(ActivityVoter::SEE),
ActivityVoter::FULL => [
ActivityVoter::CREATE_PERSON,
ActivityVoter::CREATE_ACCOMPANYING_COURSE,
ActivityVoter::DELETE,
ActivityVoter::UPDATE
],
)
));
$container->prependExtensionConfig('chill_main', [
'routing' => [
'resources' => [
'@ChillActivityBundle/config/routes.yaml',
],
],
]);
}
protected function prependCruds(ContainerBuilder $container)
@ -112,17 +95,17 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
'actions' => [
'index' => [
'template' => '@ChillActivity/ActivityType/index.html.twig',
'role' => 'ROLE_ADMIN'
'role' => 'ROLE_ADMIN',
],
'new' => [
'new' => [
'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityType/new.html.twig',
],
'edit' => [
'edit' => [
'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityType/edit.html.twig',
]
]
],
],
],
[
'class' => \Chill\ActivityBundle\Entity\ActivityTypeCategory::class,
@ -133,17 +116,17 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
'actions' => [
'index' => [
'template' => '@ChillActivity/ActivityTypeCategory/index.html.twig',
'role' => 'ROLE_ADMIN'
'role' => 'ROLE_ADMIN',
],
'new' => [
'new' => [
'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityTypeCategory/new.html.twig',
],
'edit' => [
'edit' => [
'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityTypeCategory/edit.html.twig',
]
]
],
],
],
[
'class' => \Chill\ActivityBundle\Entity\ActivityPresence::class,
@ -154,19 +137,19 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
'actions' => [
'index' => [
'template' => '@ChillActivity/ActivityPresence/index.html.twig',
'role' => 'ROLE_ADMIN'
'role' => 'ROLE_ADMIN',
],
'new' => [
'new' => [
'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityPresence/new.html.twig',
],
'edit' => [
'edit' => [
'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityPresence/edit.html.twig',
]
]
],
],
],
]
],
]);
}
}

View File

@ -1,71 +1,73 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/**
* This is the class that validates and merges configuration from your app/config files
* This is the class that validates and merges configuration from your app/config files.
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
*/
class Configuration implements ConfigurationInterface
{
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder('chill_activity');
$rootNode = $treeBuilder->getRootNode('chill_activity');
$rootNode
->children()
->arrayNode('form')
->canBeEnabled()
->children()
->arrayNode('time_duration')
->isRequired()
->requiresAtLeastOneElement()
->defaultValue(
array(
[ 'label' => '5 minutes', 'seconds' => 300],
[ 'label' => '10 minutes', 'seconds' => 600],
[ 'label' => '15 minutes', 'seconds' => 900],
[ 'label' => '20 minutes', 'seconds' => 1200],
[ 'label' => '25 minutes', 'seconds' => 1500],
[ 'label' => '30 minutes', 'seconds' => 1800],
[ 'label' => '45 minutes', 'seconds' => 2700],
[ 'label' => '1 hour', 'seconds' => 3600],
[ 'label' => '1 hour 15', 'seconds' => 4500],
[ 'label' => '1 hour 30', 'seconds' => 5400],
[ 'label' => '1 hour 45', 'seconds' => 6300],
[ 'label' => '2 hours', 'seconds' => 7200],
)
)
->info('The intervals of time to show in activity form')
->prototype('array')
->children()
->scalarNode('seconds')
->info("The number of seconds of this duration. Must be an integer.")
->cannotBeEmpty()
->validate()
->ifTrue(function($data) {
->children()
->arrayNode('form')
->canBeEnabled()
->children()
->arrayNode('time_duration')
->isRequired()
->requiresAtLeastOneElement()
->defaultValue(
[
['label' => '5 minutes', 'seconds' => 300],
['label' => '10 minutes', 'seconds' => 600],
['label' => '15 minutes', 'seconds' => 900],
['label' => '20 minutes', 'seconds' => 1200],
['label' => '25 minutes', 'seconds' => 1500],
['label' => '30 minutes', 'seconds' => 1800],
['label' => '45 minutes', 'seconds' => 2700],
['label' => '1 hour', 'seconds' => 3600],
['label' => '1 hour 15', 'seconds' => 4500],
['label' => '1 hour 30', 'seconds' => 5400],
['label' => '1 hour 45', 'seconds' => 6300],
['label' => '2 hours', 'seconds' => 7200],
]
)
->info('The intervals of time to show in activity form')
->prototype('array')
->children()
->scalarNode('seconds')
->info('The number of seconds of this duration. Must be an integer.')
->cannotBeEmpty()
->validate()
->ifTrue(function ($data) {
return !is_int($data);
})->thenInvalid("The value %s is not a valid integer")
->end()
->end()
->scalarNode('label')
->cannotBeEmpty()
->info("The label to show into fields")
->end()
->end()
->end()
})->thenInvalid('The value %s is not a valid integer')
->end()
->end()
->scalarNode('label')
->cannotBeEmpty()
->info('The label to show into fields')
->end()
->end()
->end()
// ->validate()
//
//
// ->ifTrue(function ($data) {
// // test this is an array
// if (!is_array($data)) {
@ -84,11 +86,10 @@ class Configuration implements ConfigurationInterface
// })
// ->thenInvalid("The data are invalid. The keys must be a string and the value integers")
// ->end()
->end()
->end()
->end()
->end();
->end()
->end()
->end()
->end();
return $treeBuilder;
}

View File

@ -1,39 +1,46 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Entity;
use Chill\DocStoreBundle\Entity\Document;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
use Chill\MainBundle\Entity\HasCenterInterface;
use Chill\MainBundle\Entity\HasScopeInterface;
use Chill\MainBundle\Entity\Location;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User;
use Chill\PersonBundle\AccompanyingPeriod\SocialIssueConsistency\AccompanyingPeriodLinkedWithSocialIssuesEntityInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
use Chill\ThirdPartyBundle\Entity\ThirdParty;
use Doctrine\ORM\Mapping as ORM;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Center;
use Chill\PersonBundle\Entity\Person;
use Chill\MainBundle\Entity\HasCenterInterface;
use Chill\MainBundle\Entity\HasScopeInterface;
use Doctrine\Common\Collections\Collection;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName;
/**
* Class Activity
* Class Activity.
*
* @package Chill\ActivityBundle\Entity
* @ORM\Entity(repositoryClass="Chill\ActivityBundle\Repository\ActivityRepository")
* @ORM\Table(name="activity")
* @ORM\HasLifecycleCallbacks()
* @ORM\HasLifecycleCallbacks
* @DiscriminatorMap(typeProperty="type", mapping={
* "activity"=Activity::class
* })
* "activity": Activity::class
* })
*/
/*
@ -46,60 +53,15 @@ use Symfony\Component\Serializer\Annotation\SerializedName;
class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPeriodLinkedWithSocialIssuesEntityInterface
{
const SENTRECEIVED_SENT = 'sent';
const SENTRECEIVED_RECEIVED = 'received';
public const SENTRECEIVED_RECEIVED = 'received';
public const SENTRECEIVED_SENT = 'sent';
/**
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod")
* @Groups({"read"})
*/
private ?int $id = null;
/**
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
*/
private User $user;
/**
* @ORM\Column(type="datetime")
*/
private \DateTime $date;
/**
* @ORM\Column(type="time", nullable=true)
*/
private ?\DateTime $durationTime = null;
/**
* @ORM\Column(type="time", nullable=true)
*/
private ?\DateTime $travelTime = null;
/**
* @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityPresence")
*/
private ?ActivityPresence $attendee = null;
/**
* @ORM\ManyToMany(targetEntity="Chill\ActivityBundle\Entity\ActivityReason")
*/
private Collection $reasons;
/**
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialIssue")
* @ORM\JoinTable(name="chill_activity_activity_chill_person_socialissue")
* @Groups({"read"})
*/
private Collection $socialIssues;
/**
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialAction")
* @ORM\JoinTable(name="chill_activity_activity_chill_person_socialaction")
* @Groups({"read"})
*/
private Collection $socialActions;
private ?AccompanyingPeriod $accompanyingPeriod = null;
/**
* @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityType")
@ -110,32 +72,89 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
private ActivityType $activityType;
/**
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Scope")
* @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityPresence")
*/
private ?Scope $scope = null;
/**
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\Person")
*/
private ?Person $person = null;
/**
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod")
* @Groups({"read"})
*/
private ?AccompanyingPeriod $accompanyingPeriod = null;
private ?ActivityPresence $attendee = null;
/**
* @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\CommentEmbeddable", columnPrefix="comment_")
*/
private CommentEmbeddable $comment;
/**
* @ORM\Column(type="datetime")
*/
private DateTime $date;
/**
* @ORM\ManyToMany(targetEntity="Chill\DocStoreBundle\Entity\StoredObject", cascade={"persist"})
*/
private Collection $documents;
/**
* @ORM\Column(type="time", nullable=true)
*/
private ?DateTime $durationTime = null;
/**
* @ORM\Column(type="boolean", options={"default": false})
*/
private bool $emergency = false;
/**
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
* @Groups({"read"})
*/
private ?int $id = null;
/**
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Location")
* @groups({"read"})
*/
private ?Location $location = null;
/**
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\Person")
*/
private ?Person $person = null;
/**
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\Person")
* @Groups({"read"})
*/
private ?Collection $persons = null;
/**
* @ORM\ManyToMany(targetEntity="Chill\ActivityBundle\Entity\ActivityReason")
*/
private Collection $reasons;
/**
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Scope")
*/
private ?Scope $scope = null;
/**
* @ORM\Column(type="string", options={"default": ""})
*/
private string $sentReceived = '';
/**
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialAction")
* @ORM\JoinTable(name="chill_activity_activity_chill_person_socialaction")
* @Groups({"read"})
*/
private Collection $socialActions;
/**
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialIssue")
* @ORM\JoinTable(name="chill_activity_activity_chill_person_socialissue")
* @Groups({"read"})
*/
private Collection $socialIssues;
/**
* @ORM\ManyToMany(targetEntity="Chill\ThirdPartyBundle\Entity\ThirdParty")
* @Groups({"read"})
@ -143,9 +162,14 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
private ?Collection $thirdParties = null;
/**
* @ORM\ManyToMany(targetEntity="Chill\DocStoreBundle\Entity\StoredObject", cascade={"persist"})
* @ORM\Column(type="time", nullable=true)
*/
private Collection $documents;
private ?DateTime $travelTime = null;
/**
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
*/
private User $user;
/**
* @ORM\ManyToMany(targetEntity="Chill\MainBundle\Entity\User")
@ -153,23 +177,6 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
*/
private ?Collection $users = null;
/**
* @ORM\Column(type="boolean", options={"default"=false})
*/
private bool $emergency = false;
/**
* @ORM\Column(type="string", options={"default"=""})
*/
private string $sentReceived = '';
/**
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Location")
* @groups({"read"})
*/
private ?Location $location = null;
public function __construct()
{
$this->reasons = new ArrayCollection();
@ -182,71 +189,25 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
$this->socialActions = new ArrayCollection();
}
public function getId(): ?int
public function addDocument(Document $document): self
{
return $this->id;
}
public function setUser(UserInterface $user): self
{
$this->user = $user;
$this->documents[] = $document;
return $this;
}
public function getUser(): User
/**
* Add a person to the person list.
*/
public function addPerson(?Person $person): self
{
return $this->user;
}
public function setDate(\DateTime $date): self
{
$this->date = $date;
if (null !== $person) {
$this->persons[] = $person;
}
return $this;
}
public function getDate(): \DateTime
{
return $this->date;
}
public function setDurationTime(?\DateTime $durationTime): self
{
$this->durationTime = $durationTime;
return $this;
}
public function getDurationTime(): ?\DateTime
{
return $this->durationTime;
}
public function setTravelTime(\DateTime $travelTime): self
{
$this->travelTime = $travelTime;
return $this;
}
public function getTravelTime(): ?\DateTime
{
return $this->travelTime;
}
public function setAttendee(ActivityPresence $attendee): self
{
$this->attendee = $attendee;
return $this;
}
public function getAttendee(): ?ActivityPresence
{
return $this->attendee;
}
public function addReason(ActivityReason $reason): self
{
$this->reasons->add($reason);
@ -254,49 +215,6 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
return $this;
}
public function removeReason(ActivityReason $reason): void
{
$this->reasons->removeElement($reason);
}
public function getReasons(): Collection
{
return $this->reasons;
}
public function setReasons(?ArrayCollection $reasons): self
{
$this->reasons = $reasons;
return $this;
}
public function getSocialIssues(): Collection
{
return $this->socialIssues;
}
public function addSocialIssue(SocialIssue $socialIssue): self
{
if (!$this->socialIssues->contains($socialIssue)) {
$this->socialIssues[] = $socialIssue;
}
return $this;
}
public function removeSocialIssue(SocialIssue $socialIssue): self
{
$this->socialIssues->removeElement($socialIssue);
return $this;
}
public function getSocialActions(): Collection
{
return $this->socialActions;
}
public function addSocialAction(SocialAction $socialAction): self
{
if (!$this->socialActions->contains($socialAction)) {
@ -306,82 +224,51 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
return $this;
}
public function removeSocialAction(SocialAction $socialAction): self
public function addSocialIssue(SocialIssue $socialIssue): self
{
$this->socialActions->removeElement($socialAction);
if (!$this->socialIssues->contains($socialIssue)) {
$this->socialIssues[] = $socialIssue;
}
return $this;
}
public function setActivityType(ActivityType $activityType): self
public function addThirdParty(?ThirdParty $thirdParty): self
{
$this->activityType = $activityType;
if (null !== $thirdParty) {
$this->thirdParties[] = $thirdParty;
}
return $this;
}
public function getActivityType(): ActivityType
public function addUser(?User $user): self
{
return $this->activityType;
}
/**
* @deprecated
*/
public function setType(ActivityType $activityType): self
{
$this->activityType = $activityType;
if (null !== $user) {
$this->users[] = $user;
}
return $this;
}
/**
* @deprecated
*/
public function getType(): ActivityType
{
return $this->activityType;
}
public function setScope(Scope $scope): self
{
$this->scope = $scope;
return $this;
}
public function getScope(): ?Scope
{
return $this->scope;
}
public function setPerson(?Person $person): self
{
$this->person = $person;
return $this;
}
public function getPerson(): ?Person
{
return $this->person;
}
public function getAccompanyingPeriod(): ?AccompanyingPeriod
{
return $this->accompanyingPeriod;
}
public function setAccompanyingPeriod(?AccompanyingPeriod $accompanyingPeriod): self
public function getActivityType(): ActivityType
{
$this->accompanyingPeriod = $accompanyingPeriod;
return $this->activityType;
}
return $this;
public function getAttendee(): ?ActivityPresence
{
return $this->attendee;
}
/**
* get the center
* center is extracted from person
* center is extracted from person.
*/
public function getCenter(): ?Center
{
@ -397,28 +284,39 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
return $this->comment;
}
public function setComment(CommentEmbeddable $comment): self
public function getDate(): DateTime
{
$this->comment = $comment;
return $this;
return $this->date;
}
/**
* Add a person to the person list
*/
public function addPerson(?Person $person): self
public function getDocuments(): Collection
{
if (null !== $person) {
$this->persons[] = $person;
}
return $this;
return $this->documents;
}
public function removePerson(Person $person): void
public function getDurationTime(): ?DateTime
{
$this->persons->removeElement($person);
return $this->durationTime;
}
public function getEmergency(): bool
{
return $this->emergency;
}
public function getId(): ?int
{
return $this->id;
}
public function getLocation(): ?Location
{
return $this->location;
}
public function getPerson(): ?Person
{
return $this->person;
}
public function getPersons(): Collection
@ -430,13 +328,16 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
{
if (null !== $this->accompanyingPeriod) {
$personsAssociated = [];
foreach ($this->accompanyingPeriod->getParticipations() as $participation) {
if ($this->persons->contains($participation->getPerson())) {
$personsAssociated[] = $participation->getPerson();
}
}
return $personsAssociated;
}
return [];
}
@ -444,28 +345,103 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
{
if (null !== $this->accompanyingPeriod) {
$personsNotAssociated = [];
foreach ($this->persons as $person) {
if (!in_array($person, $this->getPersonsAssociated())) {
$personsNotAssociated[] = $person;
$personsNotAssociated[] = $person;
}
}
return $personsNotAssociated;
}
return [];
}
public function setPersons(?Collection $persons): self
public function getReasons(): Collection
{
$this->persons = $persons;
return $this->reasons;
}
public function getScope(): ?Scope
{
return $this->scope;
}
public function getSentReceived(): string
{
return $this->sentReceived;
}
public function getSocialActions(): Collection
{
return $this->socialActions;
}
public function getSocialIssues(): Collection
{
return $this->socialIssues;
}
public function getThirdParties(): Collection
{
return $this->thirdParties;
}
public function getTravelTime(): ?DateTime
{
return $this->travelTime;
}
/**
* @deprecated
*/
public function getType(): ActivityType
{
return $this->activityType;
}
public function getUser(): User
{
return $this->user;
}
public function getUsers(): Collection
{
return $this->users;
}
public function isEmergency(): bool
{
return $this->getEmergency();
}
public function removeDocument(Document $document): void
{
$this->documents->removeElement($document);
}
public function removePerson(Person $person): void
{
$this->persons->removeElement($person);
}
public function removeReason(ActivityReason $reason): void
{
$this->reasons->removeElement($reason);
}
public function removeSocialAction(SocialAction $socialAction): self
{
$this->socialActions->removeElement($socialAction);
return $this;
}
public function addThirdParty(?ThirdParty $thirdParty): self
public function removeSocialIssue(SocialIssue $socialIssue): self
{
if (null !== $thirdParty) {
$this->thirdParties[] = $thirdParty;
}
$this->socialIssues->removeElement($socialIssue);
return $this;
}
@ -474,33 +450,44 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
$this->thirdParties->removeElement($thirdParty);
}
public function getThirdParties(): Collection
public function removeUser(User $user): void
{
return $this->thirdParties;
$this->users->removeElement($user);
}
public function setThirdParties(?Collection $thirdParties): self
public function setAccompanyingPeriod(?AccompanyingPeriod $accompanyingPeriod): self
{
$this->thirdParties = $thirdParties;
$this->accompanyingPeriod = $accompanyingPeriod;
return $this;
}
public function addDocument(Document $document): self
public function setActivityType(ActivityType $activityType): self
{
$this->documents[] = $document;
$this->activityType = $activityType;
return $this;
}
public function removeDocument(Document $document): void
public function setAttendee(ActivityPresence $attendee): self
{
$this->documents->removeElement($document);
$this->attendee = $attendee;
return $this;
}
public function getDocuments(): Collection
public function setComment(CommentEmbeddable $comment): self
{
return $this->documents;
$this->comment = $comment;
return $this;
}
public function setDate(DateTime $date): self
{
$this->date = $date;
return $this;
}
public function setDocuments(Collection $documents): self
@ -510,41 +497,13 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
return $this;
}
public function addUser(?User $user): self
public function setDurationTime(?DateTime $durationTime): self
{
if (null !== $user) {
$this->users[] = $user;
}
return $this;
}
public function removeUser(User $user): void
{
$this->users->removeElement($user);
}
public function getUsers(): Collection
{
return $this->users;
}
public function setUsers(?Collection $users): self
{
$this->users = $users;
$this->durationTime = $durationTime;
return $this;
}
public function isEmergency(): bool
{
return $this->getEmergency();
}
public function getEmergency(): bool
{
return $this->emergency;
}
public function setEmergency(bool $emergency): self
{
$this->emergency = $emergency;
@ -552,9 +511,39 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
return $this;
}
public function getSentReceived(): string
public function setLocation(?Location $location): Activity
{
return $this->sentReceived;
$this->location = $location;
return $this;
}
public function setPerson(?Person $person): self
{
$this->person = $person;
return $this;
}
public function setPersons(?Collection $persons): self
{
$this->persons = $persons;
return $this;
}
public function setReasons(?ArrayCollection $reasons): self
{
$this->reasons = $reasons;
return $this;
}
public function setScope(Scope $scope): self
{
$this->scope = $scope;
return $this;
}
public function setSentReceived(?string $sentReceived): self
@ -564,21 +553,41 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
return $this;
}
/**
* @return Location|null
*/
public function getLocation(): ?Location
public function setThirdParties(?Collection $thirdParties): self
{
return $this->location;
$this->thirdParties = $thirdParties;
return $this;
}
public function setTravelTime(DateTime $travelTime): self
{
$this->travelTime = $travelTime;
return $this;
}
/**
* @param Location|null $location
* @return Activity
* @deprecated
*/
public function setLocation(?Location $location): Activity
public function setType(ActivityType $activityType): self
{
$this->location = $location;
$this->activityType = $activityType;
return $this;
}
public function setUser(UserInterface $user): self
{
$this->user = $user;
return $this;
}
public function setUsers(?Collection $users): self
{
$this->users = $users;
return $this;
}
}

View File

@ -1,21 +1,10 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2015, Champs Libres Cooperative SCRLFS, <http://www.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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Entity;
@ -23,15 +12,19 @@ namespace Chill\ActivityBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Class ActivityPresence
* Class ActivityPresence.
*
* @package Chill\ActivityBundle\Entity
* @ORM\Entity()
* @ORM\Entity
* @ORM\Table(name="activitytpresence")
* @ORM\HasLifecycleCallbacks()
* @ORM\HasLifecycleCallbacks
*/
class ActivityPresence
{
/**
* @ORM\Column(type="boolean")
*/
private bool $active = true;
/**
* @ORM\Id
* @ORM\Column(name="id", type="integer")
@ -44,28 +37,6 @@ class ActivityPresence
*/
private array $name = [];
/**
* @ORM\Column(type="boolean")
*/
private bool $active = true;
public function getId(): int
{
return $this->id;
}
public function setName(array $name): self
{
$this->name = $name;
return $this;
}
public function getName(): array
{
return $this->name;
}
/**
* Get active
* return true if the category type is active.
@ -75,9 +46,19 @@ class ActivityPresence
return $this->active;
}
public function getId(): int
{
return $this->id;
}
public function getName(): array
{
return $this->name;
}
/**
* Is active
* return true if the category type is active
* return true if the category type is active.
*/
public function isActive(): bool
{
@ -86,7 +67,7 @@ class ActivityPresence
/**
* Set active
* set to true if the category type is active
* set to true if the category type is active.
*/
public function setActive(bool $active): self
{
@ -94,4 +75,11 @@ class ActivityPresence
return $this;
}
public function setName(array $name): self
{
$this->name = $name;
return $this;
}
}

View File

@ -1,40 +1,41 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2015, Champs Libres Cooperative SCRLFS, <http://www.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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Chill\ActivityBundle\Entity\ActivityReasonCategory;
/**
* Class ActivityReason
* Class ActivityReason.
*
* @package Chill\ActivityBundle\Entity
* @ORM\Entity()
* @ORM\Entity
* @ORM\Table(name="activityreason")
* @ORM\HasLifecycleCallbacks()
* @ORM\HasLifecycleCallbacks
*/
class ActivityReason
{
/**
* @var integer
* @var bool
* @ORM\Column(type="boolean")
*/
private $active = true;
/**
* @var ActivityReasonCategory
* @ORM\ManyToOne(
* targetEntity="Chill\ActivityBundle\Entity\ActivityReasonCategory",
* inversedBy="reasons")
*/
private $category;
/**
* @var int
*
* @ORM\Id
* @ORM\Column(name="id", type="integer")
@ -49,86 +50,17 @@ class ActivityReason
private $name;
/**
* @var ActivityReasonCategory
* @ORM\ManyToOne(
* targetEntity="Chill\ActivityBundle\Entity\ActivityReasonCategory",
* inversedBy="reasons")
*/
private $category;
/**
* @var boolean
* @ORM\Column(type="boolean")
*/
private $active = true;
/**
* Get id
* Get active.
*
* @return integer
* @return bool
*/
public function getId()
public function getActive()
{
return $this->id;
return $this->active;
}
/**
* Set name
*
* @param array $name
* @return ActivityReason
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return array | string
*/
public function getName($locale = null)
{
if ($locale) {
if (isset($this->name[$locale])) {
return $this->name[$locale];
} else {
foreach ($this->name as $name) {
if (!empty($name)) {
return $name;
}
}
}
return '';
} else {
return $this->name;
}
}
/**
* Set category of the reason. If you set to the reason an inactive
* category, the reason will become inactive
*
* @param ActivityReasonCategory $category
* @return ActivityReason
*/
public function setCategory(ActivityReasonCategory $category)
{
if($this->category !== $category && ! $category->getActive()) {
$this->setActive(False);
}
$this->category = $category;
return $this;
}
/**
* Get category
* Get category.
*
* @return ActivityReasonCategory
*/
@ -138,9 +70,46 @@ class ActivityReason
}
/**
* Set active
* Get id.
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Get name.
*
* @param mixed|null $locale
*
* @return array | string
*/
public function getName($locale = null)
{
if ($locale) {
if (isset($this->name[$locale])) {
return $this->name[$locale];
}
foreach ($this->name as $name) {
if (!empty($name)) {
return $name;
}
}
return '';
}
return $this->name;
}
/**
* Set active.
*
* @param bool $active
*
* @param boolean $active
* @return ActivityReason
*/
public function setActive($active)
@ -151,13 +120,33 @@ class ActivityReason
}
/**
* Get active
* Set category of the reason. If you set to the reason an inactive
* category, the reason will become inactive.
*
* @return boolean
* @return ActivityReason
*/
public function getActive()
public function setCategory(ActivityReasonCategory $category)
{
return $this->active;
if ($this->category !== $category && !$category->getActive()) {
$this->setActive(false);
}
$this->category = $category;
return $this;
}
/**
* Set name.
*
* @param array $name
*
* @return ActivityReason
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
}

View File

@ -1,39 +1,34 @@
<?php
/*
* Copyright (C) 2015, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Class ActivityReasonCategory
* Class ActivityReasonCategory.
*
* @package Chill\ActivityBundle\Entity
* @ORM\Entity()
* @ORM\Entity
* @ORM\Table(name="activityreasoncategory")
* @ORM\HasLifecycleCallbacks()
* @ORM\HasLifecycleCallbacks
*/
class ActivityReasonCategory
{
/**
* @var integer
* @var bool
* @ORM\Column(type="boolean")
*/
private $active = true;
/**
* @var int
*
* @ORM\Id
* @ORM\Column(name="id", type="integer")
@ -48,17 +43,12 @@ class ActivityReasonCategory
private $name;
/**
* @var boolean
* @ORM\Column(type="boolean")
*/
private $active = true;
/**
* Array of ActivityReason
* Array of ActivityReason.
*
* @var ArrayCollection
* @ORM\OneToMany(
* targetEntity="Chill\ActivityBundle\Entity\ActivityReason",
* mappedBy="category")
* mappedBy="category")
*/
private $reasons;
@ -75,13 +65,23 @@ class ActivityReasonCategory
*/
public function __toString()
{
return 'ActivityReasonCategory('.$this->getName('x').')';
return 'ActivityReasonCategory(' . $this->getName('x') . ')';
}
/**
* Get id
* Get active.
*
* @return integer
* @return bool
*/
public function getActive()
{
return $this->active;
}
/**
* Get id.
*
* @return int
*/
public function getId()
{
@ -89,20 +89,9 @@ class ActivityReasonCategory
}
/**
* Set name
* Get name.
*
* @param array $name
* @return ActivityReasonCategory
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
* @param mixed|null $locale
*
* @return array
*/
@ -111,30 +100,32 @@ class ActivityReasonCategory
if ($locale) {
if (isset($this->name[$locale])) {
return $this->name[$locale];
} else {
foreach ($this->name as $name) {
if (!empty($name)) {
return $name;
}
}
foreach ($this->name as $name) {
if (!empty($name)) {
return $name;
}
}
return '';
} else {
return $this->name;
}
return $this->name;
}
/**
* Declare a category as active (or not). When a category is set
* as unactive, all the reason have this entity as category is also
* set as unactive
* set as unactive.
*
* @param bool $active
*
* @param boolean $active
* @return ActivityReasonCategory
*/
public function setActive($active)
{
if($this->active !== $active && !$active) {
if ($this->active !== $active && !$active) {
foreach ($this->reasons as $reason) {
$reason->setActive($active);
}
@ -146,13 +137,16 @@ class ActivityReasonCategory
}
/**
* Get active
* Set name.
*
* @return boolean
* @param array $name
*
* @return ActivityReasonCategory
*/
public function getActive()
public function setName($name)
{
return $this->active;
$this->name = $name;
return $this;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Entity;
@ -7,12 +14,17 @@ namespace Chill\ActivityBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity()
* @ORM\Entity
* @ORM\Table(name="activitytypecategory")
* @ORM\HasLifecycleCallbacks()
* @ORM\HasLifecycleCallbacks
*/
class ActivityTypeCategory
{
/**
* @ORM\Column(type="boolean")
*/
private bool $active = true;
/**
* @ORM\Id
* @ORM\Column(name="id", type="integer")
@ -26,38 +38,10 @@ class ActivityTypeCategory
private array $name = [];
/**
* @ORM\Column(type="boolean")
*/
private bool $active = true;
/**
* @ORM\Column(type="float", options={"default"="0.0"})
* @ORM\Column(type="float", options={"default": "0.0"})
*/
private float $ordering = 0.0;
public function getId(): ?int
{
return $this->id;
}
/**
* Set name
*/
public function setName(array $name): self
{
$this->name = $name;
return $this;
}
/**
* Get name
*/
public function getName(): array
{
return $this->name;
}
/**
* Get active
* return true if the category type is active.
@ -67,9 +51,27 @@ class ActivityTypeCategory
return $this->active;
}
public function getId(): ?int
{
return $this->id;
}
/**
* Get name.
*/
public function getName(): array
{
return $this->name;
}
public function getOrdering(): float
{
return $this->ordering;
}
/**
* Is active
* return true if the category type is active
* return true if the category type is active.
*/
public function isActive(): bool
{
@ -78,7 +80,7 @@ class ActivityTypeCategory
/**
* Set active
* set to true if the category type is active
* set to true if the category type is active.
*/
public function setActive(bool $active): self
{
@ -87,9 +89,14 @@ class ActivityTypeCategory
return $this;
}
public function getOrdering(): float
/**
* Set name.
*/
public function setName(array $name): self
{
return $this->ordering;
$this->name = $name;
return $this;
}
public function setOrdering(float $ordering): self

View File

@ -1,22 +1,30 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Repository\ActivityReasonCategoryRepository;
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Doctrine\ORM\QueryBuilder;
use Chill\MainBundle\Export\AggregatorInterface;
use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\Query\Expr\Join;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use RuntimeException;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
class ActivityReasonAggregator implements AggregatorInterface, ExportElementValidatedInterface
{
@ -36,42 +44,47 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function alterQuery(QueryBuilder $qb, $data)
{
// add select element
if ($data['level'] === 'reasons') {
if ('reasons' === $data['level']) {
$elem = 'reasons.id';
$alias = 'activity_reasons_id';
} elseif ($data['level'] === 'categories') {
} elseif ('categories' === $data['level']) {
$elem = 'category.id';
$alias = 'activity_categories_id';
} else {
throw new \RuntimeException('The data provided are not recognized.');
throw new RuntimeException('The data provided are not recognized.');
}
$qb->addSelect($elem.' as '.$alias);
$qb->addSelect($elem . ' as ' . $alias);
// make a jointure only if needed
$join = $qb->getDQLPart('join');
if (
(array_key_exists('activity', $join)
&&
!$this->checkJoinAlreadyDefined($join['activity'], 'reasons')
(
array_key_exists('activity', $join)
&& !$this->checkJoinAlreadyDefined($join['activity'], 'reasons')
)
OR
(! array_key_exists('activity', $join))
or (!array_key_exists('activity', $join))
) {
$qb->add(
'join',
[
'activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons')
'activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons'),
],
true
);
}
// join category if necessary
if ($alias === 'activity_categories_id') {
if ('activity_categories_id' === $alias) {
// add join only if needed
if (!$this->checkJoinAlreadyDefined($qb->getDQLPart('join')['activity'], 'category')) {
$qb->join('reasons.category', 'category');
@ -88,24 +101,6 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
}
}
/**
* Check if a join between Activity and another alias
*
* @param Join[] $joins
* @param string $alias the alias to search for
* @return boolean
*/
private function checkJoinAlreadyDefined(array $joins, $alias)
{
foreach ($joins as $join) {
if ($join->getAlias() === $alias) {
return true;
}
}
return false;
}
public function applyOn()
{
return 'activity';
@ -118,52 +113,37 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
ChoiceType::class,
[
'choices' => [
'By reason' => 'reasons',
'By category of reason' => 'categories'
'By reason' => 'reasons',
'By category of reason' => 'categories',
],
'multiple' => false,
'expanded' => true,
'label' => "Reason's level"
'label' => "Reason's level",
]
);
}
public function validateForm($data, ExecutionContextInterface $context)
{
if ($data['level'] === null) {
$context
->buildViolation("The reasons's level should not be empty.")
->addViolation();
}
}
public function getTitle()
{
return 'Aggregate by activity reason';
}
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function getLabels($key, array $values, $data)
{
// for performance reason, we load data from db only once
switch ($data['level']) {
case 'reasons':
$this->activityReasonRepository->findBy(['id' => $values]);
break;
case 'categories':
$this->activityReasonCategoryRepository->findBy(['id' => $values]);
break;
default:
throw new \RuntimeException(sprintf("The level data '%s' is invalid.", $data['level']));
throw new RuntimeException(sprintf("The level data '%s' is invalid.", $data['level']));
}
return function($value) use ($data) {
if ($value === '_header') {
return $data['level'] === 'reasons' ? 'Group by reasons' : 'Group by categories of reason';
return function ($value) use ($data) {
if ('_header' === $value) {
return 'reasons' === $data['level'] ? 'Group by reasons' : 'Group by categories of reason';
}
switch ($data['level']) {
@ -171,32 +151,63 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
$r = $this->activityReasonRepository->find($value);
return sprintf(
"%s > %s",
'%s > %s',
$this->translatableStringHelper->localize($r->getCategory()->getName()),
$this->translatableStringHelper->localize($r->getName())
);
case 'categories':
$c = $this->activityReasonCategoryRepository->find($value);
return $this->translatableStringHelper->localize($c->getName());
}
};
}
public function getQueryKeys($data)
{
// add select element
if ($data['level'] === 'reasons') {
return array('activity_reasons_id');
if ('reasons' === $data['level']) {
return ['activity_reasons_id'];
}
if ($data['level'] === 'categories') {
return array ('activity_categories_id');
if ('categories' === $data['level']) {
return ['activity_categories_id'];
}
throw new \RuntimeException('The data provided are not recognised.');
throw new RuntimeException('The data provided are not recognised.');
}
public function getTitle()
{
return 'Aggregate by activity reason';
}
public function validateForm($data, ExecutionContextInterface $context)
{
if (null === $data['level']) {
$context
->buildViolation("The reasons's level should not be empty.")
->addViolation();
}
}
/**
* Check if a join between Activity and another alias.
*
* @param Join[] $joins
* @param string $alias the alias to search for
*
* @return bool
*/
private function checkJoinAlreadyDefined(array $joins, $alias)
{
foreach ($joins as $join) {
if ($join->getAlias() === $alias) {
return true;
}
}
return false;
}
}

View File

@ -1,26 +1,34 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Doctrine\ORM\QueryBuilder;
use Chill\MainBundle\Export\AggregatorInterface;
use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Closure;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
class ActivityTypeAggregator implements AggregatorInterface
{
public const KEY = 'activity_type_aggregator';
protected ActivityTypeRepository $activityTypeRepository;
protected TranslatableStringHelperInterface $translatableStringHelper;
public const KEY = 'activity_type_aggregator';
public function __construct(
ActivityTypeRepository $activityTypeRepository,
TranslatableStringHelperInterface $translatableStringHelper
@ -29,6 +37,11 @@ class ActivityTypeAggregator implements AggregatorInterface
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function alterQuery(QueryBuilder $qb, $data)
{
// add select element
@ -38,24 +51,6 @@ class ActivityTypeAggregator implements AggregatorInterface
$qb->addGroupBy(self::KEY);
}
/**
* Check if a join between Activity and another alias
*
* @param Join[] $joins
* @param string $alias the alias to search for
* @return boolean
*/
private function checkJoinAlreadyDefined(array $joins, $alias)
{
foreach ($joins as $join) {
if ($join->getAlias() === $alias) {
return true;
}
}
return false;
}
public function applyOn()
{
return 'activity';
@ -66,23 +61,13 @@ class ActivityTypeAggregator implements AggregatorInterface
// no form required for this aggregator
}
public function getTitle()
{
return 'Aggregate by activity type';
}
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function getLabels($key, array $values, $data): \Closure
public function getLabels($key, array $values, $data): Closure
{
// for performance reason, we load data from db only once
$this->activityTypeRepository->findBy(['id' => $values]);
return function($value): string {
if ($value === '_header') {
return function ($value): string {
if ('_header' === $value) {
return 'Activity type';
}
@ -97,4 +82,27 @@ class ActivityTypeAggregator implements AggregatorInterface
return [self::KEY];
}
public function getTitle()
{
return 'Aggregate by activity type';
}
/**
* Check if a join between Activity and another alias.
*
* @param Join[] $joins
* @param string $alias the alias to search for
*
* @return bool
*/
private function checkJoinAlreadyDefined(array $joins, $alias)
{
foreach ($joins as $join) {
if ($join->getAlias() === $alias) {
return true;
}
}
return false;
}
}

View File

@ -1,13 +1,21 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\MainBundle\Repository\UserRepository;
use Symfony\Component\Form\FormBuilderInterface;
use Doctrine\ORM\QueryBuilder;
use Chill\MainBundle\Export\AggregatorInterface;
use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Repository\UserRepository;
use Closure;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
class ActivityUserAggregator implements AggregatorInterface
{
@ -45,13 +53,13 @@ class ActivityUserAggregator implements AggregatorInterface
// nothing to add
}
public function getLabels($key, $values, $data): \Closure
public function getLabels($key, $values, $data): Closure
{
// preload users at once
$this->userRepository->findBy(['id' => $values]);
return function($value) {
if ($value === '_header') {
return function ($value) {
if ('_header' === $value) {
return 'activity user';
}
@ -61,7 +69,7 @@ class ActivityUserAggregator implements AggregatorInterface
public function getQueryKeys($data)
{
return [ self::KEY ];
return [self::KEY];
}
public function getTitle(): string

View File

@ -1,16 +1,24 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Export;
use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Doctrine\ORM\Query;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
use Doctrine\ORM\Query;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
class CountActivity implements ExportInterface
{
@ -24,7 +32,11 @@ class CountActivity implements ExportInterface
public function buildForm(FormBuilderInterface $builder)
{
}
public function getAllowedFormattersTypes()
{
return [FormatterInterface::TYPE_TABULAR];
}
public function getDescription()
@ -32,6 +44,25 @@ class CountActivity implements ExportInterface
return 'Count activities by various parameters.';
}
public function getLabels($key, array $values, $data)
{
if ('export_count_activity' !== $key) {
throw new LogicException("the key {$key} is not used by this export");
}
return static fn ($value) => '_header' === $value ? 'Number of activities' : $value;
}
public function getQueryKeys($data)
{
return ['export_count_activity'];
}
public function getResult($qb, $data)
{
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getTitle()
{
return 'Count activities';
@ -42,9 +73,9 @@ class CountActivity implements ExportInterface
return 'activity';
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = array())
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(static fn($el) => $el['center'], $acl);
$centers = array_map(static fn ($el) => $el['center'], $acl);
$qb = $this
->activityRepository
@ -59,38 +90,13 @@ class CountActivity implements ExportInterface
return $qb;
}
public function supportsModifiers()
{
return ['person', 'activity'];
}
public function requiredRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function getAllowedFormattersTypes()
public function supportsModifiers()
{
return [FormatterInterface::TYPE_TABULAR];
return ['person', 'activity'];
}
public function getLabels($key, array $values, $data)
{
if ($key !== 'export_count_activity') {
throw new \LogicException("the key $key is not used by this export");
}
return static fn($value) => $value === '_header' ? 'Number of activities' : $value;
}
public function getQueryKeys($data)
{
return ['export_count_activity'];
}
public function getResult($qb, $data)
{
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
}

View File

@ -1,35 +1,38 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Export;
use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\MainBundle\Export\ListInterface;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\DBAL\Exception\InvalidArgumentException;
use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Symfony\Component\Form\FormBuilderInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\ListInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use DateTime;
use Doctrine\DBAL\Exception\InvalidArgumentException;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\Constraints\Callback;
use Doctrine\ORM\Query;
use Chill\MainBundle\Export\FormatterInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use function array_key_exists;
class ListActivity implements ListInterface
{
private ActivityRepository $activityRepository;
protected EntityManagerInterface $entityManager;
protected TranslatorInterface $translator;
protected TranslatableStringHelperInterface $translatableStringHelper;
protected array $fields = [
'id',
'date',
@ -41,9 +44,15 @@ class ListActivity implements ListInterface
'type_name',
'person_firstname',
'person_lastname',
'person_id'
'person_id',
];
protected TranslatableStringHelperInterface $translatableStringHelper;
protected TranslatorInterface $translator;
private ActivityRepository $activityRepository;
public function __construct(
EntityManagerInterface $em,
TranslatorInterface $translator,
@ -62,18 +71,17 @@ class ListActivity implements ListInterface
'multiple' => true,
'expanded' => true,
'choices' => array_combine($this->fields, $this->fields),
'label' => 'Fields to include in export',
'label' => 'Fields to include in export',
'constraints' => [new Callback([
'callback' => function($selected, ExecutionContextInterface $context) {
'callback' => function ($selected, ExecutionContextInterface $context) {
if (count($selected) === 0) {
$context->buildViolation('You must select at least one element')
->atPath('fields')
->addViolation();
}
}
])]
},
])],
]);
}
public function getAllowedFormattersTypes()
@ -83,69 +91,72 @@ class ListActivity implements ListInterface
public function getDescription()
{
return "List activities";
return 'List activities';
}
public function getLabels($key, array $values, $data)
{
switch ($key)
{
case 'date' :
return static function($value) {
if ($value === '_header') {
switch ($key) {
case 'date':
return static function ($value) {
if ('_header' === $value) {
return 'date';
}
$date = \DateTime::createFromFormat('Y-m-d H:i:s', $value);
$date = DateTime::createFromFormat('Y-m-d H:i:s', $value);
return $date->format('d-m-Y');
};
case 'attendee':
return static function($value) {
if ($value === '_header') {
return static function ($value) {
if ('_header' === $value) {
return 'attendee';
}
return $value ? 1 : 0;
};
case 'list_reasons' :
case 'list_reasons':
$activityRepository = $this->activityRepository;
return function($value) use ($activityRepository): string {
if ($value === '_header') {
return function ($value) use ($activityRepository): string {
if ('_header' === $value) {
return 'activity reasons';
}
$activity = $activityRepository->find($value);
return implode(", ", array_map(function(ActivityReason $r) {
return '"'.
return implode(', ', array_map(function (ActivityReason $r) {
return '"' .
$this->translatableStringHelper->localize($r->getCategory()->getName())
.' > '.
. ' > ' .
$this->translatableStringHelper->localize($r->getName())
.'"';
. '"';
}, $activity->getReasons()->toArray()));
};
case 'circle_name' :
return function($value) {
if ($value === '_header') {
case 'circle_name':
return function ($value) {
if ('_header' === $value) {
return 'circle';
}
return $this->translatableStringHelper->localize(json_decode($value, true));
};
case 'type_name' :
return function($value) {
if ($value === '_header') {
case 'type_name':
return function ($value) {
if ('_header' === $value) {
return 'activity type';
}
return $this->translatableStringHelper->localize(json_decode($value, true));
};
default:
return static function($value) use ($key) {
if ($value === '_header') {
return static function ($value) use ($key) {
if ('_header' === $value) {
return $key;
}
@ -176,59 +187,75 @@ class ListActivity implements ListInterface
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(function($el) { return $el['center']; }, $acl);
$centers = array_map(function ($el) { return $el['center']; }, $acl);
// throw an error if any fields are present
if (!\array_key_exists('fields', $data)) {
if (!array_key_exists('fields', $data)) {
throw new InvalidArgumentException('Any fields have been checked.');
}
$qb = $this->entityManager->createQueryBuilder();
$qb
->from('ChillActivityBundle:Activity', 'activity')
->join('activity.person', 'person')
->join('person.center', 'center')
->andWhere('center IN (:authorized_centers)')
->setParameter('authorized_centers', $centers);
->from('ChillActivityBundle:Activity', 'activity')
->join('activity.person', 'person')
->join('person.center', 'center')
->andWhere('center IN (:authorized_centers)')
->setParameter('authorized_centers', $centers);
foreach ($this->fields as $f) {
if (in_array($f, $data['fields'])) {
switch ($f) {
case 'id':
$qb->addSelect('activity.id AS id');
break;
case 'person_firstname':
$qb->addSelect('person.firstName AS person_firstname');
break;
case 'person_lastname':
$qb->addSelect('person.lastName AS person_lastname');
break;
case 'person_id':
$qb->addSelect('person.id AS person_id');
break;
case 'user_username':
$qb->join('activity.user', 'user');
$qb->addSelect('user.username AS user_username');
break;
case 'circle_name':
$qb->join('activity.scope', 'circle');
$qb->addSelect('circle.name AS circle_name');
break;
case 'type_name':
$qb->join('activity.type', 'type');
$qb->addSelect('type.name AS type_name');
break;
case 'list_reasons':
// this is a trick... The reasons is filled with the
// activity id which will be used to load reasons
$qb->addSelect('activity.id AS list_reasons');
break;
default:
$qb->addSelect(sprintf('activity.%s as %s', $f, $f));
break;
}
}
}
@ -244,5 +271,4 @@ class ListActivity implements ListInterface
{
return ['activity', 'person'];
}
}

View File

@ -1,16 +1,24 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Export;
use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Doctrine\ORM\Query;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
use Doctrine\ORM\Query;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
/**
* This export allow to compute stats on activity duration.
@ -19,8 +27,6 @@ use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
*/
class StatActivityDuration implements ExportInterface
{
private ActivityRepository $activityRepository;
public const SUM = 'sum';
/**
@ -28,6 +34,8 @@ class StatActivityDuration implements ExportInterface
*/
protected string $action;
private ActivityRepository $activityRepository;
/**
* @param string $action the stat to perform
*/
@ -41,59 +49,6 @@ class StatActivityDuration implements ExportInterface
public function buildForm(FormBuilderInterface $builder)
{
}
public function getDescription()
{
if ($this->action === self::SUM) {
return 'Sum activities duration by various parameters.';
}
}
public function getTitle()
{
if ($this->action === self::SUM) {
return 'Sum activity duration';
}
}
public function getType()
{
return 'activity';
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(
static fn(array $el): string => $el['center'],
$acl
);
$qb = $this->activityRepository->createQueryBuilder('activity');
$select = null;
if ($this->action === self::SUM) {
$select = 'SUM(activity.durationTime) AS export_stat_activity';
}
return $qb->select($select)
->join('activity.person', 'person')
->join('person.center', 'center')
->where($qb->expr()->in('center', ':centers'))
->setParameter(':centers', $centers);
}
public function supportsModifiers()
{
return ['person', 'activity'];
}
public function requiredRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function getAllowedFormattersTypes()
@ -101,15 +56,22 @@ class StatActivityDuration implements ExportInterface
return [FormatterInterface::TYPE_TABULAR];
}
public function getDescription()
{
if (self::SUM === $this->action) {
return 'Sum activities duration by various parameters.';
}
}
public function getLabels($key, array $values, $data)
{
if ($key !== 'export_stat_activity') {
throw new \LogicException(sprintf('The key %s is not used by this export', $key));
if ('export_stat_activity' !== $key) {
throw new LogicException(sprintf('The key %s is not used by this export', $key));
}
$header = $this->action === self::SUM ? 'Sum of activities duration' : false;
$header = self::SUM === $this->action ? 'Sum of activities duration' : false;
return static fn(string $value) => $value === '_header' ? $header : $value;
return static fn (string $value) => '_header' === $value ? $header : $value;
}
public function getQueryKeys($data)
@ -122,4 +84,47 @@ class StatActivityDuration implements ExportInterface
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getTitle()
{
if (self::SUM === $this->action) {
return 'Sum activity duration';
}
}
public function getType()
{
return 'activity';
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(
static fn (array $el): string => $el['center'],
$acl
);
$qb = $this->activityRepository->createQueryBuilder('activity');
$select = null;
if (self::SUM === $this->action) {
$select = 'SUM(activity.durationTime) AS export_stat_activity';
}
return $qb->select($select)
->join('activity.person', 'person')
->join('person.center', 'center')
->where($qb->expr()->in('center', ':centers'))
->setParameter(':centers', $centers);
}
public function requiredRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function supportsModifiers()
{
return ['person', 'activity'];
}
}

View File

@ -1,25 +1,33 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\Export\FilterType;
use DateTime;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormError;
use Chill\MainBundle\Form\Type\Export\FilterType;
use Doctrine\ORM\Query\Expr;
use Symfony\Component\Translation\TranslatorInterface;
class ActivityDateFilter implements FilterInterface
{
protected TranslatorInterface $translator;
function __construct(TranslatorInterface $translator)
public function __construct(TranslatorInterface $translator)
{
$this->translator = $translator;
}
@ -32,8 +40,11 @@ class ActivityDateFilter implements FilterInterface
public function alterQuery(QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
$clause = $qb->expr()->between('activity.date', ':date_from',
':date_to');
$clause = $qb->expr()->between(
'activity.date',
':date_from',
':date_to'
);
if ($where instanceof Expr\Andx) {
$where->add($clause);
@ -58,9 +69,9 @@ class ActivityDateFilter implements FilterInterface
DateType::class,
[
'label' => 'Activities after this date',
'data' => new \DateTime(),
'attr' => ['class' => 'datepicker'],
'widget'=> 'single_text',
'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
]
);
@ -70,46 +81,49 @@ class ActivityDateFilter implements FilterInterface
DateType::class,
[
'label' => 'Activities before this date',
'data' => new \DateTime(),
'attr' => ['class' => 'datepicker'],
'widget'=> 'single_text',
'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
]
);
$builder->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
/* @var $filterForm \Symfony\Component\Form\FormInterface */
$filterForm = $event->getForm()->getParent();
$enabled = $filterForm->get(FilterType::ENABLED_FIELD)->getData();
if ($enabled === true) {
if (true === $enabled) {
// if the filter is enabled, add some validation
$form = $event->getForm();
$form = $event->getForm();
$date_from = $form->get('date_from')->getData();
$date_to = $form->get('date_to')->getData();
$date_to = $form->get('date_to')->getData();
// check that fields are not empty
if ($date_from === null) {
if (null === $date_from) {
$form->get('date_from')->addError(new FormError(
$this->translator->trans('This field '
. 'should not be empty')));
. 'should not be empty')
));
}
if ($date_to === null) {
if (null === $date_to) {
$form->get('date_to')->addError(new FormError(
$this->translator->trans('This field '
. 'should not be empty')));
. 'should not be empty')
));
}
// check that date_from is before date_to
if (
($date_from !== null && $date_to !== null)
&&
$date_from >= $date_to
(null !== $date_from && null !== $date_to)
&& $date_from >= $date_to
) {
$form->get('date_to')->addError(new FormError(
$this->translator->trans('This date should be after '
. 'the date given in "Implied in an activity after '
. 'this date" field')));
. 'this date" field')
));
}
}
});
@ -121,8 +135,8 @@ class ActivityDateFilter implements FilterInterface
'Filtered by date of activity: only between %date_from% and %date_to%',
[
'%date_from%' => $data['date_from']->format('d-m-Y'),
'%date_to%' => $data['date_to']->format('d-m-Y')
]
'%date_to%' => $data['date_to']->format('d-m-Y'),
],
];
}
@ -130,5 +144,4 @@ class ActivityDateFilter implements FilterInterface
{
return 'Filtered by date activity';
}
}

View File

@ -1,30 +1,37 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\Query\Expr;
use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Doctrine\ORM\Query\Expr\Join;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
class ActivityReasonFilter implements FilterInterface, ExportElementValidatedInterface
{
protected TranslatableStringHelperInterface $translatableStringHelper;
protected ActivityReasonRepository $activityReasonRepository;
protected TranslatableStringHelperInterface $translatableStringHelper;
public function __construct(
TranslatableStringHelper $helper,
ActivityReasonRepository $activityReasonRepository
@ -33,26 +40,30 @@ class ActivityReasonFilter implements FilterInterface, ExportElementValidatedInt
$this->activityReasonRepository = $activityReasonRepository;
}
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function alterQuery(QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
$join = $qb->getDQLPart('join');
$join = $qb->getDQLPart('join');
$clause = $qb->expr()->in('reasons', ':selected_activity_reasons');
//dump($join);
// add a join to reasons only if needed
if (
(array_key_exists('activity', $join)
&&
!$this->checkJoinAlreadyDefined($join['activity'], 'reasons')
(
array_key_exists('activity', $join)
&& !$this->checkJoinAlreadyDefined($join['activity'], 'reasons')
)
||
(! array_key_exists('activity', $join))
|| (!array_key_exists('activity', $join))
) {
$qb->add(
'join',
array('activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons')),
true
);
'join',
['activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons')],
true
);
}
if ($where instanceof Expr\Andx) {
@ -65,11 +76,57 @@ class ActivityReasonFilter implements FilterInterface, ExportElementValidatedInt
$qb->setParameter('selected_activity_reasons', $data['reasons']);
}
public function applyOn()
{
return 'activity';
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('reasons', EntityType::class, [
'class' => ActivityReason::class,
'choice_label' => fn (ActivityReason $reason) => $this->translatableStringHelper->localize($reason->getName()),
'group_by' => fn (ActivityReason $reason) => $this->translatableStringHelper->localize($reason->getCategory()->getName()),
'multiple' => true,
'expanded' => false,
]);
}
public function describeAction($data, $format = 'string')
{
// collect all the reasons'name used in this filter in one array
$reasonsNames = array_map(
fn (ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"',
$this->activityReasonRepository->findBy(['id' => $data['reasons']->toArray()])
);
return [
'Filtered by reasons: only %list%',
[
'%list%' => implode(', ', $reasonsNames),
],
];
}
public function getTitle()
{
return 'Filter by reason';
}
public function validateForm($data, ExecutionContextInterface $context)
{
if (null === $data['reasons'] || count($data['reasons']) === 0) {
$context
->buildViolation('At least one reason must be chosen')
->addViolation();
}
}
/**
* Check if a join between Activity and Reason is already defined
* Check if a join between Activity and Reason is already defined.
*
* @param Join[] $joins
* @return boolean
* @param mixed $alias
*/
private function checkJoinAlreadyDefined(array $joins, $alias): bool
{
@ -81,55 +138,4 @@ class ActivityReasonFilter implements FilterInterface, ExportElementValidatedInt
return false;
}
public function applyOn()
{
return 'activity';
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('reasons', EntityType::class, [
'class' => ActivityReason::class,
'choice_label' => fn(ActivityReason $reason) => $this->translatableStringHelper->localize($reason->getName()),
'group_by' => fn(ActivityReason $reason) => $this->translatableStringHelper->localize($reason->getCategory()->getName()),
'multiple' => true,
'expanded' => false
]);
}
public function validateForm($data, ExecutionContextInterface $context)
{
if ($data['reasons'] === null || count($data['reasons']) === 0) {
$context
->buildViolation('At least one reason must be chosen')
->addViolation();
}
}
public function getTitle()
{
return 'Filter by reason';
}
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function describeAction($data, $format = 'string')
{
// collect all the reasons'name used in this filter in one array
$reasonsNames = array_map(
fn(ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"',
$this->activityReasonRepository->findBy(array('id' => $data['reasons']->toArray()))
);
return [
'Filtered by reasons: only %list%',
[
'%list%' => implode(", ", $reasonsNames),
]
];
}
}

View File

@ -1,29 +1,36 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Entity\ActivityType;
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\Query\Expr;
use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\ActivityBundle\Entity\ActivityType;
class ActivityTypeFilter implements FilterInterface, ExportElementValidatedInterface
{
protected TranslatableStringHelperInterface $translatableStringHelper;
protected ActivityTypeRepository $activityTypeRepository;
protected TranslatableStringHelperInterface $translatableStringHelper;
public function __construct(
TranslatableStringHelperInterface $translatableStringHelper,
ActivityTypeRepository $activityTypeRepository
@ -32,6 +39,11 @@ class ActivityTypeFilter implements FilterInterface, ExportElementValidatedInter
$this->activityTypeRepository = $activityTypeRepository;
}
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function alterQuery(QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
@ -47,23 +59,6 @@ class ActivityTypeFilter implements FilterInterface, ExportElementValidatedInter
$qb->setParameter('selected_activity_types', $data['types']);
}
/**
* Check if a join between Activity and Reason is already defined
*
* @param Join[] $joins
* @return boolean
*/
private function checkJoinAlreadyDefined(array $joins, $alias)
{
foreach ($joins as $join) {
if ($join->getAlias() === $alias) {
return true;
}
}
return false;
}
public function applyOn()
{
return 'activity';
@ -76,20 +71,27 @@ class ActivityTypeFilter implements FilterInterface, ExportElementValidatedInter
EntityType::class,
[
'class' => ActivityType::class,
'choice_label' => fn(ActivityType $type) => $this->translatableStringHelper->localize($type->getName()),
'choice_label' => fn (ActivityType $type) => $this->translatableStringHelper->localize($type->getName()),
'multiple' => true,
'expanded' => false
'expanded' => false,
]
);
}
public function validateForm($data, ExecutionContextInterface $context)
public function describeAction($data, $format = 'string')
{
if ($data['types'] === null || count($data['types']) === 0) {
$context
->buildViolation('At least one type must be chosen')
->addViolation();
}
// collect all the reasons'name used in this filter in one array
$reasonsNames = array_map(
fn (ActivityType $t): string => '"' . $this->translatableStringHelper->localize($t->getName()) . '"',
$this->activityTypeRepository->findBy(['id' => $data['types']->toArray()])
);
return [
'Filtered by activity type: only %list%',
[
'%list%' => implode(', ', $reasonsNames),
],
];
}
public function getTitle()
@ -97,24 +99,31 @@ class ActivityTypeFilter implements FilterInterface, ExportElementValidatedInter
return 'Filter by activity type';
}
public function addRole()
public function validateForm($data, ExecutionContextInterface $context)
{
return new Role(ActivityStatsVoter::STATS);
if (null === $data['types'] || count($data['types']) === 0) {
$context
->buildViolation('At least one type must be chosen')
->addViolation();
}
}
public function describeAction($data, $format = 'string')
/**
* Check if a join between Activity and Reason is already defined.
*
* @param Join[] $joins
* @param mixed $alias
*
* @return bool
*/
private function checkJoinAlreadyDefined(array $joins, $alias)
{
// collect all the reasons'name used in this filter in one array
$reasonsNames = array_map(
fn(ActivityType $t): string => '"' . $this->translatableStringHelper->localize($t->getName()) . '"',
$this->activityTypeRepository->findBy(['id' => $data['types']->toArray()])
);
foreach ($joins as $join) {
if ($join->getAlias() === $alias) {
return true;
}
}
return [
'Filtered by activity type: only %list%',
[
'%list%' => implode(", ", $reasonsNames),
]
];
return false;
}
}

View File

@ -1,35 +1,43 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\Export\FilterType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Export\Declarations;
use DateTime;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormError;
use Chill\MainBundle\Form\Type\Export\FilterType;
use Doctrine\ORM\Query\Expr;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\PersonBundle\Export\Declarations;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
class PersonHavingActivityBetweenDateFilter implements FilterInterface, ExportElementValidatedInterface
{
protected TranslatableStringHelperInterface $translatableStringHelper;
protected ActivityReasonRepository $activityReasonRepository;
protected TranslatableStringHelperInterface $translatableStringHelper;
protected TranslatorInterface $translator;
public function __construct(
@ -66,7 +74,8 @@ class PersonHavingActivityBetweenDateFilter implements FilterInterface, ExportEl
$sqb->andWhere(
$sqb->expr()->in(
'reasons_person_having_activity', ':person_having_activity_reasons'
'reasons_person_having_activity',
':person_having_activity_reasons'
)
);
@ -80,10 +89,14 @@ class PersonHavingActivityBetweenDateFilter implements FilterInterface, ExportEl
}
$qb->add('where', $where);
$qb->setParameter('person_having_activity_between_date_from',
$data['date_from']);
$qb->setParameter('person_having_activity_between_date_to',
$data['date_to']);
$qb->setParameter(
'person_having_activity_between_date_from',
$data['date_from']
);
$qb->setParameter(
'person_having_activity_between_date_to',
$data['date_to']
);
$qb->setParameter('person_having_activity_reasons', $data['reasons']);
}
@ -96,76 +109,71 @@ class PersonHavingActivityBetweenDateFilter implements FilterInterface, ExportEl
{
$builder->add('date_from', DateType::class, [
'label' => 'Implied in an activity after this date',
'data' => new \DateTime(),
'attr' => ['class' => 'datepicker'],
'widget'=> 'single_text',
'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
]);
$builder->add('date_to', DateType::class, [
'label' => 'Implied in an activity before this date',
'data' => new \DateTime(),
'attr' => ['class' => 'datepicker'],
'widget'=> 'single_text',
'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
]);
$builder->add('reasons', EntityType::class, [
'class' => ActivityReason::class,
'choice_label' => fn (ActivityReason $reason): ?string => $this->translatableStringHelper->localize($reason->getName()),
'group_by' => fn(ActivityReason $reason): ?string => $this->translatableStringHelper->localize($reason->getCategory()->getName()),
'group_by' => fn (ActivityReason $reason): ?string => $this->translatableStringHelper->localize($reason->getCategory()->getName()),
'data' => $this->activityReasonRepository->findAll(),
'multiple' => true,
'expanded' => false,
'label' => 'Activity reasons for those activities'
'label' => 'Activity reasons for those activities',
]);
$builder->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
/* @var FormInterface $filterForm */
$filterForm = $event->getForm()->getParent();
$enabled = $filterForm->get(FilterType::ENABLED_FIELD)->getData();
if ($enabled === true) {
if (true === $enabled) {
// if the filter is enabled, add some validation
$form = $event->getForm();
$form = $event->getForm();
$date_from = $form->get('date_from')->getData();
$date_to = $form->get('date_to')->getData();
$date_to = $form->get('date_to')->getData();
// check that fields are not empty
if ($date_from === null) {
if (null === $date_from) {
$form->get('date_from')->addError(new FormError(
$this->translator->trans('This field '
. 'should not be empty')));
. 'should not be empty')
));
}
if ($date_to === null) {
if (null === $date_to) {
$form->get('date_to')->addError(new FormError(
$this->translator->trans('This field '
. 'should not be empty')));
. 'should not be empty')
));
}
// check that date_from is before date_to
if (
($date_from !== null && $date_to !== null)
&&
$date_from >= $date_to
(null !== $date_from && null !== $date_to)
&& $date_from >= $date_to
) {
$form->get('date_to')->addError(new FormError(
$this->translator->trans('This date '
. 'should be after the date given in "Implied in an '
. 'activity after this date" field')));
. 'activity after this date" field')
));
}
}
});
}
public function validateForm($data, ExecutionContextInterface $context)
{
if ($data['reasons'] === null || count($data['reasons']) === 0) {
$context->buildViolation('At least one reason must be chosen')
->addViolation();
}
}
public function describeAction($data, $format = 'string')
{
return [
@ -173,15 +181,15 @@ class PersonHavingActivityBetweenDateFilter implements FilterInterface, ExportEl
. '%date_to% with reasons %reasons_name%',
[
'%date_from%' => $data['date_from']->format('d-m-Y'),
'%date_to%' => $data['date_to']->format('d-m-Y'),
'%reasons_name%' => implode(
", ",
'%date_to%' => $data['date_to']->format('d-m-Y'),
'%reasons_name%' => implode(
', ',
array_map(
fn(ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"',
fn (ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"',
$data['reasons']
)
)
]
),
],
];
}
@ -190,4 +198,11 @@ class PersonHavingActivityBetweenDateFilter implements FilterInterface, ExportEl
return 'Filtered by person having an activity in a period';
}
public function validateForm($data, ExecutionContextInterface $context)
{
if (null === $data['reasons'] || count($data['reasons']) === 0) {
$context->buildViolation('At least one reason must be chosen')
->addViolation();
}
}
}

View File

@ -1,13 +1,20 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Entity\ActivityPresence;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
class ActivityPresenceType extends AbstractType
{
@ -15,19 +22,19 @@ class ActivityPresenceType extends AbstractType
{
$builder
->add('name', TranslatableStringFormType::class)
->add('active', ChoiceType::class, array(
'choices' => array(
->add('active', ChoiceType::class, [
'choices' => [
'Yes' => true,
'No' => false
),
'expanded' => true
));
'No' => false,
],
'expanded' => true,
]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults(array(
'data_class' => ActivityPresence::class
));
$resolver->setDefaults([
'data_class' => ActivityPresence::class,
]);
}
}

View File

@ -1,25 +1,27 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Form;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
class ActivityReasonCategoryType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TranslatableStringFormType::class)
->add('active', CheckboxType::class, array('required' => false))
;
->add('active', CheckboxType::class, ['required' => false]);
}
/**
@ -27,9 +29,9 @@ class ActivityReasonCategoryType extends AbstractType
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Chill\ActivityBundle\Entity\ActivityReasonCategory'
));
$resolver->setDefaults([
'data_class' => 'Chill\ActivityBundle\Entity\ActivityReasonCategory',
]);
}
/**

View File

@ -1,37 +1,36 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Form\Type\TranslatableActivityReasonCategory;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
use Chill\ActivityBundle\Form\Type\TranslatableActivityReasonCategory;
class ActivityReasonType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TranslatableStringFormType::class)
->add('active', CheckboxType::class, array('required' => false))
->add('category', TranslatableActivityReasonCategory::class)
;
->add('active', CheckboxType::class, ['required' => false])
->add('category', TranslatableActivityReasonCategory::class);
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Chill\ActivityBundle\Entity\ActivityReason'
));
$resolver->setDefaults([
'data_class' => 'Chill\ActivityBundle\Entity\ActivityReason',
]);
}
/**

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Entity\Activity;
@ -7,54 +14,56 @@ use Chill\ActivityBundle\Entity\ActivityPresence;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\DocStoreBundle\Form\StoredObjectType;
use Chill\MainBundle\Entity\Location;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Form\Type\ChillCollectionType;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Form\Type\CommentType;
use Chill\MainBundle\Form\Type\ScopePickerType;
use Chill\MainBundle\Form\Type\UserPickerType;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
use Chill\ThirdPartyBundle\Entity\ThirdParty;
use DateInterval;
use DateTime;
use DateTimeZone;
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ObjectManager;
use RuntimeException;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Doctrine\Persistence\ObjectManager;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Chill\MainBundle\Entity\User;
use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\MainBundle\Form\Type\UserPickerType;
use Chill\MainBundle\Form\Type\ScopePickerType;
use Chill\MainBundle\Form\Type\ChillDateType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\CallbackTransformer;
use Chill\PersonBundle\Form\DataTransformer\PersonToIdTransformer;
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class ActivityType extends AbstractType
{
protected User $user;
protected AuthorizationHelper $authorizationHelper;
protected ObjectManager $om;
protected TranslatableStringHelper $translatableStringHelper;
protected SocialActionRender $socialActionRender;
protected SocialIssueRender $socialIssueRender;
protected SocialActionRender $socialActionRender;
protected array $timeChoices;
public function __construct (
protected TranslatableStringHelper $translatableStringHelper;
protected User $user;
public function __construct(
TokenStorageInterface $tokenStorage,
AuthorizationHelper $authorizationHelper,
ObjectManager $om,
@ -64,7 +73,7 @@ class ActivityType extends AbstractType
SocialActionRender $socialActionRender
) {
if (!$tokenStorage->getToken()->getUser() instanceof User) {
throw new \RuntimeException("you should have a valid user");
throw new RuntimeException('you should have a valid user');
}
$this->user = $tokenStorage->getToken()->getUser();
@ -100,12 +109,13 @@ class ActivityType extends AbstractType
'center' => $options['center'],
'role' => $options['role'],
// TODO make required again once scope and rights are fixed
'required' => false
'required' => false,
]);
}
/** @var ? \Chill\PersonBundle\Entity\AccompanyingPeriod $accompanyingPeriod */
$accompanyingPeriod = NULL;
$accompanyingPeriod = null;
if ($options['accompanyingPeriod']) {
$accompanyingPeriod = $options['accompanyingPeriod'];
}
@ -113,49 +123,53 @@ class ActivityType extends AbstractType
if ($activityType->isVisible('socialIssues') && $accompanyingPeriod) {
$builder->add('socialIssues', HiddenType::class);
$builder->get('socialIssues')
->addModelTransformer(new CallbackTransformer(
function (iterable $socialIssuesAsIterable): string {
->addModelTransformer(new CallbackTransformer(
function (iterable $socialIssuesAsIterable): string {
$socialIssueIds = [];
foreach ($socialIssuesAsIterable as $value) {
$socialIssueIds[] = $value->getId();
$socialIssueIds[] = $value->getId();
}
return implode(',', $socialIssueIds);
},
function (?string $socialIssuesAsString): array {
function (?string $socialIssuesAsString): array {
if (null === $socialIssuesAsString) {
return [];
return [];
}
return array_map(
fn(string $id): ?SocialIssue => $this->om->getRepository(SocialIssue::class)->findOneBy(['id' => (int) $id]),
explode(',', $socialIssuesAsString)
fn (string $id): ?SocialIssue => $this->om->getRepository(SocialIssue::class)->findOneBy(['id' => (int) $id]),
explode(',', $socialIssuesAsString)
);
}
))
;
));
}
if ($activityType->isVisible('socialActions') && $accompanyingPeriod) {
$builder->add('socialActions', HiddenType::class);
$builder->get('socialActions')
->addModelTransformer(new CallbackTransformer(
function (iterable $socialActionsAsIterable): string {
->addModelTransformer(new CallbackTransformer(
function (iterable $socialActionsAsIterable): string {
$socialActionIds = [];
foreach ($socialActionsAsIterable as $value) {
$socialActionIds[] = $value->getId();
$socialActionIds[] = $value->getId();
}
return implode(',', $socialActionIds);
},
function (?string $socialActionsAsString): array {
function (?string $socialActionsAsString): array {
if (null === $socialActionsAsString) {
return [];
return [];
}
return array_map(
fn(string $id): ?SocialAction => $this->om->getRepository(SocialAction::class)->findOneBy(['id' => (int) $id]),
explode(',', $socialActionsAsString)
fn (string $id): ?SocialAction => $this->om->getRepository(SocialAction::class)->findOneBy(['id' => (int) $id]),
explode(',', $socialActionsAsString)
);
}
))
;
));
}
if ($activityType->isVisible('date')) {
@ -200,7 +214,7 @@ class ActivityType extends AbstractType
'label' => $activityType->getLabel('user'),
'required' => $activityType->isRequired('user'),
'center' => $options['center'],
'role' => $options['role']
'role' => $options['role'],
]);
}
@ -213,7 +227,7 @@ class ActivityType extends AbstractType
'choice_label' => function (ActivityReason $activityReason) {
return $this->translatableStringHelper->localize($activityReason->getName());
},
'attr' => array('class' => 'select2 '),
'attr' => ['class' => 'select2 '],
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('a')
->where('a.active = true');
@ -232,43 +246,45 @@ class ActivityType extends AbstractType
if ($activityType->isVisible('persons')) {
$builder->add('persons', HiddenType::class);
$builder->get('persons')
->addModelTransformer(new CallbackTransformer(
function (iterable $personsAsIterable): string {
->addModelTransformer(new CallbackTransformer(
function (iterable $personsAsIterable): string {
$personIds = [];
foreach ($personsAsIterable as $value) {
$personIds[] = $value->getId();
$personIds[] = $value->getId();
}
return implode(',', $personIds);
},
function (?string $personsAsString): array {
function (?string $personsAsString): array {
return array_map(
fn(string $id): ?Person => $this->om->getRepository(Person::class)->findOneBy(['id' => (int) $id]),
explode(',', $personsAsString)
fn (string $id): ?Person => $this->om->getRepository(Person::class)->findOneBy(['id' => (int) $id]),
explode(',', $personsAsString)
);
}
))
;
));
}
if ($activityType->isVisible('thirdParties')) {
$builder->add('thirdParties', HiddenType::class);
$builder->get('thirdParties')
->addModelTransformer(new CallbackTransformer(
function (iterable $thirdpartyAsIterable): string {
->addModelTransformer(new CallbackTransformer(
function (iterable $thirdpartyAsIterable): string {
$thirdpartyIds = [];
foreach ($thirdpartyAsIterable as $value) {
$thirdpartyIds[] = $value->getId();
$thirdpartyIds[] = $value->getId();
}
return implode(',', $thirdpartyIds);
},
function (?string $thirdpartyAsString): array {
function (?string $thirdpartyAsString): array {
return array_map(
fn(string $id): ?ThirdParty => $this->om->getRepository(ThirdParty::class)->findOneBy(['id' => (int) $id]),
fn (string $id): ?ThirdParty => $this->om->getRepository(ThirdParty::class)->findOneBy(['id' => (int) $id]),
explode(',', $thirdpartyAsString)
);
}
))
;
));
}
if ($activityType->isVisible('documents')) {
@ -278,29 +294,30 @@ class ActivityType extends AbstractType
'required' => $activityType->isRequired('documents'),
'allow_add' => true,
'button_add_label' => 'activity.Insert a document',
'button_remove_label' => 'activity.Remove a document'
'button_remove_label' => 'activity.Remove a document',
]);
}
if ($activityType->isVisible('users')) {
$builder->add('users', HiddenType::class);
$builder->get('users')
->addModelTransformer(new CallbackTransformer(
function (iterable $usersAsIterable): string {
->addModelTransformer(new CallbackTransformer(
function (iterable $usersAsIterable): string {
$userIds = [];
foreach ($usersAsIterable as $value) {
$userIds[] = $value->getId();
}
return implode(',', $userIds);
},
function (?string $usersAsString): array {
function (?string $usersAsString): array {
return array_map(
fn(string $id): ?User => $this->om->getRepository(User::class)->findOneBy(['id' => (int) $id]),
fn (string $id): ?User => $this->om->getRepository(User::class)->findOneBy(['id' => (int) $id]),
explode(',', $usersAsString)
);
}
))
;
));
}
if ($activityType->isVisible('location')) {
@ -311,13 +328,13 @@ class ActivityType extends AbstractType
if (null === $location) {
return '';
}
return $location->getId();
},
function (?string $id): ?Location {
return $this->om->getRepository(Location::class)->findOneBy(['id' => (int) $id]);
}
))
;
));
}
if ($activityType->isVisible('emergency')) {
@ -347,7 +364,7 @@ class ActivityType extends AbstractType
->addModelTransformer($durationTimeTransformer);
$builder->get($fieldName)
->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $formEvent) use (
->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $formEvent) use (
$timeChoices,
$builder,
$durationTimeTransformer,
@ -356,14 +373,14 @@ class ActivityType extends AbstractType
) {
// set the timezone to GMT, and fix the difference between current and GMT
// the datetimetransformer will then handle timezone as GMT
$timezoneUTC = new \DateTimeZone('GMT');
$timezoneUTC = new DateTimeZone('GMT');
/* @var $data \DateTime */
$data = $formEvent->getData() === NULL ?
\DateTime::createFromFormat('U', 300) :
$data = $formEvent->getData() === null ?
DateTime::createFromFormat('U', 300) :
$formEvent->getData();
$seconds = $data->getTimezone()->getOffset($data);
$data->setTimeZone($timezoneUTC);
$data->add(new \DateInterval('PT'.$seconds.'S'));
$data->add(new DateInterval('PT' . $seconds . 'S'));
// test if the timestamp is in the choices.
// If not, recreate the field with the new timestamp
@ -371,9 +388,10 @@ class ActivityType extends AbstractType
// the data are not in the possible values. add them
$timeChoices[$data->format('H:i')] = $data->getTimestamp();
$form = $builder->create($fieldName, ChoiceType::class, array_merge(
$durationTimeOptions, [
$durationTimeOptions,
[
'choices' => $timeChoices,
'auto_initialize' => false
'auto_initialize' => false,
]
));
$form->addModelTransformer($durationTimeTransformer);
@ -383,12 +401,10 @@ class ActivityType extends AbstractType
}
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Activity::class
'data_class' => Activity::class,
]);
$resolver
@ -396,8 +412,7 @@ class ActivityType extends AbstractType
->setAllowedTypes('center', ['null', 'Chill\MainBundle\Entity\Center'])
->setAllowedTypes('role', 'Symfony\Component\Security\Core\Role\Role')
->setAllowedTypes('activityType', \Chill\ActivityBundle\Entity\ActivityType::class)
->setAllowedTypes('accompanyingPeriod', [\Chill\PersonBundle\Entity\AccompanyingPeriod::class, 'null'])
;
->setAllowedTypes('accompanyingPeriod', [\Chill\PersonBundle\Entity\AccompanyingPeriod::class, 'null']);
}
public function getBlockPrefix(): string

View File

@ -1,14 +1,21 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Entity\ActivityTypeCategory;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
class ActivityTypeCategoryType extends AbstractType
{
@ -16,24 +23,23 @@ class ActivityTypeCategoryType extends AbstractType
{
$builder
->add('name', TranslatableStringFormType::class)
->add('active', ChoiceType::class, array(
'choices' => array(
->add('active', ChoiceType::class, [
'choices' => [
'Yes' => true,
'No' => false
),
'expanded' => true
))
'No' => false,
],
'expanded' => true,
])
->add('ordering', NumberType::class, [
'required' => true,
'scale' => 5
])
;
'scale' => 5,
]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults(array(
'data_class' => ActivityTypeCategory::class
));
$resolver->setDefaults([
'data_class' => ActivityTypeCategory::class,
]);
}
}

View File

@ -1,18 +1,25 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Entity\ActivityTypeCategory;
use Chill\ActivityBundle\Form\Type\ActivityFieldPresence;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
class ActivityTypeType extends AbstractType
{
@ -30,9 +37,9 @@ class ActivityTypeType extends AbstractType
->add('active', ChoiceType::class, [
'choices' => [
'Yes' => true,
'No' => false
'No' => false,
],
'expanded' => true
'expanded' => true,
])
->add('category', EntityType::class, [
'class' => ActivityTypeCategory::class,
@ -42,20 +49,20 @@ class ActivityTypeType extends AbstractType
])
->add('ordering', NumberType::class, [
'required' => true,
'scale' => 5
])
;
'scale' => 5,
]);
$fields = [
'persons', 'user', 'date', 'place', 'persons',
'thirdParties', 'durationTime', 'travelTime', 'attendee',
'reasons', 'comment', 'sentReceived', 'documents',
'emergency', 'accompanyingPeriod', 'socialData', 'users'
'emergency', 'accompanyingPeriod', 'socialData', 'users',
];
foreach ($fields as $field) {
$builder
->add($field.'Visible', ActivityFieldPresence::class)
->add($field.'Label', TextType::class, [
->add($field . 'Visible', ActivityFieldPresence::class)
->add($field . 'Label', TextType::class, [
'required' => false,
'empty_data' => '',
]);
@ -64,8 +71,8 @@ class ActivityTypeType extends AbstractType
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => \Chill\ActivityBundle\Entity\ActivityType::class
));
$resolver->setDefaults([
'data_class' => \Chill\ActivityBundle\Entity\ActivityType::class,
]);
}
}

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Form\Type;
use Chill\ActivityBundle\Entity\ActivityType;
@ -9,21 +16,21 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
class ActivityFieldPresence extends AbstractType
{
public function getParent()
{
return ChoiceType::class;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
array(
[
'choices' => [
'Invisible' => ActivityType::FIELD_INVISIBLE,
'Optional' => ActivityType::FIELD_OPTIONAL,
'Required' => ActivityType::FIELD_REQUIRED,
],
)
]
);
}
public function getParent()
{
return ChoiceType::class;
}
}

View File

@ -1,54 +1,37 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2014-2020, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\EntityRepository;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Templating\Entity\ActivityReasonRender;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* FormType to choose amongst activity reasons
*
* FormType to choose amongst activity reasons.
*/
class TranslatableActivityReason extends AbstractType
{
/**
*
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
/**
*
* @var ActivityReasonRender
*/
protected $reasonRender;
/**
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
public function __construct(
TranslatableStringHelper $translatableStringHelper,
ActivityReasonRender $reasonRender
@ -57,6 +40,30 @@ class TranslatableActivityReason extends AbstractType
$this->reasonRender = $reasonRender;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'class' => 'ChillActivityBundle:ActivityReason',
'choice_label' => function (ActivityReason $choice) {
return $this->reasonRender->renderString($choice, []);
},
'group_by' => function (ActivityReason $choice): ?string {
if (null !== $category = $choice->getCategory()) {
return $this->translatableStringHelper->localize($category->getName());
}
return null;
},
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('r')
->where('r.active = true');
},
'attr' => ['class' => ' select2 '],
]
);
}
public function getBlockPrefix()
{
return 'translatable_activity_reason';
@ -66,28 +73,4 @@ class TranslatableActivityReason extends AbstractType
{
return EntityType::class;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
array(
'class' => 'ChillActivityBundle:ActivityReason',
'choice_label' => function(ActivityReason $choice) {
return $this->reasonRender->renderString($choice, []);
},
'group_by' => function(ActivityReason $choice): ?string {
if (null !== $category = $choice->getCategory()) {
return $this->translatableStringHelper->localize($category->getName());
}
return null;
},
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('r')
->where('r.active = true');
},
'attr' => [ 'class' => ' select2 ']
)
);
}
}

View File

@ -1,40 +1,23 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* Description of TranslatableActivityReasonCategory
*
* @author Champs-Libres Coop
* Description of TranslatableActivityReasonCategory.
*/
class TranslatableActivityReasonCategory extends AbstractType
{
/**
@ -47,6 +30,21 @@ class TranslatableActivityReasonCategory extends AbstractType
$this->requestStack = $requestStack;
}
public function configureOptions(OptionsResolver $resolver)
{
$locale = $this->requestStack->getCurrentRequest()->getLocale();
$resolver->setDefaults(
[
'class' => 'ChillActivityBundle:ActivityReasonCategory',
'choice_label' => 'name[' . $locale . ']',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('c')
->where('c.active = true');
},
]
);
}
public function getBlockPrefix()
{
return 'translatable_activity_reason_category';
@ -56,19 +54,4 @@ class TranslatableActivityReasonCategory extends AbstractType
{
return EntityType::class;
}
public function configureOptions(OptionsResolver $resolver)
{
$locale = $this->requestStack->getCurrentRequest()->getLocale();
$resolver->setDefaults(
array(
'class' => 'ChillActivityBundle:ActivityReasonCategory',
'choice_label' => 'name['.$locale.']',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('c')
->where('c.active = true');
}
)
);
}
}

View File

@ -1,25 +1,32 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Form\Type;
use Chill\ActivityBundle\Entity\ActivityType;
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Chill\ActivityBundle\Entity\ActivityType;
class TranslatableActivityType extends AbstractType
{
protected TranslatableStringHelperInterface $translatableStringHelper;
protected ActivityTypeRepository $activityTypeRepository;
protected TranslatableStringHelperInterface $translatableStringHelper;
public function __construct(
TranslatableStringHelperInterface $helper,
ActivityTypeRepository $activityTypeRepository
@ -28,6 +35,32 @@ class TranslatableActivityType extends AbstractType
$this->activityTypeRepository = $activityTypeRepository;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
/* @var QueryBuilder $qb */
$qb = $options['query_builder'];
if (true === $options['active_only']) {
$qb->where($qb->expr()->eq('at.active', ':active'));
$qb->setParameter('active', true, Types::BOOLEAN);
}
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'class' => ActivityType::class,
'active_only' => true,
'query_builder' => $this->activityTypeRepository
->createQueryBuilder('at'),
'choice_label' => function (ActivityType $type) {
return $this->translatableStringHelper->localize($type->getName());
},
]
);
}
public function getBlockPrefix()
{
return 'translatable_activity_type';
@ -37,29 +70,4 @@ class TranslatableActivityType extends AbstractType
{
return EntityType::class;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
/* @var QueryBuilder $qb */
$qb = $options['query_builder'];
if ($options['active_only'] === true) {
$qb->where($qb->expr()->eq('at.active', ':active'));
$qb->setParameter('active', true, Types::BOOLEAN);
}
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
array(
'class' => ActivityType::class,
'active_only' => true,
'query_builder' => $this->activityTypeRepository
->createQueryBuilder('at'),
'choice_label' => function (ActivityType $type) {
return $this->translatableStringHelper->localize($type->getName());
}
)
);
}
}

View File

@ -1,22 +1,27 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Menu;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
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 TranslatorInterface $translator;
protected Security $security;
protected TranslatorInterface $translator;
public function __construct(
Security $security,
TranslatorInterface $translator
@ -24,10 +29,6 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
$this->security = $security;
$this->translator = $translator;
}
public static function getMenuIds(): array
{
return ['accompanyingCourse'];
}
public function buildMenu($menuId, MenuItem $menu, array $parameters)
{
@ -39,8 +40,13 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
'route' => 'chill_activity_activity_list',
'routeParameters' => [
'accompanying_period_id' => $period->getId(),
]])
], ])
->setExtras(['order' => 40]);
}
}
public static function getMenuIds(): array
{
return ['accompanyingCourse'];
}
}

View File

@ -1,4 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Menu;
@ -16,11 +24,6 @@ final class AdminMenuBuilder implements LocalMenuBuilderInterface
$this->security = $security;
}
public static function getMenuIds(): array
{
return ['admin_index', 'admin_section', 'admin_activity'];
}
public function buildMenu($menuId, MenuItem $menu, array $parameters)
{
if (!$this->security->isGranted('ROLE_ADMIN')) {
@ -29,20 +32,25 @@ final class AdminMenuBuilder implements LocalMenuBuilderInterface
if (in_array($menuId, ['admin_index', 'admin_section'])) {
$menu->addChild('Activities', [
'route' => 'chill_admin_activity_index'
'route' => 'chill_admin_activity_index',
])
->setExtras([
'order' => 2000,
'explain' => "Activity configuration"
'explain' => 'Activity configuration',
]);
} else {
$menu
->addChild('Activities', [
'route' => 'chill_admin_activity_index'
'route' => 'chill_admin_activity_index',
])
->setExtras([
'order' => '60'
'order' => '60',
]);
}
}
}
public static function getMenuIds(): array
{
return ['admin_index', 'admin_section', 'admin_activity'];
}
}

View File

@ -1,68 +1,55 @@
<?php
/*
* Copyright (C) 2018 Julien Fastré <julien.fastre@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Menu;
namespace Chill\ActivityBundle\Menu;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Symfony\Component\Translation\TranslatorInterface;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class PersonMenuBuilder implements LocalMenuBuilderInterface
{
/**
*
* @var TranslatorInterface
*/
protected $translator;
/**
*
* @var AuthorizationCheckerInterface
*/
protected $authorizationChecker;
/**
* @var TranslatorInterface
*/
protected $translator;
public function __construct(
AuthorizationCheckerInterface $authorizationChecker,
TranslatorInterface $translator)
TranslatorInterface $translator
)
{
$this->translator = $translator;
$this->authorizationChecker = $authorizationChecker;
}
public function buildMenu($menuId, MenuItem $menu, array $parameters)
{
/* @var $person \Chill\PersonBundle\Entity\Person */
$person = $parameters['person'];
if ($this->authorizationChecker->isGranted(ActivityVoter::SEE, $person)) {
$menu->addChild(
$this->translator->trans('Activity list'), [
$this->translator->trans('Activity list'),
[
'route' => 'chill_activity_activity_list',
'routeParameters' => [ 'person_id' => $person->getId() ],
])
->setExtra('order', 201)
;
'routeParameters' => ['person_id' => $person->getId()],
]
)
->setExtra('order', 201);
}
}

View File

@ -1,17 +1,19 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Notification;
use Chill\MainBundle\Entity\Notification;
use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\Entity\Notification;
final class ActivityNotificationRenderer
{
public function supports(Notification $notification, array $options = []): bool
{
return $notification->getRelatedEntityClass() == Activity::class;
}
public function getTemplate()
{
return '@ChillActivity/Activity/showInNotification.html.twig';
@ -21,4 +23,9 @@ final class ActivityNotificationRenderer
{
return ['notification' => $notification];
}
public function supports(Notification $notification, array $options = []): bool
{
return $notification->getRelatedEntityClass() == Activity::class;
}
}

View File

@ -1,35 +1,42 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Repository;
use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Role\Role;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Security;
use function in_array;
final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInterface
{
private AuthorizationHelper $authorizationHelper;
private TokenStorageInterface $tokenStorage;
private ActivityRepository $repository;
private CenterResolverDispatcherInterface $centerResolverDispatcher;
private EntityManagerInterface $em;
private ActivityRepository $repository;
private Security $security;
private CenterResolverDispatcherInterface $centerResolverDispatcher;
private TokenStorageInterface $tokenStorage;
public function __construct(
AuthorizationHelper $authorizationHelper,
@ -47,34 +54,11 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
$this->security = $security;
}
/**
* @param Person $person
* @param string $role
* @param int|null $start
* @param int|null $limit
* @param array $orderBy
* @return array|Activity[]
*/
public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array
{
$user = $this->security->getUser();
$center = $this->centerResolverDispatcher->resolveCenter($person);
if (0 === count($orderBy)) {
$orderBy = ['date' => 'DESC'];
}
$reachableScopes = $this->authorizationHelper
->getReachableCircles($user, $role, $center);
return $this->em->getRepository(Activity::class)
->findByPersonImplied($person, $reachableScopes, $orderBy, $limit, $start);
;
}
public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array
{
$user = $this->security->getUser();
$center = $this->centerResolverDispatcher->resolveCenter($period);
if (0 === count($orderBy)) {
$orderBy = ['date' => 'DESC'];
}
@ -86,6 +70,27 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
->findByAccompanyingPeriod($period, $scopes, true, $limit, $start, $orderBy);
}
/**
* @param array $orderBy
*
* @return Activity[]|array
*/
public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array
{
$user = $this->security->getUser();
$center = $this->centerResolverDispatcher->resolveCenter($person);
if (0 === count($orderBy)) {
$orderBy = ['date' => 'DESC'];
}
$reachableScopes = $this->authorizationHelper
->getReachableCircles($user, $role, $center);
return $this->em->getRepository(Activity::class)
->findByPersonImplied($person, $reachableScopes, $orderBy, $limit, $start);
}
public function queryTimelineIndexer(string $context, array $args = []): array
{
$metadataActivity = $this->em->getClassMetadata(Activity::class);
@ -94,15 +99,15 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
[$where, $parameters] = $this->getWhereClause($context, $args);
return [
'id' => $metadataActivity->getTableName()
.'.'.$metadataActivity->getColumnName('id'),
'type' => 'activity',
'date' => $metadataActivity->getTableName()
.'.'.$metadataActivity->getColumnName('date'),
'FROM' => $from,
'WHERE' => $where,
'parameters' => $parameters
];
'id' => $metadataActivity->getTableName()
. '.' . $metadataActivity->getColumnName('id'),
'type' => 'activity',
'date' => $metadataActivity->getTableName()
. '.' . $metadataActivity->getColumnName('date'),
'FROM' => $from,
'WHERE' => $where,
'parameters' => $parameters,
];
}
private function getFromClauseCenter(array $args): string
@ -111,13 +116,12 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
$metadataPerson = $this->em->getClassMetadata(Person::class);
$associationMapping = $metadataActivity->getAssociationMapping('person');
return $metadataActivity->getTableName().' JOIN '
.$metadataPerson->getTableName().' ON '
.$metadataPerson->getTableName().'.'.
return $metadataActivity->getTableName() . ' JOIN '
. $metadataPerson->getTableName() . ' ON '
. $metadataPerson->getTableName() . '.' .
$associationMapping['joinColumns'][0]['referencedColumnName']
.' = '
.$associationMapping['joinColumns'][0]['name']
;
. ' = '
. $associationMapping['joinColumns'][0]['name'];
}
private function getWhereClause(string $context, array $args): array
@ -128,21 +132,22 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
$metadataActivity = $this->em->getClassMetadata(Activity::class);
$metadataPerson = $this->em->getClassMetadata(Person::class);
$activityToPerson = $metadataActivity->getAssociationMapping('person')['joinColumns'][0]['name'];
$activityToScope = $metadataActivity->getAssociationMapping('scope')['joinColumns'][0]['name'];
$activityToScope = $metadataActivity->getAssociationMapping('scope')['joinColumns'][0]['name'];
$personToCenter = $metadataPerson->getAssociationMapping('center')['joinColumns'][0]['name'];
// acls:
$role = new Role(ActivityVoter::SEE);
$reachableCenters = $this->authorizationHelper->getReachableCenters($this->tokenStorage->getToken()->getUser(),
$role);
$reachableCenters = $this->authorizationHelper->getReachableCenters(
$this->tokenStorage->getToken()->getUser(),
$role
);
if (count($reachableCenters) === 0) {
// insert a dummy condition
return 'FALSE = TRUE';
}
if ($context === 'person') {
if ('person' === $context) {
// we start with activities having the person_id linked to person
$where .= sprintf('%s = ? AND ', $activityToPerson);
$parameters[] = $person->getId();
@ -151,21 +156,22 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
// we add acl (reachable center and scopes)
$where .= '('; // first loop for the for centers
$centersI = 0; // like centers#i
foreach ($reachableCenters as $center) {
// we pass if not in centers
if (!\in_array($center, $args['centers'])) {
if (!in_array($center, $args['centers'])) {
continue;
}
// we get all the reachable scopes for this center
$reachableScopes = $this->authorizationHelper->getReachableScopes($this->tokenStorage->getToken()->getUser(), $role, $center);
// we get the ids for those scopes
$reachablesScopesId = array_map(
function(Scope $scope) { return $scope->getId(); },
function (Scope $scope) { return $scope->getId(); },
$reachableScopes
);
// if not the first center
if ($centersI > 0) {
if (0 < $centersI) {
$where .= ') OR (';
}
@ -178,21 +184,20 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
$scopesI = 0; //like scope#i
foreach ($reachablesScopesId as $scopeId) {
if ($scopesI > 0) {
if (0 < $scopesI) {
$where .= ' OR ';
}
$where .= sprintf(' %s.%s = ? ', $metadataActivity->getTableName(), $activityToScope);
$parameters[] = $scopeId;
$scopesI ++;
++$scopesI;
}
// close loop for scopes
$where .= ') ';
$centersI++;
++$centersI;
}
// close loop for centers
$where .= ')';
return [$where, $parameters];
}
}

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Repository;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
@ -8,12 +15,12 @@ use Chill\PersonBundle\Entity\Person;
interface ActivityACLAwareRepositoryInterface
{
/**
* @return array|Activity[]
*/
public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array;
/**
* @return array|Activity[]
* @return Activity[]|array
*/
public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array;
/**
* @return Activity[]|array
*/
public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array;
}

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Repository;

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Repository;

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Repository;
@ -23,34 +30,6 @@ class ActivityRepository extends ServiceEntityRepository
parent::__construct($registry, Activity::class);
}
/**
* @return Activity[]
*/
public function findByPersonImplied(Person $person, array $scopes, ?array $orderBy = [ 'date' => 'DESC'], ?int $limit = 100, ?int $offset = 0): array
{
$qb = $this->createQueryBuilder('a');
$qb->select('a');
$qb
->where($qb->expr()->in('a.scope', ':scopes'))
->setParameter('scopes', $scopes)
->andWhere(
$qb->expr()->orX(
$qb->expr()->eq('a.person', ':person'),
':person MEMBER OF a.persons'
)
)
->setParameter('person', $person);
foreach ($orderBy as $k => $dir) {
$qb->addOrderBy('a.'.$k, $dir);
}
$qb->setMaxResults($limit)->setFirstResult($offset);
return $qb->getQuery()->getResult();
}
/**
* @return Activity[]
*/
@ -81,7 +60,35 @@ class ActivityRepository extends ServiceEntityRepository
->setParameter('period', $period);
foreach ($orderBy as $k => $dir) {
$qb->addOrderBy('a.'.$k, $dir);
$qb->addOrderBy('a.' . $k, $dir);
}
$qb->setMaxResults($limit)->setFirstResult($offset);
return $qb->getQuery()->getResult();
}
/**
* @return Activity[]
*/
public function findByPersonImplied(Person $person, array $scopes, ?array $orderBy = ['date' => 'DESC'], ?int $limit = 100, ?int $offset = 0): array
{
$qb = $this->createQueryBuilder('a');
$qb->select('a');
$qb
->where($qb->expr()->in('a.scope', ':scopes'))
->setParameter('scopes', $scopes)
->andWhere(
$qb->expr()->orX(
$qb->expr()->eq('a.person', ':person'),
':person MEMBER OF a.persons'
)
)
->setParameter('person', $person);
foreach ($orderBy as $k => $dir) {
$qb->addOrderBy('a.' . $k, $dir);
}
$qb->setMaxResults($limit)->setFirstResult($offset);

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Repository;

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Repository;

View File

@ -1,13 +1,36 @@
<?php
use Symfony\Component\HttpKernel\Kernel;
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\HttpKernel\Kernel;
class AppKernel extends Kernel
{
/**
* @return string
*/
public function getCacheDir()
{
return sys_get_temp_dir() . '/ActivityBundle/cache';
}
/**
* @return string
*/
public function getLogDir()
{
return sys_get_temp_dir() . '/ActivityBundle/logs';
}
public function registerBundles()
{
return array(
return [
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Chill\CustomFieldsBundle\ChillCustomFieldsBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
@ -20,28 +43,12 @@ class AppKernel extends Kernel
new \Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle(),
new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(),
#add here all the required bundle (some bundle are not required)
);
//add here all the required bundle (some bundle are not required)
];
}
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load($this->getRootDir().'/config/config_'.$this->getEnvironment().'.yml');
}
/**
* @return string
*/
public function getCacheDir()
{
return sys_get_temp_dir().'/ActivityBundle/cache';
}
/**
* @return string
*/
public function getLogDir()
{
return sys_get_temp_dir().'/ActivityBundle/logs';
$loader->load($this->getRootDir() . '/config/config_' . $this->getEnvironment() . '.yml');
}
}

View File

@ -1,11 +1,18 @@
<?php
use Doctrine\Common\Annotations\AnnotationRegistry;
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
use Composer\Autoload\ClassLoader;
use Doctrine\Common\Annotations\AnnotationRegistry;
/** @var ClassLoader $loader */
$loader = require __DIR__.'/../../../../../vendor/autoload.php';
$loader = require __DIR__ . '/../../../../../vendor/autoload.php';
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
AnnotationRegistry::registerLoader([$loader, 'loadClass']);
return $loader;

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,14 @@
<?php
use Symfony\Component\HttpFoundation\Request;
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
use Symfony\Component\Debug\Debug;
use Symfony\Component\HttpFoundation\Request;
// If you don't want to setup permissions the proper way, just uncomment the following PHP line
// read http://symfony.com/doc/current/book/installation.html#configuration-and-setup for more information
@ -11,16 +18,17 @@ use Symfony\Component\Debug\Debug;
// Feel free to remove this, extend it, or make something more sophisticated.
if (isset($_SERVER['HTTP_CLIENT_IP'])
|| isset($_SERVER['HTTP_X_FORWARDED_FOR'])
|| !(in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', 'fe80::1', '::1')) || php_sapi_name() === 'cli-server')
|| !(in_array(@$_SERVER['REMOTE_ADDR'], ['127.0.0.1', 'fe80::1', '::1']) || php_sapi_name() === 'cli-server')
) {
header('HTTP/1.0 403 Forbidden');
exit('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.');
exit('You are not allowed to access this file. Check ' . basename(__FILE__) . ' for more information.');
}
$loader = require_once __DIR__.'/../app/bootstrap.php.cache';
$loader = require_once __DIR__ . '/../app/bootstrap.php.cache';
Debug::enable();
require_once __DIR__.'/../app/AppKernel.php';
require_once __DIR__ . '/../app/AppKernel.php';
$kernel = new AppKernel('dev', true);
$kernel->loadClassCache();

View File

@ -1,41 +1,27 @@
<?php
/*
* Copyright (C) 2016 Champs-Libres <info@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Security\Authorization;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
use Chill\MainBundle\Entity\Center;
use function in_array;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class ActivityStatsVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
{
const STATS = 'CHILL_ACTIVITY_STATS';
const LISTS = 'CHILL_ACTIVITY_LIST';
public const LISTS = 'CHILL_ACTIVITY_LIST';
public const STATS = 'CHILL_ACTIVITY_STATS';
/**
*
* @var AuthorizationHelper
*/
protected $helper;
@ -45,25 +31,24 @@ class ActivityStatsVoter extends AbstractChillVoter implements ProvideRoleHierar
$this->helper = $helper;
}
private function getAttributes()
public function getRoles(): array
{
return array(self::STATS, self::LISTS);
return $this->getAttributes();
}
public function getRolesWithHierarchy(): array
{
return ['Activity' => $this->getRoles()];
}
public function getRolesWithoutScope(): array
{
return $this->getAttributes();
}
protected function getSupportedClasses()
{
return array(Center::class);
}
protected function supports($attribute, $subject)
{
if ($subject instanceof Center
&& \in_array($attribute, $this->getAttributes())) {
return true;
}
return false;
return [Center::class];
}
protected function isGranted($attribute, $object, $user = null)
@ -75,18 +60,18 @@ class ActivityStatsVoter extends AbstractChillVoter implements ProvideRoleHierar
return $this->helper->userHasAccess($user, $object, $attribute);
}
public function getRoles(): array
protected function supports($attribute, $subject)
{
return $this->getAttributes();
if ($subject instanceof Center
&& in_array($attribute, $this->getAttributes())) {
return true;
}
return false;
}
public function getRolesWithoutScope(): array
private function getAttributes()
{
return $this->getAttributes();
}
public function getRolesWithHierarchy(): array
{
return ['Activity' => $this->getRoles()];
return [self::STATS, self::LISTS];
}
}

View File

@ -1,21 +1,30 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Security\Authorization;
use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
use Chill\MainBundle\Security\Authorization\VoterHelperFactoryInterface;
use Chill\MainBundle\Security\Authorization\VoterHelperInterface;
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use RuntimeException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
use Chill\MainBundle\Entity\User;
use Chill\ActivityBundle\Entity\Activity;
use Chill\PersonBundle\Entity\Person;
use Symfony\Component\Security\Core\Security;
use function in_array;
class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
{
@ -30,40 +39,44 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
/**
* role to allow to create an activity associated win an accompanying course.
*
* Before using this, check if @link{self::CREATE} is not sufficiant
* Before using this, check if @see{self::CREATE} is not sufficiant
*
* @internal
*/
public const CREATE_ACCOMPANYING_COURSE = 'CHILL_ACTIVITY_CREATE_ACCOMPANYING_COURSE';
/**
* role to allow to create an activity associated with a person
* role to allow to create an activity associated with a person.
*
* Before using this, check if @link{self::CREATE} is not sufficiant
* Before using this, check if @see{self::CREATE} is not sufficiant
*
* @internal
*/
public const CREATE_PERSON = 'CHILL_ACTIVITY_CREATE_PERSON';
public const SEE = 'CHILL_ACTIVITY_SEE';
public const SEE_DETAILS = 'CHILL_ACTIVITY_SEE_DETAILS';
public const UPDATE = 'CHILL_ACTIVITY_UPDATE';
public const DELETE = 'CHILL_ACTIVITY_DELETE';
public const FULL = 'CHILL_ACTIVITY_FULL';
public const SEE = 'CHILL_ACTIVITY_SEE';
public const SEE_DETAILS = 'CHILL_ACTIVITY_SEE_DETAILS';
public const UPDATE = 'CHILL_ACTIVITY_UPDATE';
private const ALL = [
self::CREATE,
self::SEE,
self::UPDATE,
self::DELETE,
self::SEE_DETAILS,
self::FULL
self::FULL,
];
protected VoterHelperInterface $voterHelper;
protected Security $security;
protected VoterHelperInterface $voterHelper;
public function __construct(
Security $security,
VoterHelperFactoryInterface $voterHelperFactory
@ -76,6 +89,27 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
->build();
}
public function getRoles(): array
{
return [
self::CREATE_PERSON,
self::CREATE_ACCOMPANYING_COURSE,
self::UPDATE,
self::DELETE,
self::FULL,
];
}
public function getRolesWithHierarchy(): array
{
return ['Activity' => $this->getRoles()];
}
public function getRolesWithoutScope(): array
{
return [];
}
protected function supports($attribute, $subject): bool
{
return $this->voterHelper->supports($attribute, $subject);
@ -110,11 +144,11 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
$attribute = self::CREATE_ACCOMPANYING_COURSE;
}
} else {
throw new \RuntimeException('Could not determine context of activity.');
throw new RuntimeException('Could not determine context of activity.');
}
} elseif ($subject instanceof AccompanyingPeriod) {
if (AccompanyingPeriod::STEP_CLOSED === $subject->getStep()) {
if (\in_array($attribute, [self::UPDATE, self::CREATE, self::DELETE], true)) {
if (in_array($attribute, [self::UPDATE, self::CREATE, self::DELETE], true)) {
return false;
}
}
@ -132,26 +166,4 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
return $this->voterHelper->voteOnAttribute($attribute, $subject, $token);
}
public function getRoles(): array
{
return [
self::CREATE_PERSON,
self::CREATE_ACCOMPANYING_COURSE,
self::UPDATE,
self::DELETE,
self::FULL
];
}
public function getRolesWithoutScope(): array
{
return [];
}
public function getRolesWithHierarchy(): array
{
return ['Activity' => $this->getRoles()];
}
}

View File

@ -1,37 +1,24 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2014-2020, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Templating\Entity;
use Chill\MainBundle\Templating\Entity\AbstractChillEntityRender;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\MainBundle\Templating\Entity\AbstractChillEntityRender;
use Chill\MainBundle\Templating\TranslatableStringHelper;
/**
* Render activity reason
*
* Render activity reason.
*/
class ActivityReasonRender extends AbstractChillEntityRender
{
/**
*
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
@ -41,34 +28,29 @@ class ActivityReasonRender extends AbstractChillEntityRender
$this->translatableStringHelper = $translatableStringHelper;
}
public function renderBox($entity, array $options): string
{
return
$this->getDefaultOpeningBox('activity-reason').
'<span class="badge bg-chill-pink">'.
'<i class="fa fa-question-circle"></i>&nbsp;'.
'<span class="category">'.
$this->getDefaultOpeningBox('activity-reason') .
'<span class="badge bg-chill-pink">' .
'<i class="fa fa-question-circle"></i>&nbsp;' .
'<span class="category">' .
$this->translatableStringHelper->localize(
$entity->getCategory()->getName()
).
'</span>'.
'<span class="separator">&nbsp;>&nbsp;</span>'.
'<span class="reason">'.
) .
'</span>' .
'<span class="separator">&nbsp;>&nbsp;</span>' .
'<span class="reason">' .
$this->translatableStringHelper->localize(
$entity->getName()
).
'</span>'.
'</span>'.
$this->getDefaultClosingBox()
;
) .
'</span>' .
'</span>' .
$this->getDefaultClosingBox();
}
/**
*
* @param ActivityReason $entity
* @param array $options
* @return string
*/
public function renderString($entity, array $options): string
{
@ -76,7 +58,8 @@ class ActivityReasonRender extends AbstractChillEntityRender
if (null !== $entity->getCategory()) {
$category = $this->translatableStringHelper->localize(
$entity->getCategory()->getName()). ' > ';
$entity->getCategory()->getName()
) . ' > ';
}
return $category .

View File

@ -1,20 +1,10 @@
<?php
/*
* Copyright (C) 2015 Julien Fastré <julien.fastre@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Test;
@ -24,26 +14,19 @@ use Chill\MainBundle\Entity\Scope;
use Chill\PersonBundle\Entity\Person;
/**
* Prepare entities useful in tests
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* Prepare entities useful in tests.
*/
trait PrepareActivityTrait
{
/**
* Return an activity with a scope and a person inside
*
* @param Scope $scope
* @param Person $person
* Return an activity with a scope and a person inside.
*
* @return Activity
*/
public function prepareActivity(Scope $scope, Person $person)
{
return (new Activity())
->setScope($scope)
->setPerson($person)
;
->setPerson($person);
}
}

View File

@ -1,16 +1,78 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Tests\Controller;
use RuntimeException;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\HttpFoundation\Response;
/**
* @internal
* @coversNothing
*/
class ActivityControllerTest extends WebTestCase
{
public function getSecuredPagesAuthenticated()
{
static::bootKernel();
$person = $this->getPersonFromFixtures();
$activities = $this->getActivitiesForPerson($person);
$user = $this->createFakeUser();
return [
[
$this->getAuthenticatedClient('center b_social'),
sprintf('fr/person/%d/activity/', $person->getId()),
],
[
$this->getAuthenticatedClient('center b_social'),
sprintf('fr/person/%d/activity/new', $person->getId()),
],
[
$this->getAuthenticatedClient('center b_social'),
sprintf('fr/person/%d/activity/%d/show', $person->getId(), $activities[0]->getId()),
],
[
$this->getAuthenticatedClient('center b_social'),
sprintf('fr/person/%d/activity/%d/edit', $person->getId(), $activities[0]->getId()),
],
[
$this->getAuthenticatedClient($user->getUsername()),
sprintf('fr/person/%d/activity/new', $person->getId()),
],
];
}
/**
* Provide a client unauthenticated and.
*/
public function getSecuredPagesUnauthenticated()
{
static::bootKernel();
$person = $this->getPersonFromFixtures();
$activities = $this->getActivitiesForPerson($person);
return [
[sprintf('fr/person/%d/activity/', $person->getId())],
[sprintf('fr/person/%d/activity/new', $person->getId())],
[sprintf('fr/person/%d/activity/%d/show', $person->getId(), $activities[0]->getId())],
[sprintf('fr/person/%d/activity/%d/edit', $person->getId(), $activities[0]->getId())],
];
}
/**
* @dataProvider getSecuredPagesUnauthenticated
*
* @param mixed $url
*/
public function testAccessIsDeniedForUnauthenticated($url)
{
@ -19,13 +81,15 @@ class ActivityControllerTest extends WebTestCase
$client->request('GET', $url);
$this->assertEquals(302, $client->getResponse()->getStatusCode());
$this->assertTrue($client->getResponse()->isRedirect('http://localhost/login'),
sprintf('the page "%s" does not redirect to http://localhost/login', $url));
$this->assertTrue(
$client->getResponse()->isRedirect('http://localhost/login'),
sprintf('the page "%s" does not redirect to http://localhost/login', $url)
);
}
/**
*
* @dataProvider getSecuredPagesAuthenticated
*
* @param type $client
* @param type $url
*/
@ -36,63 +100,6 @@ class ActivityControllerTest extends WebTestCase
$this->assertEquals(403, $client->getResponse()->getStatusCode());
}
public function getSecuredPagesAuthenticated()
{
static::bootKernel();
$person = $this->getPersonFromFixtures();
$activities = $this->getActivitiesForPerson($person);
$user = $this->createFakeUser();
return array(
array(
$this->getAuthenticatedClient('center b_social'),
sprintf('fr/person/%d/activity/', $person->getId())
),
array(
$this->getAuthenticatedClient('center b_social'),
sprintf('fr/person/%d/activity/new', $person->getId())
),
array(
$this->getAuthenticatedClient('center b_social'),
sprintf('fr/person/%d/activity/%d/show', $person->getId(), $activities[0]->getId())
),
array(
$this->getAuthenticatedClient('center b_social'),
sprintf('fr/person/%d/activity/%d/edit', $person->getId(), $activities[0]->getId())
),
array(
$this->getAuthenticatedClient($user->getUsername()),
sprintf('fr/person/%d/activity/new', $person->getId())
)
);
}
/**
* Provide a client unauthenticated and
*
*/
public function getSecuredPagesUnauthenticated()
{
static::bootKernel();
$person = $this->getPersonFromFixtures();
$activities = $this->getActivitiesForPerson($person);
return array(
[ sprintf('fr/person/%d/activity/', $person->getId()) ],
[ sprintf('fr/person/%d/activity/new', $person->getId()) ],
[ sprintf('fr/person/%d/activity/%d/show', $person->getId(), $activities[0]->getId()) ],
[ sprintf('fr/person/%d/activity/%d/edit', $person->getId(), $activities[0]->getId()) ],
);
}
public function testCompleteScenario()
{
// Create a new client to browse the application
@ -100,27 +107,32 @@ class ActivityControllerTest extends WebTestCase
$person = $this->getPersonFromFixtures();
// Create a new entry in the database
$crawler = $client->request('GET', sprintf('en/person/%d/activity/',
$person->getId()));
$this->assertEquals(200, $client->getResponse()->getStatusCode(),
"Unexpected HTTP status code for GET /activity/");
$crawler = $client->request('GET', sprintf(
'en/person/%d/activity/',
$person->getId()
));
$this->assertEquals(
200,
$client->getResponse()->getStatusCode(),
'Unexpected HTTP status code for GET /activity/'
);
$crawler = $client->click($crawler->selectLink('Ajouter une nouvelle activité')
->link());
->link());
$reason1 = $this->getRandomActivityReason();
$reason2 = $this->getRandomActivityReason(array($reason1->getId()));
$reason2 = $this->getRandomActivityReason([$reason1->getId()]);
// Fill in the form and submit it
$form = $crawler->selectButton('Ajouter une nouvelle activité')->form(array(
'chill_activitybundle_activity'=> array(
'date' => '15-01-2015',
'durationTime' => 600,
// 'remark' => 'blabla',
'scope' => $this->getRandomScope('center a_social', 'Center A')->getId(),
'type' => $this->getRandomActivityType()->getId()
)
));
$form['chill_activitybundle_activity[reasons]']->select(array ($reason1->getId(), $reason2->getId()));
$form = $crawler->selectButton('Ajouter une nouvelle activité')->form([
'chill_activitybundle_activity' => [
'date' => '15-01-2015',
'durationTime' => 600,
// 'remark' => 'blabla',
'scope' => $this->getRandomScope('center a_social', 'Center A')->getId(),
'type' => $this->getRandomActivityType()->getId(),
],
]);
$form['chill_activitybundle_activity[reasons]']->select([$reason1->getId(), $reason2->getId()]);
$client->submit($form);
@ -128,18 +140,21 @@ class ActivityControllerTest extends WebTestCase
$crawler = $client->followRedirect();
// Check data in the show view
$this->assertGreaterThan(0, $crawler->filter('dd:contains("January 15, 2015")')->count(),
'Missing element dd:contains("January 15, 2015")');
$this->assertGreaterThan(
0,
$crawler->filter('dd:contains("January 15, 2015")')->count(),
'Missing element dd:contains("January 15, 2015")'
);
// Edit the entity
$crawler = $client->click($crawler->selectLink("Modifier l'activité")->link());
$form = $crawler->selectButton("Sauver l'activité")->form(array(
'chill_activitybundle_activity' => array(
'date' => '25-01-2015',
// 'remark' => 'Foo'
)
));
$form = $crawler->selectButton("Sauver l'activité")->form([
'chill_activitybundle_activity' => [
'date' => '25-01-2015',
// 'remark' => 'Foo'
],
]);
$client->submit($form);
@ -148,164 +163,33 @@ class ActivityControllerTest extends WebTestCase
$crawler = $client->followRedirect();
// check that new data are present
$this->assertGreaterThan(0,
$crawler->filter('dd:contains("January 25, 2015")')->count(),
'Missing element dd:contains("January 25, 2015")');
$this->assertGreaterThan(0,
$crawler->filter('dd:contains("Foo")')->count(),
'Missing element dd:contains("Foo")');
$this->assertGreaterThan(
0,
$crawler->filter('dd:contains("January 25, 2015")')->count(),
'Missing element dd:contains("January 25, 2015")'
);
$this->assertGreaterThan(
0,
$crawler->filter('dd:contains("Foo")')->count(),
'Missing element dd:contains("Foo")'
);
// delete the actvity
$crawler = $client->click($crawler->selectLink("Supprimer")->link());
$crawler = $client->click($crawler->selectLink('Supprimer')->link());
$button = $crawler->selectButton('Supprimer');
$button = $crawler->selectButton('Supprimer');
$form = $button->form();
$form = $button->form();
$client->submit($form);
$this->assertTrue($client->getResponse()->isRedirect(sprintf('/en/person/%d/activity/',
$person->getId())));
$client->submit($form);
$this->assertTrue($client->getResponse()->isRedirect(sprintf(
'/en/person/%d/activity/',
$person->getId()
)));
$crawler = $client->followRedirect();
$crawler = $client->followRedirect();
$this->assertNotContains('January 25, 2015', $crawler->text());
}
/**
*
* @return \Symfony\Component\BrowserKit\Client
*/
private function getAuthenticatedClient($username = 'center a_social')
{
return static::createClient(array(), array(
'PHP_AUTH_USER' => $username,
'PHP_AUTH_PW' => 'password',
));
}
/**
*
* @return \Chill\PersonBundle\Entity\Person
*/
private function getPersonFromFixtures()
{
$em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager');
$person = $em->getRepository('ChillPersonBundle:Person')
->findOneBy(array(
'firstName' => 'Depardieu',
'lastName' => 'Gérard'
));
if ($person === NULL) {
throw new \RuntimeException("We need a person with firstname Gérard and"
. " lastname Depardieu. Did you add fixtures ?");
}
return $person;
}
private function getActivitiesForPerson(\Chill\PersonBundle\Entity\Person $person)
{
$em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager');
$activities = $em->getRepository('ChillActivityBundle:Activity')
->findBy(array('person' => $person));
if (count($activities) === 0) {
throw new \RuntimeException("We need activities associated with this "
. "person. Did you forget to add fixtures ?");
}
return $activities;
}
/**
*
* @param string $username
* @param string $centerName
* @return \Chill\MainBundle\Entity\Scope
*/
private function getRandomScope($username, $centerName)
{
$user = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('ChillMainBundle:User')
->findOneByUsername($username);
if ($user === NULL) {
throw new \RuntimeException("The user with username $username "
. "does not exists in database. Did you add fixtures ?");
}
$center = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('ChillMainBundle:Center')
->findOneByName($centerName);
// get scope reachable by both role UPDATE and DELETE
$reachableScopesUpdate = static::$kernel->getContainer()
->get('chill.main.security.authorization.helper')
->getReachableScopes($user, new Role('CHILL_ACTIVITY_UPDATE'),
$center);
$reachableScopesDelete = static::$kernel->getContainer()
->get('chill.main.security.authorization.helper')
->getReachableScopes($user, new Role('CHILL_ACTIVITY_DELETE'),
$center);
$reachableScopesId = array_intersect(
array_map(function ($s) { return $s->getId(); }, $reachableScopesDelete),
array_map(function ($s) { return $s->getId(); }, $reachableScopesUpdate)
);
if (count($reachableScopesId) === 0) {
throw new \RuntimeException("there are not scope reachable for "
. "both CHILL_ACTIVITY_UPDATE and CHILL_ACTIVITY_DELETE");
}
foreach($reachableScopesUpdate as $scope) {
if (in_array($scope->getId(), $reachableScopesId)) {
$reachableScopes[] = $scope;
}
}
return $reachableScopes[array_rand($reachableScopes)];
}
/**
*
* @param int[] $excludeIds An array of id to exclude
* @return \Chill\ActivityBundle\Entity\ActivityReason
*/
private function getRandomActivityReason(array $excludeIds = array())
{
$reasons = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('ChillActivityBundle:ActivityReason')
->findAll();
$reason = $reasons[array_rand($reasons)];
if (in_array($reason->getId(), $excludeIds)) {
return $this->getRandomActivityReason($excludeIds);
}
return $reason;
}
/**
*
* @return \Chill\ActivityBundle\Entity\ActivityType
*/
private function getRandomActivityType()
{
$types = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('ChillActivityBundle:ActivityType')
->findAll();
return $types[array_rand($types)];
$this->assertNotContains('January 25, 2015', $crawler->text());
}
/**
@ -321,10 +205,10 @@ class ActivityControllerTest extends WebTestCase
//get the social PermissionGroup, and remove CHILL_ACTIVITY_*
$socialPermissionGroup = $em
->getRepository('ChillMainBundle:PermissionsGroup')
->findOneByName('social');
->getRepository('ChillMainBundle:PermissionsGroup')
->findOneByName('social');
$withoutActivityPermissionGroup = (new \Chill\MainBundle\Entity\PermissionsGroup())
->setName('social without activity');
->setName('social without activity');
//copy role scopes where ACTIVITY is not present
foreach ($socialPermissionGroup->getRoleScopes() as $roleScope) {
if (!strpos($roleScope->getRole(), 'ACTIVITY')) {
@ -334,8 +218,8 @@ class ActivityControllerTest extends WebTestCase
//create groupCenter
$groupCenter = new \Chill\MainBundle\Entity\GroupCenter();
$groupCenter->setCenter($em->getRepository('ChillMainBundle:Center')
->findOneBy(array('name' => 'Center A')))
->setPermissionsGroup($withoutActivityPermissionGroup);
->findOneBy(['name' => 'Center A']))
->setPermissionsGroup($withoutActivityPermissionGroup);
$em->persist($withoutActivityPermissionGroup);
$em->persist($groupCenter);
@ -344,10 +228,10 @@ class ActivityControllerTest extends WebTestCase
$username = $faker->name;
$user = new \Chill\MainBundle\Entity\User();
$user
->setPassword($container->get('security.password_encoder')
->encodePassword($user, 'password'))
->setUsername($username)
->addGroupCenter($groupCenter);
->setPassword($container->get('security.password_encoder')
->encodePassword($user, 'password'))
->setUsername($username)
->addGroupCenter($groupCenter);
$em->persist($user);
@ -355,4 +239,146 @@ class ActivityControllerTest extends WebTestCase
return $user;
}
private function getActivitiesForPerson(\Chill\PersonBundle\Entity\Person $person)
{
$em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager');
$activities = $em->getRepository('ChillActivityBundle:Activity')
->findBy(['person' => $person]);
if (count($activities) === 0) {
throw new RuntimeException('We need activities associated with this '
. 'person. Did you forget to add fixtures ?');
}
return $activities;
}
/**
* @param mixed $username
*
* @return \Symfony\Component\BrowserKit\Client
*/
private function getAuthenticatedClient($username = 'center a_social')
{
return static::createClient([], [
'PHP_AUTH_USER' => $username,
'PHP_AUTH_PW' => 'password',
]);
}
/**
* @return \Chill\PersonBundle\Entity\Person
*/
private function getPersonFromFixtures()
{
$em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager');
$person = $em->getRepository('ChillPersonBundle:Person')
->findOneBy([
'firstName' => 'Depardieu',
'lastName' => 'Gérard',
]);
if (null === $person) {
throw new RuntimeException('We need a person with firstname Gérard and'
. ' lastname Depardieu. Did you add fixtures ?');
}
return $person;
}
/**
* @param int[] $excludeIds An array of id to exclude
*
* @return \Chill\ActivityBundle\Entity\ActivityReason
*/
private function getRandomActivityReason(array $excludeIds = [])
{
$reasons = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('ChillActivityBundle:ActivityReason')
->findAll();
$reason = $reasons[array_rand($reasons)];
if (in_array($reason->getId(), $excludeIds)) {
return $this->getRandomActivityReason($excludeIds);
}
return $reason;
}
/**
* @return \Chill\ActivityBundle\Entity\ActivityType
*/
private function getRandomActivityType()
{
$types = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('ChillActivityBundle:ActivityType')
->findAll();
return $types[array_rand($types)];
}
/**
* @param string $username
* @param string $centerName
*
* @return \Chill\MainBundle\Entity\Scope
*/
private function getRandomScope($username, $centerName)
{
$user = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('ChillMainBundle:User')
->findOneByUsername($username);
if (null === $user) {
throw new RuntimeException("The user with username {$username} "
. 'does not exists in database. Did you add fixtures ?');
}
$center = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('ChillMainBundle:Center')
->findOneByName($centerName);
// get scope reachable by both role UPDATE and DELETE
$reachableScopesUpdate = static::$kernel->getContainer()
->get('chill.main.security.authorization.helper')
->getReachableScopes(
$user,
new Role('CHILL_ACTIVITY_UPDATE'),
$center
);
$reachableScopesDelete = static::$kernel->getContainer()
->get('chill.main.security.authorization.helper')
->getReachableScopes(
$user,
new Role('CHILL_ACTIVITY_DELETE'),
$center
);
$reachableScopesId = array_intersect(
array_map(function ($s) { return $s->getId(); }, $reachableScopesDelete),
array_map(function ($s) { return $s->getId(); }, $reachableScopesUpdate)
);
if (count($reachableScopesId) === 0) {
throw new RuntimeException('there are not scope reachable for '
. 'both CHILL_ACTIVITY_UPDATE and CHILL_ACTIVITY_DELETE');
}
foreach ($reachableScopesUpdate as $scope) {
if (in_array($scope->getId(), $reachableScopesId)) {
$reachableScopes[] = $scope;
}
}
return $reachableScopes[array_rand($reachableScopes)];
}
}

View File

@ -1,15 +1,27 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
* @internal
* @coversNothing
*/
class ActivityReasonCategoryControllerTest extends WebTestCase
{
public function testToWrite()
{
$this->markTestSkipped();
}
/*
public function testCompleteScenario()
{
@ -55,5 +67,5 @@ class ActivityReasonCategoryControllerTest extends WebTestCase
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
}
*/
*/
}

View File

@ -1,15 +1,27 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
* @internal
* @coversNothing
*/
class ActivityReasonControllerTest extends WebTestCase
{
public function testToWrite()
{
$this->markTestSkipped();
}
/*
public function testCompleteScenario()
{
@ -55,5 +67,5 @@ class ActivityReasonControllerTest extends WebTestCase
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
}
*/
*/
}

View File

@ -1,15 +1,27 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
* @internal
* @coversNothing
*/
class ActivityTypeControllerTest extends WebTestCase
{
public function testToWrite()
{
$this->markTestSkipped();
}
/*
public function testCompleteScenario()
{
@ -55,5 +67,5 @@ class ActivityTypeControllerTest extends WebTestCase
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
}
*/
*/
}

View File

@ -1,20 +1,10 @@
<?php
/*
* Copyright (C) 2017 Champs-Libres <info@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Tests\Aggregator;
@ -22,59 +12,59 @@ namespace Chill\ActivityBundle\Tests\Aggregator;
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
/**
* Add tests for ActivityReasonAggregator
* Add tests for ActivityReasonAggregator.
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @internal
* @coversNothing
*/
class ActivityReasonAggregatorTest extends AbstractAggregatorTest
{
/**
*
* @var \Chill\ActivityBundle\Export\Aggregator\ActivityReasonAggregator
*/
private $aggregator;
public function setUp()
{
static::bootKernel();
$container = static::$kernel->getContainer();
$this->aggregator = $container->get('chill.activity.export.reason_aggregator');
$this->aggregator = $container->get('chill.activity.export.reason_aggregator');
// add a fake request with a default locale (used in translatable string)
$prophet = new \Prophecy\Prophet;
$prophet = new \Prophecy\Prophet();
$request = $prophet->prophesize();
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
$request->getLocale()->willReturn('fr');
$container->get('request_stack')
->push($request->reveal());
->push($request->reveal());
}
public function getAggregator()
{
return $this->aggregator;
}
public function getFormData()
{
return array(
array('level' => 'reasons'),
array('level' => 'categories')
);
return [
['level' => 'reasons'],
['level' => 'categories'],
];
}
public function getQueryBuilders()
{
if (static::$kernel === null) {
if (null === static::$kernel) {
static::bootKernel();
}
$em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager');
return array(
return [
$em->createQueryBuilder()
->select('count(activity.id)')
->from('ChillActivityBundle:Activity', 'activity'),
@ -86,8 +76,7 @@ class ActivityReasonAggregatorTest extends AbstractAggregatorTest
->select('count(activity.id)')
->from('ChillActivityBundle:Activity', 'activity')
->join('activity.reasons', 'reasons')
->join('reasons.category', 'category')
);
->join('reasons.category', 'category'),
];
}
}

View File

@ -1,20 +1,10 @@
<?php
/*
* Copyright (C) 2017 Champs-Libres <info@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Tests\Aggregator;
@ -22,58 +12,58 @@ namespace Chill\ActivityBundle\Tests\Aggregator;
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
/**
* Add tests for ActivityTypeAggregator
* Add tests for ActivityTypeAggregator.
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @internal
* @coversNothing
*/
class ActivityTypeAggregatorTest extends AbstractAggregatorTest
{
/**
*
* @var \Chill\ActivityBundle\Export\Aggregator\ActivityReasonAggregator
*/
private $aggregator;
public function setUp()
{
static::bootKernel();
$container = static::$kernel->getContainer();
$this->aggregator = $container->get('chill.activity.export.type_aggregator');
$this->aggregator = $container->get('chill.activity.export.type_aggregator');
// add a fake request with a default locale (used in translatable string)
$prophet = new \Prophecy\Prophet;
$prophet = new \Prophecy\Prophet();
$request = $prophet->prophesize();
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
$request->getLocale()->willReturn('fr');
$container->get('request_stack')
->push($request->reveal());
->push($request->reveal());
}
public function getAggregator()
{
return $this->aggregator;
}
public function getFormData()
{
return array(
array()
);
return [
[],
];
}
public function getQueryBuilders()
{
if (static::$kernel === null) {
if (null === static::$kernel) {
static::bootKernel();
}
$em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager');
return array(
return [
$em->createQueryBuilder()
->select('count(activity.id)')
->from('ChillActivityBundle:Activity', 'activity'),
@ -85,8 +75,7 @@ class ActivityTypeAggregatorTest extends AbstractAggregatorTest
->select('count(activity.id)')
->from('ChillActivityBundle:Activity', 'activity')
->join('activity.reasons', 'reasons')
->join('reasons.category', 'category')
);
->join('reasons.category', 'category'),
];
}
}

View File

@ -1,20 +1,10 @@
<?php
/*
* Copyright (C) 2017 Champs-Libres <info@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Tests\Aggregator;
@ -22,57 +12,58 @@ namespace Chill\ActivityBundle\Tests\Aggregator;
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
/**
* Add tests for ActivityUsernAggregator
* Add tests for ActivityUsernAggregator.
*
* @internal
* @coversNothing
*/
class ActivityUserAggregatorTest extends AbstractAggregatorTest
{
/**
*
* @var \Chill\ActivityBundle\Export\Aggregator\ActivityUserAggregator
*/
private $aggregator;
public function setUp()
{
static::bootKernel();
$container = static::$kernel->getContainer();
$this->aggregator = $container->get('chill.activity.export.user_aggregator');
$this->aggregator = $container->get('chill.activity.export.user_aggregator');
// add a fake request with a default locale (used in translatable string)
$prophet = new \Prophecy\Prophet;
$prophet = new \Prophecy\Prophet();
$request = $prophet->prophesize();
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
$request->getLocale()->willReturn('fr');
$container->get('request_stack')
->push($request->reveal());
->push($request->reveal());
}
public function getAggregator()
{
return $this->aggregator;
}
public function getFormData()
{
return array(
array()
);
return [
[],
];
}
public function getQueryBuilders()
{
if (static::$kernel === null) {
if (null === static::$kernel) {
static::bootKernel();
}
$em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager');
return array(
return [
$em->createQueryBuilder()
->select('count(activity.id)')
->from('ChillActivityBundle:Activity', 'activity'),
@ -84,8 +75,7 @@ class ActivityUserAggregatorTest extends AbstractAggregatorTest
->select('count(activity.id)')
->from('ChillActivityBundle:Activity', 'activity')
->join('activity.reasons', 'reasons')
->join('reasons.category', 'category')
);
->join('reasons.category', 'category'),
];
}
}

View File

@ -1,32 +1,37 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Tests\Export\Export;
use Chill\MainBundle\Test\Export\AbstractExportTest;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @internal
* @coversNothing
*/
class CountActivityTest extends AbstractExportTest
{
/**
*
* @var
* @var
*/
private $export;
public function setUp()
{
static::bootKernel();
/* @var $container \Symfony\Component\DependencyInjection\ContainerInterface */
$container = self::$kernel->getContainer();
$this->export = $container->get('chill.activity.export.count_activity');
}
public function getExport()
{
return $this->export;
@ -34,17 +39,16 @@ class CountActivityTest extends AbstractExportTest
public function getFormData()
{
return array(
array()
);
return [
[],
];
}
public function getModifiersCombination()
{
return array(
array('activity'),
array('activity', 'person')
);
return [
['activity'],
['activity', 'person'],
];
}
}

View File

@ -1,20 +1,10 @@
<?php
/*
* Copyright (C) 2017 Champs-Libres <info@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Tests\Export\Export;
@ -22,67 +12,33 @@ namespace Chill\ActivityBundle\Tests\Export\Export;
use Chill\MainBundle\Test\Export\AbstractExportTest;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @internal
* @coversNothing
*/
class ListActivityTest extends AbstractExportTest
{
/**
*
* @var \Chill\ActivityBundle\Export\Export\ListActivity
*/
private $export;
public function setUp()
{
static::bootKernel();
/* @var $container \Symfony\Component\DependencyInjection\ContainerInterface */
$container = self::$kernel->getContainer();
$this->export = $container->get('chill.activity.export.list_activity');
// add a fake request with a default locale (used in translatable string)
$prophet = new \Prophecy\Prophet;
$prophet = new \Prophecy\Prophet();
$request = $prophet->prophesize();
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
$request->getLocale()->willReturn('fr');
$container->get('request_stack')
->push($request->reveal());
}
public function getFormData()
{
return array(
array('fields' => array(
'id',
'date',
'durationTime',
'attendee',
'user_username',
'circle_name',
'type_name',
'person_firstname',
'person_lastname',
'person_id'
)),
array('fields' => array(
'id',
'list_reasons'
)),
);
}
public function getModifiersCombination()
{
return array(
array('activity'),
array('activity', 'person')
);
->push($request->reveal());
}
public function getExport()
@ -90,4 +46,33 @@ class ListActivityTest extends AbstractExportTest
return $this->export;
}
public function getFormData()
{
return [
['fields' => [
'id',
'date',
'durationTime',
'attendee',
'user_username',
'circle_name',
'type_name',
'person_firstname',
'person_lastname',
'person_id',
]],
['fields' => [
'id',
'list_reasons',
]],
];
}
public function getModifiersCombination()
{
return [
['activity'],
['activity', 'person'],
];
}
}

View File

@ -1,32 +1,39 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Tests\Export\Export;
use Chill\MainBundle\Test\Export\AbstractExportTest;
/**
* Test the "sum" part of StatActivityDuration
* Test the "sum" part of StatActivityDuration.
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @internal
* @coversNothing
*/
class StatActivityDurationSumTest extends AbstractExportTest
{
/**
*
* @var \Chill\ActivityBundle\Export\Export\StatActivityDuration
*/
private $export;
public function setUp()
{
static::bootKernel();
/* @var $container \Symfony\Component\DependencyInjection\ContainerInterface */
$container = self::$kernel->getContainer();
$this->export = $container->get('chill.activity.export.sum_activity_duration');
}
public function getExport()
{
return $this->export;
@ -34,17 +41,16 @@ class StatActivityDurationSumTest extends AbstractExportTest
public function getFormData()
{
return array(
array()
);
return [
[],
];
}
public function getModifiersCombination()
{
return array(
array('activity'),
array('activity', 'person')
);
return [
['activity'],
['activity', 'person'],
];
}
}

View File

@ -1,20 +1,10 @@
<?php
/*
* Copyright (C) 2017 Champs-Libres <info@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Tests\Filter;
@ -23,37 +13,34 @@ use Chill\MainBundle\Test\Export\AbstractFilterTest;
use Doctrine\Common\Collections\ArrayCollection;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @internal
* @coversNothing
*/
class ActivityReasonFilterTest extends AbstractFilterTest
{
/**
*
* @var \Chill\PersonBundle\Export\Filter\GenderFilter
*/
private $filter;
public function setUp()
{
static::bootKernel();
$container = static::$kernel->getContainer();
$this->filter = $container->get('chill.activity.export.reason_filter');
// add a fake request with a default locale (used in translatable string)
$prophet = new \Prophecy\Prophet;
$prophet = new \Prophecy\Prophet();
$request = $prophet->prophesize();
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
$request->getLocale()->willReturn('fr');
$container->get('request_stack')
->push($request->reveal());
->push($request->reveal());
}
public function getFilter()
{
return $this->filter;
@ -61,36 +48,35 @@ class ActivityReasonFilterTest extends AbstractFilterTest
public function getFormData()
{
if (static::$kernel === null) {
if (null === static::$kernel) {
static::bootKernel();
}
$em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager')
;
$reasons = $em->createQuery("SELECT reason "
. "FROM ChillActivityBundle:ActivityReason reason")
->getResult();
->get('doctrine.orm.entity_manager');
$reasons = $em->createQuery('SELECT reason '
. 'FROM ChillActivityBundle:ActivityReason reason')
->getResult();
// generate an array of 5 different combination of results
for ($i=0; $i < 5; $i++) {
$r[] = array('reasons' => new ArrayCollection(array_splice($reasons, ($i + 1) * -1)));
for ($i = 0; 5 > $i; ++$i) {
$r[] = ['reasons' => new ArrayCollection(array_splice($reasons, ($i + 1) * -1))];
}
return $r;
}
public function getQueryBuilders()
{
if (static::$kernel === null) {
if (null === static::$kernel) {
static::bootKernel();
}
$em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager');
return array(
return [
$em->createQueryBuilder()
->select('count(activity.id)')
->from('ChillActivityBundle:Activity', 'activity'),
@ -102,8 +88,7 @@ class ActivityReasonFilterTest extends AbstractFilterTest
->select('count(activity.id)')
->from('ChillActivityBundle:Activity', 'activity')
->join('activity.reasons', 'reasons')
->join('reasons.category', 'category')
);
->join('reasons.category', 'category'),
];
}
}

View File

@ -1,56 +1,47 @@
<?php
/*
* Copyright (C) 2017 Champs Libres Cooperative <info@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Tests\Filter;
use Chill\MainBundle\Test\Export\AbstractFilterTest;
use DateTime;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @internal
* @coversNothing
*/
class PersonHavingActivityBetweenDateFilterTest extends AbstractFilterTest
{
/**
*
* @var \Chill\PersonBundle\Export\Filter\PersonHavingActivityBetweenDateFilter
*/
private $filter;
public function setUp()
{
static::bootKernel();
$container = static::$kernel->getContainer();
$this->filter = $container->get('chill.activity.export.'
. 'person_having_an_activity_between_date_filter');
// add a fake request with a default locale (used in translatable string)
$prophet = new \Prophecy\Prophet;
$prophet = new \Prophecy\Prophet();
$request = $prophet->prophesize();
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
$request->getLocale()->willReturn('fr');
$container->get('request_stack')
->push($request->reveal());
->push($request->reveal());
}
public function getFilter()
{
return $this->filter;
@ -58,49 +49,33 @@ class PersonHavingActivityBetweenDateFilterTest extends AbstractFilterTest
public function getFormData()
{
$date_from = \DateTime::createFromFormat('Y-m-d', '2015-01-15');
$date_to = new \DateTime(); // today
$date_from = DateTime::createFromFormat('Y-m-d', '2015-01-15');
$date_to = new DateTime(); // today
$reasons = $this->getActivityReasons();
$data = array();
for ($i = 0; $i < 4; $i++) {
$data[] = array(
$data = [];
for ($i = 0; 4 > $i; ++$i) {
$data[] = [
'date_from' => $date_from,
'date_to' => $date_to,
'reasons' => array_slice($reasons, 0, 1 + $i)
);
'date_to' => $date_to,
'reasons' => array_slice($reasons, 0, 1 + $i),
];
}
return $data;
}
/**
* Return all activity reasons
*
* @return \Chill\ActivityBundle\Entity\ActivityReason[]
*/
private function getActivityReasons()
{
if (static::$kernel === null) {
static::bootKernel();
}
return static::$kernel->getContainer()
->get('chill_activity.repository.reason')
->findAll();
}
public function getQueryBuilders()
{
if (static::$kernel === null) {
if (null === static::$kernel) {
static::bootKernel();
}
$em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager');
return array(
return [
$em->createQueryBuilder()
->select('count(person.id)')
->from('ChillPersonBundle:Person', 'person')
@ -112,6 +87,22 @@ class PersonHavingActivityBetweenDateFilterTest extends AbstractFilterTest
->join('activity.person', 'person')
// add a fake where clause
->where('person.id > 0'),
);
];
}
/**
* Return all activity reasons.
*
* @return \Chill\ActivityBundle\Entity\ActivityReason[]
*/
private function getActivityReasons()
{
if (null === static::$kernel) {
static::bootKernel();
}
return static::$kernel->getContainer()
->get('chill_activity.repository.reason')
->findAll();
}
}

View File

@ -1,183 +1,170 @@
<?php
/*
* Copyright (C) 2016 Champs-Libres <info@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Tests\Form;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Chill\ActivityBundle\Form\ActivityType;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Form\ActivityType;
use DateTime;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Form\Extension\Core\Type\FormType;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @internal
* @coversNothing
*/
class ActivityTypeTest extends KernelTestCase
{
/**
*
* @var \Symfony\Component\Form\FormBuilderInterface
* @var \Chill\MainBundle\Entity\Center
*/
protected $formBuilder;
protected $center;
/**
*
* @var \Symfony\Component\DependencyInjection\ContainerInterface
*/
protected $container;
/**
*
* @var \Symfony\Component\Form\FormBuilderInterface
*/
protected $formBuilder;
/**
* @var \Symfony\Component\Security\Core\User\UserInterface
*/
protected $user;
/**
*
* @var \Chill\MainBundle\Entity\Center
*/
protected $center;
public function setUp()
{
self::bootKernel();
$this->container = self::$kernel->getContainer();
$prophet = new \Prophecy\Prophet;
$prophet = new \Prophecy\Prophet();
$this->formBuilder = $this->container
->get('form.factory')
->createBuilder(FormType::class, null, array(
'csrf_protection' => false,
'csrf_field_name' => '_token'
));
->get('form.factory')
->createBuilder(FormType::class, null, [
'csrf_protection' => false,
'csrf_field_name' => '_token',
]);
$request = new \Symfony\Component\HttpFoundation\Request();
$request->setLocale('fr');
self::$kernel->getContainer()
->get('request_stack')
->push($request);
->get('request_stack')
->push($request);
$this->user = $this->container->get('doctrine.orm.entity_manager')
->getRepository('ChillMainBundle:User')
->findOneBy(array('username' => 'center a_social'));
->getRepository('ChillMainBundle:User')
->findOneBy(['username' => 'center a_social']);
$this->center = $this->container->get('doctrine.orm.entity_manager')
->getRepository('ChillMainBundle:Center')
->findOneBy(array('name' => 'Center A'));
->getRepository('ChillMainBundle:Center')
->findOneBy(['name' => 'Center A']);
$token = $prophet->prophesize();
$token->willExtend(AbstractToken::class);
$token->getUser()->willReturn($this->user);
$this->container->get('security.token_storage')
->setToken($token->reveal());
->setToken($token->reveal());
}
public function testForm()
{
$form = $this->formBuilder
->add('activity', ActivityType::class, array(
'center' => $this->center,
'role' => new Role('CHILL_ACTIVITY_CREATE')
))
->getForm();
->add('activity', ActivityType::class, [
'center' => $this->center,
'role' => new Role('CHILL_ACTIVITY_CREATE'),
])
->getForm();
$form->submit(array());
$form->submit([]);
$this->assertTrue($form->isSynchronized());
$this->assertTrue($form->isValid());
$this->assertInstanceOf(Activity::class, $form->getData()['activity']);
}
public function testFormSubmitting()
{
$form = $this->formBuilder
->add('activity', ActivityType::class, array(
'center' => $this->center,
'role' => new Role('CHILL_ACTIVITY_CREATE')
))
->getForm();
->add('activity', ActivityType::class, [
'center' => $this->center,
'role' => new Role('CHILL_ACTIVITY_CREATE'),
])
->getForm();
$form->submit(array( 'activity' => array(
$form->submit(['activity' => [
'date' => '9-3-2015',
'durationTime' => 300,
// 'remark' => 'blabla',
'attendee' => true
)));
// 'remark' => 'blabla',
'attendee' => true,
]]);
// var_dump($form->getErrors()->count()); var_dump($form->isValid());
// foreach($form->getErrors() as $e) { fwrite(STDOUT, var_dump($e->getMessage())); }
// var_dump($form->getErrors());
$this->assertTrue($form->isSynchronized(), "Test the form is synchronized");
$this->assertTrue($form->isValid(), "test the form is valid");
$this->assertTrue($form->isSynchronized(), 'Test the form is synchronized');
$this->assertTrue($form->isValid(), 'test the form is valid');
$this->assertInstanceOf(Activity::class, $form->getData()['activity']);
// test the activity
/* @var $activity Activity */
$activity = $form->getData()['activity'];
$this->assertEquals('09-03-2015', $activity->getDate()->format('d-m-Y'),
"Test the date is correct");
$this->assertEquals('00:05', $activity->getDurationTime()->format('H:i'),
"Test the formatted hour is correct");
$this->assertEquals(
'09-03-2015',
$activity->getDate()->format('d-m-Y'),
'Test the date is correct'
);
$this->assertEquals(
'00:05',
$activity->getDurationTime()->format('H:i'),
'Test the formatted hour is correct'
);
$this->assertEquals(true, $activity->getAttendee());
// $this->assertEquals('blabla', $activity->getRemark());
// $this->assertEquals('blabla', $activity->getRemark());
}
/**
* Test that the form correctly build even with a durationTime which is not in
* the listed in the possible durationTime
* the listed in the possible durationTime.
*/
public function testFormWithActivityHavingDifferentTime()
{
$activity = new Activity();
$activity->setDurationTime(\DateTime::createFromFormat('U', 60));
$activity->setDurationTime(DateTime::createFromFormat('U', 60));
$builder = $this->container
->get('form.factory')
->createBuilder(FormType::class, array('activity' => $activity), array(
'csrf_protection' => false,
'csrf_field_name' => '_token'
));
->get('form.factory')
->createBuilder(FormType::class, ['activity' => $activity], [
'csrf_protection' => false,
'csrf_field_name' => '_token',
]);
$form = $builder
->add('activity', ActivityType::class, array(
'center' => $this->center,
'role' => new Role('CHILL_ACTIVITY_CREATE')
))
->getForm();
->add('activity', ActivityType::class, [
'center' => $this->center,
'role' => new Role('CHILL_ACTIVITY_CREATE'),
])
->getForm();
$form->submit(array( 'activity' => array(
$form->submit(['activity' => [
'date' => '9-3-2015',
'durationTime' => 60,
// 'remark' => 'blabla',
'attendee' => true
)));
// 'remark' => 'blabla',
'attendee' => true,
]]);
$this->assertTrue($form->isSynchronized());
$this->assertTrue($form->isValid());
@ -186,8 +173,11 @@ class ActivityTypeTest extends KernelTestCase
/* @var $activity Activity */
$activity = $form->getData()['activity'];
$this->assertEquals('00:01', $activity->getDurationTime()->format('H:i'),
"Test the formatted hour is correct");
$this->assertEquals(
'00:01',
$activity->getDurationTime()->format('H:i'),
'Test the formatted hour is correct'
);
// test the view : we want to be sure that the entry with 60 seconds exists
$view = $form->createView();
@ -195,11 +185,11 @@ class ActivityTypeTest extends KernelTestCase
$this->assertTrue(isset($view['activity']['durationTime']));
// map all the values in an array
$values = array_map(function($choice) { return $choice->value; },
$view['activity']['durationTime']->vars['choices']);
$values = array_map(
function ($choice) { return $choice->value; },
$view['activity']['durationTime']->vars['choices']
);
$this->assertContains(60, $values);
}
}

View File

@ -1,110 +1,97 @@
<?php
/*
/**
* Chill is a software for social workers
* Copyright (C) 2015 Champs Libres <info@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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Tests\Form\Type;
use Symfony\Component\Form\Test\TypeTestCase;
use Chill\ActivityBundle\Form\Type\TranslatableActivityReason;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Symfony\Component\Form\PreloadedExtension;
use Symfony\Component\Form\Test\TypeTestCase;
/**
* Test translatableActivityReason
* Test translatableActivityReason.
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @author Champs Libres <info@champs-libres.coop>
* @internal
* @coversNothing
*/
class TranslatableActivityReasonTest extends TypeTestCase
{
/**
*
* @var Prophecy\Prophet
* @var Prophecy\Prophet
*/
private static $prophet;
public function setUp()
{
parent::setUp();
}
protected function getExtensions()
{
$entityType = $this->getEntityType();
return array(new PreloadedExtension(array(
'entity' => $entityType
), array()));
}
public function testSimple()
{
$translatableActivityReasonType = new TranslatableActivityReason(
$this->getTranslatableStringHelper()
);
$this->markTestSkipped("See issue 651");
$this->getTranslatableStringHelper()
);
$this->markTestSkipped('See issue 651');
}
/**
*
* @param string $locale
* @param string $fallbackLocale
* @return TranslatableStringHelper
*/
protected function getTranslatableStringHelper($locale = 'en',
$fallbackLocale = 'en')
{
$prophet = new \Prophecy\Prophet;
$requestStack = $prophet->prophesize();
$request = $prophet->prophesize();
$translator = $prophet->prophesize();
$request->willExtend('Symfony\Component\HttpFoundation\Request');
$request->getLocale()->willReturn($fallbackLocale);
$requestStack->willExtend('Symfony\Component\HttpFoundation\RequestStack');
$requestStack->getCurrentRequest()->will(function () use ($request) {
return $request;
});
$translator->willExtend('Symfony\Component\Translation\Translator');
$translator->getFallbackLocales()->willReturn($locale);
return new TranslatableStringHelper($requestStack->reveal(),
$translator->reveal());
}
/**
*
* @return \Symfony\Bridge\Doctrine\Form\Type\EntityType
*/
protected function getEntityType()
{
$managerRegistry = (new \Prophecy\Prophet())->prophesize();
$managerRegistry->willImplement('Doctrine\Common\Persistence\ManagerRegistry');
return new \Symfony\Bridge\Doctrine\Form\Type\EntityType($managerRegistry->reveal());
}
protected function getExtensions()
{
$entityType = $this->getEntityType();
return [new PreloadedExtension([
'entity' => $entityType,
], [])];
}
/**
* @param string $locale
* @param string $fallbackLocale
*
* @return TranslatableStringHelper
*/
protected function getTranslatableStringHelper(
$locale = 'en',
$fallbackLocale = 'en'
)
{
$prophet = new \Prophecy\Prophet();
$requestStack = $prophet->prophesize();
$request = $prophet->prophesize();
$translator = $prophet->prophesize();
$request->willExtend('Symfony\Component\HttpFoundation\Request');
$request->getLocale()->willReturn($fallbackLocale);
$requestStack->willExtend('Symfony\Component\HttpFoundation\RequestStack');
$requestStack->getCurrentRequest()->will(function () use ($request) {
return $request;
});
$translator->willExtend('Symfony\Component\Translation\Translator');
$translator->getFallbackLocales()->willReturn($locale);
return new TranslatableStringHelper(
$requestStack->reveal(),
$translator->reveal()
);
}
}

View File

@ -1,116 +1,101 @@
<?php
/*
* Copyright (C) 2016 Champs-Libres <info@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Tests\Form\Type;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Chill\ActivityBundle\Form\Type\TranslatableActivityType;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Form\Extension\Core\Type\FormType;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @internal
* @coversNothing
*/
class TranslatableActivityTypeTest extends KernelTestCase
{
/**
*
* @var \Symfony\Component\Form\FormBuilderInterface
*/
protected $builder;
/**
*
* @var \Symfony\Component\DependencyInjection\ContainerInterface
*/
protected $container;
public function setUp()
{
self::bootKernel();
$this->container = self::$kernel->getContainer();
$this->builder = $this->container
->get('form.factory')
->createBuilder(FormType::class, null, array(
'csrf_protection' => false,
'csrf_field_name' => '_token'
));
->get('form.factory')
->createBuilder(FormType::class, null, [
'csrf_protection' => false,
'csrf_field_name' => '_token',
]);
$request = new \Symfony\Component\HttpFoundation\Request();
$request->setLocale('fr');
$this->container->get('request_stack')
->push($request);
->push($request);
}
/**
*
* @return \Chill\ActivityBundle\Entity\ActivityType
*/
protected function getRandomType($active = true)
{
$types = $this->container->get('doctrine.orm.entity_manager')
->getRepository('ChillActivityBundle:ActivityType')
->findBy(array('active' => $active));
return $types[array_rand($types)];
}
public function testForm()
{
$type = $this->getRandomType();
$form = $this->builder->add('type', TranslatableActivityType::class)
->getForm();
$form->submit(array(
'type' => $type->getId()
));
->getForm();
$form->submit([
'type' => $type->getId(),
]);
$this->assertTrue($form->isSynchronized());
$this->assertInstanceOf(\Chill\ActivityBundle\Entity\ActivityType::class,
$form->getData()['type'],
"The data is an instance of Chill\ActivityBundle\Entity\ActivityType");
$this->assertInstanceOf(
\Chill\ActivityBundle\Entity\ActivityType::class,
$form->getData()['type'],
'The data is an instance of Chill\\ActivityBundle\\Entity\\ActivityType'
);
$this->assertEquals($type->getId(), $form->getData()['type']->getId());
// test the ordering of the types in the form
// since 2016-11-14 the types are not alphabetically ordered, skipping
/*$view = $form->createView();
$this->assertGreaterThan(0, count($view['type']->vars['choices']),
"test that there are at least one choice");
foreach($view['type']->vars['choices'] as $choice) {
// initialize the previous value is not set (this is the first)
if (!isset($previous)) {
$previous = $choice->label;
if (!isset($previous)) {
$previous = $choice->label;
} else {
$this->assertTrue($previous < $choice->label);
$previous = $choice->label;
}
}*/
}
/**
* @param mixed $active
*
* @return \Chill\ActivityBundle\Entity\ActivityType
*/
protected function getRandomType($active = true)
{
$types = $this->container->get('doctrine.orm.entity_manager')
->getRepository('ChillActivityBundle:ActivityType')
->findBy(['active' => $active]);
return $types[array_rand($types)];
}
}

View File

@ -1,103 +1,55 @@
<?php
/*
* Copyright (C) 2015 Julien Fastré <julien.fastre@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Tests\Security\Authorization;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Chill\ActivityBundle\Test\PrepareActivityTrait;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Test\PrepareUserTrait;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Test\PrepareCenterTrait;
use Chill\MainBundle\Test\PrepareScopeTrait;
use Chill\MainBundle\Test\PrepareUserTrait;
use Chill\PersonBundle\Test\PreparePersonTrait;
use Chill\ActivityBundle\Test\PrepareActivityTrait;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @internal
* @coversNothing
*/
class ActivityVoterTest extends KernelTestCase
{
use PrepareUserTrait, PrepareCenterTrait, PrepareScopeTrait,
PreparePersonTrait, PrepareActivityTrait;
use PrepareUserTrait;
use PrepareCenterTrait;
use PrepareScopeTrait;
use PreparePersonTrait;
use PrepareActivityTrait;
/**
*
* @var \Chill\PersonBundle\Security\Authorization\PersonVoter
*/
protected $voter;
/**
*
* @var \Prophecy\Prophet
*/
protected $prophet;
/**
* @var \Chill\PersonBundle\Security\Authorization\PersonVoter
*/
protected $voter;
public function setUp()
{
static::bootKernel();
$this->voter = static::$kernel->getContainer()
->get('chill.activity.security.authorization.activity_voter');
->get('chill.activity.security.authorization.activity_voter');
$this->prophet = new \Prophecy\Prophet();
}
public function testNullUser()
{
$token = $this->prepareToken();
$center = $this->prepareCenter(1, 'center');
$person = $this->preparePerson($center);
$scope = $this->prepareScope(1, 'default');
$activity = $this->prepareActivity($scope, $person);
$this->assertEquals(
VoterInterface::ACCESS_DENIED,
$this->voter->vote($token, $activity, array('CHILL_ACTIVITY_SEE')),
"assert that a null user is not allowed to see"
);
}
/**
*
* @dataProvider dataProvider_testVoteAction
* @param type $expectedResult
* @param User $user
* @param Scope $scope
* @param Center $center
* @param string $attribute
* @param string $message
*/
public function testVoteAction($expectedResult, User $user, Scope $scope,
Center $center, $attribute, $message)
{
$token = $this->prepareToken($user);
$activity = $this->prepareActivity($scope, $this->preparePerson($center));
$this->assertEquals(
$expectedResult,
$this->voter->vote($token, $activity, array($attribute)),
$message
);
}
public function dataProvider_testVoteAction()
{
$centerA = $this->prepareCenter(1, 'center A');
@ -105,72 +57,112 @@ class ActivityVoterTest extends KernelTestCase
$scopeA = $this->prepareScope(1, 'scope default');
$scopeB = $this->prepareScope(2, 'scope B');
$scopeC = $this->prepareScope(3, 'scope C');
$userA = $this->prepareUser(array(
array(
'center' => $centerA,
'permissionsGroup' => array(
$userA = $this->prepareUser([
[
'center' => $centerA,
'permissionsGroup' => [
['scope' => $scopeB, 'role' => 'CHILL_ACTIVITY_CREATE'],
['scope' => $scopeA, 'role' => 'CHILL_ACTIVITY_SEE']
)
),
array(
'center' => $centerB,
'permissionsGroup' => array(
['scope' => $scopeA, 'role' => 'CHILL_ACTIVITY_CREATE'],
['scope' => $scopeC, 'role' => 'CHILL_ACTIVITY_CREATE']
)
)
));
return array(
array(
['scope' => $scopeA, 'role' => 'CHILL_ACTIVITY_SEE'],
],
],
[
'center' => $centerB,
'permissionsGroup' => [
['scope' => $scopeA, 'role' => 'CHILL_ACTIVITY_CREATE'],
['scope' => $scopeC, 'role' => 'CHILL_ACTIVITY_CREATE'],
],
],
]);
return [
[
VoterInterface::ACCESS_GRANTED,
$userA,
$scopeB,
$centerA,
'CHILL_ACTIVITY_CREATE',
'assert that a user granted with same rights'
),
array(
'assert that a user granted with same rights',
],
[
VoterInterface::ACCESS_GRANTED,
$userA,
$scopeB,
$centerA,
'CHILL_ACTIVITY_SEE',
'assert that a user granted with inheritance rights'
),
array(
'assert that a user granted with inheritance rights',
],
[
VoterInterface::ACCESS_DENIED,
$userA,
$scopeC,
$centerA,
'CHILL_ACTIVITY_SEE',
'assert that a suer is denied if he is not granted right on this center'
)
'assert that a suer is denied if he is not granted right on this center',
],
];
}
public function testNullUser()
{
$token = $this->prepareToken();
$center = $this->prepareCenter(1, 'center');
$person = $this->preparePerson($center);
$scope = $this->prepareScope(1, 'default');
$activity = $this->prepareActivity($scope, $person);
$this->assertEquals(
VoterInterface::ACCESS_DENIED,
$this->voter->vote($token, $activity, ['CHILL_ACTIVITY_SEE']),
'assert that a null user is not allowed to see'
);
}
/**
* prepare a token interface with correct rights
*
* @dataProvider dataProvider_testVoteAction
*
* @param type $expectedResult
* @param string $attribute
* @param string $message
*/
public function testVoteAction(
$expectedResult,
User $user,
Scope $scope,
Center $center,
$attribute,
$message
)
{
$token = $this->prepareToken($user);
$activity = $this->prepareActivity($scope, $this->preparePerson($center));
$this->assertEquals(
$expectedResult,
$this->voter->vote($token, $activity, [$attribute]),
$message
);
}
/**
* prepare a token interface with correct rights.
*
* if $permissions = null, user will be null (no user associated with token
*
*
* @return \Symfony\Component\Security\Core\Authentication\Token\TokenInterface
*/
protected function prepareToken(User $user = null)
{
protected function prepareToken(?User $user = null)
{
$token = $this->prophet->prophesize();
$token
->willImplement('\Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
if ($user === NULL) {
if (null === $user) {
$token->getUser()->willReturn(null);
} else {
$token->getUser()->willReturn($user);
}
return $token->reveal();
}
}

View File

@ -1,20 +1,10 @@
<?php
/*
* Copyright (C) 2015 Julien Fastré <julien.fastre@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Tests\Timeline;
@ -22,15 +12,13 @@ namespace Chill\ActivityBundle\Tests\Timeline;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @internal
* @coversNothing
*/
class TimelineProviderTest extends WebTestCase
{
public function testAnActivityIsShownOnTimeline()
{
$this->markTestSkipped("we have to write fixtures before writing this tests");
$this->markTestSkipped('we have to write fixtures before writing this tests');
}
}

View File

@ -1,33 +1,45 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Timeline;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Repository\ActivityACLAwareRepository;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface;
use Chill\MainBundle\Timeline\TimelineProviderInterface;
use Chill\ActivityBundle\Repository\ActivityACLAwareRepository;
use Chill\MainBundle\Timeline\TimelineSingleQuery;
use Chill\PersonBundle\Entity\Person;
use Doctrine\ORM\EntityManagerInterface;
use LogicException;
use RuntimeException;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Role\Role;
use Chill\PersonBundle\Entity\Person;
use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\Timeline\TimelineSingleQuery;
use Symfony\Component\Security\Core\User\UserInterface;
use function implode;
use function in_array;
use function strtr;
class TimelineActivityProvider implements TimelineProviderInterface
{
private const SUPPORTED_CONTEXTS = ['center', 'person'];
protected ActivityACLAwareRepository $aclAwareRepository;
protected EntityManagerInterface $em;
protected AuthorizationHelperInterface $helper;
protected UserInterface $user;
protected ActivityACLAwareRepository $aclAwareRepository;
private const SUPPORTED_CONTEXTS = [ 'center', 'person'];
public function __construct(
EntityManagerInterface $em,
AuthorizationHelperInterface $helper,
@ -38,18 +50,13 @@ class TimelineActivityProvider implements TimelineProviderInterface
$this->helper = $helper;
$this->aclAwareRepository = $aclAwareRepository;
if (!$storage->getToken()->getUser() instanceof User)
{
throw new \RuntimeException('A user should be authenticated !');
if (!$storage->getToken()->getUser() instanceof User) {
throw new RuntimeException('A user should be authenticated !');
}
$this->user = $storage->getToken()->getUser();
}
/**
*
* {@inheritDoc}
*/
public function fetchQuery($context, array $args)
{
if ('center' === $context) {
@ -59,80 +66,28 @@ class TimelineActivityProvider implements TimelineProviderInterface
$metadataActivity = $this->em->getClassMetadata(Activity::class);
[$where, $parameters] = $this->getWhereClauseForPerson($args['person']);
[$where, $parameters] = $this->getWhereClauseForPerson($args['person']);
return TimelineSingleQuery::fromArray([
'id' => $metadataActivity->getTableName()
.'.'.$metadataActivity->getColumnName('id'),
'type' => 'activity',
'date' => $metadataActivity->getTableName()
.'.'.$metadataActivity->getColumnName('date'),
'FROM' => $this->getFromClausePerson(),
'WHERE' => $where,
'parameters' => $parameters
]);
}
private function getWhereClauseForPerson(Person $person)
{
$parameters = [];
$metadataActivity = $this->em->getClassMetadata(Activity::class);
$associationMapping = $metadataActivity->getAssociationMapping('person');
$role = new Role('CHILL_ACTIVITY_SEE');
$reachableScopes = $this->helper->getReachableScopes($this->user, $role->getRole(), $person->getCenter());
$whereClause = sprintf(' {activity.person_id} = ? AND {activity.scope_id} IN ({scopes_ids}) ');
$scopes_ids = [];
// first parameter: activity.person_id
$parameters[] = $person->getId();
// loop on reachable scopes
foreach ($reachableScopes as $scope) {
if (\in_array($scope->getId(), $scopes_ids)) {
continue;
}
$scopes_ids[] = '?';
$parameters[] = $scope->getId();
}
return [
\strtr(
$whereClause,
[
'{activity.person_id}' => $associationMapping['joinColumns'][0]['name'],
'{activity.scope_id}' => $metadataActivity->getTableName().'.'.
$metadataActivity->getAssociationMapping('scope')['joinColumns'][0]['name'],
'{scopes_ids}' => \implode(", ", $scopes_ids)
,
]
),
$parameters
];
}
private function getFromClausePerson(): string
{
$metadataActivity = $this->em->getClassMetadata(Activity::class);
$metadataPerson = $this->em->getClassMetadata(Person::class);
$associationMapping = $metadataActivity->getAssociationMapping('person');
return sprintf(
"%s JOIN %s ON %s.%s = %s",
$metadataActivity->getTableName(),
$metadataPerson->getTableName(),
$metadataPerson->getTableName(),
$associationMapping['joinColumns'][0]['referencedColumnName'],
$associationMapping['joinColumns'][0]['name']
);
'id' => $metadataActivity->getTableName()
. '.' . $metadataActivity->getColumnName('id'),
'type' => 'activity',
'date' => $metadataActivity->getTableName()
. '.' . $metadataActivity->getColumnName('date'),
'FROM' => $this->getFromClausePerson(),
'WHERE' => $where,
'parameters' => $parameters,
]);
}
public function getEntities(array $ids): array
{
$activities = $this->em->getRepository(Activity::class)
->findBy(array('id' => $ids));
->findBy(['id' => $ids]);
$result = array();
foreach($activities as $activity) {
$result = [];
foreach ($activities as $activity) {
$result[$activity->getId()] = $activity;
}
@ -144,28 +99,28 @@ class TimelineActivityProvider implements TimelineProviderInterface
$this->checkContext($context);
return [
'template' => 'ChillActivityBundle:Timeline:activity_person_context.html.twig',
'template_data' => [
'activity' => $entity,
'context' => $context
]
'template' => 'ChillActivityBundle:Timeline:activity_person_context.html.twig',
'template_data' => [
'activity' => $entity,
'context' => $context,
],
];
}
public function supportsType($type): bool
{
return $type === 'activity';
return 'activity' === $type;
}
/**
* Check if the context is supported.
*
* @throws \LogicException if the context is not supported
* @throws LogicException if the context is not supported
*/
private function checkContext(string $context)
{
if (FALSE === \in_array($context, self::SUPPORTED_CONTEXTS)) {
throw new \LogicException(
if (false === in_array($context, self::SUPPORTED_CONTEXTS)) {
throw new LogicException(
sprintf(
"The context '%s' is not supported. Currently only 'person' is supported",
$context
@ -174,4 +129,55 @@ class TimelineActivityProvider implements TimelineProviderInterface
}
}
private function getFromClausePerson(): string
{
$metadataActivity = $this->em->getClassMetadata(Activity::class);
$metadataPerson = $this->em->getClassMetadata(Person::class);
$associationMapping = $metadataActivity->getAssociationMapping('person');
return sprintf(
'%s JOIN %s ON %s.%s = %s',
$metadataActivity->getTableName(),
$metadataPerson->getTableName(),
$metadataPerson->getTableName(),
$associationMapping['joinColumns'][0]['referencedColumnName'],
$associationMapping['joinColumns'][0]['name']
);
}
private function getWhereClauseForPerson(Person $person)
{
$parameters = [];
$metadataActivity = $this->em->getClassMetadata(Activity::class);
$associationMapping = $metadataActivity->getAssociationMapping('person');
$role = new Role('CHILL_ACTIVITY_SEE');
$reachableScopes = $this->helper->getReachableScopes($this->user, $role->getRole(), $person->getCenter());
$whereClause = sprintf(' {activity.person_id} = ? AND {activity.scope_id} IN ({scopes_ids}) ');
$scopes_ids = [];
// first parameter: activity.person_id
$parameters[] = $person->getId();
// loop on reachable scopes
foreach ($reachableScopes as $scope) {
if (in_array($scope->getId(), $scopes_ids)) {
continue;
}
$scopes_ids[] = '?';
$parameters[] = $scope->getId();
}
return [
strtr(
$whereClause,
[
'{activity.person_id}' => $associationMapping['joinColumns'][0]['name'],
'{activity.scope_id}' => $metadataActivity->getTableName() . '.' .
$metadataActivity->getAssociationMapping('scope')['joinColumns'][0]['name'],
'{scopes_ids}' => implode(', ', $scopes_ids),
]
),
$parameters,
];
}
}

View File

@ -1,38 +1,40 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@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/>.
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\Migrations\Activity;
use Doctrine\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
class Version20150701091248 extends AbstractMigration
{
/**
* @param Schema $schema
*/
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('ALTER TABLE Activity DROP CONSTRAINT FK_55026B0C59BB1592');
$this->addSql('ALTER TABLE ActivityReason DROP CONSTRAINT FK_654A2FCD12469DE2');
$this->addSql('ALTER TABLE Activity DROP CONSTRAINT FK_55026B0CC54C8C93');
$this->addSql('DROP SEQUENCE Activity_id_seq CASCADE');
$this->addSql('DROP SEQUENCE ActivityReason_id_seq CASCADE');
$this->addSql('DROP SEQUENCE ActivityReasonCategory_id_seq CASCADE');
$this->addSql('DROP SEQUENCE ActivityType_id_seq CASCADE');
$this->addSql('DROP TABLE Activity');
$this->addSql('DROP TABLE ActivityReason');
$this->addSql('DROP TABLE ActivityReasonCategory');
$this->addSql('DROP TABLE ActivityType');
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
@ -59,25 +61,4 @@ class Version20150701091248 extends AbstractMigration
$this->addSql('ALTER TABLE Activity ADD CONSTRAINT FK_55026B0C217BBB47 FOREIGN KEY (person_id) REFERENCES Person (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE ActivityReason ADD CONSTRAINT FK_654A2FCD12469DE2 FOREIGN KEY (category_id) REFERENCES ActivityReasonCategory (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
}
/**
* @param Schema $schema
*/
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('ALTER TABLE Activity DROP CONSTRAINT FK_55026B0C59BB1592');
$this->addSql('ALTER TABLE ActivityReason DROP CONSTRAINT FK_654A2FCD12469DE2');
$this->addSql('ALTER TABLE Activity DROP CONSTRAINT FK_55026B0CC54C8C93');
$this->addSql('DROP SEQUENCE Activity_id_seq CASCADE');
$this->addSql('DROP SEQUENCE ActivityReason_id_seq CASCADE');
$this->addSql('DROP SEQUENCE ActivityReasonCategory_id_seq CASCADE');
$this->addSql('DROP SEQUENCE ActivityType_id_seq CASCADE');
$this->addSql('DROP TABLE Activity');
$this->addSql('DROP TABLE ActivityReason');
$this->addSql('DROP TABLE ActivityReasonCategory');
$this->addSql('DROP TABLE ActivityType');
}
}
}

View File

@ -1,54 +1,22 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@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/>.
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\Migrations\Activity;
use Doctrine\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
class Version20150702093317 extends AbstractMigration
{
/**
* @param Schema $schema
*/
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('ALTER TABLE ActivityReasonCategory DROP COLUMN label;');
$this->addSql('ALTER TABLE ActivityReasonCategory ADD COLUMN name JSON;');
$this->addSql('ALTER TABLE ActivityReason DROP COLUMN label;');
$this->addSql('ALTER TABLE ActivityReason ADD COLUMN name JSON;');
$this->addSql('ALTER TABLE ActivityType DROP COLUMN name;');
$this->addSql('ALTER TABLE ActivityType ADD COLUMN name JSON;');
}
/**
* @param Schema $schema
*/
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
@ -61,4 +29,17 @@ class Version20150702093317 extends AbstractMigration
$this->addSql('ALTER TABLE ActivityType DROP COLUMN name;');
$this->addSql('ALTER TABLE ActivityType ADD COLUMN name VARCHAR(255) NOT NULL;');
}
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('ALTER TABLE ActivityReasonCategory DROP COLUMN label;');
$this->addSql('ALTER TABLE ActivityReasonCategory ADD COLUMN name JSON;');
$this->addSql('ALTER TABLE ActivityReason DROP COLUMN label;');
$this->addSql('ALTER TABLE ActivityReason ADD COLUMN name JSON;');
$this->addSql('ALTER TABLE ActivityType DROP COLUMN name;');
$this->addSql('ALTER TABLE ActivityType ADD COLUMN name JSON;');
}
}

View File

@ -1,51 +1,22 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@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/>.
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\Migrations\Activity;
use Doctrine\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Db Migration
*
* Db Migration.
*/
class Version20150704091347 extends AbstractMigration
{
/**
* @param Schema $schema
*/
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('ALTER TABLE Activity ALTER COLUMN remark DROP NOT NULL;');
$this->addSql('ALTER TABLE Activity ALTER COLUMN attendee DROP NOT NULL;');
}
/**
* @param Schema $schema
*/
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
@ -54,4 +25,13 @@ class Version20150704091347 extends AbstractMigration
$this->addSql('ALTER TABLE Activity ALTER COLUMN remark SET NOT NULL;');
$this->addSql('ALTER TABLE Activity ALTER COLUMN attendee DROP NOT NULL;');
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('ALTER TABLE Activity ALTER COLUMN remark DROP NOT NULL;');
$this->addSql('ALTER TABLE Activity ALTER COLUMN attendee DROP NOT NULL;');
}
}

View File

@ -1,60 +1,31 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\Migrations\Activity;
use Doctrine\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Migrate schema to allow multiple or empty reasons on an activity.
*
* Migrate schema to allow multiple or empty reasons on an activity.
*
* The relation between the activity and reason **was** oneToMany. After this
* migration, the relation will be manyToMany.
*/
class Version20160222103457 extends AbstractMigration
{
/**
* @param Schema $schema
*/
public function up(Schema $schema): void
{
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'postgresql',
'Migration can only be executed safely on \'postgresql\'.');
// create the new table activity reason
$this->addSql('CREATE TABLE activity_activityreason ('
. 'activity_id INT NOT NULL, '
. 'activityreason_id INT NOT NULL, '
. 'PRIMARY KEY(activity_id, activityreason_id))'
);
$this->addSql('CREATE INDEX IDX_338A864381C06096 ON activity_activityreason (activity_id)');
$this->addSql('CREATE INDEX IDX_338A8643D771E0FC ON activity_activityreason (activityreason_id)');
$this->addSql('ALTER TABLE activity_activityreason '
. 'ADD CONSTRAINT FK_338A864381C06096 FOREIGN KEY (activity_id) '
. 'REFERENCES Activity (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE activity_activityreason '
. 'ADD CONSTRAINT FK_338A8643D771E0FC FOREIGN KEY (activityreason_id) '
. 'REFERENCES ActivityReason (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
// migrate old data to new table
$this->addSql('INSERT INTO activity_activityreason (activity_id, activityreason_id) '
. 'SELECT id, reason_id FROM activity WHERE reason_id IS NOT NULL');
// remove old column
$this->addSql('ALTER TABLE activity DROP CONSTRAINT fk_55026b0c59bb1592');
$this->addSql('DROP INDEX idx_55026b0c59bb1592');
$this->addSql('ALTER TABLE activity DROP reason_id');
}
/**
* @param Schema $schema
*/
public function down(Schema $schema): void
{
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'postgresql',
'Migration can only be executed safely on \'postgresql\'.');
$this->abortIf(
$this->connection->getDatabasePlatform()->getName() != 'postgresql',
'Migration can only be executed safely on \'postgresql\'.'
);
$this->addSql('ALTER TABLE Activity ADD reason_id INT DEFAULT NULL');
$this->addSql('ALTER TABLE Activity ADD CONSTRAINT '
@ -63,17 +34,49 @@ class Version20160222103457 extends AbstractMigration
$this->addSql('CREATE INDEX idx_55026b0c59bb1592 ON Activity (reason_id)');
// try to keep at least on activity reason...
$this->addSql('UPDATE activity
$this->addSql(
'UPDATE activity
SET reason_id=rid
FROM (
SELECT activity_id AS aid, MIN(activityreason_id) AS rid
FROM activity_activityreason
GROUP BY activity_id ) AS sb
WHERE sb.aid = activity.id'
);
);
$this->addSql('DROP TABLE activity_activityreason');
}
public function up(Schema $schema): void
{
$this->abortIf(
$this->connection->getDatabasePlatform()->getName() != 'postgresql',
'Migration can only be executed safely on \'postgresql\'.'
);
// create the new table activity reason
$this->addSql(
'CREATE TABLE activity_activityreason ('
. 'activity_id INT NOT NULL, '
. 'activityreason_id INT NOT NULL, '
. 'PRIMARY KEY(activity_id, activityreason_id))'
);
$this->addSql('CREATE INDEX IDX_338A864381C06096 ON activity_activityreason (activity_id)');
$this->addSql('CREATE INDEX IDX_338A8643D771E0FC ON activity_activityreason (activityreason_id)');
$this->addSql('ALTER TABLE activity_activityreason '
. 'ADD CONSTRAINT FK_338A864381C06096 FOREIGN KEY (activity_id) '
. 'REFERENCES Activity (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE activity_activityreason '
. 'ADD CONSTRAINT FK_338A8643D771E0FC FOREIGN KEY (activityreason_id) '
. 'REFERENCES ActivityReason (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
// migrate old data to new table
$this->addSql('INSERT INTO activity_activityreason (activity_id, activityreason_id) '
. 'SELECT id, reason_id FROM activity WHERE reason_id IS NOT NULL');
// remove old column
$this->addSql('ALTER TABLE activity DROP CONSTRAINT fk_55026b0c59bb1592');
$this->addSql('DROP INDEX idx_55026b0c59bb1592');
$this->addSql('ALTER TABLE activity DROP reason_id');
}
}

View File

@ -1,29 +1,29 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\Migrations\Activity;
use Doctrine\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Types\Types;
use Doctrine\Migrations\AbstractMigration;
/**
* Add an "active" column on activitytype table
* Add an "active" column on activitytype table.
*/
class Version20161114085659 extends AbstractMigration
{
/**
* @param Schema $schema
*/
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE activitytype ADD active BOOLEAN NOT NULL DEFAULT \'t\'');
}
/**
* @param Schema $schema
*/
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE ActivityType DROP active');
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE activitytype ADD active BOOLEAN NOT NULL DEFAULT \'t\'');
}
}

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\Migrations\Activity;
@ -12,20 +19,7 @@ use Doctrine\Migrations\AbstractMigration;
*/
final class Version20210304154629 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE activity ADD comment_comment TEXT DEFAULT NULL');
$this->addSql('ALTER TABLE activity ADD comment_userId INT DEFAULT NULL');
$this->addSql('ALTER TABLE activity ADD comment_date TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
}
public function down(Schema $schema) : void
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
@ -33,4 +27,17 @@ final class Version20210304154629 extends AbstractMigration
$this->addSql('ALTER TABLE activity DROP comment_userId');
$this->addSql('ALTER TABLE activity DROP comment_date');
}
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE activity ADD comment_comment TEXT DEFAULT NULL');
$this->addSql('ALTER TABLE activity ADD comment_userId INT DEFAULT NULL');
$this->addSql('ALTER TABLE activity ADD comment_date TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
}
}

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\Migrations\Activity;
@ -12,21 +19,20 @@ use Doctrine\Migrations\AbstractMigration;
*/
final class Version20210311114250 extends AbstractMigration
{
public function getDescription() : string
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
}
public function getDescription(): string
{
return '';
}
public function up(Schema $schema) : void
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('UPDATE activity SET comment_comment = remark');
$this->addSql('ALTER TABLE activity DROP remark');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
}
}

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\Migrations\Activity;
@ -12,24 +19,23 @@ use Doctrine\Migrations\AbstractMigration;
*/
final class Version20210401090853 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SEQUENCE activitytypecategory_id_seq INCREMENT BY 1 MINVALUE 1 START 1000');
$this->addSql('CREATE TABLE activitytypecategory (id INT NOT NULL, name JSON NOT NULL, active BOOLEAN NOT NULL, PRIMARY KEY(id))');
$this->addSql('INSERT INTO activitytypecategory VALUES(1, \'{"fr": "Défaut", "en": "Default"}\', true)');
}
public function down(Schema $schema) : void
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP SEQUENCE activitytypecategory_id_seq CASCADE');
$this->addSql('DROP TABLE activitytypecategory');
}
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SEQUENCE activitytypecategory_id_seq INCREMENT BY 1 MINVALUE 1 START 1000');
$this->addSql('CREATE TABLE activitytypecategory (id INT NOT NULL, name JSON NOT NULL, active BOOLEAN NOT NULL, PRIMARY KEY(id))');
$this->addSql('INSERT INTO activitytypecategory VALUES(1, \'{"fr": "Défaut", "en": "Default"}\', true)');
}
}

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\Migrations\Activity;
@ -12,48 +19,7 @@ use Doctrine\Migrations\AbstractMigration;
*/
final class Version20210408122329 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
$this->addSql('ALTER TABLE activitytype ADD personVisible SMALLINT DEFAULT 2 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD personLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD userVisible SMALLINT DEFAULT 2 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD userLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD dateVisible SMALLINT DEFAULT 2 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD dateLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD placeVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD placeLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD personsVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD personsLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD thirdpartyVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD thirdpartyLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD durationTimeVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD durationTimeLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD attendeeVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD attendeeLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD reasonsVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD reasonsLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD commentVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD commentLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD sentReceivedVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD sentReceivedLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD documentVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD documentLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD emergencyVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD emergencyLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD accompanyingPeriodVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD accompanyingPeriodLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD socialDataVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD socialDataLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ALTER name SET NOT NULL');
$this->addSql('ALTER TABLE activitytype ALTER active DROP DEFAULT');
}
public function down(Schema $schema) : void
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE activitytype DROP personVisible');
$this->addSql('ALTER TABLE activitytype DROP personLabel');
@ -89,4 +55,45 @@ final class Version20210408122329 extends AbstractMigration
$this->addSql('ALTER TABLE activitytype ALTER active SET DEFAULT \'true\'');
$this->addSql('COMMENT ON COLUMN activitytype.name IS NULL');
}
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE activitytype ADD personVisible SMALLINT DEFAULT 2 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD personLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD userVisible SMALLINT DEFAULT 2 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD userLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD dateVisible SMALLINT DEFAULT 2 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD dateLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD placeVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD placeLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD personsVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD personsLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD thirdpartyVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD thirdpartyLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD durationTimeVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD durationTimeLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD attendeeVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD attendeeLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD reasonsVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD reasonsLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD commentVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD commentLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD sentReceivedVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD sentReceivedLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD documentVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD documentLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD emergencyVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD emergencyLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD accompanyingPeriodVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD accompanyingPeriodLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD socialDataVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD socialDataLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ALTER name SET NOT NULL');
$this->addSql('ALTER TABLE activitytype ALTER active DROP DEFAULT');
}
}

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\Migrations\Activity;
@ -12,24 +19,7 @@ use Doctrine\Migrations\AbstractMigration;
*/
final class Version20210415113216 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
$this->addSql('ALTER TABLE activitytype ADD thirdPartiesVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD thirdPartiesLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD documentsVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD documentsLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype DROP thirdpartyvisible');
$this->addSql('ALTER TABLE activitytype DROP thirdpartylabel');
$this->addSql('ALTER TABLE activitytype DROP documentvisible');
$this->addSql('ALTER TABLE activitytype DROP documentlabel');
}
public function down(Schema $schema) : void
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE activitytype ADD thirdpartyvisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD thirdpartylabel VARCHAR(255) DEFAULT \'\' NOT NULL');
@ -40,4 +30,21 @@ final class Version20210415113216 extends AbstractMigration
$this->addSql('ALTER TABLE activitytype DROP documentsVisible');
$this->addSql('ALTER TABLE activitytype DROP documentsLabel');
}
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE activitytype ADD thirdPartiesVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD thirdPartiesLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD documentsVisible SMALLINT DEFAULT 1 NOT NULL');
$this->addSql('ALTER TABLE activitytype ADD documentsLabel VARCHAR(255) DEFAULT \'\' NOT NULL');
$this->addSql('ALTER TABLE activitytype DROP thirdpartyvisible');
$this->addSql('ALTER TABLE activitytype DROP thirdpartylabel');
$this->addSql('ALTER TABLE activitytype DROP documentvisible');
$this->addSql('ALTER TABLE activitytype DROP documentlabel');
}
}

View File

@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\Migrations\Activity;
@ -12,33 +19,7 @@ use Doctrine\Migrations\AbstractMigration;
*/
final class Version20210422073711 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
$this->addSql('CREATE SEQUENCE activitytpresence_id_seq INCREMENT BY 1 MINVALUE 1 START 6');
$this->addSql('CREATE TABLE activitytpresence (id INT NOT NULL, name JSON NOT NULL, active BOOLEAN NOT NULL, PRIMARY KEY(id))');
$list = [
'Usager pésent', "Absence de l''usager",
"Refus de visite ou d''entretien", 'Domicile non trouvé',
'Domicile erronéee'
];
for ($i = 1; $i <= count($list); $i++) {
$this->addSql("INSERT INTO activitytpresence VALUES(".$i.", json_build_object('fr', '".$list[$i-1]."'), true)");
}
$this->addSql('ALTER TABLE activity ADD emergency BOOLEAN NOT NULL DEFAULT false');
$this->addSql('ALTER TABLE activity ADD sentReceived VARCHAR(255) NOT NULL DEFAULT \'\' ');
$this->addSql('ALTER TABLE activity ALTER attendee TYPE INT USING CASE WHEN attendee is false THEN 2 WHEN attendee is true THEN 1 ELSE null END');
$this->addSql('ALTER TABLE activity RENAME COLUMN attendee TO attendee_id');
$this->addSql('ALTER TABLE activity ADD CONSTRAINT FK_AC74095ABCFD782A FOREIGN KEY (attendee_id) REFERENCES activitytpresence (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
}
public function down(Schema $schema) : void
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE activity DROP emergency');
$this->addSql('ALTER TABLE activity DROP CONSTRAINT FK_AC74095ABCFD782A');
@ -49,4 +30,31 @@ final class Version20210422073711 extends AbstractMigration
$this->addSql('DROP SEQUENCE activitytpresence_id_seq CASCADE');
$this->addSql('DROP TABLE activitytpresence');
}
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
$this->addSql('CREATE SEQUENCE activitytpresence_id_seq INCREMENT BY 1 MINVALUE 1 START 6');
$this->addSql('CREATE TABLE activitytpresence (id INT NOT NULL, name JSON NOT NULL, active BOOLEAN NOT NULL, PRIMARY KEY(id))');
$list = [
'Usager pésent', "Absence de l''usager",
"Refus de visite ou d''entretien", 'Domicile non trouvé',
'Domicile erronéee',
];
for ($i = 1; count($list) >= $i; ++$i) {
$this->addSql('INSERT INTO activitytpresence VALUES(' . $i . ", json_build_object('fr', '" . $list[$i - 1] . "'), true)");
}
$this->addSql('ALTER TABLE activity ADD emergency BOOLEAN NOT NULL DEFAULT false');
$this->addSql('ALTER TABLE activity ADD sentReceived VARCHAR(255) NOT NULL DEFAULT \'\' ');
$this->addSql('ALTER TABLE activity ALTER attendee TYPE INT USING CASE WHEN attendee is false THEN 2 WHEN attendee is true THEN 1 ELSE null END');
$this->addSql('ALTER TABLE activity RENAME COLUMN attendee TO attendee_id');
$this->addSql('ALTER TABLE activity ADD CONSTRAINT FK_AC74095ABCFD782A FOREIGN KEY (attendee_id) REFERENCES activitytpresence (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
}
}

Some files were not shown because too many files have changed in this diff Show More