Merge branch 'master' into 295_resume_retouches

This commit is contained in:
2021-11-24 11:47:47 +01:00
1254 changed files with 68603 additions and 65686 deletions

2
.gitignore vendored
View File

@@ -20,3 +20,5 @@ docs/build/
.phpunit.result.cache .phpunit.result.cache
###< phpunit/phpunit ### ###< phpunit/phpunit ###
/.php-cs-fixer.cache
/.idea/

View File

@@ -1,50 +1,87 @@
--- ---
image: registry.gitlab.com/chill-projet/chill-app/php-base-image:7.4
# Select what we should cache between builds # Select what we should cache between builds
cache: cache:
paths: paths:
- tests/app/vendor/ - tests/app/vendor/
- .composer - .cache
before_script:
# add extensions to postgres
- PGPASSWORD=$POSTGRES_PASSWORD psql -U $POSTGRES_USER -h db -c "CREATE EXTENSION IF NOT EXISTS unaccent; CREATE EXTENSION IF NOT EXISTS pg_trgm;"
# Install and run Composer
- mkdir -p $COMPOSER_HOME
- curl -sS https://getcomposer.org/installer | php
- php -d memory_limit=2G composer.phar install
- php tests/app/bin/console doctrine:migrations:migrate -n
- php -d memory_limit=2G tests/app/bin/console cache:clear --env=dev
- php -d memory_limit=3G tests/app/bin/console doctrine:fixtures:load -n
- php -d memory_limit=2G tests/app/bin/console cache:clear --env=test
- echo "before_script finished"
# Bring in any services we need http://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-a-service # Bring in any services we need http://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-a-service
# See http://docs.gitlab.com/ee/ci/services/README.html for examples. # See http://docs.gitlab.com/ee/ci/services/README.html for examples.
services: services:
- name: postgis/postgis:12-3.1-alpine - name: postgis/postgis:12-3.1-alpine
alias: db alias: db
- name: redis - name: redis
alias: redis alias: redis
# Set any variables we need # Set any variables we need
variables: variables:
# Configure postgres environment variables (https://hub.docker.com/r/_/postgres/) GIT_DEPTH: 1
POSTGRES_USER: postgres # Configure postgres environment variables (https://hub.docker.com/r/_/postgres/)
POSTGRES_PASSWORD: postgres POSTGRES_USER: postgres
# fetch the chill-app using git submodules POSTGRES_PASSWORD: postgres
GIT_SUBMODULE_STRATEGY: recursive # fetch the chill-app using git submodules
REDIS_HOST: redis GIT_SUBMODULE_STRATEGY: recursive
REDIS_PORT: 6379 REDIS_HOST: redis
REDIS_URL: redis://redis:6379 REDIS_PORT: 6379
# change vendor dir to make the app install into tests/apps REDIS_URL: redis://redis:6379
COMPOSER_VENDOR_DIR: tests/app/vendor # change vendor dir to make the app install into tests/apps
# cache some composer data COMPOSER_VENDOR_DIR: tests/app/vendor
COMPOSER_HOME: .composer
stages:
- Composer install
- Tests
# Run our tests build:
test: stage: Composer install
script: image: registry.gitlab.com/chill-projet/chill-app/php-base-image:7.4
- php -d memory_limit=3G bin/phpunit --colors=never before_script:
- curl -sS https://getcomposer.org/installer | php
- php -d memory_limit=2G composer.phar config -g cache-dir "$(pwd)/.cache"
script:
- php -d memory_limit=2G composer.phar install --optimize-autoloader --no-ansi --no-interaction --no-progress
cache:
paths:
- .cache/
artifacts:
expire_in: 30 min
paths:
- bin
- tests/app/vendor/
code_style:
stage: Tests
image: registry.gitlab.com/chill-projet/chill-app/php-base-image:7.4
script:
- bin/grumphp run --tasks=phpcsfixer
artifacts:
expire_in: 30 min
paths:
- bin
- tests/app/vendor/
sa_tests:
stage: Tests
image: registry.gitlab.com/chill-projet/chill-app/php-base-image:7.4
script:
- bin/grumphp run --tasks=phpstan
artifacts:
expire_in: 30 min
paths:
- bin
- tests/app/vendor/
unit_tests:
stage: Tests
image: registry.gitlab.com/chill-projet/chill-app/php-base-image:7.4
script:
- php tests/app/bin/console doctrine:migrations:migrate -n
- php -d memory_limit=2G tests/app/bin/console cache:clear --env=dev
- php -d memory_limit=3G tests/app/bin/console doctrine:fixtures:load -n
- php -d memory_limit=2G tests/app/bin/console cache:clear --env=test
- php -d memory_limit=3G bin/phpunit --colors=never
artifacts:
expire_in: 30 min
paths:
- bin
- tests/app/vendor/

79
.php_cs.dist.php Normal file
View File

@@ -0,0 +1,79 @@
<?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);
/** @var \drupol\PhpCsFixerConfigsPhp\Config\Php73 $config */
$config = require __DIR__ . '/tests/app/vendor/drupol/php-conventions/config/php73/php_cs_fixer.config.php';
$config
->getFinder()
->ignoreDotFiles(false)
->notPath('tests/app')
->name(['.php_cs.dist.php']);
$rules = $config->getRules();
$riskyRules = [
'final_internal_class' => false,
'no_useless_sprintf' => false,
'dir_constant' => false,
'no_alias_functions' => false,
'implode_call' => false,
'combine_nested_dirname' => false,
'pow_to_exponentiation' => false,
'comment_to_phpdoc' => false,
'no_unset_on_property' => false,
'strict_param' => false,
'native_constant_invocation' => false,
'php_unit_test_annotation' => false,
'php_unit_no_expectation_annotation' => false,
'declare_strict_types' => false,
'function_to_constant' => false,
'is_null' => false,
'native_function_invocation' => false,
'ternary_to_elvis_operator' => false,
'no_trailing_whitespace_in_string' => false,
'no_unreachable_default_argument_value' => false,
'php_unit_test_case_static_method_calls' => false,
'strict_comparison' => false,
'array_push' => false,
'ereg_to_preg' => false,
'error_suppression' => false,
'fopen_flag_order' => false,
'fopen_flags' => false,
'logical_operators' => false,
'modernize_types_casting' => false,
'no_homoglyph_names' => false,
'no_unneeded_final_method' => false,
'non_printable_character' => false,
'ordered_traits' => false,
'php_unit_mock_short_will_return' => false,
'php_unit_set_up_tear_down_visibility' => false,
'set_type_to_cast' => false,
'string_line_ending' => false,
'ordered_interfaces' => false,
'php_unit_expectation' => false,
'php_unit_mock' => false,
'php_unit_namespaced' => false,
'random_api_migration' => false,
'static_lambda' => false,
'php_unit_construct' => false,
'psr_autoloading' => false,
'php_unit_dedicate_assert' => false,
];
$rules = array_merge(
$rules,
$riskyRules
);
$rules['header_comment']['header'] = trim(file_get_contents(__DIR__ . '/resource/header.txt'));
return $config->setRules($rules);

View File

@@ -11,7 +11,19 @@ and this project adheres to
## Unreleased ## Unreleased
<!-- write down unreleased development here --> <!-- write down unreleased development here -->
* Use the user.label in accompanying course banner, instead of username;
* fix: show validation message when closing accompanying course;
## Test releases
### Test release 2021-11-22
* [activity] delete admin_user_show in twig template because this route is not defined and should be defined
* [activity] suggest requestor, user and ressources for adding persons|user|3rdparty
* [calendar] suggest persons, professionals and invites for adding persons|3rdparty|user
* [activity] take into account the restrictions on person|thirdparties|users visibilities defined in ActivityType
* [main] Add currentLocation to the User entity + add a page for selecting this location + add in the user menu (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/133)
* [activity] add user current location as default location for a new activity (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/133)
* [task] Select2 field in task form to allow search for a user (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/167) * [task] Select2 field in task form to allow search for a user (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/167)
* remove "search by phone configuration option": search by phone is now executed by default * remove "search by phone configuration option": search by phone is now executed by default
* remplacer le classement par ordre alphabétique par un classement par ordre de pertinence, qui tient compte: * remplacer le classement par ordre alphabétique par un classement par ordre de pertinence, qui tient compte:
@@ -29,10 +41,11 @@ and this project adheres to
* [person] fix bounds for computing current person address: the new address appears immediatly * [person] fix bounds for computing current person address: the new address appears immediatly
* [docgen] create a normalizer and serializer for normalization on doc format * [docgen] create a normalizer and serializer for normalization on doc format
* [person normalization] the key center is now "centers" and is an array. Empty array if no center * [person normalization] the key center is now "centers" and is an array. Empty array if no center
* [accompanyingCourse] Ability to close accompanying course (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/296)
* [task] Select2 field in task form to allow search for a user (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/167)
* [list result] show all courses, except ones with period closed
## Test releases
### Test release 2021-11-15 ### Test release 2021-11-15
* [main] fix adding multiple AddresseDeRelais (combine PickAddressType with ChillCollection) * [main] fix adding multiple AddresseDeRelais (combine PickAddressType with ChillCollection)
@@ -49,6 +62,8 @@ and this project adheres to
* [person] do not ask for center any more on person creation * [person] do not ask for center any more on person creation
* [3party] do not ask for center any more on 3party creation * [3party] do not ask for center any more on 3party creation
## Test releases
### Test release 2021-11-08 ### Test release 2021-11-08
* [person]: Display the name of a user when searching after a User (TMS) * [person]: Display the name of a user when searching after a User (TMS)

View File

@@ -629,12 +629,12 @@ to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found. the "copyright" line and a pointer to where the full notice is found.
chill-bundles <one line to give the program's name and a brief idea of what it does.>
Copyright (C) 2021 Chill Project Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU Affero General Public License as published by
by the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,

View File

@@ -52,10 +52,9 @@
}, },
"require-dev": { "require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.3", "doctrine/doctrine-fixtures-bundle": "^3.3",
"drupol/php-conventions": "^5",
"fakerphp/faker": "^1.13", "fakerphp/faker": "^1.13",
"nelmio/alice": "^3.8", "nelmio/alice": "^3.8",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan": "^1.0",
"phpstan/phpstan-strict-rules": "^1.0", "phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^7.0", "phpunit/phpunit": "^7.0",
"symfony/debug-bundle": "^5.1", "symfony/debug-bundle": "^5.1",

View File

@@ -1,17 +1,20 @@
<?php <?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; namespace Chill\PersonBundle\Export\Filter;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Export\FilterInterface;
use DateTime;
use Doctrine\ORM\Query\Expr;
use Symfony\Component\Form\Extension\Core\Type\DateType; use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Validator\Context\ExecutionContextInterface; 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 class BirthdateFilter implements FilterInterface, ExportElementValidatedInterface
{ {
@@ -22,78 +25,16 @@ class BirthdateFilter implements FilterInterface, ExportElementValidatedInterfac
return null; return null;
} }
// 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',
'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',
'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 // here, we alter the query created by Export
public function alterQuery(\Doctrine\ORM\QueryBuilder $qb, $data) public function alterQuery(\Doctrine\ORM\QueryBuilder $qb, $data)
{ {
$where = $qb->getDQLPart('where'); $where = $qb->getDQLPart('where');
// we create the clause here // we create the clause here
$clause = $qb->expr()->between('person.birthdate', ':date_from', $clause = $qb->expr()->between(
':date_to'); 'person.birthdate',
':date_from',
':date_to'
);
// we have to take care **not to** remove previous clauses... // we have to take care **not to** remove previous clauses...
if ($where instanceof Expr\Andx) { if ($where instanceof Expr\Andx) {
@@ -108,16 +49,76 @@ class BirthdateFilter implements FilterInterface, ExportElementValidatedInterfac
$qb->setParameter('date_to', $data['date_to']); $qb->setParameter('date_to', $data['date_to']);
} }
// we give information on which type of export this filter applies
public function applyOn()
{
return 'person';
}
// 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, [
'label' => 'Born after this date',
'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
]);
$builder->add('date_to', DateType::class, [
'label' => 'Born before this date',
'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
]);
}
// here, we create a simple string which will describe the action of // here, we create a simple string which will describe the action of
// the filter in the Response // the filter in the Response
public function describeAction($data, $format = 'string') public function describeAction($data, $format = 'string')
{ {
return array('Filtered by person\'s birtdate: ' return ['Filtered by person\'s birtdate: '
. 'between %date_from% and %date_to%', array( . 'between %date_from% and %date_to%', [
'%date_from%' => $data['date_from']->format('d-m-Y'), '%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,74 +1,74 @@
<?php <?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; namespace Chill\PersonBundle\Export\Export;
use Chill\MainBundle\Export\ExportInterface; 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\MainBundle\Export\FormatterInterface;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Doctrine\ORM\EntityManagerInterface; 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 class CountPerson implements ExportInterface
{ {
/** /**
*
* @var EntityManagerInterface * @var EntityManagerInterface
*/ */
protected $entityManager; protected $entityManager;
public function __construct( public function __construct(
EntityManagerInterface $em EntityManagerInterface $em
) ) {
{
$this->entityManager = $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() 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() public function getQueryKeys($data)
{ {
return new Role(PersonVoter::STATS); // this array match the result keys in the query. We have only
} // one column.
return ['export_result'];
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) public function getResult($qb, $data)
@@ -76,43 +76,40 @@ class CountPerson implements ExportInterface
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR); return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
} }
public function getQueryKeys($data) public function getTitle()
{ {
// this array match the result keys in the query. We have only return 'Count peoples';
// one column.
return array('export_result');
} }
public function getLabels($key, array $values, $data) public function getType()
{ {
return Declarations::PERSON_TYPE;
// 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 getAllowedFormattersTypes() public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{ {
return array(FormatterInterface::TYPE_TABULAR); // 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 buildForm(FormBuilderInterface $builder) { public function requiredRole()
// this export does not add any form {
return new Role(PersonVoter::STATS);
} }
public function supportsModifiers() public function supportsModifiers()
{ {
// explain the export manager which formatters and filters are allowed // 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,20 +1,25 @@
<?php <?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; namespace Chill\MyBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class ItemController extends Controller {
class ItemController extends Controller
{
public function yourAction() public function yourAction()
{ {
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
// first, get the number of total item are available // first, get the number of total item are available
$total = $em $total = $em
->createQuery("SELECT COUNT (item.id) FROM ChillMyBundle:Item item") ->createQuery('SELECT COUNT (item.id) FROM ChillMyBundle:Item item')
->getSingleScalarResult(); ->getSingleScalarResult();
// get the PaginatorFactory // get the PaginatorFactory
$paginatorFactory = $this->get('chill_main.paginator_factory'); $paginatorFactory = $this->get('chill_main.paginator_factory');
@@ -25,18 +30,18 @@ class ItemController extends Controller {
// launch your query on item. Limit the query to the results // launch your query on item. Limit the query to the results
// for the current page using the paginator // 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 // use the paginator to get the first item number
->setFirstResult($paginator->getCurrentPage()->getFirstItemNumber()) ->setFirstResult($paginator->getCurrentPage()->getFirstItemNumber())
// use the paginator to get the number of items to display // use the paginator to get the number of items to display
->setMaxResults($paginator->getItemsPerPage()); ->setMaxResults($paginator->getItemsPerPage());
return $this->render('ChillMyBundle:Item:list.html.twig', array( return $this->render(
'ChillMyBundle:Item:list.html.twig',
[
'items' => $items, 'items' => $items,
'paginator' => $paginator 'paginator' => $paginator,
); ]
);
} }
} }

View File

@@ -1,19 +1,27 @@
<?php <?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; namespace Chill\HealthBundle\Controller;
use Chill\HealthBundle\Security\Authorization\ConsultationVoter; use Chill\HealthBundle\Security\Authorization\ConsultationVoter;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Chill\PersonBundle\Security\Authorization\PersonVoter; use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\Role;
class ConsultationController extends Controller class ConsultationController extends Controller
{ {
/** /**
*
* @param int $id personId * @param int $id personId
* @return \Symfony\Component\HttpFoundation\Response *
* @throws type * @throws type
*
* @return \Symfony\Component\HttpFoundation\Response
*/ */
public function listAction($id) public function listAction($id)
{ {
@@ -21,8 +29,8 @@ class ConsultationController extends Controller
$person = $this->get('chill.person.repository.person') $person = $this->get('chill.person.repository.person')
->find($id); ->find($id);
if ($person === null) { if (null === $person) {
throw $this->createNotFoundException("The person is not found"); throw $this->createNotFoundException('The person is not found');
} }
$this->denyAccessUnlessGranted(PersonVoter::SEE, $person); $this->denyAccessUnlessGranted(PersonVoter::SEE, $person);
@@ -35,7 +43,7 @@ class ConsultationController extends Controller
$this->getUser(), $this->getUser(),
new Role(ConsultationVoter::SEE), new Role(ConsultationVoter::SEE),
$person->getCenter() $person->getCenter()
); );
// create a query which take circles into account // create a query which take circles into account
$consultations = $this->getDoctrine()->getManager() $consultations = $this->getDoctrine()->getManager()
@@ -46,10 +54,9 @@ class ConsultationController extends Controller
->setParameter('circles', $circles) ->setParameter('circles', $circles)
->getResult(); ->getResult();
return $this->render('ChillHealthBundle:Consultation:list.html.twig', array( return $this->render('ChillHealthBundle:Consultation:list.html.twig', [
'person' => $person, 'person' => $person,
'consultations' => $consultations 'consultations' => $consultations,
)); ]);
} }
} }

View File

@@ -1,64 +1,61 @@
<?php <?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\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\ConfigurationInterface;
use Chill\MainBundle\DependencyInjection\Widget\AddWidgetConfigurationTrait;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
/** /**
* Configure the main bundle * Configure the main bundle.
*/ */
class Configuration implements ConfigurationInterface class Configuration implements ConfigurationInterface
{ {
use AddWidgetConfigurationTrait; use AddWidgetConfigurationTrait;
/** /**
* * @var ContainerBuilder
* @var ContainerBuilder */
*/
private $containerBuilder; private $containerBuilder;
public function __construct(
public function __construct(array $widgetFactories = array(), array $widgetFactories = [],
ContainerBuilder $containerBuilder) ContainerBuilder $containerBuilder
{ ) {
// we register here widget factories (see below) // we register here widget factories (see below)
$this->setWidgetFactories($widgetFactories); $this->setWidgetFactories($widgetFactories);
// we will need the container builder later... // we will need the container builder later...
$this->containerBuilder = $containerBuilder; $this->containerBuilder = $containerBuilder;
} }
/**
* {@inheritDoc}
*/
public function getConfigTreeBuilder() public function getConfigTreeBuilder()
{ {
$treeBuilder = new TreeBuilder(); $treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('chill_main'); $rootNode = $treeBuilder->root('chill_main');
$rootNode $rootNode
->children() ->children()
// ... // ...
->arrayNode('widgets')
->arrayNode('widgets') ->canBeDisabled()
->canBeDisabled() ->children()
->children()
// we declare here all configuration for homepage place // we declare here all configuration for homepage place
->append($this->addWidgetsConfiguration('homepage', $this->containerBuilder)) ->append($this->addWidgetsConfiguration('homepage', $this->containerBuilder))
->end() // end of widgets/children ->end() // end of widgets/children
->end() // end of widgets ->end() // end of widgets
->end() // end of root/children ->end() // end of root/children
->end() // end of root ->end() // end of root
; ;
return $treeBuilder;
return $treeBuilder;
} }
} }

View File

@@ -1,16 +1,17 @@
<?php <?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; 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\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. * This class load config for chillMainExtension.
@@ -18,19 +19,23 @@ use Chill\MainBundle\DependencyInjection\Configuration;
class ChillMainExtension extends Extension implements Widget\HasWidgetFactoriesExtensionInterface class ChillMainExtension extends Extension implements Widget\HasWidgetFactoriesExtensionInterface
{ {
/** /**
* widget factory * widget factory.
* *
* @var WidgetFactoryInterface[] * @var WidgetFactoryInterface[]
*/ */
protected $widgetFactories = array(); protected $widgetFactories = [];
public function addWidgetFactory(WidgetFactoryInterface $factory) public function addWidgetFactory(WidgetFactoryInterface $factory)
{ {
$this->widgetFactories[] = $factory; $this->widgetFactories[] = $factory;
} }
public function getConfiguration(array $config, ContainerBuilder $container)
{
return new Configuration($this->widgetFactories, $container);
}
/** /**
*
* @return WidgetFactoryInterface[] * @return WidgetFactoryInterface[]
*/ */
public function getWidgetFactories() public function getWidgetFactories()
@@ -45,15 +50,11 @@ class ChillMainExtension extends Extension implements Widget\HasWidgetFactoriesE
$config = $this->processConfiguration($configuration, $configs); $config = $this->processConfiguration($configuration, $configs);
// add the key 'widget' without the key 'enable' // add the key 'widget' without the key 'enable'
$container->setParameter('chill_main.widgets', $container->setParameter(
array('homepage' => $config['widgets']['homepage'])); 'chill_main.widgets',
['homepage' => $config['widgets']['homepage']]
);
// ... // ...
} }
public function getConfiguration(array $config, ContainerBuilder $container)
{
return new Configuration($this->widgetFactories, $container);
}
} }

View File

@@ -1,55 +1,49 @@
<?php <?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; namespace Chill\PersonBundle\Widget;
use Chill\MainBundle\DependencyInjection\Widget\Factory\AbstractWidgetFactory; use Chill\MainBundle\DependencyInjection\Widget\Factory\AbstractWidgetFactory;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\Definition\Builder\NodeBuilder; use Symfony\Component\Config\Definition\Builder\NodeBuilder;
use Symfony\Component\DependencyInjection\ContainerBuilder;
/** /**
* add configuration for the person_list widget. * add configuration for the person_list widget.
*/ */
class PersonListWidgetFactory extends AbstractWidgetFactory class PersonListWidgetFactory extends AbstractWidgetFactory
{ {
/* /*
* append the option to the configuration * append the option to the configuration
* see http://symfony.com/doc/current/components/config/definition.html * see http://symfony.com/doc/current/components/config/definition.html
* *
*/ */
public function configureOptions($place, NodeBuilder $node) public function configureOptions($place, NodeBuilder $node)
{ {
$node->booleanNode('only_active') $node->booleanNode('only_active')
->defaultTrue() ->defaultTrue()
->end(); ->end();
$node->integerNode('number_of_items') $node->integerNode('number_of_items')
->defaultValue(50) ->defaultValue(50)
->end(); ->end();
$node->scalarNode('filtering_class') $node->scalarNode('filtering_class')
->defaultNull() ->defaultNull()
->end(); ->end();
} }
/* /*
* return an array with the allowed places where the widget can be rendered * return an array with the allowed places where the widget can be rendered
* *
* @return string[] * @return string[]
*/ */
public function getAllowedPlaces() public function getAllowedPlaces()
{ {
return array('homepage'); return ['homepage'];
}
/*
* return the widget alias
*
* @return string
*/
public function getWidgetAlias()
{
return 'person_list';
} }
/* /*
@@ -65,5 +59,13 @@ class PersonListWidgetFactory extends AbstractWidgetFactory
return 'chill_person.widget.person_list'; return 'chill_person.widget.person_list';
} }
/*
* return the widget alias
*
* @return string
*/
public function getWidgetAlias()
{
return 'person_list';
}
} }

View File

@@ -1,18 +1,26 @@
<?php <?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; namespace Chill\PersonBundle\Widget;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Templating\Widget\WidgetInterface; 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\EntityRepository;
use Doctrine\ORM\Query\Expr; 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 Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Symfony\Component\Security\Core\Role\Role; 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.
@@ -21,46 +29,43 @@ use Doctrine\ORM\EntityManager;
*/ */
class PersonListWidget implements WidgetInterface class PersonListWidget implements WidgetInterface
{ {
/** /**
* Repository for persons * the authorization helper.
*
* @var EntityRepository
*/
protected $personRepository;
/**
* The entity manager
*
* @var EntityManager
*/
protected $entityManager;
/**
* the authorization helper
* *
* @var AuthorizationHelper; * @var AuthorizationHelper;
*/ */
protected $authorizationHelper; protected $authorizationHelper;
/** /**
* The entity manager.
* *
* @var EntityManager
*/
protected $entityManager;
/**
* Repository for persons.
*
* @var EntityRepository
*/
protected $personRepository;
/**
* @var TokenStorage * @var TokenStorage
*/ */
protected $tokenStorage; protected $tokenStorage;
/** /**
*
* @var UserInterface * @var UserInterface
*/ */
protected $user; protected $user;
public function __construct( public function __construct(
EntityRepository $personRepostory, EntityRepository $personRepostory,
EntityManager $em, EntityManager $em,
AuthorizationHelper $authorizationHelper, AuthorizationHelper $authorizationHelper,
TokenStorage $tokenStorage TokenStorage $tokenStorage
) { ) {
$this->personRepository = $personRepostory; $this->personRepository = $personRepostory;
$this->authorizationHelper = $authorizationHelper; $this->authorizationHelper = $authorizationHelper;
$this->tokenStorage = $tokenStorage; $this->tokenStorage = $tokenStorage;
@@ -68,27 +73,24 @@ class PersonListWidget implements WidgetInterface
} }
/** /**
*
* @param type $place * @param type $place
* @param array $context *
* @param array $config
* @return string * @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 $qb = $this->personRepository
->createQueryBuilder('person'); ->createQueryBuilder('person');
// show only the person from the authorized centers // show only the person from the authorized centers
$and = $qb->expr()->andX(); $and = $qb->expr()->andX();
$centers = $this->authorizationHelper $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')); $and->add($qb->expr()->in('person.center', ':centers'));
$qb->setParameter('centers', $centers); $qb->setParameter('centers', $centers);
// add the "only active" where clause // add the "only active" where clause
if ($config['only_active'] === true) { if (true === $config['only_active']) {
$qb->join('person.accompanyingPeriods', 'ap'); $qb->join('person.accompanyingPeriods', 'ap');
$or = new Expr\Orx(); $or = new Expr\Orx();
// add the case where closingDate IS NULL // add the case where closingDate IS NULL
@@ -98,10 +100,10 @@ class PersonListWidget implements WidgetInterface
$or->add($andWhenClosingDateIsNull); $or->add($andWhenClosingDateIsNull);
// add the case when now is between opening date and closing date // add the case when now is between opening date and closing date
$or->add( $or->add(
(new Expr())->between(':now', 'ap.openingDate', 'ap.closingDate') (new Expr())->between(':now', 'ap.openingDate', 'ap.closingDate')
); );
$and->add($or); $and->add($or);
$qb->setParameter('now', new \DateTime(), Type::DATE); $qb->setParameter('now', new DateTime(), Type::DATE);
} }
// adding the where clause to the query // adding the where clause to the query
@@ -113,17 +115,15 @@ class PersonListWidget implements WidgetInterface
return $env->render( return $env->render(
'ChillPersonBundle:Widget:homepage_person_list.html.twig', 'ChillPersonBundle:Widget:homepage_person_list.html.twig',
array('persons' => $persons) ['persons' => $persons]
); );
} }
/** /**
*
* @return UserInterface * @return UserInterface
*/ */
private function getUser() private function getUser()
{ {
// return a user // return a user
} }
} }

View File

@@ -1,51 +1,46 @@
<?php <?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; namespace Chill\PersonBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder; 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 Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Chill\MainBundle\DependencyInjection\MissingBundleException; use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
/** /**
* 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} * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
*/ */
class ChillPersonExtension extends Extension implements PrependExtensionInterface class ChillPersonExtension extends Extension implements PrependExtensionInterface
{ {
/**
* {@inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container) 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 * @param \Chill\PersonBundle\DependencyInjection\containerBuilder $container
*/ */
public function prepend(ContainerBuilder $container) public function prepend(ContainerBuilder $container)
{ {
$container->prependExtensionConfig('chill_main', array( $container->prependExtensionConfig('chill_main', [
'widgets' => array( 'widgets' => [
'homepage' => array( 'homepage' => [
array( [
'widget_alias' => 'add_person', 'widget_alias' => 'add_person',
'order' => 2 'order' => 2,
) ],
) ],
) ],
)); ]);
} }
} }

14
grumphp.yml Normal file
View File

@@ -0,0 +1,14 @@
imports:
- {
resource: tests/app/vendor/drupol/php-conventions/config/php73/grumphp.yml,
}
parameters:
tasks.phpcsfixer.config: .php_cs.dist.php
tasks.license.name: AGPL-3.0
tasks.license.holder: Champs-Libres
tasks.license.date_from: 2001
tasks.phpcsfixer.allow_risky: false
tasks.phpcsfixer.diff: true
tasks.phpstan.level: 1

1638
phpstan-deprecations.neon Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -495,11 +495,6 @@ parameters:
count: 2 count: 2
path: src/Bundle/ChillMainBundle/Security/Authorization/AbstractChillVoter.php path: src/Bundle/ChillMainBundle/Security/Authorization/AbstractChillVoter.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2
path: src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelper.php
- -
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2 count: 2

View File

@@ -3,6 +3,7 @@ parameters:
paths: paths:
- src/ - src/
excludePaths: excludePaths:
- docs/
- src/Bundle/*/Tests/* - src/Bundle/*/Tests/*
- src/Bundle/*/tests/* - src/Bundle/*/tests/*
- src/Bundle/*/Test/* - src/Bundle/*/Test/*
@@ -18,7 +19,8 @@ parameters:
- src/Bundle/*/src/Resources/* - src/Bundle/*/src/Resources/*
includes: includes:
- phpstan-types.neon
- phpstan-critical.neon
- phpstan-baseline.neon - phpstan-baseline.neon
- phpstan-critical.neon
- phpstan-deprecations.neon
- phpstan-types.neon

5
resource/header.txt Normal file
View File

@@ -0,0 +1,5 @@
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.

View File

@@ -1,5 +1,12 @@
<?php <?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; namespace Chill\ActivityBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\HttpKernel\Bundle\Bundle;

View File

@@ -1,15 +1,25 @@
<?php <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Controller; namespace Chill\ActivityBundle\Controller;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Entity\ActivityReason; use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Form\ActivityType;
use Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface; use Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface;
use Chill\ActivityBundle\Repository\ActivityRepository; use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\ActivityBundle\Repository\ActivityTypeCategoryRepository; use Chill\ActivityBundle\Repository\ActivityTypeCategoryRepository;
use Chill\ActivityBundle\Repository\ActivityTypeRepository; use Chill\ActivityBundle\Repository\ActivityTypeRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter; use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
use Chill\MainBundle\Repository\LocationRepository; use Chill\MainBundle\Repository\LocationRepository;
use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\Person;
@@ -17,45 +27,44 @@ use Chill\PersonBundle\Privacy\PrivacyEvent;
use Chill\PersonBundle\Repository\AccompanyingPeriodRepository; use Chill\PersonBundle\Repository\AccompanyingPeriodRepository;
use Chill\PersonBundle\Repository\PersonRepository; use Chill\PersonBundle\Repository\PersonRepository;
use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository; use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
use DateTime;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request; 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\HttpFoundation\Response;
use Symfony\Component\Security\Core\Role\Role; 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; use Symfony\Component\Serializer\SerializerInterface;
final class ActivityController extends AbstractController final class ActivityController extends AbstractController
{ {
private EventDispatcherInterface $eventDispatcher; private AccompanyingPeriodRepository $accompanyingPeriodRepository;
private LoggerInterface $logger;
private SerializerInterface $serializer;
private ActivityACLAwareRepositoryInterface $activityACLAwareRepository; private ActivityACLAwareRepositoryInterface $activityACLAwareRepository;
private ActivityRepository $activityRepository;
private ActivityTypeCategoryRepository $activityTypeCategoryRepository;
private ActivityTypeRepository $activityTypeRepository; private ActivityTypeRepository $activityTypeRepository;
private ThirdPartyRepository $thirdPartyRepository;
private PersonRepository $personRepository;
private LocationRepository $locationRepository;
private EntityManagerInterface $entityManager; 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( public function __construct(
ActivityACLAwareRepositoryInterface $activityACLAwareRepository, ActivityACLAwareRepositoryInterface $activityACLAwareRepository,
@@ -85,6 +94,150 @@ final class ActivityController extends AbstractController
$this->serializer = $serializer; $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. * Lists all Activity entities.
*/ */
@@ -103,7 +256,7 @@ final class ActivityController extends AbstractController
$event = new PrivacyEvent($person, [ $event = new PrivacyEvent($person, [
'element_class' => Activity::class, 'element_class' => Activity::class,
'action' => 'list' 'action' => 'list',
]); ]);
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
@@ -121,12 +274,152 @@ final class ActivityController extends AbstractController
$view, $view,
[ [
'activities' => $activities, 'activities' => $activities,
'person' => $person, 'person' => $person,
'accompanyingCourse' => $accompanyingPeriod, '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 public function selectTypeAction(Request $request): Response
{ {
$view = null; $view = null;
@@ -159,7 +452,7 @@ final class ActivityController extends AbstractController
]; ];
} }
if ($view === null) { if (null === $view) {
throw $this->createNotFoundException('Template not found'); throw $this->createNotFoundException('Template not found');
} }
@@ -171,143 +464,7 @@ final class ActivityController extends AbstractController
]); ]);
} }
public function newAction(Request $request): Response public function showAction(Request $request, int $id): 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);
}
}
// TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_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']);
return $this->render($view, [
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
'entity' => $entity,
'form' => $form->createView(),
'activity_json' => $activity_array
]);
}
public function showAction(Request $request, $id): Response
{ {
$view = null; $view = null;
@@ -327,8 +484,8 @@ final class ActivityController extends AbstractController
if (null !== $accompanyingPeriod) { if (null !== $accompanyingPeriod) {
// @TODO: Properties created dynamically. // @TODO: Properties created dynamically.
$entity->personsAssociated = $entity->getPersonsAssociated(); $entity->personsAssociated = $entity->getPersonsAssociated();
$entity->personsNotAssociated = $entity->getPersonsNotAssociated(); $entity->personsNotAssociated = $entity->getPersonsNotAssociated();
} }
// TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période // TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période
@@ -344,160 +501,33 @@ final class ActivityController extends AbstractController
'action' => 'show' 'action' => 'show'
)); ));
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
*/ */
if ($view === null) { if (null === $view) {
throw $this->createNotFoundException('Template not found'); throw $this->createNotFoundException('Template not found');
} }
return $this->render($view, [ 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($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, 'person' => $person,
'accompanyingCourse' => $accompanyingPeriod, 'accompanyingCourse' => $accompanyingPeriod,
'activity_json' => $activity_array 'entity' => $entity,
'delete_form' => $deleteForm->createView(),
]); ]);
} }
/** private function buildParamsToUrl(?Person $person, ?AccompanyingPeriod $accompanyingPeriod): array
* Deletes a Activity entity.
*/
public function deleteAction(Request $request, $id)
{ {
$view = null; $params = [];
[$person, $accompanyingPeriod] = $this->getEntity($request); if (null !== $person) {
$params['person_id'] = $person->getId();
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 (null !== $accompanyingPeriod) {
$params['accompanying_period_id'] = $accompanyingPeriod->getId();
if (!$activity) {
throw $this->createNotFoundException('Unable to find Activity entity.');
} }
// TODO return $params;
// $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,
]);
} }
/** /**
@@ -517,13 +547,13 @@ final class ActivityController extends AbstractController
private function getEntity(Request $request): array private function getEntity(Request $request): array
{ {
$person = $accompanyingPeriod = null; $person = $accompanyingPeriod = null;
if ($request->query->has('person_id')) { if ($request->query->has('person_id')) {
$person_id = $request->get('person_id'); $person_id = $request->get('person_id');
$person = $this->personRepository->find($person_id); $person = $this->personRepository->find($person_id);
if ($person === null) { if (null === $person) {
throw $this->createNotFoundException('Person not found'); throw $this->createNotFoundException('Person not found');
} }
@@ -532,34 +562,19 @@ final class ActivityController extends AbstractController
$accompanying_period_id = $request->get('accompanying_period_id'); $accompanying_period_id = $request->get('accompanying_period_id');
$accompanyingPeriod = $this->accompanyingPeriodRepository->find($accompanying_period_id); $accompanyingPeriod = $this->accompanyingPeriodRepository->find($accompanying_period_id);
if ($accompanyingPeriod === null) { if (null === $accompanyingPeriod) {
throw $this->createNotFoundException('Accompanying Period not found'); throw $this->createNotFoundException('Accompanying Period not found');
} }
// TODO Add permission // TODO Add permission
// $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person); // $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
} else { } else {
throw $this->createNotFoundException("Person or Accompanying Period not found"); throw $this->createNotFoundException('Person or Accompanying Period not found');
} }
return [ return [
$person, $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 <?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; 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\Entity\ActivityReasonCategory;
use Chill\ActivityBundle\Form\ActivityReasonCategoryType; 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. * ActivityReasonCategory controller.
*
*/ */
class ActivityReasonCategoryController extends AbstractController 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. * Creates a new ActivityReasonCategory entity.
*
*/ */
public function createAction(Request $request) public function createAction(Request $request)
{ {
@@ -45,71 +35,19 @@ class ActivityReasonCategoryController extends AbstractController
$em->persist($entity); $em->persist($entity);
$em->flush(); $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, 'entity' => $entity,
'form' => $form->createView(), '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,
));
} }
/** /**
* Displays a form to edit an existing ActivityReasonCategory entity. * Displays a form to edit an existing ActivityReasonCategory entity.
* *
* @param mixed $id
*/ */
public function editAction($id) public function editAction($id)
{ {
@@ -123,33 +61,64 @@ class ActivityReasonCategoryController extends AbstractController
$editForm = $this->createEditForm($entity); $editForm = $this->createEditForm($entity);
return $this->render('ChillActivityBundle:ActivityReasonCategory:edit.html.twig', array( return $this->render('ChillActivityBundle:ActivityReasonCategory:edit.html.twig', [
'entity' => $entity, 'entity' => $entity,
'edit_form' => $editForm->createView(), 'edit_form' => $editForm->createView(),
)); ]);
} }
/** /**
* Creates a form to edit a ActivityReasonCategory entity. * Lists all ActivityReasonCategory entities.
* */
* @param ActivityReasonCategory $entity The entity public function indexAction()
*
* @return \Symfony\Component\Form\Form The form
*/
private function createEditForm(ActivityReasonCategory $entity)
{ {
$form = $this->createForm(ActivityReasonCategoryType::class, $entity, array( $em = $this->getDoctrine()->getManager();
'action' => $this->generateUrl('chill_activity_activityreasoncategory_update', array('id' => $entity->getId())),
'method' => 'PUT',
));
$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. * Edits an existing ActivityReasonCategory entity.
* *
* @param mixed $id
*/ */
public function updateAction(Request $request, $id) public function updateAction(Request $request, $id)
{ {
@@ -167,12 +136,50 @@ class ActivityReasonCategoryController extends AbstractController
if ($editForm->isValid()) { if ($editForm->isValid()) {
$em->flush(); $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( return $this->render('ChillActivityBundle:ActivityReasonCategory:edit.html.twig', [
'entity' => $entity, 'entity' => $entity,
'edit_form' => $editForm->createView(), '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 <?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; 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\Entity\ActivityReason;
use Chill\ActivityBundle\Form\ActivityReasonType; 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. * ActivityReason controller.
*
*/ */
class ActivityReasonController extends AbstractController 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. * Creates a new ActivityReason entity.
*
*/ */
public function createAction(Request $request) public function createAction(Request $request)
{ {
@@ -45,71 +35,19 @@ class ActivityReasonController extends AbstractController
$em->persist($entity); $em->persist($entity);
$em->flush(); $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, 'entity' => $entity,
'form' => $form->createView(), '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,
));
} }
/** /**
* Displays a form to edit an existing ActivityReason entity. * Displays a form to edit an existing ActivityReason entity.
* *
* @param mixed $id
*/ */
public function editAction($id) public function editAction($id)
{ {
@@ -123,33 +61,64 @@ class ActivityReasonController extends AbstractController
$editForm = $this->createEditForm($entity); $editForm = $this->createEditForm($entity);
return $this->render('ChillActivityBundle:ActivityReason:edit.html.twig', array( return $this->render('ChillActivityBundle:ActivityReason:edit.html.twig', [
'entity' => $entity, 'entity' => $entity,
'edit_form' => $editForm->createView() 'edit_form' => $editForm->createView(),
)); ]);
} }
/** /**
* Creates a form to edit a ActivityReason entity. * Lists all ActivityReason entities.
* */
* @param ActivityReason $entity The entity public function indexAction()
*
* @return \Symfony\Component\Form\Form The form
*/
private function createEditForm(ActivityReason $entity)
{ {
$form = $this->createForm(ActivityReasonType::class, $entity, array( $em = $this->getDoctrine()->getManager();
'action' => $this->generateUrl('chill_activity_activityreason_update', array('id' => $entity->getId())),
'method' => 'PUT',
));
$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. * Edits an existing ActivityReason entity.
* *
* @param mixed $id
*/ */
public function updateAction(Request $request, $id) public function updateAction(Request $request, $id)
{ {
@@ -167,12 +136,50 @@ class ActivityReasonController extends AbstractController
if ($editForm->isValid()) { if ($editForm->isValid()) {
$em->flush(); $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( return $this->render('ChillActivityBundle:ActivityReason:edit.html.twig', [
'entity' => $entity, 'entity' => $entity,
'edit_form' => $editForm->createView() '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 <?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; namespace Chill\ActivityBundle\Controller;
use Chill\MainBundle\CRUD\Controller\CRUDController; use Chill\MainBundle\CRUD\Controller\CRUDController;
@@ -9,10 +16,8 @@ use Symfony\Component\HttpFoundation\Request;
class AdminActivityPresenceController extends CRUDController class AdminActivityPresenceController extends CRUDController
{ {
/** /**
* @param string $action
* @param \Doctrine\ORM\QueryBuilder|mixed $query * @param \Doctrine\ORM\QueryBuilder|mixed $query
* @param Request $request *
* @param PaginatorInterface $paginator
* @return \Doctrine\ORM\QueryBuilder|mixed * @return \Doctrine\ORM\QueryBuilder|mixed
*/ */
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator) protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)

View File

@@ -1,5 +1,12 @@
<?php <?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; namespace Chill\ActivityBundle\Controller;
use Chill\MainBundle\CRUD\Controller\CRUDController; use Chill\MainBundle\CRUD\Controller\CRUDController;
@@ -9,10 +16,8 @@ use Symfony\Component\HttpFoundation\Request;
class AdminActivityTypeCategoryController extends CRUDController class AdminActivityTypeCategoryController extends CRUDController
{ {
/** /**
* @param string $action
* @param \Doctrine\ORM\QueryBuilder|mixed $query * @param \Doctrine\ORM\QueryBuilder|mixed $query
* @param Request $request *
* @param PaginatorInterface $paginator
* @return \Doctrine\ORM\QueryBuilder|mixed * @return \Doctrine\ORM\QueryBuilder|mixed
*/ */
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator) protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)

View File

@@ -1,5 +1,12 @@
<?php <?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; namespace Chill\ActivityBundle\Controller;
use Chill\MainBundle\CRUD\Controller\CRUDController; use Chill\MainBundle\CRUD\Controller\CRUDController;
@@ -9,10 +16,8 @@ use Symfony\Component\HttpFoundation\Request;
class AdminActivityTypeController extends CRUDController class AdminActivityTypeController extends CRUDController
{ {
/** /**
* @param string $action
* @param \Doctrine\ORM\QueryBuilder|mixed $query * @param \Doctrine\ORM\QueryBuilder|mixed $query
* @param Request $request *
* @param PaginatorInterface $paginator
* @return \Doctrine\ORM\QueryBuilder|mixed * @return \Doctrine\ORM\QueryBuilder|mixed
*/ */
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator) protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)

View File

@@ -1,33 +1,18 @@
<?php <?php
/* /**
* Chill is a software for social workers * 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 * For the full copyright and license information, please view
* it under the terms of the GNU Affero General Public License as published by * the LICENSE file that was distributed with this source code.
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\Controller; namespace Chill\ActivityBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
/** /**
* Controller for activity configuration * Controller for activity configuration.
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @author Champs Libres <info@champs-libres.coop>
*/ */
class AdminController extends AbstractController class AdminController extends AbstractController
{ {

View File

@@ -1,48 +1,34 @@
<?php <?php
/* /**
* Chill is a software for social workers * Chill is a software for social workers
* *
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS, * For the full copyright and license information, please view
* <http://www.champs-libres.coop>, <info@champs-libres.coop> * the LICENSE file that was distributed with this source code.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\DataFixtures\ORM; 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 Chill\PersonBundle\Entity\Person;
use Doctrine\Common\DataFixtures\AbstractFixture; use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectManager;
use Faker\Factory as FakerFactory; 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 class LoadActivity extends AbstractFixture implements OrderedFixtureInterface
{ {
use \Symfony\Component\DependencyInjection\ContainerAwareTrait; use \Symfony\Component\DependencyInjection\ContainerAwareTrait;
private EntityManagerInterface $em;
/** /**
* @var \Faker\Generator * @var \Faker\Generator
*/ */
private $faker; private $faker;
private EntityManagerInterface $em;
public function __construct(EntityManagerInterface $em) public function __construct(EntityManagerInterface $em)
{ {
@@ -55,30 +41,53 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface
return 16400; return 16400;
} }
/** public function load(ObjectManager $manager)
* Return a random scope
*
* @return \Chill\MainBundle\Entity\Scope
*/
private function getRandomScope()
{ {
$scopeRef = LoadScopes::$references[array_rand(LoadScopes::$references)]; $persons = $this->em
return $this->getReference($scopeRef); ->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 a random activityReason.
*
* @return \Chill\ActivityBundle\Entity\ActivityType
*/
private function getRandomActivityType()
{
$typeRef = LoadActivityType::$references[array_rand(LoadActivityType::$references)];
return $this->getReference($typeRef);
}
/**
* Return a random activityReason
* *
* @return \Chill\ActivityBundle\Entity\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 * @return \Chill\MainBundle\Entity\User
*/ */
private function getRandomUser() private function getRandomUser()
{ {
$userRef = array_rand(LoadUsers::$refs); $userRef = array_rand(LoadUsers::$refs);
return $this->getReference($userRef); 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 <?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; namespace Chill\ActivityBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\DataFixtures\ORM\LoadAbstractNotificationsTrait; 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 class LoadActivityNotifications extends AbstractFixture implements DependentFixtureInterface
{ {
@@ -25,9 +31,9 @@ class LoadActivityNotifications extends AbstractFixture implements DependentFixt
'center a_social', 'center a_social',
'center a_administrative', 'center a_administrative',
'center a_direction', 'center a_direction',
'multi_center' 'multi_center',
], ],
] ],
]; ];
public function getDependencies() public function getDependencies()

View File

@@ -1,77 +1,62 @@
<?php <?php
/* /**
* Chill is a software for social workers * Chill is a software for social workers
* *
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS, * For the full copyright and license information, please view
* <http://www.champs-libres.coop>, <info@champs-libres.coop> * the LICENSE file that was distributed with this source code.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\DataFixtures\ORM; namespace Chill\ActivityBundle\DataFixtures\ORM;
use Chill\ActivityBundle\Entity\ActivityReason;
use Doctrine\Common\DataFixtures\AbstractFixture; use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectManager;
use Chill\ActivityBundle\Entity\ActivityReason;
/** /**
* Description of LoadActivityReason * Description of LoadActivityReason.
*
* @author Champs-Libres Coop
*/ */
class LoadActivityReason extends AbstractFixture implements OrderedFixtureInterface class LoadActivityReason extends AbstractFixture implements OrderedFixtureInterface
{ {
public static $references = [];
public function getOrder() public function getOrder()
{ {
return 16300; return 16300;
} }
public static $references = array();
public function load(ObjectManager $manager) public function load(ObjectManager $manager)
{ {
$reasons = [ $reasons = [
[ [
'name' => ['fr' => 'Recherche logement', 'en' => 'Housing research', 'nl' => 'Woning zoektoch'], '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'], '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'], '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'], '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'], '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'], '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) { foreach ($reasons as $r) {
print "Creating activity reason : " . $r['name']['en'] . "\n"; echo 'Creating activity reason : ' . $r['name']['en'] . "\n";
$activityReason = (new ActivityReason()) $activityReason = (new ActivityReason())
->setName(($r['name'])) ->setName(($r['name']))
->setActive(true) ->setActive(true)
->setCategory($this->getReference($r['category'])); ->setCategory($this->getReference($r['category']));
$manager->persist($activityReason); $manager->persist($activityReason);
$reference = 'activity_reason_'.$r['name']['en']; $reference = 'activity_reason_' . $r['name']['en'];
$this->addReference($reference, $activityReason); $this->addReference($reference, $activityReason);
static::$references[] = $reference; static::$references[] = $reference;
} }

View File

@@ -1,35 +1,21 @@
<?php <?php
/* /**
* Chill is a software for social workers * Chill is a software for social workers
* *
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS, * For the full copyright and license information, please view
* <http://www.champs-libres.coop>, <info@champs-libres.coop> * the LICENSE file that was distributed with this source code.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\DataFixtures\ORM; namespace Chill\ActivityBundle\DataFixtures\ORM;
use Chill\ActivityBundle\Entity\ActivityReasonCategory;
use Doctrine\Common\DataFixtures\AbstractFixture; use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectManager;
use Chill\ActivityBundle\Entity\ActivityReasonCategory;
/** /**
* Description of LoadActivityReasonCategory * Description of LoadActivityReasonCategory.
*
* @author Champs-Libres Coop
*/ */
class LoadActivityReasonCategory extends AbstractFixture implements OrderedFixtureInterface class LoadActivityReasonCategory extends AbstractFixture implements OrderedFixtureInterface
{ {
@@ -41,21 +27,20 @@ class LoadActivityReasonCategory extends AbstractFixture implements OrderedFixtu
public function load(ObjectManager $manager) public function load(ObjectManager $manager)
{ {
$categs = [ $categs = [
['name' => ['name' => ['fr' => 'Logement', 'en' => 'Housing', 'nl' => 'Woning']],
['fr' => 'Logement', 'en' => 'Housing', 'nl' => 'Woning']], ['name' => ['fr' => 'Démarches chômage', 'en' => 'Unemployment procedure', 'nl' => 'Werkloosheid werkwijze']],
['name' =>
['fr' => 'Démarches chômage', 'en' => 'Unemployment procedure', 'nl' => 'Werkloosheid werkwijze']],
]; ];
foreach ($categs as $c) { 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()) $activityReasonCategory = (new ActivityReasonCategory())
->setName(($c['name'])) ->setName(($c['name']))
->setActive(true); ->setActive(true);
$manager->persist($activityReasonCategory); $manager->persist($activityReasonCategory);
$this->addReference( $this->addReference(
'cat_'.$c['name']['en'], 'cat_' . $c['name']['en'],
$activityReasonCategory); $activityReasonCategory
);
} }
$manager->flush(); $manager->flush();

View File

@@ -1,86 +1,65 @@
<?php <?php
/* /**
* Chill is a software for social workers * Chill is a software for social workers
* *
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS, * For the full copyright and license information, please view
* <http://www.champs-libres.coop>, <info@champs-libres.coop> * the LICENSE file that was distributed with this source code.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\DataFixtures\ORM; namespace Chill\ActivityBundle\DataFixtures\ORM;
use Chill\ActivityBundle\Entity\ActivityType;
use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectManager;
use Chill\ActivityBundle\Entity\ActivityType;
/** /**
* Description of LoadActivityType * Description of LoadActivityType.
*
* @author Champs-Libres Coop
*/ */
class LoadActivityType extends Fixture implements OrderedFixtureInterface class LoadActivityType extends Fixture implements OrderedFixtureInterface
{ {
public static $references = [];
public function getOrder() public function getOrder()
{ {
return 16100; return 16100;
} }
public static $references = array();
public function load(ObjectManager $manager) public function load(ObjectManager $manager)
{ {
$types = [ $types = [
# Exange // Exange
[ [
'name' => 'name' => ['fr' => 'Entretien physique avec l\'usager'],
['fr' => 'Entretien physique avec l\'usager'], 'category' => 'exchange', ],
'category' => 'exchange' ],
[ [
'name' => 'name' => ['fr' => 'Appel téléphonique', 'en' => 'Telephone call', 'nl' => 'Telefoon appel'],
['fr' => 'Appel téléphonique', 'en' => 'Telephone call', 'nl' => 'Telefoon appel'], 'category' => 'exchange', ],
'category' => 'exchange' ],
[ [
'name' => 'name' => ['fr' => 'Courriel', 'en' => 'Email', 'nl' => 'Email'],
['fr' => 'Courriel', 'en' => 'Email', 'nl' => 'Email'], 'category' => 'exchange', ],
'category' => 'exchange' ], // Meeting
# Meeting
[ [
'name' => 'name' => ['fr' => 'Point technique encadrant'],
['fr' => 'Point technique encadrant'], 'category' => 'meeting', ],
'category' => 'meeting' ],
[ [
'name' => 'name' => ['fr' => 'Réunion avec des partenaires'],
['fr' => 'Réunion avec des partenaires'], 'category' => 'meeting', ],
'category' => 'meeting' ],
[ [
'name' => 'name' => ['fr' => 'Commission pluridisciplinaire et pluri-institutionnelle'],
['fr' => 'Commission pluridisciplinaire et pluri-institutionnelle'], 'category' => 'meeting', ],
'category' => 'meeting' ],
]; ];
foreach ($types as $t) { 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()) $activityType = (new ActivityType())
->setName(($t['name'])) ->setName(($t['name']))
->setCategory($this->getReference('activity_type_cat_'.$t['category'])) ->setCategory($this->getReference('activity_type_cat_' . $t['category']))
->setSocialIssuesVisible(1) ->setSocialIssuesVisible(1)
->setSocialActionsVisible(1); ->setSocialActionsVisible(1);
$manager->persist($activityType); $manager->persist($activityType);
$reference = 'activity_type_'.$t['name']['fr']; $reference = 'activity_type_' . $t['name']['fr'];
$this->addReference($reference, $activityType); $this->addReference($reference, $activityType);
static::$references[] = $reference; static::$references[] = $reference;
} }

View File

@@ -1,40 +1,25 @@
<?php <?php
/* /**
* Chill is a software for social workers * Chill is a software for social workers
* *
* Copyright (C) 2014-2021, Champs Libres Cooperative SCRLFS, * For the full copyright and license information, please view
* <http://www.champs-libres.coop>, <info@champs-libres.coop> * the LICENSE file that was distributed with this source code.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\DataFixtures\ORM; namespace Chill\ActivityBundle\DataFixtures\ORM;
use Chill\ActivityBundle\Entity\ActivityTypeCategory;
use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectManager;
use Chill\ActivityBundle\Entity\ActivityTypeCategory;
/** /**
* Fixtures for ActivityTypeCategory * Fixtures for ActivityTypeCategory.
*
* @author Champs-Libres Coop
*/ */
class LoadActivityTypeCategory extends Fixture implements OrderedFixtureInterface class LoadActivityTypeCategory extends Fixture implements OrderedFixtureInterface
{ {
public static $references = array(); public static $references = [];
public function getOrder() public function getOrder()
{ {
@@ -55,13 +40,13 @@ class LoadActivityTypeCategory extends Fixture implements OrderedFixtureInterfac
]; ];
foreach ($categories as $cat) { foreach ($categories as $cat) {
print "Creating activity type category : " . $cat['ref'] . "\n"; echo 'Creating activity type category : ' . $cat['ref'] . "\n";
$newCat = (new ActivityTypeCategory()) $newCat = (new ActivityTypeCategory())
->setName(($cat['name'])); ->setName(($cat['name']));
$manager->persist($newCat); $manager->persist($newCat);
$reference = 'activity_type_cat_'.$cat['ref']; $reference = 'activity_type_cat_' . $cat['ref'];
$this->addReference($reference, $newCat); $this->addReference($reference, $newCat);
static::$references[] = $reference; static::$references[] = $reference;

View File

@@ -1,37 +1,26 @@
<?php <?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 * For the full copyright and license information, please view
* it under the terms of the GNU Affero General Public License as published by * the LICENSE file that was distributed with this source code.
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\DataFixtures\ORM; 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\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager; 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, * Add a role CHILL_ACTIVITY_UPDATE & CHILL_ACTIVITY_CREATE for all groups except administrative,
* and a role CHILL_ACTIVITY_SEE for administrative * and a role CHILL_ACTIVITY_SEE for administrative.
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/ */
class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterface class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterface
{ {
@@ -40,12 +29,12 @@ class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterfac
return 16000; return 16000;
} }
public function load(ObjectManager $manager) public function load(ObjectManager $manager)
{ {
foreach (LoadPermissionsGroup::$refs as $permissionsGroupRef) { foreach (LoadPermissionsGroup::$refs as $permissionsGroupRef) {
$permissionsGroup = $this->getReference($permissionsGroupRef); $permissionsGroup = $this->getReference($permissionsGroupRef);
foreach (LoadScopes::$references as $scopeRef){
foreach (LoadScopes::$references as $scopeRef) {
$scope = $this->getReference($scopeRef); $scope = $this->getReference($scopeRef);
//create permission group //create permission group
switch ($permissionsGroup->getName()) { switch ($permissionsGroup->getName()) {
@@ -53,47 +42,52 @@ class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterfac
if ($scope->getName()['en'] === 'administrative') { if ($scope->getName()['en'] === 'administrative') {
break 2; // we do not want any power on administrative break 2; // we do not want any power on administrative
} }
break; break;
case 'administrative': case 'administrative':
case 'direction': 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 2; // we do not want any power on social or administrative
} }
break; 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", . "permission group, scope '%s' \n",
$permissionsGroup->getName(), $scope->getName()['en']); $permissionsGroup->getName(),
$scope->getName()['en']
);
$roleScopeUpdate = (new RoleScope()) $roleScopeUpdate = (new RoleScope())
->setRole('CHILL_ACTIVITY_UPDATE') ->setRole('CHILL_ACTIVITY_UPDATE')
->setScope($scope); ->setScope($scope);
$permissionsGroup->addRoleScope($roleScopeUpdate); $permissionsGroup->addRoleScope($roleScopeUpdate);
$roleScopeCreate = (new RoleScope()) $roleScopeCreate = (new RoleScope())
->setRole('CHILL_ACTIVITY_CREATE') ->setRole(ActivityVoter::CREATE_ACCOMPANYING_COURSE)
->setScope($scope); ->setScope($scope);
$roleScopeCreate = (new RoleScope())
->setRole(ActivityVoter::CREATE_PERSON)
->setScope($scope);
$permissionsGroup->addRoleScope($roleScopeCreate); $permissionsGroup->addRoleScope($roleScopeCreate);
$roleScopeDelete = (new RoleScope()) $roleScopeDelete = (new RoleScope())
->setRole('CHILL_ACTIVITY_DELETE') ->setRole('CHILL_ACTIVITY_DELETE')
->setScope($scope); ->setScope($scope);
$permissionsGroup->addRoleScope($roleScopeDelete); $permissionsGroup->addRoleScope($roleScopeDelete);
$roleScopeList = (new RoleScope()) $roleScopeList = (new RoleScope())
->setRole(ActivityStatsVoter::LISTS) ->setRole(ActivityStatsVoter::LISTS);
;
$permissionsGroup->addRoleScope($roleScopeList); $permissionsGroup->addRoleScope($roleScopeList);
$roleScopeStat = (new RoleScope()) $roleScopeStat = (new RoleScope())
->setRole(ActivityStatsVoter::STATS) ->setRole(ActivityStatsVoter::STATS);
;
$permissionsGroup->addRoleScope($roleScopeStat); $permissionsGroup->addRoleScope($roleScopeStat);
$manager->persist($roleScopeUpdate); $manager->persist($roleScopeUpdate);
$manager->persist($roleScopeCreate); $manager->persist($roleScopeCreate);
$manager->persist($roleScopeDelete); $manager->persist($roleScopeDelete);
} }
} }
$manager->flush(); $manager->flush();
} }
} }

View File

@@ -1,45 +1,28 @@
<?php <?php
/* /**
* Chill is a software for social workers * Chill is a software for social workers
* *
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS, * For the full copyright and license information, please view
* <http://www.champs-libres.coop>, <info@champs-libres.coop> * the LICENSE file that was distributed with this source code.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\DependencyInjection; 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 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} * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
*/ */
class ChillActivityExtension extends Extension implements PrependExtensionInterface class ChillActivityExtension extends Extension implements PrependExtensionInterface
{ {
/**
* {@inheritdoc}
*/
public function load(array $configs, ContainerBuilder $container) public function load(array $configs, ContainerBuilder $container)
{ {
$configuration = new Configuration(); $configuration = new Configuration();
@@ -47,7 +30,7 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
$container->setParameter('chill_activity.form.time_duration', $config['form']['time_duration']); $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.yaml');
$loader->load('services/export.yaml'); $loader->load('services/export.yaml');
$loader->load('services/repositories.yaml'); $loader->load('services/repositories.yaml');
@@ -65,33 +48,38 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
$this->prependCruds($container); $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) /* (non-PHPdoc)
* @see \Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface::prepend() * @see \Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface::prepend()
*/ */
public function prependRoutes(ContainerBuilder $container) public function prependRoutes(ContainerBuilder $container)
{ {
//add routes for custom bundle //add routes for custom bundle
$container->prependExtensionConfig('chill_main', array( $container->prependExtensionConfig('chill_main', [
'routing' => array( 'routing' => [
'resources' => array( 'resources' => [
'@ChillActivityBundle/config/routes.yaml' '@ChillActivityBundle/config/routes.yaml',
) ],
) ],
)); ]);
}
public function prependAuthorization(ContainerBuilder $container)
{
$container->prependExtensionConfig('security', array(
'role_hierarchy' => array(
ActivityVoter::UPDATE => array(ActivityVoter::SEE_DETAILS),
ActivityVoter::CREATE => array(ActivityVoter::SEE_DETAILS),
ActivityVoter::DELETE => array(ActivityVoter::SEE_DETAILS),
ActivityVoter::SEE_DETAILS => array(ActivityVoter::SEE),
ActivityVoter::FULL => [ActivityVoter::CREATE, ActivityVoter::DELETE,
ActivityVoter::UPDATE],
)
));
} }
protected function prependCruds(ContainerBuilder $container) protected function prependCruds(ContainerBuilder $container)
@@ -107,17 +95,17 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
'actions' => [ 'actions' => [
'index' => [ 'index' => [
'template' => '@ChillActivity/ActivityType/index.html.twig', 'template' => '@ChillActivity/ActivityType/index.html.twig',
'role' => 'ROLE_ADMIN' 'role' => 'ROLE_ADMIN',
], ],
'new' => [ 'new' => [
'role' => 'ROLE_ADMIN', 'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityType/new.html.twig', 'template' => '@ChillActivity/ActivityType/new.html.twig',
], ],
'edit' => [ 'edit' => [
'role' => 'ROLE_ADMIN', 'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityType/edit.html.twig', 'template' => '@ChillActivity/ActivityType/edit.html.twig',
] ],
] ],
], ],
[ [
'class' => \Chill\ActivityBundle\Entity\ActivityTypeCategory::class, 'class' => \Chill\ActivityBundle\Entity\ActivityTypeCategory::class,
@@ -128,17 +116,17 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
'actions' => [ 'actions' => [
'index' => [ 'index' => [
'template' => '@ChillActivity/ActivityTypeCategory/index.html.twig', 'template' => '@ChillActivity/ActivityTypeCategory/index.html.twig',
'role' => 'ROLE_ADMIN' 'role' => 'ROLE_ADMIN',
], ],
'new' => [ 'new' => [
'role' => 'ROLE_ADMIN', 'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityTypeCategory/new.html.twig', 'template' => '@ChillActivity/ActivityTypeCategory/new.html.twig',
], ],
'edit' => [ 'edit' => [
'role' => 'ROLE_ADMIN', 'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityTypeCategory/edit.html.twig', 'template' => '@ChillActivity/ActivityTypeCategory/edit.html.twig',
] ],
] ],
], ],
[ [
'class' => \Chill\ActivityBundle\Entity\ActivityPresence::class, 'class' => \Chill\ActivityBundle\Entity\ActivityPresence::class,
@@ -149,19 +137,19 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
'actions' => [ 'actions' => [
'index' => [ 'index' => [
'template' => '@ChillActivity/ActivityPresence/index.html.twig', 'template' => '@ChillActivity/ActivityPresence/index.html.twig',
'role' => 'ROLE_ADMIN' 'role' => 'ROLE_ADMIN',
], ],
'new' => [ 'new' => [
'role' => 'ROLE_ADMIN', 'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityPresence/new.html.twig', 'template' => '@ChillActivity/ActivityPresence/new.html.twig',
], ],
'edit' => [ 'edit' => [
'role' => 'ROLE_ADMIN', 'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityPresence/edit.html.twig', 'template' => '@ChillActivity/ActivityPresence/edit.html.twig',
] ],
] ],
], ],
] ],
]); ]);
} }
} }

View File

@@ -1,69 +1,71 @@
<?php <?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; namespace Chill\ActivityBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface; 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} * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
*/ */
class Configuration implements ConfigurationInterface class Configuration implements ConfigurationInterface
{ {
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder() public function getConfigTreeBuilder()
{ {
$treeBuilder = new TreeBuilder('chill_activity'); $treeBuilder = new TreeBuilder('chill_activity');
$rootNode = $treeBuilder->getRootNode('chill_activity'); $rootNode = $treeBuilder->getRootNode('chill_activity');
$rootNode $rootNode
->children() ->children()
->arrayNode('form') ->arrayNode('form')
->canBeEnabled() ->canBeEnabled()
->children() ->children()
->arrayNode('time_duration') ->arrayNode('time_duration')
->isRequired() ->isRequired()
->requiresAtLeastOneElement() ->requiresAtLeastOneElement()
->defaultValue( ->defaultValue(
array( [
[ 'label' => '5 minutes', 'seconds' => 300], ['label' => '5 minutes', 'seconds' => 300],
[ 'label' => '10 minutes', 'seconds' => 600], ['label' => '10 minutes', 'seconds' => 600],
[ 'label' => '15 minutes', 'seconds' => 900], ['label' => '15 minutes', 'seconds' => 900],
[ 'label' => '20 minutes', 'seconds' => 1200], ['label' => '20 minutes', 'seconds' => 1200],
[ 'label' => '25 minutes', 'seconds' => 1500], ['label' => '25 minutes', 'seconds' => 1500],
[ 'label' => '30 minutes', 'seconds' => 1800], ['label' => '30 minutes', 'seconds' => 1800],
[ 'label' => '45 minutes', 'seconds' => 2700], ['label' => '45 minutes', 'seconds' => 2700],
[ 'label' => '1 hour', 'seconds' => 3600], ['label' => '1 hour', 'seconds' => 3600],
[ 'label' => '1 hour 15', 'seconds' => 4500], ['label' => '1 hour 15', 'seconds' => 4500],
[ 'label' => '1 hour 30', 'seconds' => 5400], ['label' => '1 hour 30', 'seconds' => 5400],
[ 'label' => '1 hour 45', 'seconds' => 6300], ['label' => '1 hour 45', 'seconds' => 6300],
[ 'label' => '2 hours', 'seconds' => 7200], ['label' => '2 hours', 'seconds' => 7200],
) ]
) )
->info('The intervals of time to show in activity form') ->info('The intervals of time to show in activity form')
->prototype('array')
->prototype('array') ->children()
->children() ->scalarNode('seconds')
->scalarNode('seconds') ->info('The number of seconds of this duration. Must be an integer.')
->info("The number of seconds of this duration. Must be an integer.") ->cannotBeEmpty()
->cannotBeEmpty() ->validate()
->validate() ->ifTrue(function ($data) {
->ifTrue(function($data) { return !is_int($data);
return !is_int($data); })->thenInvalid('The value %s is not a valid integer')
})->thenInvalid("The value %s is not a valid integer") ->end()
->end() ->end()
->end() ->scalarNode('label')
->scalarNode('label') ->cannotBeEmpty()
->cannotBeEmpty() ->info('The label to show into fields')
->info("The label to show into fields") ->end()
->end() ->end()
->end() ->end()
->end()
// ->validate() // ->validate()
// //
// ->ifTrue(function ($data) { // ->ifTrue(function ($data) {
@@ -84,11 +86,10 @@ class Configuration implements ConfigurationInterface
// }) // })
// ->thenInvalid("The data are invalid. The keys must be a string and the value integers") // ->thenInvalid("The data are invalid. The keys must be a string and the value integers")
// ->end() // ->end()
->end() ->end()
->end() ->end()
->end()
->end() ->end();
->end();
return $treeBuilder; return $treeBuilder;
} }

View File

@@ -1,38 +1,46 @@
<?php <?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; namespace Chill\ActivityBundle\Entity;
use Chill\DocStoreBundle\Entity\Document; use Chill\DocStoreBundle\Entity\Document;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable; 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\Location;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User;
use Chill\PersonBundle\AccompanyingPeriod\SocialIssueConsistency\AccompanyingPeriodLinkedWithSocialIssuesEntityInterface; use Chill\PersonBundle\AccompanyingPeriod\SocialIssueConsistency\AccompanyingPeriodLinkedWithSocialIssuesEntityInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\SocialWork\SocialAction; use Chill\PersonBundle\Entity\SocialWork\SocialAction;
use Chill\PersonBundle\Entity\SocialWork\SocialIssue; use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
use Chill\ThirdPartyBundle\Entity\ThirdParty; use Chill\ThirdPartyBundle\Entity\ThirdParty;
use Doctrine\ORM\Mapping as ORM; use DateTime;
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 Doctrine\Common\Collections\ArrayCollection; 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\Security\Core\User\UserInterface;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\DiscriminatorMap; 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\Entity(repositoryClass="Chill\ActivityBundle\Repository\ActivityRepository")
* @ORM\Table(name="activity") * @ORM\Table(name="activity")
* @ORM\HasLifecycleCallbacks() * @ORM\HasLifecycleCallbacks
* @DiscriminatorMap(typeProperty="type", mapping={ * @DiscriminatorMap(typeProperty="type", mapping={
* "activity"=Activity::class * "activity": Activity::class
* }) * })
*/ */
/* /*
@@ -45,8 +53,53 @@ use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPeriodLinkedWithSocialIssuesEntityInterface class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPeriodLinkedWithSocialIssuesEntityInterface
{ {
const SENTRECEIVED_SENT = 'sent'; public const SENTRECEIVED_RECEIVED = 'received';
const SENTRECEIVED_RECEIVED = 'received';
public const SENTRECEIVED_SENT = 'sent';
/**
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod")
* @Groups({"read"})
*/
private ?AccompanyingPeriod $accompanyingPeriod = null;
/**
* @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityType")
* @Groups({"read"})
* @SerializedName("activityType")
* @ORM\JoinColumn(name="type_id")
*/
private ActivityType $activityType;
/**
* @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityPresence")
*/
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\Id
@@ -57,29 +110,21 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
private ?int $id = null; private ?int $id = null;
/** /**
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User") * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Location")
* @groups({"read"})
*/ */
private User $user; private ?Location $location = null;
/** /**
* @ORM\Column(type="datetime") * @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\Person")
*/ */
private \DateTime $date; private ?Person $person = null;
/** /**
* @ORM\Column(type="time", nullable=true) * @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\Person")
* @Groups({"read"})
*/ */
private ?\DateTime $durationTime = null; private ?Collection $persons = 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") * @ORM\ManyToMany(targetEntity="Chill\ActivityBundle\Entity\ActivityReason")
@@ -87,11 +132,14 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
private Collection $reasons; private Collection $reasons;
/** /**
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialIssue") * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Scope")
* @ORM\JoinTable(name="chill_activity_activity_chill_person_socialissue")
* @Groups({"read"})
*/ */
private Collection $socialIssues; private ?Scope $scope = null;
/**
* @ORM\Column(type="string", options={"default": ""})
*/
private string $sentReceived = '';
/** /**
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialAction") * @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialAction")
@@ -101,36 +149,11 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
private Collection $socialActions; private Collection $socialActions;
/** /**
* @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityType") * @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialIssue")
*/ * @ORM\JoinTable(name="chill_activity_activity_chill_person_socialissue")
private ActivityType $type;
/**
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Scope")
*/
private ?Scope $scope = null;
/**
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\Person")
*/
private ?Person $person = null;
/**
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod")
* @Groups({"read"}) * @Groups({"read"})
*/ */
private ?AccompanyingPeriod $accompanyingPeriod = null; private Collection $socialIssues;
/**
* @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\CommentEmbeddable", columnPrefix="comment_")
*/
private CommentEmbeddable $comment;
/**
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\Person")
* @Groups({"read"})
*/
private ?Collection $persons = null;
/** /**
* @ORM\ManyToMany(targetEntity="Chill\ThirdPartyBundle\Entity\ThirdParty") * @ORM\ManyToMany(targetEntity="Chill\ThirdPartyBundle\Entity\ThirdParty")
@@ -139,9 +162,14 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
private ?Collection $thirdParties = null; 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") * @ORM\ManyToMany(targetEntity="Chill\MainBundle\Entity\User")
@@ -149,23 +177,6 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
*/ */
private ?Collection $users = null; 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() public function __construct()
{ {
$this->reasons = new ArrayCollection(); $this->reasons = new ArrayCollection();
@@ -178,71 +189,25 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
$this->socialActions = new ArrayCollection(); $this->socialActions = new ArrayCollection();
} }
public function getId(): ?int public function addDocument(Document $document): self
{ {
return $this->id; $this->documents[] = $document;
}
public function setUser(UserInterface $user): self
{
$this->user = $user;
return $this; return $this;
} }
public function getUser(): User /**
* Add a person to the person list.
*/
public function addPerson(?Person $person): self
{ {
return $this->user; if (null !== $person) {
} $this->persons[] = $person;
}
public function setDate(\DateTime $date): self
{
$this->date = $date;
return $this; 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 public function addReason(ActivityReason $reason): self
{ {
$this->reasons->add($reason); $this->reasons->add($reason);
@@ -250,49 +215,6 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
return $this; 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 public function addSocialAction(SocialAction $socialAction): self
{ {
if (!$this->socialActions->contains($socialAction)) { if (!$this->socialActions->contains($socialAction)) {
@@ -302,67 +224,51 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
return $this; 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; return $this;
} }
public function addThirdParty(?ThirdParty $thirdParty): self
public function setType(ActivityType $type): self
{ {
$this->type = $type; if (null !== $thirdParty) {
$this->thirdParties[] = $thirdParty;
}
return $this; return $this;
} }
public function getType(): ActivityType public function addUser(?User $user): self
{ {
return $this->type; if (null !== $user) {
} $this->users[] = $user;
}
public function setScope(Scope $scope): self
{
$this->scope = $scope;
return $this; 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 public function getAccompanyingPeriod(): ?AccompanyingPeriod
{ {
return $this->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 * get the center
* center is extracted from person * center is extracted from person.
*/ */
public function getCenter(): ?Center public function getCenter(): ?Center
{ {
@@ -378,28 +284,39 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
return $this->comment; return $this->comment;
} }
public function setComment(CommentEmbeddable $comment): self public function getDate(): DateTime
{ {
$this->comment = $comment; return $this->date;
return $this;
} }
/** public function getDocuments(): Collection
* Add a person to the person list
*/
public function addPerson(?Person $person): self
{ {
if (null !== $person) { return $this->documents;
$this->persons[] = $person;
}
return $this;
} }
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 public function getPersons(): Collection
@@ -411,13 +328,16 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
{ {
if (null !== $this->accompanyingPeriod) { if (null !== $this->accompanyingPeriod) {
$personsAssociated = []; $personsAssociated = [];
foreach ($this->accompanyingPeriod->getParticipations() as $participation) { foreach ($this->accompanyingPeriod->getParticipations() as $participation) {
if ($this->persons->contains($participation->getPerson())) { if ($this->persons->contains($participation->getPerson())) {
$personsAssociated[] = $participation->getPerson(); $personsAssociated[] = $participation->getPerson();
} }
} }
return $personsAssociated; return $personsAssociated;
} }
return []; return [];
} }
@@ -425,28 +345,103 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
{ {
if (null !== $this->accompanyingPeriod) { if (null !== $this->accompanyingPeriod) {
$personsNotAssociated = []; $personsNotAssociated = [];
foreach ($this->persons as $person) { foreach ($this->persons as $person) {
if (!in_array($person, $this->getPersonsAssociated())) { if (!in_array($person, $this->getPersonsAssociated())) {
$personsNotAssociated[] = $person; $personsNotAssociated[] = $person;
} }
} }
return $personsNotAssociated; return $personsNotAssociated;
} }
return []; 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; return $this;
} }
public function addThirdParty(?ThirdParty $thirdParty): self public function removeSocialIssue(SocialIssue $socialIssue): self
{ {
if (null !== $thirdParty) { $this->socialIssues->removeElement($socialIssue);
$this->thirdParties[] = $thirdParty;
}
return $this; return $this;
} }
@@ -455,33 +450,44 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
$this->thirdParties->removeElement($thirdParty); $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; return $this;
} }
public function addDocument(Document $document): self public function setActivityType(ActivityType $activityType): self
{ {
$this->documents[] = $document; $this->activityType = $activityType;
return $this; 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 public function setDocuments(Collection $documents): self
@@ -491,41 +497,13 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
return $this; return $this;
} }
public function addUser(?User $user): self public function setDurationTime(?DateTime $durationTime): self
{ {
if (null !== $user) { $this->durationTime = $durationTime;
$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;
return $this; return $this;
} }
public function isEmergency(): bool
{
return $this->getEmergency();
}
public function getEmergency(): bool
{
return $this->emergency;
}
public function setEmergency(bool $emergency): self public function setEmergency(bool $emergency): self
{ {
$this->emergency = $emergency; $this->emergency = $emergency;
@@ -533,9 +511,39 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
return $this; 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 public function setSentReceived(?string $sentReceived): self
@@ -545,21 +553,41 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
return $this; return $this;
} }
/** public function setThirdParties(?Collection $thirdParties): self
* @return Location|null
*/
public function getLocation(): ?Location
{ {
return $this->location; $this->thirdParties = $thirdParties;
return $this;
}
public function setTravelTime(DateTime $travelTime): self
{
$this->travelTime = $travelTime;
return $this;
} }
/** /**
* @param Location|null $location * @deprecated
* @return Activity
*/ */
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; return $this;
} }
} }

View File

@@ -1,21 +1,10 @@
<?php <?php
/* /**
* Chill is a software for social workers
* *
* Copyright (C) 2015, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop> * For the full copyright and license information, please view
* * the LICENSE file that was distributed with this source code.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\Entity; namespace Chill\ActivityBundle\Entity;
@@ -23,15 +12,19 @@ namespace Chill\ActivityBundle\Entity;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
/** /**
* Class ActivityPresence * Class ActivityPresence.
* *
* @package Chill\ActivityBundle\Entity * @ORM\Entity
* @ORM\Entity()
* @ORM\Table(name="activitytpresence") * @ORM\Table(name="activitytpresence")
* @ORM\HasLifecycleCallbacks() * @ORM\HasLifecycleCallbacks
*/ */
class ActivityPresence class ActivityPresence
{ {
/**
* @ORM\Column(type="boolean")
*/
private bool $active = true;
/** /**
* @ORM\Id * @ORM\Id
* @ORM\Column(name="id", type="integer") * @ORM\Column(name="id", type="integer")
@@ -44,28 +37,6 @@ class ActivityPresence
*/ */
private array $name = []; 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 * Get active
* return true if the category type is active. * return true if the category type is active.
@@ -75,9 +46,19 @@ class ActivityPresence
return $this->active; return $this->active;
} }
public function getId(): int
{
return $this->id;
}
public function getName(): array
{
return $this->name;
}
/** /**
* Is active * Is active
* return true if the category type is active * return true if the category type is active.
*/ */
public function isActive(): bool public function isActive(): bool
{ {
@@ -86,7 +67,7 @@ class ActivityPresence
/** /**
* Set active * 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 public function setActive(bool $active): self
{ {
@@ -94,4 +75,11 @@ class ActivityPresence
return $this; return $this;
} }
public function setName(array $name): self
{
$this->name = $name;
return $this;
}
} }

View File

@@ -1,40 +1,41 @@
<?php <?php
/* /**
* Chill is a software for social workers
* *
* Copyright (C) 2015, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop> * For the full copyright and license information, please view
* * the LICENSE file that was distributed with this source code.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\Entity; namespace Chill\ActivityBundle\Entity;
use Doctrine\ORM\Mapping as ORM; 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\Table(name="activityreason")
* @ORM\HasLifecycleCallbacks() * @ORM\HasLifecycleCallbacks
*/ */
class ActivityReason 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\Id
* @ORM\Column(name="id", type="integer") * @ORM\Column(name="id", type="integer")
@@ -49,86 +50,17 @@ class ActivityReason
private $name; private $name;
/** /**
* @var ActivityReasonCategory * Get active.
* @ORM\ManyToOne(
* targetEntity="Chill\ActivityBundle\Entity\ActivityReasonCategory",
* inversedBy="reasons")
*/
private $category;
/**
* @var boolean
* @ORM\Column(type="boolean")
*/
private $active = true;
/**
* Get id
* *
* @return integer * @return bool
*/ */
public function getId() public function getActive()
{ {
return $this->id; return $this->active;
} }
/** /**
* Set name * Get category.
*
* @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
* *
* @return ActivityReasonCategory * @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 * @return ActivityReason
*/ */
public function setActive($active) 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 <?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 * For the full copyright and license information, please view
* it under the terms of the GNU Affero General Public License as * the LICENSE file that was distributed with this source code.
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\Entity; namespace Chill\ActivityBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection; 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\Table(name="activityreasoncategory")
* @ORM\HasLifecycleCallbacks() * @ORM\HasLifecycleCallbacks
*/ */
class ActivityReasonCategory class ActivityReasonCategory
{ {
/** /**
* @var integer * @var bool
* @ORM\Column(type="boolean")
*/
private $active = true;
/**
* @var int
* *
* @ORM\Id * @ORM\Id
* @ORM\Column(name="id", type="integer") * @ORM\Column(name="id", type="integer")
@@ -48,17 +43,12 @@ class ActivityReasonCategory
private $name; private $name;
/** /**
* @var boolean * Array of ActivityReason.
* @ORM\Column(type="boolean") *
*/
private $active = true;
/**
* Array of ActivityReason
* @var ArrayCollection * @var ArrayCollection
* @ORM\OneToMany( * @ORM\OneToMany(
* targetEntity="Chill\ActivityBundle\Entity\ActivityReason", * targetEntity="Chill\ActivityBundle\Entity\ActivityReason",
* mappedBy="category") * mappedBy="category")
*/ */
private $reasons; private $reasons;
@@ -75,13 +65,23 @@ class ActivityReasonCategory
*/ */
public function __toString() 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() public function getId()
{ {
@@ -89,20 +89,9 @@ class ActivityReasonCategory
} }
/** /**
* Set name * Get name.
* *
* @param array $name * @param mixed|null $locale
* @return ActivityReasonCategory
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
* *
* @return array * @return array
*/ */
@@ -111,30 +100,32 @@ class ActivityReasonCategory
if ($locale) { if ($locale) {
if (isset($this->name[$locale])) { if (isset($this->name[$locale])) {
return $this->name[$locale]; return $this->name[$locale];
} else { }
foreach ($this->name as $name) {
if (!empty($name)) { foreach ($this->name as $name) {
return $name; if (!empty($name)) {
} return $name;
} }
} }
return ''; return '';
} else {
return $this->name;
} }
return $this->name;
} }
/** /**
* Declare a category as active (or not). When a category is set * Declare a category as active (or not). When a category is set
* as unactive, all the reason have this entity as category is also * 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 * @return ActivityReasonCategory
*/ */
public function setActive($active) public function setActive($active)
{ {
if($this->active !== $active && !$active) { if ($this->active !== $active && !$active) {
foreach ($this->reasons as $reason) { foreach ($this->reasons as $reason) {
$reason->setActive($active); $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 <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Entity; namespace Chill\ActivityBundle\Entity;
@@ -7,12 +14,17 @@ namespace Chill\ActivityBundle\Entity;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
/** /**
* @ORM\Entity() * @ORM\Entity
* @ORM\Table(name="activitytypecategory") * @ORM\Table(name="activitytypecategory")
* @ORM\HasLifecycleCallbacks() * @ORM\HasLifecycleCallbacks
*/ */
class ActivityTypeCategory class ActivityTypeCategory
{ {
/**
* @ORM\Column(type="boolean")
*/
private bool $active = true;
/** /**
* @ORM\Id * @ORM\Id
* @ORM\Column(name="id", type="integer") * @ORM\Column(name="id", type="integer")
@@ -26,38 +38,10 @@ class ActivityTypeCategory
private array $name = []; private array $name = [];
/** /**
* @ORM\Column(type="boolean") * @ORM\Column(type="float", options={"default": "0.0"})
*/
private bool $active = true;
/**
* @ORM\Column(type="float", options={"default"="0.0"})
*/ */
private float $ordering = 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 * Get active
* return true if the category type is active. * return true if the category type is active.
@@ -67,9 +51,27 @@ class ActivityTypeCategory
return $this->active; 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 * Is active
* return true if the category type is active * return true if the category type is active.
*/ */
public function isActive(): bool public function isActive(): bool
{ {
@@ -78,7 +80,7 @@ class ActivityTypeCategory
/** /**
* Set active * 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 public function setActive(bool $active): self
{ {
@@ -87,9 +89,14 @@ class ActivityTypeCategory
return $this; 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 public function setOrdering(float $ordering): self

View File

@@ -1,22 +1,30 @@
<?php <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator; namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Repository\ActivityReasonCategoryRepository; use Chill\ActivityBundle\Repository\ActivityReasonCategoryRepository;
use Chill\ActivityBundle\Repository\ActivityReasonRepository; 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\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\MainBundle\Export\AggregatorInterface;
use Doctrine\ORM\Query\Expr\Join;
use Chill\MainBundle\Export\ExportElementValidatedInterface; 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\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 class ActivityReasonAggregator implements AggregatorInterface, ExportElementValidatedInterface
{ {
@@ -36,42 +44,47 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
$this->translatableStringHelper = $translatableStringHelper; $this->translatableStringHelper = $translatableStringHelper;
} }
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
// add select element // add select element
if ($data['level'] === 'reasons') { if ('reasons' === $data['level']) {
$elem = 'reasons.id'; $elem = 'reasons.id';
$alias = 'activity_reasons_id'; $alias = 'activity_reasons_id';
} elseif ($data['level'] === 'categories') { } elseif ('categories' === $data['level']) {
$elem = 'category.id'; $elem = 'category.id';
$alias = 'activity_categories_id'; $alias = 'activity_categories_id';
} else { } 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 // make a jointure only if needed
$join = $qb->getDQLPart('join'); $join = $qb->getDQLPart('join');
if ( if (
(array_key_exists('activity', $join) (
&& array_key_exists('activity', $join)
!$this->checkJoinAlreadyDefined($join['activity'], 'reasons') && !$this->checkJoinAlreadyDefined($join['activity'], 'reasons')
) )
OR or (!array_key_exists('activity', $join))
(! array_key_exists('activity', $join))
) { ) {
$qb->add( $qb->add(
'join', 'join',
[ [
'activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons') 'activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons'),
], ],
true true
); );
} }
// join category if necessary // join category if necessary
if ($alias === 'activity_categories_id') { if ('activity_categories_id' === $alias) {
// add join only if needed // add join only if needed
if (!$this->checkJoinAlreadyDefined($qb->getDQLPart('join')['activity'], 'category')) { if (!$this->checkJoinAlreadyDefined($qb->getDQLPart('join')['activity'], 'category')) {
$qb->join('reasons.category', '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() public function applyOn()
{ {
return 'activity'; return 'activity';
@@ -118,52 +113,37 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
ChoiceType::class, ChoiceType::class,
[ [
'choices' => [ 'choices' => [
'By reason' => 'reasons', 'By reason' => 'reasons',
'By category of reason' => 'categories' 'By category of reason' => 'categories',
], ],
'multiple' => false, 'multiple' => false,
'expanded' => true, '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) public function getLabels($key, array $values, $data)
{ {
// for performance reason, we load data from db only once // for performance reason, we load data from db only once
switch ($data['level']) { switch ($data['level']) {
case 'reasons': case 'reasons':
$this->activityReasonRepository->findBy(['id' => $values]); $this->activityReasonRepository->findBy(['id' => $values]);
break; break;
case 'categories': case 'categories':
$this->activityReasonCategoryRepository->findBy(['id' => $values]); $this->activityReasonCategoryRepository->findBy(['id' => $values]);
break; break;
default: 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) { return function ($value) use ($data) {
if ($value === '_header') { if ('_header' === $value) {
return $data['level'] === 'reasons' ? 'Group by reasons' : 'Group by categories of reason'; return 'reasons' === $data['level'] ? 'Group by reasons' : 'Group by categories of reason';
} }
switch ($data['level']) { switch ($data['level']) {
@@ -171,32 +151,63 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
$r = $this->activityReasonRepository->find($value); $r = $this->activityReasonRepository->find($value);
return sprintf( return sprintf(
"%s > %s", '%s > %s',
$this->translatableStringHelper->localize($r->getCategory()->getName()), $this->translatableStringHelper->localize($r->getCategory()->getName()),
$this->translatableStringHelper->localize($r->getName()) $this->translatableStringHelper->localize($r->getName())
); );
case 'categories': case 'categories':
$c = $this->activityReasonCategoryRepository->find($value); $c = $this->activityReasonCategoryRepository->find($value);
return $this->translatableStringHelper->localize($c->getName()); return $this->translatableStringHelper->localize($c->getName());
} }
}; };
} }
public function getQueryKeys($data) public function getQueryKeys($data)
{ {
// add select element // add select element
if ($data['level'] === 'reasons') { if ('reasons' === $data['level']) {
return array('activity_reasons_id'); return ['activity_reasons_id'];
} }
if ($data['level'] === 'categories') { if ('categories' === $data['level']) {
return array ('activity_categories_id'); 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 <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator; namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Repository\ActivityTypeRepository; 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\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\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
class ActivityTypeAggregator implements AggregatorInterface class ActivityTypeAggregator implements AggregatorInterface
{ {
public const KEY = 'activity_type_aggregator';
protected ActivityTypeRepository $activityTypeRepository; protected ActivityTypeRepository $activityTypeRepository;
protected TranslatableStringHelperInterface $translatableStringHelper; protected TranslatableStringHelperInterface $translatableStringHelper;
public const KEY = 'activity_type_aggregator';
public function __construct( public function __construct(
ActivityTypeRepository $activityTypeRepository, ActivityTypeRepository $activityTypeRepository,
TranslatableStringHelperInterface $translatableStringHelper TranslatableStringHelperInterface $translatableStringHelper
@@ -29,6 +37,11 @@ class ActivityTypeAggregator implements AggregatorInterface
$this->translatableStringHelper = $translatableStringHelper; $this->translatableStringHelper = $translatableStringHelper;
} }
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
// add select element // add select element
@@ -38,24 +51,6 @@ class ActivityTypeAggregator implements AggregatorInterface
$qb->addGroupBy(self::KEY); $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() public function applyOn()
{ {
return 'activity'; return 'activity';
@@ -66,23 +61,13 @@ class ActivityTypeAggregator implements AggregatorInterface
// no form required for this aggregator // no form required for this aggregator
} }
public function getTitle() public function getLabels($key, array $values, $data): Closure
{
return 'Aggregate by activity type';
}
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function getLabels($key, array $values, $data): \Closure
{ {
// for performance reason, we load data from db only once // for performance reason, we load data from db only once
$this->activityTypeRepository->findBy(['id' => $values]); $this->activityTypeRepository->findBy(['id' => $values]);
return function($value): string { return function ($value): string {
if ($value === '_header') { if ('_header' === $value) {
return 'Activity type'; return 'Activity type';
} }
@@ -97,4 +82,27 @@ class ActivityTypeAggregator implements AggregatorInterface
return [self::KEY]; 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 <?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; 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\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 class ActivityUserAggregator implements AggregatorInterface
{ {
@@ -45,13 +53,13 @@ class ActivityUserAggregator implements AggregatorInterface
// nothing to add // nothing to add
} }
public function getLabels($key, $values, $data): \Closure public function getLabels($key, $values, $data): Closure
{ {
// preload users at once // preload users at once
$this->userRepository->findBy(['id' => $values]); $this->userRepository->findBy(['id' => $values]);
return function($value) { return function ($value) {
if ($value === '_header') { if ('_header' === $value) {
return 'activity user'; return 'activity user';
} }
@@ -61,7 +69,7 @@ class ActivityUserAggregator implements AggregatorInterface
public function getQueryKeys($data) public function getQueryKeys($data)
{ {
return [ self::KEY ]; return [self::KEY];
} }
public function getTitle(): string public function getTitle(): string

View File

@@ -1,16 +1,24 @@
<?php <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Export; namespace Chill\ActivityBundle\Export\Export;
use Chill\ActivityBundle\Repository\ActivityRepository; use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\FormatterInterface;
use Doctrine\ORM\Query;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\Role;
use Doctrine\ORM\Query;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
class CountActivity implements ExportInterface class CountActivity implements ExportInterface
{ {
@@ -24,7 +32,11 @@ class CountActivity implements ExportInterface
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)
{ {
}
public function getAllowedFormattersTypes()
{
return [FormatterInterface::TYPE_TABULAR];
} }
public function getDescription() public function getDescription()
@@ -32,6 +44,25 @@ class CountActivity implements ExportInterface
return 'Count activities by various parameters.'; 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() public function getTitle()
{ {
return 'Count activities'; return 'Count activities';
@@ -42,9 +73,9 @@ class CountActivity implements ExportInterface
return 'activity'; 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 $qb = $this
->activityRepository ->activityRepository
@@ -59,38 +90,13 @@ class CountActivity implements ExportInterface
return $qb; return $qb;
} }
public function supportsModifiers()
{
return ['person', 'activity'];
}
public function requiredRole() public function requiredRole()
{ {
return new Role(ActivityStatsVoter::STATS); 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 <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Export; namespace Chill\ActivityBundle\Export\Export;
use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\MainBundle\Export\ListInterface;
use Chill\ActivityBundle\Entity\ActivityReason; use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\ActivityBundle\Repository\ActivityRepository;
use Doctrine\DBAL\Exception\InvalidArgumentException;
use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter; 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\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\Translation\TranslatorInterface;
use Symfony\Component\Validator\Constraints\Callback; 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 Symfony\Component\Validator\Context\ExecutionContextInterface;
use function array_key_exists;
class ListActivity implements ListInterface class ListActivity implements ListInterface
{ {
private ActivityRepository $activityRepository;
protected EntityManagerInterface $entityManager; protected EntityManagerInterface $entityManager;
protected TranslatorInterface $translator;
protected TranslatableStringHelperInterface $translatableStringHelper;
protected array $fields = [ protected array $fields = [
'id', 'id',
'date', 'date',
@@ -41,9 +44,15 @@ class ListActivity implements ListInterface
'type_name', 'type_name',
'person_firstname', 'person_firstname',
'person_lastname', 'person_lastname',
'person_id' 'person_id',
]; ];
protected TranslatableStringHelperInterface $translatableStringHelper;
protected TranslatorInterface $translator;
private ActivityRepository $activityRepository;
public function __construct( public function __construct(
EntityManagerInterface $em, EntityManagerInterface $em,
TranslatorInterface $translator, TranslatorInterface $translator,
@@ -62,18 +71,17 @@ class ListActivity implements ListInterface
'multiple' => true, 'multiple' => true,
'expanded' => true, 'expanded' => true,
'choices' => array_combine($this->fields, $this->fields), 'choices' => array_combine($this->fields, $this->fields),
'label' => 'Fields to include in export', 'label' => 'Fields to include in export',
'constraints' => [new Callback([ 'constraints' => [new Callback([
'callback' => function($selected, ExecutionContextInterface $context) { 'callback' => function ($selected, ExecutionContextInterface $context) {
if (count($selected) === 0) { if (count($selected) === 0) {
$context->buildViolation('You must select at least one element') $context->buildViolation('You must select at least one element')
->atPath('fields') ->atPath('fields')
->addViolation(); ->addViolation();
} }
} },
])] ])],
]); ]);
} }
public function getAllowedFormattersTypes() public function getAllowedFormattersTypes()
@@ -83,69 +91,72 @@ class ListActivity implements ListInterface
public function getDescription() public function getDescription()
{ {
return "List activities"; return 'List activities';
} }
public function getLabels($key, array $values, $data) public function getLabels($key, array $values, $data)
{ {
switch ($key) switch ($key) {
{ case 'date':
case 'date' : return static function ($value) {
return static function($value) { if ('_header' === $value) {
if ($value === '_header') {
return 'date'; 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'); return $date->format('d-m-Y');
}; };
case 'attendee': case 'attendee':
return static function($value) { return static function ($value) {
if ($value === '_header') { if ('_header' === $value) {
return 'attendee'; return 'attendee';
} }
return $value ? 1 : 0; return $value ? 1 : 0;
}; };
case 'list_reasons' :
case 'list_reasons':
$activityRepository = $this->activityRepository; $activityRepository = $this->activityRepository;
return function($value) use ($activityRepository): string { return function ($value) use ($activityRepository): string {
if ($value === '_header') { if ('_header' === $value) {
return 'activity reasons'; return 'activity reasons';
} }
$activity = $activityRepository->find($value); $activity = $activityRepository->find($value);
return implode(", ", array_map(function(ActivityReason $r) { return implode(', ', array_map(function (ActivityReason $r) {
return '"' .
return '"'.
$this->translatableStringHelper->localize($r->getCategory()->getName()) $this->translatableStringHelper->localize($r->getCategory()->getName())
.' > '. . ' > ' .
$this->translatableStringHelper->localize($r->getName()) $this->translatableStringHelper->localize($r->getName())
.'"'; . '"';
}, $activity->getReasons()->toArray())); }, $activity->getReasons()->toArray()));
}; };
case 'circle_name' :
return function($value) { case 'circle_name':
if ($value === '_header') { return function ($value) {
if ('_header' === $value) {
return 'circle'; return 'circle';
} }
return $this->translatableStringHelper->localize(json_decode($value, true)); return $this->translatableStringHelper->localize(json_decode($value, true));
}; };
case 'type_name' :
return function($value) { case 'type_name':
if ($value === '_header') { return function ($value) {
if ('_header' === $value) {
return 'activity type'; return 'activity type';
} }
return $this->translatableStringHelper->localize(json_decode($value, true)); return $this->translatableStringHelper->localize(json_decode($value, true));
}; };
default: default:
return static function($value) use ($key) { return static function ($value) use ($key) {
if ($value === '_header') { if ('_header' === $value) {
return $key; return $key;
} }
@@ -176,59 +187,75 @@ class ListActivity implements ListInterface
public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) 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 // 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.'); throw new InvalidArgumentException('Any fields have been checked.');
} }
$qb = $this->entityManager->createQueryBuilder(); $qb = $this->entityManager->createQueryBuilder();
$qb $qb
->from('ChillActivityBundle:Activity', 'activity') ->from('ChillActivityBundle:Activity', 'activity')
->join('activity.person', 'person') ->join('activity.person', 'person')
->join('person.center', 'center') ->join('person.center', 'center')
->andWhere('center IN (:authorized_centers)') ->andWhere('center IN (:authorized_centers)')
->setParameter('authorized_centers', $centers); ->setParameter('authorized_centers', $centers);
foreach ($this->fields as $f) { foreach ($this->fields as $f) {
if (in_array($f, $data['fields'])) { if (in_array($f, $data['fields'])) {
switch ($f) { switch ($f) {
case 'id': case 'id':
$qb->addSelect('activity.id AS id'); $qb->addSelect('activity.id AS id');
break; break;
case 'person_firstname': case 'person_firstname':
$qb->addSelect('person.firstName AS person_firstname'); $qb->addSelect('person.firstName AS person_firstname');
break; break;
case 'person_lastname': case 'person_lastname':
$qb->addSelect('person.lastName AS person_lastname'); $qb->addSelect('person.lastName AS person_lastname');
break; break;
case 'person_id': case 'person_id':
$qb->addSelect('person.id AS person_id'); $qb->addSelect('person.id AS person_id');
break; break;
case 'user_username': case 'user_username':
$qb->join('activity.user', 'user'); $qb->join('activity.user', 'user');
$qb->addSelect('user.username AS user_username'); $qb->addSelect('user.username AS user_username');
break; break;
case 'circle_name': case 'circle_name':
$qb->join('activity.scope', 'circle'); $qb->join('activity.scope', 'circle');
$qb->addSelect('circle.name AS circle_name'); $qb->addSelect('circle.name AS circle_name');
break; break;
case 'type_name': case 'type_name':
$qb->join('activity.type', 'type'); $qb->join('activity.type', 'type');
$qb->addSelect('type.name AS type_name'); $qb->addSelect('type.name AS type_name');
break; break;
case 'list_reasons': case 'list_reasons':
// this is a trick... The reasons is filled with the // this is a trick... The reasons is filled with the
// activity id which will be used to load reasons // activity id which will be used to load reasons
$qb->addSelect('activity.id AS list_reasons'); $qb->addSelect('activity.id AS list_reasons');
break; break;
default: default:
$qb->addSelect(sprintf('activity.%s as %s', $f, $f)); $qb->addSelect(sprintf('activity.%s as %s', $f, $f));
break; break;
} }
} }
} }
@@ -244,5 +271,4 @@ class ListActivity implements ListInterface
{ {
return ['activity', 'person']; return ['activity', 'person'];
} }
} }

View File

@@ -1,16 +1,24 @@
<?php <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Export; namespace Chill\ActivityBundle\Export\Export;
use Chill\ActivityBundle\Repository\ActivityRepository; use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\FormatterInterface;
use Doctrine\ORM\Query;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role; 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. * This export allow to compute stats on activity duration.
@@ -19,8 +27,6 @@ use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
*/ */
class StatActivityDuration implements ExportInterface class StatActivityDuration implements ExportInterface
{ {
private ActivityRepository $activityRepository;
public const SUM = 'sum'; public const SUM = 'sum';
/** /**
@@ -28,6 +34,8 @@ class StatActivityDuration implements ExportInterface
*/ */
protected string $action; protected string $action;
private ActivityRepository $activityRepository;
/** /**
* @param string $action the stat to perform * @param string $action the stat to perform
*/ */
@@ -41,59 +49,6 @@ class StatActivityDuration implements ExportInterface
public function buildForm(FormBuilderInterface $builder) 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() public function getAllowedFormattersTypes()
@@ -101,15 +56,22 @@ class StatActivityDuration implements ExportInterface
return [FormatterInterface::TYPE_TABULAR]; 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) public function getLabels($key, array $values, $data)
{ {
if ($key !== 'export_stat_activity') { if ('export_stat_activity' !== $key) {
throw new \LogicException(sprintf('The key %s is not used by this export', $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) public function getQueryKeys($data)
@@ -122,4 +84,47 @@ class StatActivityDuration implements ExportInterface
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR); 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 <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter; namespace Chill\ActivityBundle\Export\Filter;
use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\Export\FilterType;
use DateTime;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents; 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; use Symfony\Component\Translation\TranslatorInterface;
class ActivityDateFilter implements FilterInterface class ActivityDateFilter implements FilterInterface
{ {
protected TranslatorInterface $translator; protected TranslatorInterface $translator;
function __construct(TranslatorInterface $translator) public function __construct(TranslatorInterface $translator)
{ {
$this->translator = $translator; $this->translator = $translator;
} }
@@ -32,8 +40,11 @@ class ActivityDateFilter implements FilterInterface
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
$where = $qb->getDQLPart('where'); $where = $qb->getDQLPart('where');
$clause = $qb->expr()->between('activity.date', ':date_from', $clause = $qb->expr()->between(
':date_to'); 'activity.date',
':date_from',
':date_to'
);
if ($where instanceof Expr\Andx) { if ($where instanceof Expr\Andx) {
$where->add($clause); $where->add($clause);
@@ -58,9 +69,9 @@ class ActivityDateFilter implements FilterInterface
DateType::class, DateType::class,
[ [
'label' => 'Activities after this date', 'label' => 'Activities after this date',
'data' => new \DateTime(), 'data' => new DateTime(),
'attr' => ['class' => 'datepicker'], 'attr' => ['class' => 'datepicker'],
'widget'=> 'single_text', 'widget' => 'single_text',
'format' => 'dd-MM-yyyy', 'format' => 'dd-MM-yyyy',
] ]
); );
@@ -70,46 +81,49 @@ class ActivityDateFilter implements FilterInterface
DateType::class, DateType::class,
[ [
'label' => 'Activities before this date', 'label' => 'Activities before this date',
'data' => new \DateTime(), 'data' => new DateTime(),
'attr' => ['class' => 'datepicker'], 'attr' => ['class' => 'datepicker'],
'widget'=> 'single_text', 'widget' => 'single_text',
'format' => 'dd-MM-yyyy', '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 */ /* @var $filterForm \Symfony\Component\Form\FormInterface */
$filterForm = $event->getForm()->getParent(); $filterForm = $event->getForm()->getParent();
$enabled = $filterForm->get(FilterType::ENABLED_FIELD)->getData(); $enabled = $filterForm->get(FilterType::ENABLED_FIELD)->getData();
if ($enabled === true) { if (true === $enabled) {
// if the filter is enabled, add some validation // if the filter is enabled, add some validation
$form = $event->getForm(); $form = $event->getForm();
$date_from = $form->get('date_from')->getData(); $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 // check that fields are not empty
if ($date_from === null) { if (null === $date_from) {
$form->get('date_from')->addError(new FormError( $form->get('date_from')->addError(new FormError(
$this->translator->trans('This field ' $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( $form->get('date_to')->addError(new FormError(
$this->translator->trans('This field ' $this->translator->trans('This field '
. 'should not be empty'))); . 'should not be empty')
));
} }
// check that date_from is before date_to // check that date_from is before date_to
if ( if (
($date_from !== null && $date_to !== null) (null !== $date_from && null !== $date_to)
&& && $date_from >= $date_to
$date_from >= $date_to
) { ) {
$form->get('date_to')->addError(new FormError( $form->get('date_to')->addError(new FormError(
$this->translator->trans('This date should be after ' $this->translator->trans('This date should be after '
. 'the date given in "Implied in an activity 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%', 'Filtered by date of activity: only between %date_from% and %date_to%',
[ [
'%date_from%' => $data['date_from']->format('d-m-Y'), '%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'; return 'Filtered by date activity';
} }
} }

View File

@@ -1,30 +1,37 @@
<?php <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter; 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\ActivityBundle\Entity\ActivityReason;
use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\ActivityBundle\Repository\ActivityReasonRepository;
use Doctrine\ORM\Query\Expr;
use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter; 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\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 class ActivityReasonFilter implements FilterInterface, ExportElementValidatedInterface
{ {
protected TranslatableStringHelperInterface $translatableStringHelper;
protected ActivityReasonRepository $activityReasonRepository; protected ActivityReasonRepository $activityReasonRepository;
protected TranslatableStringHelperInterface $translatableStringHelper;
public function __construct( public function __construct(
TranslatableStringHelper $helper, TranslatableStringHelper $helper,
ActivityReasonRepository $activityReasonRepository ActivityReasonRepository $activityReasonRepository
@@ -33,26 +40,30 @@ class ActivityReasonFilter implements FilterInterface, ExportElementValidatedInt
$this->activityReasonRepository = $activityReasonRepository; $this->activityReasonRepository = $activityReasonRepository;
} }
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
$where = $qb->getDQLPart('where'); $where = $qb->getDQLPart('where');
$join = $qb->getDQLPart('join'); $join = $qb->getDQLPart('join');
$clause = $qb->expr()->in('reasons', ':selected_activity_reasons'); $clause = $qb->expr()->in('reasons', ':selected_activity_reasons');
//dump($join); //dump($join);
// add a join to reasons only if needed // add a join to reasons only if needed
if ( if (
(array_key_exists('activity', $join) (
&& array_key_exists('activity', $join)
!$this->checkJoinAlreadyDefined($join['activity'], 'reasons') && !$this->checkJoinAlreadyDefined($join['activity'], 'reasons')
) )
|| || (!array_key_exists('activity', $join))
(! array_key_exists('activity', $join))
) { ) {
$qb->add( $qb->add(
'join', 'join',
array('activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons')), ['activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons')],
true true
); );
} }
if ($where instanceof Expr\Andx) { if ($where instanceof Expr\Andx) {
@@ -65,11 +76,57 @@ class ActivityReasonFilter implements FilterInterface, ExportElementValidatedInt
$qb->setParameter('selected_activity_reasons', $data['reasons']); $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 * @param Join[] $joins
* @return boolean * @param mixed $alias
*/ */
private function checkJoinAlreadyDefined(array $joins, $alias): bool private function checkJoinAlreadyDefined(array $joins, $alias): bool
{ {
@@ -81,55 +138,4 @@ class ActivityReasonFilter implements FilterInterface, ExportElementValidatedInt
return false; 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 <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter; namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Entity\ActivityType;
use Chill\ActivityBundle\Repository\ActivityTypeRepository; use Chill\ActivityBundle\Repository\ActivityTypeRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface; 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 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\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 Symfony\Component\Validator\Context\ExecutionContextInterface;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\ActivityBundle\Entity\ActivityType;
class ActivityTypeFilter implements FilterInterface, ExportElementValidatedInterface class ActivityTypeFilter implements FilterInterface, ExportElementValidatedInterface
{ {
protected TranslatableStringHelperInterface $translatableStringHelper;
protected ActivityTypeRepository $activityTypeRepository; protected ActivityTypeRepository $activityTypeRepository;
protected TranslatableStringHelperInterface $translatableStringHelper;
public function __construct( public function __construct(
TranslatableStringHelperInterface $translatableStringHelper, TranslatableStringHelperInterface $translatableStringHelper,
ActivityTypeRepository $activityTypeRepository ActivityTypeRepository $activityTypeRepository
@@ -32,6 +39,11 @@ class ActivityTypeFilter implements FilterInterface, ExportElementValidatedInter
$this->activityTypeRepository = $activityTypeRepository; $this->activityTypeRepository = $activityTypeRepository;
} }
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
$where = $qb->getDQLPart('where'); $where = $qb->getDQLPart('where');
@@ -47,23 +59,6 @@ class ActivityTypeFilter implements FilterInterface, ExportElementValidatedInter
$qb->setParameter('selected_activity_types', $data['types']); $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() public function applyOn()
{ {
return 'activity'; return 'activity';
@@ -76,20 +71,27 @@ class ActivityTypeFilter implements FilterInterface, ExportElementValidatedInter
EntityType::class, EntityType::class,
[ [
'class' => ActivityType::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, '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) { // collect all the reasons'name used in this filter in one array
$context $reasonsNames = array_map(
->buildViolation('At least one type must be chosen') fn (ActivityType $t): string => '"' . $this->translatableStringHelper->localize($t->getName()) . '"',
->addViolation(); $this->activityTypeRepository->findBy(['id' => $data['types']->toArray()])
} );
return [
'Filtered by activity type: only %list%',
[
'%list%' => implode(', ', $reasonsNames),
],
];
} }
public function getTitle() public function getTitle()
@@ -97,24 +99,31 @@ class ActivityTypeFilter implements FilterInterface, ExportElementValidatedInter
return 'Filter by activity type'; 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 foreach ($joins as $join) {
$reasonsNames = array_map( if ($join->getAlias() === $alias) {
fn(ActivityType $t): string => '"' . $this->translatableStringHelper->localize($t->getName()) . '"', return true;
$this->activityTypeRepository->findBy(['id' => $data['types']->toArray()]) }
); }
return [ return false;
'Filtered by activity type: only %list%',
[
'%list%' => implode(", ", $reasonsNames),
]
];
} }
} }

View File

@@ -1,35 +1,43 @@
<?php <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter; namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Repository\ActivityReasonRepository; use Chill\ActivityBundle\Repository\ActivityReasonRepository;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\Export\FilterType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Export\Declarations;
use DateTime;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder; 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\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents; 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\Form\FormInterface;
use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
class PersonHavingActivityBetweenDateFilter implements FilterInterface, ExportElementValidatedInterface class PersonHavingActivityBetweenDateFilter implements FilterInterface, ExportElementValidatedInterface
{ {
protected TranslatableStringHelperInterface $translatableStringHelper;
protected ActivityReasonRepository $activityReasonRepository; protected ActivityReasonRepository $activityReasonRepository;
protected TranslatableStringHelperInterface $translatableStringHelper;
protected TranslatorInterface $translator; protected TranslatorInterface $translator;
public function __construct( public function __construct(
@@ -66,7 +74,8 @@ class PersonHavingActivityBetweenDateFilter implements FilterInterface, ExportEl
$sqb->andWhere( $sqb->andWhere(
$sqb->expr()->in( $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->add('where', $where);
$qb->setParameter('person_having_activity_between_date_from', $qb->setParameter(
$data['date_from']); 'person_having_activity_between_date_from',
$qb->setParameter('person_having_activity_between_date_to', $data['date_from']
$data['date_to']); );
$qb->setParameter(
'person_having_activity_between_date_to',
$data['date_to']
);
$qb->setParameter('person_having_activity_reasons', $data['reasons']); $qb->setParameter('person_having_activity_reasons', $data['reasons']);
} }
@@ -96,76 +109,71 @@ class PersonHavingActivityBetweenDateFilter implements FilterInterface, ExportEl
{ {
$builder->add('date_from', DateType::class, [ $builder->add('date_from', DateType::class, [
'label' => 'Implied in an activity after this date', 'label' => 'Implied in an activity after this date',
'data' => new \DateTime(), 'data' => new DateTime(),
'attr' => ['class' => 'datepicker'], 'attr' => ['class' => 'datepicker'],
'widget'=> 'single_text', 'widget' => 'single_text',
'format' => 'dd-MM-yyyy', 'format' => 'dd-MM-yyyy',
]); ]);
$builder->add('date_to', DateType::class, [ $builder->add('date_to', DateType::class, [
'label' => 'Implied in an activity before this date', 'label' => 'Implied in an activity before this date',
'data' => new \DateTime(), 'data' => new DateTime(),
'attr' => ['class' => 'datepicker'], 'attr' => ['class' => 'datepicker'],
'widget'=> 'single_text', 'widget' => 'single_text',
'format' => 'dd-MM-yyyy', 'format' => 'dd-MM-yyyy',
]); ]);
$builder->add('reasons', EntityType::class, [ $builder->add('reasons', EntityType::class, [
'class' => ActivityReason::class, 'class' => ActivityReason::class,
'choice_label' => fn (ActivityReason $reason): ?string => $this->translatableStringHelper->localize($reason->getName()), '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(), 'data' => $this->activityReasonRepository->findAll(),
'multiple' => true, 'multiple' => true,
'expanded' => false, '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 */ /* @var FormInterface $filterForm */
$filterForm = $event->getForm()->getParent(); $filterForm = $event->getForm()->getParent();
$enabled = $filterForm->get(FilterType::ENABLED_FIELD)->getData(); $enabled = $filterForm->get(FilterType::ENABLED_FIELD)->getData();
if ($enabled === true) { if (true === $enabled) {
// if the filter is enabled, add some validation // if the filter is enabled, add some validation
$form = $event->getForm(); $form = $event->getForm();
$date_from = $form->get('date_from')->getData(); $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 // check that fields are not empty
if ($date_from === null) { if (null === $date_from) {
$form->get('date_from')->addError(new FormError( $form->get('date_from')->addError(new FormError(
$this->translator->trans('This field ' $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( $form->get('date_to')->addError(new FormError(
$this->translator->trans('This field ' $this->translator->trans('This field '
. 'should not be empty'))); . 'should not be empty')
));
} }
// check that date_from is before date_to // check that date_from is before date_to
if ( if (
($date_from !== null && $date_to !== null) (null !== $date_from && null !== $date_to)
&& && $date_from >= $date_to
$date_from >= $date_to
) { ) {
$form->get('date_to')->addError(new FormError( $form->get('date_to')->addError(new FormError(
$this->translator->trans('This date ' $this->translator->trans('This date '
. 'should be after the date given in "Implied in an ' . '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') public function describeAction($data, $format = 'string')
{ {
return [ return [
@@ -173,15 +181,15 @@ class PersonHavingActivityBetweenDateFilter implements FilterInterface, ExportEl
. '%date_to% with reasons %reasons_name%', . '%date_to% with reasons %reasons_name%',
[ [
'%date_from%' => $data['date_from']->format('d-m-Y'), '%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'),
'%reasons_name%' => implode( '%reasons_name%' => implode(
", ", ', ',
array_map( array_map(
fn(ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"', fn (ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"',
$data['reasons'] $data['reasons']
) )
) ),
] ],
]; ];
} }
@@ -190,4 +198,11 @@ class PersonHavingActivityBetweenDateFilter implements FilterInterface, ExportEl
return 'Filtered by person having an activity in a period'; 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 <?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; namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Entity\ActivityPresence; use Chill\ActivityBundle\Entity\ActivityPresence;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
class ActivityPresenceType extends AbstractType class ActivityPresenceType extends AbstractType
{ {
@@ -15,19 +22,19 @@ class ActivityPresenceType extends AbstractType
{ {
$builder $builder
->add('name', TranslatableStringFormType::class) ->add('name', TranslatableStringFormType::class)
->add('active', ChoiceType::class, array( ->add('active', ChoiceType::class, [
'choices' => array( 'choices' => [
'Yes' => true, 'Yes' => true,
'No' => false 'No' => false,
), ],
'expanded' => true 'expanded' => true,
)); ]);
} }
public function configureOptions(OptionsResolver $resolver): void public function configureOptions(OptionsResolver $resolver): void
{ {
$resolver->setDefaults(array( $resolver->setDefaults([
'data_class' => ActivityPresence::class 'data_class' => ActivityPresence::class,
)); ]);
} }
} }

View File

@@ -1,25 +1,27 @@
<?php <?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; namespace Chill\ActivityBundle\Form;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
class ActivityReasonCategoryType extends AbstractType class ActivityReasonCategoryType extends AbstractType
{ {
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options) public function buildForm(FormBuilderInterface $builder, array $options)
{ {
$builder $builder
->add('name', TranslatableStringFormType::class) ->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) public function configureOptions(OptionsResolver $resolver)
{ {
$resolver->setDefaults(array( $resolver->setDefaults([
'data_class' => 'Chill\ActivityBundle\Entity\ActivityReasonCategory' 'data_class' => 'Chill\ActivityBundle\Entity\ActivityReasonCategory',
)); ]);
} }
/** /**

View File

@@ -1,37 +1,36 @@
<?php <?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; 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\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; 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 class ActivityReasonType extends AbstractType
{ {
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options) public function buildForm(FormBuilderInterface $builder, array $options)
{ {
$builder $builder
->add('name', TranslatableStringFormType::class) ->add('name', TranslatableStringFormType::class)
->add('active', CheckboxType::class, array('required' => false)) ->add('active', CheckboxType::class, ['required' => false])
->add('category', TranslatableActivityReasonCategory::class) ->add('category', TranslatableActivityReasonCategory::class);
;
} }
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver) public function configureOptions(OptionsResolver $resolver)
{ {
$resolver->setDefaults(array( $resolver->setDefaults([
'data_class' => 'Chill\ActivityBundle\Entity\ActivityReason' 'data_class' => 'Chill\ActivityBundle\Entity\ActivityReason',
)); ]);
} }
/** /**

View File

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

View File

@@ -1,14 +1,21 @@
<?php <?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; namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Entity\ActivityTypeCategory; use Chill\ActivityBundle\Entity\ActivityTypeCategory;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
use Symfony\Component\Form\AbstractType; 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\NumberType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
class ActivityTypeCategoryType extends AbstractType class ActivityTypeCategoryType extends AbstractType
{ {
@@ -16,24 +23,23 @@ class ActivityTypeCategoryType extends AbstractType
{ {
$builder $builder
->add('name', TranslatableStringFormType::class) ->add('name', TranslatableStringFormType::class)
->add('active', ChoiceType::class, array( ->add('active', ChoiceType::class, [
'choices' => array( 'choices' => [
'Yes' => true, 'Yes' => true,
'No' => false 'No' => false,
), ],
'expanded' => true 'expanded' => true,
)) ])
->add('ordering', NumberType::class, [ ->add('ordering', NumberType::class, [
'required' => true, 'required' => true,
'scale' => 5 'scale' => 5,
]) ]);
;
} }
public function configureOptions(OptionsResolver $resolver): void public function configureOptions(OptionsResolver $resolver): void
{ {
$resolver->setDefaults(array( $resolver->setDefaults([
'data_class' => ActivityTypeCategory::class 'data_class' => ActivityTypeCategory::class,
)); ]);
} }
} }

View File

@@ -1,18 +1,25 @@
<?php <?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; namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Entity\ActivityTypeCategory; use Chill\ActivityBundle\Entity\ActivityTypeCategory;
use Chill\ActivityBundle\Form\Type\ActivityFieldPresence; use Chill\ActivityBundle\Form\Type\ActivityFieldPresence;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\MainBundle\Templating\TranslatableStringHelper;
use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType; 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\NumberType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
class ActivityTypeType extends AbstractType class ActivityTypeType extends AbstractType
{ {
@@ -30,9 +37,9 @@ class ActivityTypeType extends AbstractType
->add('active', ChoiceType::class, [ ->add('active', ChoiceType::class, [
'choices' => [ 'choices' => [
'Yes' => true, 'Yes' => true,
'No' => false 'No' => false,
], ],
'expanded' => true 'expanded' => true,
]) ])
->add('category', EntityType::class, [ ->add('category', EntityType::class, [
'class' => ActivityTypeCategory::class, 'class' => ActivityTypeCategory::class,
@@ -42,20 +49,20 @@ class ActivityTypeType extends AbstractType
]) ])
->add('ordering', NumberType::class, [ ->add('ordering', NumberType::class, [
'required' => true, 'required' => true,
'scale' => 5 'scale' => 5,
]) ]);
;
$fields = [ $fields = [
'persons', 'user', 'date', 'place', 'persons', 'persons', 'user', 'date', 'place', 'persons',
'thirdParties', 'durationTime', 'travelTime', 'attendee', 'thirdParties', 'durationTime', 'travelTime', 'attendee',
'reasons', 'comment', 'sentReceived', 'documents', 'reasons', 'comment', 'sentReceived', 'documents',
'emergency', 'accompanyingPeriod', 'socialData', 'users' 'emergency', 'accompanyingPeriod', 'socialData', 'users',
]; ];
foreach ($fields as $field) { foreach ($fields as $field) {
$builder $builder
->add($field.'Visible', ActivityFieldPresence::class) ->add($field . 'Visible', ActivityFieldPresence::class)
->add($field.'Label', TextType::class, [ ->add($field . 'Label', TextType::class, [
'required' => false, 'required' => false,
'empty_data' => '', 'empty_data' => '',
]); ]);
@@ -64,8 +71,8 @@ class ActivityTypeType extends AbstractType
public function configureOptions(OptionsResolver $resolver) public function configureOptions(OptionsResolver $resolver)
{ {
$resolver->setDefaults(array( $resolver->setDefaults([
'data_class' => \Chill\ActivityBundle\Entity\ActivityType::class 'data_class' => \Chill\ActivityBundle\Entity\ActivityType::class,
)); ]);
} }
} }

View File

@@ -1,5 +1,12 @@
<?php <?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; namespace Chill\ActivityBundle\Form\Type;
use Chill\ActivityBundle\Entity\ActivityType; use Chill\ActivityBundle\Entity\ActivityType;
@@ -9,21 +16,21 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
class ActivityFieldPresence extends AbstractType class ActivityFieldPresence extends AbstractType
{ {
public function getParent()
{
return ChoiceType::class;
}
public function configureOptions(OptionsResolver $resolver) public function configureOptions(OptionsResolver $resolver)
{ {
$resolver->setDefaults( $resolver->setDefaults(
array( [
'choices' => [ 'choices' => [
'Invisible' => ActivityType::FIELD_INVISIBLE, 'Invisible' => ActivityType::FIELD_INVISIBLE,
'Optional' => ActivityType::FIELD_OPTIONAL, 'Optional' => ActivityType::FIELD_OPTIONAL,
'Required' => ActivityType::FIELD_REQUIRED, 'Required' => ActivityType::FIELD_REQUIRED,
], ],
) ]
); );
} }
public function getParent()
{
return ChoiceType::class;
}
} }

View File

@@ -1,54 +1,37 @@
<?php <?php
/* /**
* Chill is a software for social workers * Chill is a software for social workers
* *
* Copyright (C) 2014-2020, Champs Libres Cooperative SCRLFS, * For the full copyright and license information, please view
* <http://www.champs-libres.coop>, <info@champs-libres.coop> * the LICENSE file that was distributed with this source code.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\Form\Type; 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\Entity\ActivityReason;
use Chill\ActivityBundle\Templating\Entity\ActivityReasonRender; 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 class TranslatableActivityReason extends AbstractType
{ {
/** /**
*
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
/**
*
* @var ActivityReasonRender * @var ActivityReasonRender
*/ */
protected $reasonRender; protected $reasonRender;
/**
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
public function __construct( public function __construct(
TranslatableStringHelper $translatableStringHelper, TranslatableStringHelper $translatableStringHelper,
ActivityReasonRender $reasonRender ActivityReasonRender $reasonRender
@@ -57,6 +40,30 @@ class TranslatableActivityReason extends AbstractType
$this->reasonRender = $reasonRender; $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() public function getBlockPrefix()
{ {
return 'translatable_activity_reason'; return 'translatable_activity_reason';
@@ -66,28 +73,4 @@ class TranslatableActivityReason extends AbstractType
{ {
return EntityType::class; 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 <?php
/* /**
* Chill is a software for social workers * Chill is a software for social workers
* *
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS, * For the full copyright and license information, please view
* <http://www.champs-libres.coop>, <info@champs-libres.coop> * the LICENSE file that was distributed with this source code.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\Form\Type; 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 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 * Description of TranslatableActivityReasonCategory.
*
* @author Champs-Libres Coop
*/ */
class TranslatableActivityReasonCategory extends AbstractType class TranslatableActivityReasonCategory extends AbstractType
{ {
/** /**
@@ -47,6 +30,21 @@ class TranslatableActivityReasonCategory extends AbstractType
$this->requestStack = $requestStack; $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() public function getBlockPrefix()
{ {
return 'translatable_activity_reason_category'; return 'translatable_activity_reason_category';
@@ -56,19 +54,4 @@ class TranslatableActivityReasonCategory extends AbstractType
{ {
return EntityType::class; 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 <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Form\Type; namespace Chill\ActivityBundle\Form\Type;
use Chill\ActivityBundle\Entity\ActivityType;
use Chill\ActivityBundle\Repository\ActivityTypeRepository; use Chill\ActivityBundle\Repository\ActivityTypeRepository;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Chill\ActivityBundle\Entity\ActivityType;
class TranslatableActivityType extends AbstractType class TranslatableActivityType extends AbstractType
{ {
protected TranslatableStringHelperInterface $translatableStringHelper;
protected ActivityTypeRepository $activityTypeRepository; protected ActivityTypeRepository $activityTypeRepository;
protected TranslatableStringHelperInterface $translatableStringHelper;
public function __construct( public function __construct(
TranslatableStringHelperInterface $helper, TranslatableStringHelperInterface $helper,
ActivityTypeRepository $activityTypeRepository ActivityTypeRepository $activityTypeRepository
@@ -28,6 +35,32 @@ class TranslatableActivityType extends AbstractType
$this->activityTypeRepository = $activityTypeRepository; $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() public function getBlockPrefix()
{ {
return 'translatable_activity_type'; return 'translatable_activity_type';
@@ -37,29 +70,4 @@ class TranslatableActivityType extends AbstractType
{ {
return EntityType::class; 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 <?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; namespace Chill\ActivityBundle\Menu;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter; use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Chill\MainBundle\Routing\LocalMenuBuilderInterface; use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Knp\Menu\MenuItem; use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
{ {
protected TranslatorInterface $translator;
protected Security $security; protected Security $security;
protected TranslatorInterface $translator;
public function __construct( public function __construct(
Security $security, Security $security,
TranslatorInterface $translator TranslatorInterface $translator
@@ -24,10 +29,6 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
$this->security = $security; $this->security = $security;
$this->translator = $translator; $this->translator = $translator;
} }
public static function getMenuIds(): array
{
return ['accompanyingCourse'];
}
public function buildMenu($menuId, MenuItem $menu, array $parameters) public function buildMenu($menuId, MenuItem $menu, array $parameters)
{ {
@@ -39,8 +40,13 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
'route' => 'chill_activity_activity_list', 'route' => 'chill_activity_activity_list',
'routeParameters' => [ 'routeParameters' => [
'accompanying_period_id' => $period->getId(), 'accompanying_period_id' => $period->getId(),
]]) ], ])
->setExtras(['order' => 40]); ->setExtras(['order' => 40]);
} }
} }
public static function getMenuIds(): array
{
return ['accompanyingCourse'];
}
} }

View File

@@ -1,4 +1,12 @@
<?php <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Menu; namespace Chill\ActivityBundle\Menu;
@@ -16,11 +24,6 @@ final class AdminMenuBuilder implements LocalMenuBuilderInterface
$this->security = $security; $this->security = $security;
} }
public static function getMenuIds(): array
{
return ['admin_index', 'admin_section', 'admin_activity'];
}
public function buildMenu($menuId, MenuItem $menu, array $parameters) public function buildMenu($menuId, MenuItem $menu, array $parameters)
{ {
if (!$this->security->isGranted('ROLE_ADMIN')) { if (!$this->security->isGranted('ROLE_ADMIN')) {
@@ -29,20 +32,25 @@ final class AdminMenuBuilder implements LocalMenuBuilderInterface
if (in_array($menuId, ['admin_index', 'admin_section'])) { if (in_array($menuId, ['admin_index', 'admin_section'])) {
$menu->addChild('Activities', [ $menu->addChild('Activities', [
'route' => 'chill_admin_activity_index' 'route' => 'chill_admin_activity_index',
]) ])
->setExtras([ ->setExtras([
'order' => 2000, 'order' => 2000,
'explain' => "Activity configuration" 'explain' => 'Activity configuration',
]); ]);
} else { } else {
$menu $menu
->addChild('Activities', [ ->addChild('Activities', [
'route' => 'chill_admin_activity_index' 'route' => 'chill_admin_activity_index',
]) ])
->setExtras([ ->setExtras([
'order' => '60' 'order' => '60',
]); ]);
} }
} }
public static function getMenuIds(): array
{
return ['admin_index', 'admin_section', 'admin_activity'];
}
} }

View File

@@ -1,55 +1,40 @@
<?php <?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 * For the full copyright and license information, please view
* it under the terms of the GNU Affero General Public License as published by * the LICENSE file that was distributed with this source code.
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\Menu; namespace Chill\ActivityBundle\Menu;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Chill\MainBundle\Routing\LocalMenuBuilderInterface; use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Knp\Menu\MenuItem; use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Translation\TranslatorInterface;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class PersonMenuBuilder implements LocalMenuBuilderInterface class PersonMenuBuilder implements LocalMenuBuilderInterface
{ {
/** /**
*
* @var TranslatorInterface
*/
protected $translator;
/**
*
* @var AuthorizationCheckerInterface * @var AuthorizationCheckerInterface
*/ */
protected $authorizationChecker; protected $authorizationChecker;
/**
* @var TranslatorInterface
*/
protected $translator;
public function __construct( public function __construct(
AuthorizationCheckerInterface $authorizationChecker, AuthorizationCheckerInterface $authorizationChecker,
TranslatorInterface $translator) TranslatorInterface $translator
{ ) {
$this->translator = $translator; $this->translator = $translator;
$this->authorizationChecker = $authorizationChecker; $this->authorizationChecker = $authorizationChecker;
} }
public function buildMenu($menuId, MenuItem $menu, array $parameters) public function buildMenu($menuId, MenuItem $menu, array $parameters)
{ {
/* @var $person \Chill\PersonBundle\Entity\Person */ /* @var $person \Chill\PersonBundle\Entity\Person */
@@ -57,12 +42,13 @@ class PersonMenuBuilder implements LocalMenuBuilderInterface
if ($this->authorizationChecker->isGranted(ActivityVoter::SEE, $person)) { if ($this->authorizationChecker->isGranted(ActivityVoter::SEE, $person)) {
$menu->addChild( $menu->addChild(
$this->translator->trans('Activity list'), [ $this->translator->trans('Activity list'),
[
'route' => 'chill_activity_activity_list', 'route' => 'chill_activity_activity_list',
'routeParameters' => [ 'person_id' => $person->getId() ], 'routeParameters' => ['person_id' => $person->getId()],
]) ]
->setExtra('order', 201) )
; ->setExtra('order', 201);
} }
} }

View File

@@ -1,17 +1,19 @@
<?php <?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; namespace Chill\ActivityBundle\Notification;
use Chill\MainBundle\Entity\Notification;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\Entity\Notification;
final class ActivityNotificationRenderer final class ActivityNotificationRenderer
{ {
public function supports(Notification $notification, array $options = []): bool
{
return $notification->getRelatedEntityClass() == Activity::class;
}
public function getTemplate() public function getTemplate()
{ {
return '@ChillActivity/Activity/showInNotification.html.twig'; return '@ChillActivity/Activity/showInNotification.html.twig';
@@ -21,4 +23,9 @@ final class ActivityNotificationRenderer
{ {
return ['notification' => $notification]; return ['notification' => $notification];
} }
public function supports(Notification $notification, array $options = []): bool
{
return $notification->getRelatedEntityClass() == Activity::class;
}
} }

View File

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

View File

@@ -1,5 +1,12 @@
<?php <?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; namespace Chill\ActivityBundle\Repository;
use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod;
@@ -8,12 +15,12 @@ use Chill\PersonBundle\Entity\Person;
interface ActivityACLAwareRepositoryInterface interface ActivityACLAwareRepositoryInterface
{ {
/** /**
* @return array|Activity[] * @return Activity[]|array
*/
public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array;
/**
* @return array|Activity[]
*/ */
public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): 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 <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Repository; namespace Chill\ActivityBundle\Repository;

View File

@@ -1,5 +1,12 @@
<?php <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Repository; namespace Chill\ActivityBundle\Repository;

View File

@@ -1,5 +1,12 @@
<?php <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Repository; namespace Chill\ActivityBundle\Repository;
@@ -23,34 +30,6 @@ class ActivityRepository extends ServiceEntityRepository
parent::__construct($registry, Activity::class); 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[] * @return Activity[]
*/ */
@@ -81,7 +60,35 @@ class ActivityRepository extends ServiceEntityRepository
->setParameter('period', $period); ->setParameter('period', $period);
foreach ($orderBy as $k => $dir) { 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); $qb->setMaxResults($limit)->setFirstResult($offset);

View File

@@ -1,5 +1,12 @@
<?php <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Repository; namespace Chill\ActivityBundle\Repository;

View File

@@ -1,5 +1,12 @@
<?php <?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); declare(strict_types=1);
namespace Chill\ActivityBundle\Repository; namespace Chill\ActivityBundle\Repository;

View File

@@ -1,5 +1,5 @@
<template> <template>
<teleport to="#add-persons"> <teleport to="#add-persons" v-if="isComponentVisible">
<div class="flex-bloc concerned-groups" :class="getContext"> <div class="flex-bloc concerned-groups" :class="getContext">
<persons-bloc <persons-bloc
@@ -9,10 +9,9 @@
v-bind:setPersonsInBloc="setPersonsInBloc"> v-bind:setPersonsInBloc="setPersonsInBloc">
</persons-bloc> </persons-bloc>
</div> </div>
<div v-if="getContext === 'accompanyingCourse' && suggestedEntities.length > 0">
<div v-if="getContext === 'accompanyingCourse' && filterSuggestedPersons.length > 0">
<ul class="list-unstyled"> <ul class="list-unstyled">
<li v-for="p in filterSuggestedPersons" @click="addNewPerson(p)"> <li v-for="p in suggestedEntities" @click="addSuggestedEntity(p)">
<span class="badge bg-primary" style="cursor: pointer;"> <span class="badge bg-primary" style="cursor: pointer;">
<i class="fa fa-plus fa-fw text-success"></i> <i class="fa fa-plus fa-fw text-success"></i>
{{ p.text }} {{ p.text }}
@@ -25,7 +24,7 @@
buttonTitle="activity.add_persons" buttonTitle="activity.add_persons"
modalTitle="activity.add_persons" modalTitle="activity.add_persons"
v-bind:key="addPersons.key" v-bind:key="addPersons.key"
v-bind:options="addPersons.options" v-bind:options="addPersonsOptions"
@addNewPersons="addNewPersons" @addNewPersons="addNewPersons"
ref="addPersons"> ref="addPersons">
</add-persons> </add-persons>
@@ -55,38 +54,35 @@ export default {
{ key: 'personsAssociated', { key: 'personsAssociated',
title: 'activity.bloc_persons_associated', title: 'activity.bloc_persons_associated',
persons: [], persons: [],
included: false included: window.activity ? window.activity.activityType.personsVisible !== 0 : true
}, },
{ key: 'personsNotAssociated', { key: 'personsNotAssociated',
title: 'activity.bloc_persons_not_associated', title: 'activity.bloc_persons_not_associated',
persons: [], persons: [],
included: false included: window.activity ? window.activity.activityType.personsVisible !== 0 : true
}, },
{ key: 'thirdparty', { key: 'thirdparty',
title: 'activity.bloc_thirdparty', title: 'activity.bloc_thirdparty',
persons: [], persons: [],
included: true included: window.activity ? window.activity.activityType.thirdPartiesVisible !== 0 : true
}, },
{ key: 'users', { key: 'users',
title: 'activity.bloc_users', title: 'activity.bloc_users',
persons: [], persons: [],
included: true included: window.activity ? window.activity.activityType.usersVisible !== 0 : true
}, },
], ],
addPersons: { addPersons: {
key: 'activity', key: 'activity'
options: {
type: ['person', 'thirdparty', 'user'],
priority: null,
uniq: false,
button: {
size: 'btn-sm'
}
}
} }
} }
}, },
computed: { computed: {
isComponentVisible() {
return window.activity
? (window.activity.activityType.personsVisible !== 0 || window.activity.activityType.thirdPartiesVisible !== 0 || window.activity.activityType.usersVisible !== 0)
: true
},
...mapState({ ...mapState({
persons: state => state.activity.persons, persons: state => state.activity.persons,
thirdParties: state => state.activity.thirdParties, thirdParties: state => state.activity.thirdParties,
@@ -94,14 +90,38 @@ export default {
accompanyingCourse: state => state.activity.accompanyingPeriod accompanyingCourse: state => state.activity.accompanyingPeriod
}), }),
...mapGetters([ ...mapGetters([
'filterSuggestedPersons' 'suggestedEntities'
]), ]),
getContext() { getContext() {
return (this.accompanyingCourse) ? "accompanyingCourse" : "person"; return (this.accompanyingCourse) ? "accompanyingCourse" : "person";
}, },
contextPersonsBlocs() { contextPersonsBlocs() {
return this.personsBlocs.filter(bloc => bloc.included !== false); return this.personsBlocs.filter(bloc => bloc.included !== false);
} },
addPersonsOptions() {
let optionsType = [];
if (window.activity) {
if (window.activity.activityType.personsVisible !== 0) {
optionsType.push('person')
}
if (window.activity.activityType.thirdPartiesVisible !== 0) {
optionsType.push('thirdparty')
}
if (window.activity.activityType.usersVisible !== 0) {
optionsType.push('user')
}
} else {
optionsType = ['person', 'thirdparty', 'user'];
}
return {
type: optionsType,
priority: null,
uniq: false,
button: {
size: 'btn-sm'
}
}
},
}, },
mounted() { mounted() {
this.setPersonsInBloc(); this.setPersonsInBloc();
@@ -171,7 +191,7 @@ export default {
}, },
addNewPersons({ selected, modal }) { addNewPersons({ selected, modal }) {
console.log('@@@ CLICK button addNewPersons', selected); console.log('@@@ CLICK button addNewPersons', selected);
selected.forEach(function(item) { selected.forEach((item) => {
this.$store.dispatch('addPersonsInvolved', item); this.$store.dispatch('addPersonsInvolved', item);
}, this }, this
); );
@@ -179,7 +199,7 @@ export default {
modal.showModal = false; modal.showModal = false;
this.setPersonsInBloc(); this.setPersonsInBloc();
}, },
addNewPerson(person) { addSuggestedEntity(person) {
this.$store.dispatch('addPersonsInvolved', { result: person, type: 'person' }); this.$store.dispatch('addPersonsInvolved', { result: person, type: 'person' });
this.setPersonsInBloc(); this.setPersonsInBloc();
}, },

View File

@@ -55,16 +55,17 @@ export default {
} }
}, },
mounted() { mounted() {
this.getLocationsList(); getLocations().then(response => new Promise(resolve => {
console.log('getLocations', response);
this.locations = response.results;
if (window.default_location_id) {
let location = this.locations.filter(l => l.id === window.default_location_id);
this.$store.dispatch('updateLocation', location);
}
resolve();
}))
}, },
methods: { methods: {
getLocationsList() {
getLocations().then(response => new Promise(resolve => {
console.log('getLocations', response);
this.locations = response.results;
resolve();
}))
},
customLabel(value) { customLabel(value) {
return `${value.locationType.title.fr} ${value.name ? value.name : ''}`; return `${value.locationType.title.fr} ${value.name ? value.name : ''}`;
} }

View File

@@ -19,172 +19,294 @@ const removeIdFromValue = (string, id) => {
}; };
const store = createStore({ const store = createStore({
strict: debug, strict: debug,
state: { state: {
activity: window.activity, activity: window.activity,
socialIssuesOther: [], socialIssuesOther: [],
socialActionsList: [], socialActionsList: [],
},
getters: {
filterSuggestedPersons(state) {
if (typeof(state.activity.accompanyingPeriod) === 'undefined') {
return [];
}
let existingPersonIds = state.activity.persons.map(p => p.id);
return state.activity.accompanyingPeriod.participations.filter(p => p.endDate === null)
.map(p => p.person)
.filter(p => !existingPersonIds.includes(p.id))
}
},
mutations: {
// SocialIssueAcc
addIssueInList(state, issue) {
//console.log('add issue list', issue.id);
state.activity.accompanyingPeriod.socialIssues.push(issue);
},
addIssueSelected(state, issue) {
//console.log('add issue selected', issue.id);
state.activity.socialIssues.push(issue);
},
updateIssuesSelected(state, issues) {
//console.log('update issues selected', issues);
state.activity.socialIssues = issues;
},
updateIssuesOther(state, payload) {
//console.log('update issues other');
state.socialIssuesOther = payload;
},
removeIssueInOther(state, issue) {
//console.log('remove issue other', issue.id);
state.socialIssuesOther = state.socialIssuesOther.filter(i => i.id !== issue.id);
},
resetActionsList(state) {
//console.log('reset list actions');
state.socialActionsList = [];
},
addActionInList(state, action) {
//console.log('add action list', action.id);
state.socialActionsList.push(action);
},
updateActionsSelected(state, actions) {
//console.log('update actions selected', actions);
state.activity.socialActions = actions;
},
filterList(state, list) {
const filterList = (list) => {
// remove duplicates entries
list = list.filter((value, index) => list.findIndex(array => array.id === value.id) === index);
// alpha sort
list.sort((a,b) => (a.text > b.text) ? 1 : ((b.text > a.text) ? -1 : 0));
return list;
};
if (list === 'issues') {
state.activity.accompanyingPeriod.socialIssues = filterList(state.activity.accompanyingPeriod.socialIssues);
}
if (list === 'actions') {
state.socialActionsList = filterList(state.socialActionsList);
}
}, },
getters: {
suggestedEntities(state) {
console.log(state.activity);
if (typeof state.activity.accompanyingPeriod === "undefined") {
return [];
}
const allEntities = [
...store.getters.suggestedPersons,
...store.getters.suggestedRequestor,
...store.getters.suggestedUser,
...store.getters.suggestedResources,
];
const uniqueIds = [
...new Set(allEntities.map((i) => `${i.type}-${i.id}`)),
];
return Array.from(
uniqueIds,
(id) => allEntities.filter((r) => `${r.type}-${r.id}` === id)[0]
);
},
suggestedPersons(state) {
const existingPersonIds = state.activity.persons.map((p) => p.id);
return state.activity.activityType.personsVisible === 0
? []
: state.activity.accompanyingPeriod.participations
.filter((p) => p.endDate === null)
.map((p) => p.person)
.filter((p) => !existingPersonIds.includes(p.id));
},
suggestedRequestor(state) {
if (state.activity.accompanyingPeriod.requestor === null) {
return [];
}
const existingPersonIds = state.activity.persons.map((p) => p.id);
const existingThirdPartyIds = state.activity.thirdParties.map(
(p) => p.id
);
// ConcernedGroups return [state.activity.accompanyingPeriod.requestor].filter(
addPersonsInvolved(state, payload) { (r) =>
//console.log('### mutation addPersonsInvolved', payload.result.type); (r.type === "person" &&
switch (payload.result.type) { !existingPersonIds.includes(r.id) &&
case 'person': state.activity.activityType.personsVisible !== 0) ||
state.activity.persons.push(payload.result); (r.type === "thirdparty" &&
break; !existingThirdPartyIds.includes(r.id) &&
case 'thirdparty': state.activity.activityType.thirdPartiesVisible !== 0)
state.activity.thirdParties.push(payload.result); );
break; },
case 'user': suggestedUser(state) {
state.activity.users.push(payload.result); const existingUserIds = state.activity.users.map((p) => p.id);
break; return state.activity.activityType.usersVisible === 0
}; ? []
: [state.activity.accompanyingPeriod.user].filter(
(u) => u !== null && !existingUserIds.includes(u.id)
);
},
suggestedResources(state) {
const resources = state.activity.accompanyingPeriod.resources;
const existingPersonIds = state.activity.persons.map((p) => p.id);
const existingThirdPartyIds = state.activity.thirdParties.map(
(p) => p.id
);
return state.activity.accompanyingPeriod.resources
.map((r) => r.resource)
.filter(
(r) =>
(r.type === "person" &&
!existingPersonIds.includes(r.id) &&
state.activity.activityType.personsVisible !== 0) ||
(r.type === "thirdparty" &&
!existingThirdPartyIds.includes(r.id) &&
state.activity.activityType.thirdPartiesVisible !== 0)
);
},
}, },
removePersonInvolved(state, payload) { mutations: {
//console.log('### mutation removePersonInvolved', payload.type); // SocialIssueAcc
switch (payload.type) { addIssueInList(state, issue) {
case 'person': //console.log('add issue list', issue.id);
state.activity.persons = state.activity.persons.filter(person => person !== payload); state.activity.accompanyingPeriod.socialIssues.push(issue);
break; },
case 'thirdparty': addIssueSelected(state, issue) {
state.activity.thirdParties = state.activity.thirdParties.filter(thirdparty => thirdparty !== payload); //console.log('add issue selected', issue.id);
break; state.activity.socialIssues.push(issue);
case 'user': },
state.activity.users = state.activity.users.filter(user => user !== payload); updateIssuesSelected(state, issues) {
break; //console.log('update issues selected', issues);
}; state.activity.socialIssues = issues;
},
updateIssuesOther(state, payload) {
//console.log('update issues other');
state.socialIssuesOther = payload;
},
removeIssueInOther(state, issue) {
//console.log('remove issue other', issue.id);
state.socialIssuesOther = state.socialIssuesOther.filter(
(i) => i.id !== issue.id
);
},
resetActionsList(state) {
//console.log('reset list actions');
state.socialActionsList = [];
},
addActionInList(state, action) {
//console.log('add action list', action.id);
state.socialActionsList.push(action);
},
updateActionsSelected(state, actions) {
//console.log('update actions selected', actions);
state.activity.socialActions = actions;
},
filterList(state, list) {
const filterList = (list) => {
// remove duplicates entries
list = list.filter(
(value, index) =>
list.findIndex((array) => array.id === value.id) ===
index
);
// alpha sort
list.sort((a, b) =>
a.text > b.text ? 1 : b.text > a.text ? -1 : 0
);
return list;
};
if (list === "issues") {
state.activity.accompanyingPeriod.socialIssues = filterList(
state.activity.accompanyingPeriod.socialIssues
);
}
if (list === "actions") {
state.socialActionsList = filterList(state.socialActionsList);
}
},
// ConcernedGroups
addPersonsInvolved(state, payload) {
console.log("### mutation addPersonsInvolved", payload);
switch (payload.result.type) {
case "person":
state.activity.persons.push(payload.result);
break;
case "thirdparty":
state.activity.thirdParties.push(payload.result);
break;
case "user":
state.activity.users.push(payload.result);
break;
}
},
removePersonInvolved(state, payload) {
//console.log('### mutation removePersonInvolved', payload.type);
switch (payload.type) {
case "person":
state.activity.persons = state.activity.persons.filter(
(person) => person !== payload
);
break;
case "thirdparty":
state.activity.thirdParties =
state.activity.thirdParties.filter(
(thirdparty) => thirdparty !== payload
);
break;
case "user":
state.activity.users = state.activity.users.filter(
(user) => user !== payload
);
break;
}
},
updateLocation(state, value) {
console.log("### mutation: updateLocation", value);
state.activity.location = value;
},
}, },
updateLocation(state, value) { actions: {
console.log('### mutation: updateLocation', value); addIssueSelected({ commit }, issue) {
state.activity.location = value; let aSocialIssues = document.getElementById(
} "chill_activitybundle_activity_socialIssues"
}, );
actions: { aSocialIssues.value = addIdToValue(aSocialIssues.value, issue.id);
addIssueSelected({ commit }, issue) { commit("addIssueSelected", issue);
let aSocialIssues = document.getElementById("chill_activitybundle_activity_socialIssues"); },
aSocialIssues.value = addIdToValue(aSocialIssues.value, issue.id); updateIssuesSelected({ commit }, payload) {
commit('addIssueSelected', issue); let aSocialIssues = document.getElementById(
"chill_activitybundle_activity_socialIssues"
);
aSocialIssues.value = "";
payload.forEach((item) => {
aSocialIssues.value = addIdToValue(
aSocialIssues.value,
item.id
);
});
commit("updateIssuesSelected", payload);
},
updateActionsSelected({ commit }, payload) {
let aSocialActions = document.getElementById(
"chill_activitybundle_activity_socialActions"
);
aSocialActions.value = "";
payload.forEach((item) => {
aSocialActions.value = addIdToValue(
aSocialActions.value,
item.id
);
});
commit("updateActionsSelected", payload);
},
addPersonsInvolved({ commit }, payload) {
//console.log('### action addPersonsInvolved', payload.result.type);
switch (payload.result.type) {
case "person":
let aPersons = document.getElementById(
"chill_activitybundle_activity_persons"
);
aPersons.value = addIdToValue(
aPersons.value,
payload.result.id
);
break;
case "thirdparty":
let aThirdParties = document.getElementById(
"chill_activitybundle_activity_thirdParties"
);
aThirdParties.value = addIdToValue(
aThirdParties.value,
payload.result.id
);
break;
case "user":
let aUsers = document.getElementById(
"chill_activitybundle_activity_users"
);
aUsers.value = addIdToValue(
aUsers.value,
payload.result.id
);
break;
}
commit("addPersonsInvolved", payload);
},
removePersonInvolved({ commit }, payload) {
//console.log('### action removePersonInvolved', payload);
switch (payload.type) {
case "person":
let aPersons = document.getElementById(
"chill_activitybundle_activity_persons"
);
aPersons.value = removeIdFromValue(
aPersons.value,
payload.id
);
break;
case "thirdparty":
let aThirdParties = document.getElementById(
"chill_activitybundle_activity_thirdParties"
);
aThirdParties.value = removeIdFromValue(
aThirdParties.value,
payload.id
);
break;
case "user":
let aUsers = document.getElementById(
"chill_activitybundle_activity_users"
);
aUsers.value = removeIdFromValue(aUsers.value, payload.id);
break;
}
commit("removePersonInvolved", payload);
},
updateLocation({ commit }, value) {
console.log("### action: updateLocation", value);
let hiddenLocation = document.getElementById(
"chill_activitybundle_activity_location"
);
hiddenLocation.value = value.id;
commit("updateLocation", value);
},
}, },
updateIssuesSelected({ commit }, payload) {
let aSocialIssues = document.getElementById("chill_activitybundle_activity_socialIssues");
aSocialIssues.value = '';
payload.forEach(item => {
aSocialIssues.value = addIdToValue(aSocialIssues.value, item.id);
});
commit('updateIssuesSelected', payload);
},
updateActionsSelected({ commit }, payload) {
let aSocialActions = document.getElementById("chill_activitybundle_activity_socialActions");
aSocialActions.value = '';
payload.forEach(item => {
aSocialActions.value = addIdToValue(aSocialActions.value, item.id);
});
commit('updateActionsSelected', payload);
},
addPersonsInvolved({ commit }, payload) {
//console.log('### action addPersonsInvolved', payload.result.type);
switch (payload.result.type) {
case 'person':
let aPersons = document.getElementById("chill_activitybundle_activity_persons");
aPersons.value = addIdToValue(aPersons.value, payload.result.id);
break;
case 'thirdparty':
let aThirdParties = document.getElementById("chill_activitybundle_activity_thirdParties");
aThirdParties.value = addIdToValue(aThirdParties.value, payload.result.id);
break;
case 'user':
let aUsers = document.getElementById("chill_activitybundle_activity_users");
aUsers.value = addIdToValue(aUsers.value, payload.result.id);
break;
};
commit('addPersonsInvolved', payload);
},
removePersonInvolved({ commit }, payload) {
//console.log('### action removePersonInvolved', payload);
switch (payload.type) {
case 'person':
let aPersons = document.getElementById("chill_activitybundle_activity_persons");
aPersons.value = removeIdFromValue(aPersons.value, payload.id);
break;
case 'thirdparty':
let aThirdParties = document.getElementById("chill_activitybundle_activity_thirdParties");
aThirdParties.value = removeIdFromValue(aThirdParties.value, payload.id);
break;
case 'user':
let aUsers = document.getElementById("chill_activitybundle_activity_users");
aUsers.value = removeIdFromValue(aUsers.value, payload.id);
break;
};
commit('removePersonInvolved', payload);
},
updateLocation({ commit }, value) {
console.log('### action: updateLocation', value);
let hiddenLocation = document.getElementById("chill_activitybundle_activity_location");
hiddenLocation.value = value.id;
commit('updateLocation', value);
}
}
}); });
export default store; export default store;

View File

@@ -1,13 +1,36 @@
<?php <?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\Config\Loader\LoaderInterface;
use Symfony\Component\HttpKernel\Kernel;
class AppKernel extends 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() public function registerBundles()
{ {
return array( return [
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Chill\CustomFieldsBundle\ChillCustomFieldsBundle(), new Chill\CustomFieldsBundle\ChillCustomFieldsBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(), new Symfony\Bundle\SecurityBundle\SecurityBundle(),
@@ -20,28 +43,12 @@ class AppKernel extends Kernel
new \Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle(), new \Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle(),
new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(), new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(), 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) public function registerContainerConfiguration(LoaderInterface $loader)
{ {
$loader->load($this->getRootDir().'/config/config_'.$this->getEnvironment().'.yml'); $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';
} }
} }

View File

@@ -1,11 +1,18 @@
<?php <?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 Composer\Autoload\ClassLoader;
use Doctrine\Common\Annotations\AnnotationRegistry;
/** @var ClassLoader $loader */ /** @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; return $loader;

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,14 @@
<?php <?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\Debug\Debug;
use Symfony\Component\HttpFoundation\Request;
// If you don't want to setup permissions the proper way, just uncomment the following PHP line // 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 // 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. // Feel free to remove this, extend it, or make something more sophisticated.
if (isset($_SERVER['HTTP_CLIENT_IP']) if (isset($_SERVER['HTTP_CLIENT_IP'])
|| isset($_SERVER['HTTP_X_FORWARDED_FOR']) || 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'); 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(); Debug::enable();
require_once __DIR__.'/../app/AppKernel.php'; require_once __DIR__ . '/../app/AppKernel.php';
$kernel = new AppKernel('dev', true); $kernel = new AppKernel('dev', true);
$kernel->loadClassCache(); $kernel->loadClassCache();

View File

@@ -12,12 +12,11 @@
}, },
{ 'title': 'Third parties'|trans, { 'title': 'Third parties'|trans,
'items': entity.thirdParties, 'items': entity.thirdParties,
'path' : 'chill_3party_3party_show', 'path' : 'chill_crud_3party_3party_view',
'key' : 'thirdparty_id' 'key' : 'id'
}, },
{ 'title': 'Users concerned'|trans, { 'title': 'Users concerned'|trans,
'items': entity.users, 'items': entity.users,
'path' : 'admin_user_show',
'key' : 'id' 'key' : 'id'
}, },
] %} ] %}
@@ -35,8 +34,8 @@
}, },
{ 'title': 'Third parties'|trans, { 'title': 'Third parties'|trans,
'items': entity.thirdParties, 'items': entity.thirdParties,
'path' : 'chill_3party_3party_show', 'path' : 'chill_crud_3party_3party_view',
'key' : 'thirdparty_id' 'key' : 'id'
}, },
{ 'title': 'Users concerned'|trans, { 'title': 'Users concerned'|trans,
'items': entity.users, 'items': entity.users,

View File

@@ -34,16 +34,18 @@
{{ form_row(edit_form.reasons) }} {{ form_row(edit_form.reasons) }}
{% endif %} {% endif %}
<h2 class="chill-red">{{ 'Concerned groups'|trans }}</h2> {%- if edit_form.persons is defined or edit_form.thirdParties is defined or edit_form.users is defined -%}
<h2 class="chill-red">{{ 'Concerned groups'|trans }}</h2>
{%- if edit_form.persons is defined -%} {%- if edit_form.persons is defined -%}
{{ form_widget(edit_form.persons) }} {{ form_widget(edit_form.persons) }}
{% endif %} {% endif %}
{%- if edit_form.thirdParties is defined -%} {%- if edit_form.thirdParties is defined -%}
{{ form_widget(edit_form.thirdParties) }} {{ form_widget(edit_form.thirdParties) }}
{% endif %} {% endif %}
{%- if edit_form.users is defined -%} {%- if edit_form.users is defined -%}
{{ form_widget(edit_form.users) }} {{ form_widget(edit_form.users) }}
{% endif %}
{% endif %} {% endif %}
<div id="add-persons"></div> <div id="add-persons"></div>

View File

@@ -20,12 +20,14 @@
{% include 'ChillActivityBundle:Activity:list.html.twig' with {'context': 'accompanyingCourse'} %} {% include 'ChillActivityBundle:Activity:list.html.twig' with {'context': 'accompanyingCourse'} %}
{% if is_granted('CHILL_ACTIVITY_CREATE', accompanyingCourse) %}
<ul class="record_actions sticky-form-buttons"> <ul class="record_actions sticky-form-buttons">
<li> <li>
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-create"> <a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-create">
{{ 'Add a new activity' | trans }} {{ 'Create'|trans }}
</a> </a>
</li> </li>
</ul> </ul>
{% endif %}
{% endblock %} {% endblock %}

View File

@@ -22,6 +22,7 @@
'{{ "You are going to leave a page with unsubmitted data. Are you sure you want to leave ?"|trans }}'); '{{ "You are going to leave a page with unsubmitted data. Are you sure you want to leave ?"|trans }}');
}); });
window.activity = {{ activity_json|json_encode|raw }}; window.activity = {{ activity_json|json_encode|raw }};
window.default_location_id = {{ default_location_id }};
</script> </script>
{{ encore_entry_script_tags('vue_activity') }} {{ encore_entry_script_tags('vue_activity') }}
{% endblock %} {% endblock %}

View File

@@ -1,41 +1,27 @@
<?php <?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 * For the full copyright and license information, please view
* it under the terms of the GNU Affero General Public License as published by * the LICENSE file that was distributed with this source code.
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\Security\Authorization; namespace Chill\ActivityBundle\Security\Authorization;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Security\Authorization\AbstractChillVoter; use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface; 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 class ActivityStatsVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
{ {
const STATS = 'CHILL_ACTIVITY_STATS'; public const LISTS = 'CHILL_ACTIVITY_LIST';
const LISTS = 'CHILL_ACTIVITY_LIST';
public const STATS = 'CHILL_ACTIVITY_STATS';
/** /**
*
* @var AuthorizationHelper * @var AuthorizationHelper
*/ */
protected $helper; protected $helper;
@@ -45,25 +31,24 @@ class ActivityStatsVoter extends AbstractChillVoter implements ProvideRoleHierar
$this->helper = $helper; $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() protected function getSupportedClasses()
{ {
return array(Center::class); return [Center::class];
}
protected function supports($attribute, $subject)
{
if ($subject instanceof Center
&& \in_array($attribute, $this->getAttributes())) {
return true;
}
return false;
} }
protected function isGranted($attribute, $object, $user = null) protected function isGranted($attribute, $object, $user = null)
@@ -75,18 +60,18 @@ class ActivityStatsVoter extends AbstractChillVoter implements ProvideRoleHierar
return $this->helper->userHasAccess($user, $object, $attribute); return $this->helper->userHasAccess($user, $object, $attribute);
} }
public function getRoles() protected function supports($attribute, $subject)
{ {
return $this->getAttributes(); if ($subject instanceof Center
&& in_array($attribute, $this->getAttributes())) {
return true;
}
return false;
} }
public function getRolesWithoutScope() private function getAttributes()
{ {
return $this->getAttributes(); return [self::STATS, self::LISTS];
}
public function getRolesWithHierarchy()
{
return [ 'Activity' => $this->getRoles() ];
} }
} }

View File

@@ -1,51 +1,68 @@
<?php <?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 * For the full copyright and license information, please view
* it under the terms of the GNU Affero General Public License as published by * the LICENSE file that was distributed with this source code.
* 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/>.
*/ */
declare(strict_types=1);
namespace Chill\ActivityBundle\Security\Authorization; 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\VoterHelperFactoryInterface;
use Chill\MainBundle\Security\Authorization\VoterHelperInterface; use Chill\MainBundle\Security\Authorization\VoterHelperInterface;
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use Chill\PersonBundle\Security\Authorization\PersonVoter; use Chill\PersonBundle\Security\Authorization\PersonVoter;
use RuntimeException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
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\Role\Role;
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
use function in_array;
/**
* Voter for Activity class
*/
class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
{ {
const CREATE = 'CHILL_ACTIVITY_CREATE'; /**
const SEE = 'CHILL_ACTIVITY_SEE'; * allow to create an activity, which will either be associated to an
const SEE_DETAILS = 'CHILL_ACTIVITY_SEE_DETAILS'; * accompanying course or person.
const UPDATE = 'CHILL_ACTIVITY_UPDATE'; *
const DELETE = 'CHILL_ACTIVITY_DELETE'; * It is safe for usage in template and controller
const FULL = 'CHILL_ACTIVITY_FULL'; */
public const CREATE = 'CHILL_ACTIVITY_CREATE';
/**
* role to allow to create an activity associated win an accompanying course.
*
* 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.
*
* Before using this, check if @see{self::CREATE} is not sufficiant
*
* @internal
*/
public const CREATE_PERSON = 'CHILL_ACTIVITY_CREATE_PERSON';
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 = [ private const ALL = [
self::CREATE, self::CREATE,
@@ -53,13 +70,13 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
self::UPDATE, self::UPDATE,
self::DELETE, self::DELETE,
self::SEE_DETAILS, self::SEE_DETAILS,
self::FULL self::FULL,
]; ];
protected VoterHelperInterface $voterHelper;
protected Security $security; protected Security $security;
protected VoterHelperInterface $voterHelper;
public function __construct( public function __construct(
Security $security, Security $security,
VoterHelperFactoryInterface $voterHelperFactory VoterHelperFactoryInterface $voterHelperFactory
@@ -72,13 +89,33 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
->build(); ->build();
} }
public function getRoles(): array
{
return [
self::CREATE_PERSON,
self::CREATE_ACCOMPANYING_COURSE,
self::UPDATE,
self::DELETE,
self::FULL,
];
}
protected function supports($attribute, $subject) 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); return $this->voterHelper->supports($attribute, $subject);
} }
protected function voteOnAttribute($attribute, $subject, TokenInterface $token) protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{ {
if (!$token->getUser() instanceof User) { if (!$token->getUser() instanceof User) {
return false; return false;
@@ -90,33 +127,43 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
if (!$this->security->isGranted(PersonVoter::SEE, $subject->getPerson())) { if (!$this->security->isGranted(PersonVoter::SEE, $subject->getPerson())) {
return false; return false;
} }
// change attribute CREATE
if (self::CREATE === $attribute) {
$attribute = self::CREATE_PERSON;
}
} elseif ($subject->getAccompanyingPeriod() instanceof AccompanyingPeriod) { } elseif ($subject->getAccompanyingPeriod() instanceof AccompanyingPeriod) {
if (!$this->security->isGranted(AccompanyingPeriodVoter::SEE, $subject->getAccompanyingPeriod())) { if (!$this->security->isGranted(AccompanyingPeriodVoter::SEE, $subject->getAccompanyingPeriod())) {
return false; return false;
} }
if (self::CREATE === $attribute) {
if (AccompanyingPeriod::STEP_CLOSED === $subject->getAccompanyingPeriod()->getStep()) {
return false;
}
$attribute = self::CREATE_ACCOMPANYING_COURSE;
}
} else { } 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)) {
return false;
}
}
// transform the attribute
if (self::CREATE === $attribute) {
$attribute = self::CREATE_ACCOMPANYING_COURSE;
}
} elseif ($subject instanceof Person) {
// transform the attribute
if (self::CREATE === $attribute) {
$attribute = self::CREATE_PERSON;
} }
} }
return $this->voterHelper->voteOnAttribute($attribute, $subject, $token); return $this->voterHelper->voteOnAttribute($attribute, $subject, $token);
} }
public function getRoles()
{
return self::ALL;
}
public function getRolesWithoutScope()
{
return [];
}
public function getRolesWithHierarchy()
{
return [ 'Activity' => $this->getRoles() ];
}
} }

View File

@@ -1,37 +1,24 @@
<?php <?php
/*
/**
* Chill is a software for social workers * Chill is a software for social workers
* *
* Copyright (C) 2014-2020, Champs Libres Cooperative SCRLFS, * For the full copyright and license information, please view
* <http://www.champs-libres.coop>, <info@champs-libres.coop> * the LICENSE file that was distributed with this source code.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\Templating\Entity; namespace Chill\ActivityBundle\Templating\Entity;
use Chill\MainBundle\Templating\Entity\AbstractChillEntityRender;
use Chill\ActivityBundle\Entity\ActivityReason; use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\MainBundle\Templating\Entity\AbstractChillEntityRender;
use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\MainBundle\Templating\TranslatableStringHelper;
/** /**
* Render activity reason * Render activity reason.
*
*/ */
class ActivityReasonRender extends AbstractChillEntityRender class ActivityReasonRender extends AbstractChillEntityRender
{ {
/** /**
*
* @var TranslatableStringHelper * @var TranslatableStringHelper
*/ */
protected $translatableStringHelper; protected $translatableStringHelper;
@@ -41,34 +28,29 @@ class ActivityReasonRender extends AbstractChillEntityRender
$this->translatableStringHelper = $translatableStringHelper; $this->translatableStringHelper = $translatableStringHelper;
} }
public function renderBox($entity, array $options): string public function renderBox($entity, array $options): string
{ {
return return
$this->getDefaultOpeningBox('activity-reason'). $this->getDefaultOpeningBox('activity-reason') .
'<span class="badge bg-chill-pink">'. '<span class="badge bg-chill-pink">' .
'<i class="fa fa-question-circle"></i>&nbsp;'. '<i class="fa fa-question-circle"></i>&nbsp;' .
'<span class="category">'. '<span class="category">' .
$this->translatableStringHelper->localize( $this->translatableStringHelper->localize(
$entity->getCategory()->getName() $entity->getCategory()->getName()
). ) .
'</span>'. '</span>' .
'<span class="separator">&nbsp;>&nbsp;</span>'. '<span class="separator">&nbsp;>&nbsp;</span>' .
'<span class="reason">'. '<span class="reason">' .
$this->translatableStringHelper->localize( $this->translatableStringHelper->localize(
$entity->getName() $entity->getName()
). ) .
'</span>'. '</span>' .
'</span>'. '</span>' .
$this->getDefaultClosingBox() $this->getDefaultClosingBox();
;
} }
/** /**
*
* @param ActivityReason $entity * @param ActivityReason $entity
* @param array $options
* @return string
*/ */
public function renderString($entity, array $options): string public function renderString($entity, array $options): string
{ {
@@ -76,7 +58,8 @@ class ActivityReasonRender extends AbstractChillEntityRender
if (null !== $entity->getCategory()) { if (null !== $entity->getCategory()) {
$category = $this->translatableStringHelper->localize( $category = $this->translatableStringHelper->localize(
$entity->getCategory()->getName()). ' > '; $entity->getCategory()->getName()
) . ' > ';
} }
return $category . return $category .

View File

@@ -1,20 +1,10 @@
<?php <?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 * For the full copyright and license information, please view
* it under the terms of the GNU Affero General Public License as published by * the LICENSE file that was distributed with this source code.
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\Test; namespace Chill\ActivityBundle\Test;
@@ -24,26 +14,19 @@ use Chill\MainBundle\Entity\Scope;
use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\Person;
/** /**
* Prepare entities useful in tests * Prepare entities useful in tests.
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/ */
trait PrepareActivityTrait trait PrepareActivityTrait
{ {
/** /**
* Return an activity with a scope and a person inside * Return an activity with a scope and a person inside.
* *
* @param Scope $scope
* @param Person $person
* @return Activity * @return Activity
*/ */
public function prepareActivity(Scope $scope, Person $person) public function prepareActivity(Scope $scope, Person $person)
{ {
return (new Activity()) return (new Activity())
->setScope($scope) ->setScope($scope)
->setPerson($person) ->setPerson($person);
;
} }
} }

View File

@@ -1,16 +1,78 @@
<?php <?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; namespace Chill\ActivityBundle\Tests\Controller;
use RuntimeException;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\HttpFoundation\Response;
/**
* @internal
* @coversNothing
*/
class ActivityControllerTest extends WebTestCase 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 * @dataProvider getSecuredPagesUnauthenticated
*
* @param mixed $url
*/ */
public function testAccessIsDeniedForUnauthenticated($url) public function testAccessIsDeniedForUnauthenticated($url)
{ {
@@ -19,13 +81,15 @@ class ActivityControllerTest extends WebTestCase
$client->request('GET', $url); $client->request('GET', $url);
$this->assertEquals(302, $client->getResponse()->getStatusCode()); $this->assertEquals(302, $client->getResponse()->getStatusCode());
$this->assertTrue($client->getResponse()->isRedirect('http://localhost/login'), $this->assertTrue(
sprintf('the page "%s" does not redirect to http://localhost/login', $url)); $client->getResponse()->isRedirect('http://localhost/login'),
sprintf('the page "%s" does not redirect to http://localhost/login', $url)
);
} }
/** /**
*
* @dataProvider getSecuredPagesAuthenticated * @dataProvider getSecuredPagesAuthenticated
*
* @param type $client * @param type $client
* @param type $url * @param type $url
*/ */
@@ -36,63 +100,6 @@ class ActivityControllerTest extends WebTestCase
$this->assertEquals(403, $client->getResponse()->getStatusCode()); $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() public function testCompleteScenario()
{ {
// Create a new client to browse the application // Create a new client to browse the application
@@ -100,27 +107,32 @@ class ActivityControllerTest extends WebTestCase
$person = $this->getPersonFromFixtures(); $person = $this->getPersonFromFixtures();
// Create a new entry in the database // Create a new entry in the database
$crawler = $client->request('GET', sprintf('en/person/%d/activity/', $crawler = $client->request('GET', sprintf(
$person->getId())); 'en/person/%d/activity/',
$this->assertEquals(200, $client->getResponse()->getStatusCode(), $person->getId()
"Unexpected HTTP status code for GET /activity/"); ));
$this->assertEquals(
200,
$client->getResponse()->getStatusCode(),
'Unexpected HTTP status code for GET /activity/'
);
$crawler = $client->click($crawler->selectLink('Ajouter une nouvelle activité') $crawler = $client->click($crawler->selectLink('Ajouter une nouvelle activité')
->link()); ->link());
$reason1 = $this->getRandomActivityReason(); $reason1 = $this->getRandomActivityReason();
$reason2 = $this->getRandomActivityReason(array($reason1->getId())); $reason2 = $this->getRandomActivityReason([$reason1->getId()]);
// Fill in the form and submit it // Fill in the form and submit it
$form = $crawler->selectButton('Ajouter une nouvelle activité')->form(array( $form = $crawler->selectButton('Ajouter une nouvelle activité')->form([
'chill_activitybundle_activity'=> array( 'chill_activitybundle_activity' => [
'date' => '15-01-2015', 'date' => '15-01-2015',
'durationTime' => 600, 'durationTime' => 600,
// 'remark' => 'blabla', // 'remark' => 'blabla',
'scope' => $this->getRandomScope('center a_social', 'Center A')->getId(), 'scope' => $this->getRandomScope('center a_social', 'Center A')->getId(),
'type' => $this->getRandomActivityType()->getId() 'type' => $this->getRandomActivityType()->getId(),
) ],
)); ]);
$form['chill_activitybundle_activity[reasons]']->select(array ($reason1->getId(), $reason2->getId())); $form['chill_activitybundle_activity[reasons]']->select([$reason1->getId(), $reason2->getId()]);
$client->submit($form); $client->submit($form);
@@ -128,18 +140,21 @@ class ActivityControllerTest extends WebTestCase
$crawler = $client->followRedirect(); $crawler = $client->followRedirect();
// Check data in the show view // Check data in the show view
$this->assertGreaterThan(0, $crawler->filter('dd:contains("January 15, 2015")')->count(), $this->assertGreaterThan(
'Missing element dd:contains("January 15, 2015")'); 0,
$crawler->filter('dd:contains("January 15, 2015")')->count(),
'Missing element dd:contains("January 15, 2015")'
);
// Edit the entity // Edit the entity
$crawler = $client->click($crawler->selectLink("Modifier l'activité")->link()); $crawler = $client->click($crawler->selectLink("Modifier l'activité")->link());
$form = $crawler->selectButton("Sauver l'activité")->form(array( $form = $crawler->selectButton("Sauver l'activité")->form([
'chill_activitybundle_activity' => array( 'chill_activitybundle_activity' => [
'date' => '25-01-2015', 'date' => '25-01-2015',
// 'remark' => 'Foo' // 'remark' => 'Foo'
) ],
)); ]);
$client->submit($form); $client->submit($form);
@@ -148,164 +163,33 @@ class ActivityControllerTest extends WebTestCase
$crawler = $client->followRedirect(); $crawler = $client->followRedirect();
// check that new data are present // check that new data are present
$this->assertGreaterThan(0, $this->assertGreaterThan(
$crawler->filter('dd:contains("January 25, 2015")')->count(), 0,
'Missing element dd:contains("January 25, 2015")'); $crawler->filter('dd:contains("January 25, 2015")')->count(),
$this->assertGreaterThan(0, 'Missing element dd:contains("January 25, 2015")'
$crawler->filter('dd:contains("Foo")')->count(), );
'Missing element dd:contains("Foo")'); $this->assertGreaterThan(
0,
$crawler->filter('dd:contains("Foo")')->count(),
'Missing element dd:contains("Foo")'
);
// delete the actvity // 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); $client->submit($form);
$this->assertTrue($client->getResponse()->isRedirect(sprintf('/en/person/%d/activity/', $this->assertTrue($client->getResponse()->isRedirect(sprintf(
$person->getId()))); '/en/person/%d/activity/',
$person->getId()
)));
$crawler = $client->followRedirect(); $crawler = $client->followRedirect();
$this->assertNotContains('January 25, 2015', $crawler->text()); $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)];
} }
/** /**
@@ -321,10 +205,10 @@ class ActivityControllerTest extends WebTestCase
//get the social PermissionGroup, and remove CHILL_ACTIVITY_* //get the social PermissionGroup, and remove CHILL_ACTIVITY_*
$socialPermissionGroup = $em $socialPermissionGroup = $em
->getRepository('ChillMainBundle:PermissionsGroup') ->getRepository('ChillMainBundle:PermissionsGroup')
->findOneByName('social'); ->findOneByName('social');
$withoutActivityPermissionGroup = (new \Chill\MainBundle\Entity\PermissionsGroup()) $withoutActivityPermissionGroup = (new \Chill\MainBundle\Entity\PermissionsGroup())
->setName('social without activity'); ->setName('social without activity');
//copy role scopes where ACTIVITY is not present //copy role scopes where ACTIVITY is not present
foreach ($socialPermissionGroup->getRoleScopes() as $roleScope) { foreach ($socialPermissionGroup->getRoleScopes() as $roleScope) {
if (!strpos($roleScope->getRole(), 'ACTIVITY')) { if (!strpos($roleScope->getRole(), 'ACTIVITY')) {
@@ -334,8 +218,8 @@ class ActivityControllerTest extends WebTestCase
//create groupCenter //create groupCenter
$groupCenter = new \Chill\MainBundle\Entity\GroupCenter(); $groupCenter = new \Chill\MainBundle\Entity\GroupCenter();
$groupCenter->setCenter($em->getRepository('ChillMainBundle:Center') $groupCenter->setCenter($em->getRepository('ChillMainBundle:Center')
->findOneBy(array('name' => 'Center A'))) ->findOneBy(['name' => 'Center A']))
->setPermissionsGroup($withoutActivityPermissionGroup); ->setPermissionsGroup($withoutActivityPermissionGroup);
$em->persist($withoutActivityPermissionGroup); $em->persist($withoutActivityPermissionGroup);
$em->persist($groupCenter); $em->persist($groupCenter);
@@ -344,10 +228,10 @@ class ActivityControllerTest extends WebTestCase
$username = $faker->name; $username = $faker->name;
$user = new \Chill\MainBundle\Entity\User(); $user = new \Chill\MainBundle\Entity\User();
$user $user
->setPassword($container->get('security.password_encoder') ->setPassword($container->get('security.password_encoder')
->encodePassword($user, 'password')) ->encodePassword($user, 'password'))
->setUsername($username) ->setUsername($username)
->addGroupCenter($groupCenter); ->addGroupCenter($groupCenter);
$em->persist($user); $em->persist($user);
@@ -355,4 +239,146 @@ class ActivityControllerTest extends WebTestCase
return $user; 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 <?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; namespace Chill\ActivityBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
* @internal
* @coversNothing
*/
class ActivityReasonCategoryControllerTest extends WebTestCase class ActivityReasonCategoryControllerTest extends WebTestCase
{ {
public function testToWrite() public function testToWrite()
{ {
$this->markTestSkipped(); $this->markTestSkipped();
} }
/* /*
public function testCompleteScenario() public function testCompleteScenario()
{ {
@@ -55,5 +67,5 @@ class ActivityReasonCategoryControllerTest extends WebTestCase
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent()); $this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
} }
*/ */
} }

View File

@@ -1,15 +1,27 @@
<?php <?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; namespace Chill\ActivityBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
* @internal
* @coversNothing
*/
class ActivityReasonControllerTest extends WebTestCase class ActivityReasonControllerTest extends WebTestCase
{ {
public function testToWrite() public function testToWrite()
{ {
$this->markTestSkipped(); $this->markTestSkipped();
} }
/* /*
public function testCompleteScenario() public function testCompleteScenario()
{ {
@@ -55,5 +67,5 @@ class ActivityReasonControllerTest extends WebTestCase
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent()); $this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
} }
*/ */
} }

View File

@@ -1,15 +1,27 @@
<?php <?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; namespace Chill\ActivityBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
* @internal
* @coversNothing
*/
class ActivityTypeControllerTest extends WebTestCase class ActivityTypeControllerTest extends WebTestCase
{ {
public function testToWrite() public function testToWrite()
{ {
$this->markTestSkipped(); $this->markTestSkipped();
} }
/* /*
public function testCompleteScenario() public function testCompleteScenario()
{ {
@@ -55,5 +67,5 @@ class ActivityTypeControllerTest extends WebTestCase
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent()); $this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
} }
*/ */
} }

View File

@@ -1,20 +1,10 @@
<?php <?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 * For the full copyright and license information, please view
* it under the terms of the GNU Affero General Public License as published by * the LICENSE file that was distributed with this source code.
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\Tests\Aggregator; namespace Chill\ActivityBundle\Tests\Aggregator;
@@ -22,14 +12,14 @@ namespace Chill\ActivityBundle\Tests\Aggregator;
use Chill\MainBundle\Test\Export\AbstractAggregatorTest; 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 class ActivityReasonAggregatorTest extends AbstractAggregatorTest
{ {
/** /**
*
* @var \Chill\ActivityBundle\Export\Aggregator\ActivityReasonAggregator * @var \Chill\ActivityBundle\Export\Aggregator\ActivityReasonAggregator
*/ */
private $aggregator; private $aggregator;
@@ -43,13 +33,13 @@ class ActivityReasonAggregatorTest extends AbstractAggregatorTest
$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) // add a fake request with a default locale (used in translatable string)
$prophet = new \Prophecy\Prophet; $prophet = new \Prophecy\Prophet();
$request = $prophet->prophesize(); $request = $prophet->prophesize();
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class); $request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
$request->getLocale()->willReturn('fr'); $request->getLocale()->willReturn('fr');
$container->get('request_stack') $container->get('request_stack')
->push($request->reveal()); ->push($request->reveal());
} }
public function getAggregator() public function getAggregator()
@@ -59,22 +49,22 @@ class ActivityReasonAggregatorTest extends AbstractAggregatorTest
public function getFormData() public function getFormData()
{ {
return array( return [
array('level' => 'reasons'), ['level' => 'reasons'],
array('level' => 'categories') ['level' => 'categories'],
); ];
} }
public function getQueryBuilders() public function getQueryBuilders()
{ {
if (static::$kernel === null) { if (null === static::$kernel) {
static::bootKernel(); static::bootKernel();
} }
$em = static::$kernel->getContainer() $em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager'); ->get('doctrine.orm.entity_manager');
return array( return [
$em->createQueryBuilder() $em->createQueryBuilder()
->select('count(activity.id)') ->select('count(activity.id)')
->from('ChillActivityBundle:Activity', 'activity'), ->from('ChillActivityBundle:Activity', 'activity'),
@@ -86,8 +76,7 @@ class ActivityReasonAggregatorTest extends AbstractAggregatorTest
->select('count(activity.id)') ->select('count(activity.id)')
->from('ChillActivityBundle:Activity', 'activity') ->from('ChillActivityBundle:Activity', 'activity')
->join('activity.reasons', 'reasons') ->join('activity.reasons', 'reasons')
->join('reasons.category', 'category') ->join('reasons.category', 'category'),
); ];
} }
} }

View File

@@ -1,20 +1,10 @@
<?php <?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 * For the full copyright and license information, please view
* it under the terms of the GNU Affero General Public License as published by * the LICENSE file that was distributed with this source code.
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\Tests\Aggregator; namespace Chill\ActivityBundle\Tests\Aggregator;
@@ -22,14 +12,14 @@ namespace Chill\ActivityBundle\Tests\Aggregator;
use Chill\MainBundle\Test\Export\AbstractAggregatorTest; 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 class ActivityTypeAggregatorTest extends AbstractAggregatorTest
{ {
/** /**
*
* @var \Chill\ActivityBundle\Export\Aggregator\ActivityReasonAggregator * @var \Chill\ActivityBundle\Export\Aggregator\ActivityReasonAggregator
*/ */
private $aggregator; private $aggregator;
@@ -43,13 +33,13 @@ class ActivityTypeAggregatorTest extends AbstractAggregatorTest
$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) // add a fake request with a default locale (used in translatable string)
$prophet = new \Prophecy\Prophet; $prophet = new \Prophecy\Prophet();
$request = $prophet->prophesize(); $request = $prophet->prophesize();
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class); $request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
$request->getLocale()->willReturn('fr'); $request->getLocale()->willReturn('fr');
$container->get('request_stack') $container->get('request_stack')
->push($request->reveal()); ->push($request->reveal());
} }
public function getAggregator() public function getAggregator()
@@ -59,21 +49,21 @@ class ActivityTypeAggregatorTest extends AbstractAggregatorTest
public function getFormData() public function getFormData()
{ {
return array( return [
array() [],
); ];
} }
public function getQueryBuilders() public function getQueryBuilders()
{ {
if (static::$kernel === null) { if (null === static::$kernel) {
static::bootKernel(); static::bootKernel();
} }
$em = static::$kernel->getContainer() $em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager'); ->get('doctrine.orm.entity_manager');
return array( return [
$em->createQueryBuilder() $em->createQueryBuilder()
->select('count(activity.id)') ->select('count(activity.id)')
->from('ChillActivityBundle:Activity', 'activity'), ->from('ChillActivityBundle:Activity', 'activity'),
@@ -85,8 +75,7 @@ class ActivityTypeAggregatorTest extends AbstractAggregatorTest
->select('count(activity.id)') ->select('count(activity.id)')
->from('ChillActivityBundle:Activity', 'activity') ->from('ChillActivityBundle:Activity', 'activity')
->join('activity.reasons', 'reasons') ->join('activity.reasons', 'reasons')
->join('reasons.category', 'category') ->join('reasons.category', 'category'),
); ];
} }
} }

View File

@@ -1,20 +1,10 @@
<?php <?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 * For the full copyright and license information, please view
* it under the terms of the GNU Affero General Public License as published by * the LICENSE file that was distributed with this source code.
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\Tests\Aggregator; namespace Chill\ActivityBundle\Tests\Aggregator;
@@ -22,13 +12,14 @@ namespace Chill\ActivityBundle\Tests\Aggregator;
use Chill\MainBundle\Test\Export\AbstractAggregatorTest; use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
/** /**
* Add tests for ActivityUsernAggregator * Add tests for ActivityUsernAggregator.
* *
* @internal
* @coversNothing
*/ */
class ActivityUserAggregatorTest extends AbstractAggregatorTest class ActivityUserAggregatorTest extends AbstractAggregatorTest
{ {
/** /**
*
* @var \Chill\ActivityBundle\Export\Aggregator\ActivityUserAggregator * @var \Chill\ActivityBundle\Export\Aggregator\ActivityUserAggregator
*/ */
private $aggregator; private $aggregator;
@@ -42,13 +33,13 @@ class ActivityUserAggregatorTest extends AbstractAggregatorTest
$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) // add a fake request with a default locale (used in translatable string)
$prophet = new \Prophecy\Prophet; $prophet = new \Prophecy\Prophet();
$request = $prophet->prophesize(); $request = $prophet->prophesize();
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class); $request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
$request->getLocale()->willReturn('fr'); $request->getLocale()->willReturn('fr');
$container->get('request_stack') $container->get('request_stack')
->push($request->reveal()); ->push($request->reveal());
} }
public function getAggregator() public function getAggregator()
@@ -58,21 +49,21 @@ class ActivityUserAggregatorTest extends AbstractAggregatorTest
public function getFormData() public function getFormData()
{ {
return array( return [
array() [],
); ];
} }
public function getQueryBuilders() public function getQueryBuilders()
{ {
if (static::$kernel === null) { if (null === static::$kernel) {
static::bootKernel(); static::bootKernel();
} }
$em = static::$kernel->getContainer() $em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager'); ->get('doctrine.orm.entity_manager');
return array( return [
$em->createQueryBuilder() $em->createQueryBuilder()
->select('count(activity.id)') ->select('count(activity.id)')
->from('ChillActivityBundle:Activity', 'activity'), ->from('ChillActivityBundle:Activity', 'activity'),
@@ -84,8 +75,7 @@ class ActivityUserAggregatorTest extends AbstractAggregatorTest
->select('count(activity.id)') ->select('count(activity.id)')
->from('ChillActivityBundle:Activity', 'activity') ->from('ChillActivityBundle:Activity', 'activity')
->join('activity.reasons', 'reasons') ->join('activity.reasons', 'reasons')
->join('reasons.category', 'category') ->join('reasons.category', 'category'),
); ];
} }
} }

View File

@@ -1,18 +1,23 @@
<?php <?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; namespace Chill\ActivityBundle\Tests\Export\Export;
use Chill\MainBundle\Test\Export\AbstractExportTest; use Chill\MainBundle\Test\Export\AbstractExportTest;
/** /**
* * @internal
* * @coversNothing
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/ */
class CountActivityTest extends AbstractExportTest class CountActivityTest extends AbstractExportTest
{ {
/** /**
*
* @var * @var
*/ */
private $export; private $export;
@@ -34,17 +39,16 @@ class CountActivityTest extends AbstractExportTest
public function getFormData() public function getFormData()
{ {
return array( return [
array() [],
); ];
} }
public function getModifiersCombination() public function getModifiersCombination()
{ {
return array( return [
array('activity'), ['activity'],
array('activity', 'person') ['activity', 'person'],
); ];
} }
} }

View File

@@ -1,20 +1,10 @@
<?php <?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 * For the full copyright and license information, please view
* it under the terms of the GNU Affero General Public License as published by * the LICENSE file that was distributed with this source code.
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\Tests\Export\Export; namespace Chill\ActivityBundle\Tests\Export\Export;
@@ -22,14 +12,12 @@ namespace Chill\ActivityBundle\Tests\Export\Export;
use Chill\MainBundle\Test\Export\AbstractExportTest; use Chill\MainBundle\Test\Export\AbstractExportTest;
/** /**
* * @internal
* * @coversNothing
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/ */
class ListActivityTest extends AbstractExportTest class ListActivityTest extends AbstractExportTest
{ {
/** /**
*
* @var \Chill\ActivityBundle\Export\Export\ListActivity * @var \Chill\ActivityBundle\Export\Export\ListActivity
*/ */
private $export; private $export;
@@ -44,21 +32,24 @@ class ListActivityTest extends AbstractExportTest
$this->export = $container->get('chill.activity.export.list_activity'); $this->export = $container->get('chill.activity.export.list_activity');
// add a fake request with a default locale (used in translatable string) // add a fake request with a default locale (used in translatable string)
$prophet = new \Prophecy\Prophet; $prophet = new \Prophecy\Prophet();
$request = $prophet->prophesize(); $request = $prophet->prophesize();
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class); $request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
$request->getLocale()->willReturn('fr'); $request->getLocale()->willReturn('fr');
$container->get('request_stack') $container->get('request_stack')
->push($request->reveal()); ->push($request->reveal());
} }
public function getExport()
{
return $this->export;
}
public function getFormData() public function getFormData()
{ {
return array( return [
array('fields' => array( ['fields' => [
'id', 'id',
'date', 'date',
'durationTime', 'durationTime',
@@ -68,26 +59,20 @@ class ListActivityTest extends AbstractExportTest
'type_name', 'type_name',
'person_firstname', 'person_firstname',
'person_lastname', 'person_lastname',
'person_id' 'person_id',
)), ]],
array('fields' => array( ['fields' => [
'id', 'id',
'list_reasons' 'list_reasons',
)), ]],
); ];
} }
public function getModifiersCombination() public function getModifiersCombination()
{ {
return array( return [
array('activity'), ['activity'],
array('activity', 'person') ['activity', 'person'],
); ];
} }
public function getExport()
{
return $this->export;
}
} }

View File

@@ -1,18 +1,25 @@
<?php <?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; namespace Chill\ActivityBundle\Tests\Export\Export;
use Chill\MainBundle\Test\Export\AbstractExportTest; 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 class StatActivityDurationSumTest extends AbstractExportTest
{ {
/** /**
*
* @var \Chill\ActivityBundle\Export\Export\StatActivityDuration * @var \Chill\ActivityBundle\Export\Export\StatActivityDuration
*/ */
private $export; private $export;
@@ -34,17 +41,16 @@ class StatActivityDurationSumTest extends AbstractExportTest
public function getFormData() public function getFormData()
{ {
return array( return [
array() [],
); ];
} }
public function getModifiersCombination() public function getModifiersCombination()
{ {
return array( return [
array('activity'), ['activity'],
array('activity', 'person') ['activity', 'person'],
); ];
} }
} }

View File

@@ -1,20 +1,10 @@
<?php <?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 * For the full copyright and license information, please view
* it under the terms of the GNU Affero General Public License as published by * the LICENSE file that was distributed with this source code.
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\Tests\Filter; namespace Chill\ActivityBundle\Tests\Filter;
@@ -23,14 +13,12 @@ use Chill\MainBundle\Test\Export\AbstractFilterTest;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
/** /**
* * @internal
* * @coversNothing
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/ */
class ActivityReasonFilterTest extends AbstractFilterTest class ActivityReasonFilterTest extends AbstractFilterTest
{ {
/** /**
*
* @var \Chill\PersonBundle\Export\Filter\GenderFilter * @var \Chill\PersonBundle\Export\Filter\GenderFilter
*/ */
private $filter; private $filter;
@@ -44,16 +32,15 @@ class ActivityReasonFilterTest extends AbstractFilterTest
$this->filter = $container->get('chill.activity.export.reason_filter'); $this->filter = $container->get('chill.activity.export.reason_filter');
// add a fake request with a default locale (used in translatable string) // add a fake request with a default locale (used in translatable string)
$prophet = new \Prophecy\Prophet; $prophet = new \Prophecy\Prophet();
$request = $prophet->prophesize(); $request = $prophet->prophesize();
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class); $request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
$request->getLocale()->willReturn('fr'); $request->getLocale()->willReturn('fr');
$container->get('request_stack') $container->get('request_stack')
->push($request->reveal()); ->push($request->reveal());
} }
public function getFilter() public function getFilter()
{ {
return $this->filter; return $this->filter;
@@ -61,21 +48,20 @@ class ActivityReasonFilterTest extends AbstractFilterTest
public function getFormData() public function getFormData()
{ {
if (static::$kernel === null) { if (null === static::$kernel) {
static::bootKernel(); static::bootKernel();
} }
$em = static::$kernel->getContainer() $em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager') ->get('doctrine.orm.entity_manager');
;
$reasons = $em->createQuery("SELECT reason " $reasons = $em->createQuery('SELECT reason '
. "FROM ChillActivityBundle:ActivityReason reason") . 'FROM ChillActivityBundle:ActivityReason reason')
->getResult(); ->getResult();
// generate an array of 5 different combination of results // generate an array of 5 different combination of results
for ($i=0; $i < 5; $i++) { for ($i = 0; 5 > $i; ++$i) {
$r[] = array('reasons' => new ArrayCollection(array_splice($reasons, ($i + 1) * -1))); $r[] = ['reasons' => new ArrayCollection(array_splice($reasons, ($i + 1) * -1))];
} }
return $r; return $r;
@@ -83,14 +69,14 @@ class ActivityReasonFilterTest extends AbstractFilterTest
public function getQueryBuilders() public function getQueryBuilders()
{ {
if (static::$kernel === null) { if (null === static::$kernel) {
static::bootKernel(); static::bootKernel();
} }
$em = static::$kernel->getContainer() $em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager'); ->get('doctrine.orm.entity_manager');
return array( return [
$em->createQueryBuilder() $em->createQueryBuilder()
->select('count(activity.id)') ->select('count(activity.id)')
->from('ChillActivityBundle:Activity', 'activity'), ->from('ChillActivityBundle:Activity', 'activity'),
@@ -102,8 +88,7 @@ class ActivityReasonFilterTest extends AbstractFilterTest
->select('count(activity.id)') ->select('count(activity.id)')
->from('ChillActivityBundle:Activity', 'activity') ->from('ChillActivityBundle:Activity', 'activity')
->join('activity.reasons', 'reasons') ->join('activity.reasons', 'reasons')
->join('reasons.category', 'category') ->join('reasons.category', 'category'),
); ];
} }
} }

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