diff --git a/docs/source/installation/index.rst b/docs/source/installation/index.rst index 46e8ce66d..00f27ed69 100644 --- a/docs/source/installation/index.rst +++ b/docs/source/installation/index.rst @@ -28,34 +28,42 @@ Requirements - This project use `docker `_ to be run. As a developer, use `docker-compose `_ to bootstrap a dev environment in a glance. You do not need any other dependencies ; - Make is used to automate scripts. -Installation in development mode -******************************** +Installation +************ + +If you plan to run chill in production: + +1. install it locally first, and check if everything is ok on your local machine; +2. once ready, build the image from your local machine, and deploy them. + +If you want to develop some bundles, the first step is sufficient (until you deploy on production). + 1. Get the code =============== -Clone or download the chill-app project and `cd` into the main directory. +Clone or download the chill-skeleton project and `cd` into the main directory. .. code-block:: bash - git clone https://gitlab.com/Chill-Projet/chill-app.git + git clone https://gitlab.com/Chill-Projet/chill-skeleton-basic.git cd chill-app As a developer, the code will stay on your computer and will be executed in docker container. To avoid permission problem, the code should be run with the same uid/gid from your current user. This is why we get your current user id with the command ``id -u`` in each following scripts. -2. Prepare composer download of sources -======================================= +2. Prepare composer to download the sources +=========================================== -As you are running in dev, you must configure an auth token for getting the source code. +As you are running in dev, you must configure an auth token for getting the source code. .. warning If you skip this part, the code will be downloaded from dist instead of source (with git repository). You will probably replace the source manually, but the next time you will run ```composer update```, your repository will be replaced and you might loose something. 1. Create a personal access token from https://gitlab.com/-/profile/personal_access_tokens, with the `read_api` scope. -2. add a file called ```.composer/auth.json```: +2. add a file called ```.composer/auth.json``` with this content: .. code-block:: json @@ -68,13 +76,25 @@ As you are running in dev, you must configure an auth token for getting the sour 2. Prepare your variables and environment ========================================= -Copy ```docker-compose.override.dev.yml``` into ```docker-compose.override.yml``` +Copy ```docker-compose.override.dev.yml``` into ```docker-compose.override.yml``` .. code-block:: bash cp docker-compose.override.dev.template.yml docker-compose.override.yml -Configure your environment variables, by creating a .env.local file and override the desired variables. +2. Prepare your variables and docker-compose +============================================ + +Have a look at the variable in ``.env`` and check if you need to adapt them. If they do not adapt with your need, or if some are missing: + +1. copy the file as ``.env.local``: ``cp .env .env.local`` +2. you may replace some variables inside ``.env`` + +Prepare also you docker-compose installation, and adapt it to your needs: + +1. If you plan to deploy on dev, copy the file ``docker-compose.override.dev.template.yml`` to ``docker-compose.override.yml``. +2. adapt to your needs. + **Note**: If you intend to use the bundle ``Chill-Doc-Store``, you will need to configure and install an openstack object storage container with temporary url middleware. You will have to configure `secret keys `_. @@ -90,10 +110,21 @@ This script can be run using `make` This script will : 1. force docker-compose to, eventually, pull the base images and build the image used by this project ; -2. run an install script to download `composer `_ ; +2. run an install script to download `composer `_ ; 3. install the php dependencies 4. build assets +.. warning:: + + The script will work only if the binary ``docker-compose`` is located into your ``PATH``. If you use ``compose`` as a docker plugin, + you can simulate this binary by creating this file at (for instance), ``/usr/local/bin/docker-compose`` (and run ``chmod +x /usr/local/bin/docker-compose``): + + .. code-block:: bash + + #!/bin/bash + + /usr/bin/docker compose "$@" + .. note:: @@ -117,13 +148,20 @@ This script will : .. code-block:: bash - make migrate + # mount into to container + ./docker-php.sh + # and load fixtures + bin/console doctrine:migrations:migrate + Chill will be available at ``http://localhost:8001.`` Currently, there isn't any user or data. To add fixtures, run .. code-block:: bash - docker-compose exec --user $(id -u) php bin/console doctrine:fixtures:load --purge-with-truncate + # mount into to container + ./docker-php.sh + # and load fixtures + bin/console doctrine:fixtures:load --purge-with-truncate There are several users available: @@ -134,28 +172,6 @@ The password is always ``password``. Now, read `Operations` below. -Prepare for development -*********************** - -Add a Gitlab token to ensure that you get always the source code: - -1. generate a gitlab token there: https://gitlab.com/oauth/token -2. run this command (in php container, at the app's root): :code:`composer config gitlab-token.gitlab.com ` - -The auth token should appears now in the directory :code:`.composer`: - -.. code-block: bash - - $ cat .composer/auth.json - { - "gitlab-token": { - "gitlab.com": "" - } - } - - -See also "how to switch branch and get new dependencies". - Operations ********** @@ -163,7 +179,7 @@ Operations Build assets ============ -run those commands: +run those commands: .. code-block:: bash @@ -175,8 +191,8 @@ How to execute the console ? .. code-block:: bash # if a container is running - docker-compose exec --user $(id -u) php bin/console - # if not + ./docker-php.sh + # if not docker-compose run --user $(id -u) php bin/console How to create the database schema (= run migrations) ? @@ -185,8 +201,9 @@ How to create the database schema (= run migrations) ? .. code-block:: bash # if a container is running - docker-compose exec --user $(id -u) php bin/console doctrine:migrations:migrate - # if not + ./docker-php.sh + bin/console doctrine:migrations:migrate + # if not docker-compose run --user $(id -u) php bin/console doctrine:migrations:migrate @@ -203,8 +220,9 @@ How to load fixtures ? (development mode only) .. code-block:: bash # if a container is running - docker-compose exec --user $(id -u) php bin/console doctrine:fixtures:load - # if not + ./docker-php.sh + bin/console doctrine:fixtures:load + # if not docker-compose run --user $(id -u) php bin/console doctrine:fixtures:load How to open a terminal in the project @@ -213,8 +231,8 @@ How to open a terminal in the project .. code-block:: bash # if a container is running - docker-compose exec --user $(id -u) php /bin/bash - # if not + ./docker-php.sh + # if not docker-compose run --user $(id -u) php /bin/bash How to run composer ? @@ -223,21 +241,22 @@ How to run composer ? .. code-block:: bash # if a container is running - docker-compose exec --user $(id -u) php ./composer.phar - # if not - docker-compose run --user $(id -u) php ./composer.phar + ./docker-php.sh + composer + # if not + docker-compose run --user $(id -u) php composer How to access to PGADMIN ? ========================== -Pgadmin is installed with docker-compose. +Pgadmin is installed with docker-compose, and is available **only if you uncomment the appropriate lines into ``docker-compose.override.yml``. You can access it at ``http://localhost:8002``. Credentials: -- login: admin@chill.social -- password: password +- login: from the variable you set into ``docker-composer.override.yml`` +- password: same :-) How to run tests ? ================== @@ -246,18 +265,20 @@ Tests reside inside the installed bundles. You must `cd` into that directory, do **Note**: some bundle require the fixture to be executed. See the dedicated _how-tos_. -Exemple, for running test inside `main` bundle: +Exemple, for running test inside `main` bundle: .. code-block:: bash # mount into the php image - docker-compose run --user $(id -u) php /bin/bash + ./docker-php.sh # cd into main directory - cd vendor/chill-project/main + cd vendor/chill-project/chill-bundles # download deps - php ../../../composer.phar install + git submodule init + git submodule update + composer install # run tests - /vendor/bin/phpunit + bin/phpunit src/Bundle/path/to/your/test How to run webpack interactively ================================ @@ -269,10 +290,14 @@ How to switch the branch for chill-bundles, and get new dependencies During development, you will switch to new branches for chill-bundles. As long as the dependencies are equals, this does not cause any problem. But sometimes, a new branch introduces a new dependency, and you must download it. +.. warning:: + + Ensure that you have gitlab-token ready before updating your branches. See above. + In order to do that without pain, use those steps: 0. Ensuire you have a token, set -1. at the app's root, update the `composer.json` to your current branch: +1. at the app's root, update the ``composer.json`` to your current branch: .. code-block:: json @@ -281,14 +306,7 @@ In order to do that without pain, use those steps: "chill-bundles": "dev-@dev" } -2. mount into the php container, and run `composer update` - -Build the documentation API -=========================== - -A basic configuration of `sami `_ is embedded within the project. - -A configuration file for `phpDocumentor `_ is present. +2. mount into the php container (``./docker-php.sh``), and run ``composer update`` Error `An exception has been thrown during the rendering of a template ("Asset manifest file "/var/www/app/web/build/manifest.json" does not exist.").` on first run ==================================================================================================================================================================== @@ -302,8 +320,9 @@ Currently, to run this software in production, the *state of the art* is the fol 1. Run the software locally and tweak the configuration to your needs ; 2. Build the image and store them into a private container registry. This can be done using :code:`make build-and-push-image`. - - To be sure to target the correct container registry, you have to adapt the values ``IMAGE_NGINX`` and ``IMAGE_PHP`` date in the ``.env`` file. + + To be sure to target the correct container registry, you have to adapt the image names into your ``docker-compose.override.yml`` file. +3. Push the image on your registry, or upload them to the destination machine using ``docker image save`` and ``docker image load``. 3. Run the image on your production server, using docker-compose or eventually docker stack. You have to customize the variable set in docker-compose. See also the :ref:`running-production-tips-and-tricks` below. @@ -335,7 +354,7 @@ It is worth having an eye on the configuration of logstash container. Design principles ***************** -Why the DB URL is set in environment, and not in parameters.yml ? +Why the DB URL is also set in environment, and not in .env file ? ================================================================= Because, at startup, a script does check the db is up and, if not, wait for a couple of seconds before running ``entrypoint.sh``. For avoiding double configuration, the configuration of the PHP app takes his configuration from environment also (and it will be standard in future releases, with symfony 4.0). diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityDuration.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityDuration.php index 3fc975147..f45adc0b3 100644 --- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityDuration.php +++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityDuration.php @@ -17,6 +17,8 @@ use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter; use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\GroupedExportInterface; +use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; +use Chill\PersonBundle\Entity\Person\PersonCenterHistory; use Chill\PersonBundle\Export\Declarations as PersonDeclarations; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; @@ -83,6 +85,10 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) { + $centers = array_map(static function ($el) { + return $el['center']; + }, $acl); + $qb = $this->repository->createQueryBuilder('activity'); $qb @@ -90,6 +96,18 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface ->select('AVG(activity.durationTime) as export_avg_activity_duration') ->andWhere($qb->expr()->isNotNull('activity.durationTime')); + $qb + ->andWhere( + $qb->expr()->exists( + 'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part + JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person) + WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers) + ' + ) + ) + ->setParameter('authorized_centers', $centers) + ; + return $qb; } diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityVisitDuration.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityVisitDuration.php index 69533a09d..661f169dd 100644 --- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityVisitDuration.php +++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityVisitDuration.php @@ -17,6 +17,8 @@ use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter; use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\GroupedExportInterface; +use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; +use Chill\PersonBundle\Entity\Person\PersonCenterHistory; use Chill\PersonBundle\Export\Declarations as PersonDeclarations; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; @@ -84,6 +86,10 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) { + $centers = array_map(static function ($el) { + return $el['center']; + }, $acl); + $qb = $this->repository->createQueryBuilder('activity'); $qb @@ -92,6 +98,18 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac ->andWhere($qb->expr()->isNotNull('activity.travelTime')) ; + $qb + ->andWhere( + $qb->expr()->exists( + 'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part + JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person) + WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers) + ' + ) + ) + ->setParameter('authorized_centers', $centers) + ; + return $qb; } diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/CountActivity.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/CountActivity.php index 2162b8b58..46d2f3c33 100644 --- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/CountActivity.php +++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/CountActivity.php @@ -17,6 +17,8 @@ use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter; use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\GroupedExportInterface; +use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; +use Chill\PersonBundle\Entity\Person\PersonCenterHistory; use Chill\PersonBundle\Export\Declarations as PersonDeclarations; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; @@ -84,11 +86,25 @@ class CountActivity implements ExportInterface, GroupedExportInterface public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) { - $qb = $this->repository->createQueryBuilder('activity'); + $centers = array_map(static function ($el) { + return $el['center']; + }, $acl); - if (!in_array('acp', $qb->getAllAliases(), true)) { - $qb->join('activity.accompanyingPeriod', 'acp'); - } + $qb = $this->repository + ->createQueryBuilder('activity') + ->join('activity.accompanyingPeriod', 'acp'); + + $qb + ->andWhere( + $qb->expr()->exists( + 'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part + JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person) + WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers) + ' + ) + ) + ->setParameter('authorized_centers', $centers) + ; $qb->select('COUNT(DISTINCT activity.id) as export_count_activity'); diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityDuration.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityDuration.php index e9dbaff29..405b54885 100644 --- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityDuration.php +++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityDuration.php @@ -17,6 +17,8 @@ use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter; use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\GroupedExportInterface; +use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; +use Chill\PersonBundle\Entity\Person\PersonCenterHistory; use Chill\PersonBundle\Export\Declarations as PersonDeclarations; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; @@ -84,15 +86,29 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) { - $qb = $this->repository->createQueryBuilder('activity'); + $centers = array_map(static function ($el) { + return $el['center']; + }, $acl); - if (!in_array('acp', $qb->getAllAliases(), true)) { - $qb->join('activity.accompanyingPeriod', 'acp'); - } + $qb = $this->repository + ->createQueryBuilder('activity') + ->join('activity.accompanyingPeriod', 'acp'); $qb->select('SUM(activity.durationTime) as export_sum_activity_duration') ->andWhere($qb->expr()->isNotNull('activity.durationTime')); + $qb + ->andWhere( + $qb->expr()->exists( + 'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part + JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person) + WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers) + ' + ) + ) + ->setParameter('authorized_centers', $centers) + ; + return $qb; } diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityVisitDuration.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityVisitDuration.php index d41994562..40020cb4b 100644 --- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityVisitDuration.php +++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityVisitDuration.php @@ -17,6 +17,8 @@ use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter; use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\GroupedExportInterface; +use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; +use Chill\PersonBundle\Entity\Person\PersonCenterHistory; use Chill\PersonBundle\Export\Declarations as PersonDeclarations; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; @@ -84,15 +86,29 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) { - $qb = $this->repository->createQueryBuilder('activity'); + $centers = array_map(static function ($el) { + return $el['center']; + }, $acl); - if (!in_array('acp', $qb->getAllAliases(), true)) { - $qb->join('activity.accompanyingPeriod', 'acp'); - } + $qb = $this->repository + ->createQueryBuilder('activity') + ->join('activity.accompanyingPeriod', 'acp'); $qb->select('SUM(activity.travelTime) as export_sum_activity_visit_duration') ->andWhere($qb->expr()->isNotNull('activity.travelTime')); + $qb + ->andWhere( + $qb->expr()->exists( + 'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part + JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person) + WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers) + ' + ) + ) + ->setParameter('authorized_centers', $centers) + ; + return $qb; } diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/CountActivity.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/CountActivity.php index f12507df8..116fa4b6a 100644 --- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/CountActivity.php +++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/CountActivity.php @@ -84,16 +84,25 @@ class CountActivity implements ExportInterface, GroupedExportInterface { $centers = array_map(static fn ($el) => $el['center'], $acl); - $qb = $this->activityRepository->createQueryBuilder('activity'); - - if (!in_array('person', $qb->getAllAliases(), true)) { - $qb->join('activity.person', 'person'); - } + $qb = $this->activityRepository + ->createQueryBuilder('activity') + ->join('activity.person', 'person') + ->join('person.centerHistory', 'centerHistory') + ; $qb->select('COUNT(activity.id) as export_count_activity'); $qb - ->where($qb->expr()->in('person.center', ':centers')) + ->where( + $qb->expr()->andX( + $qb->expr()->lte('centerHistory.startDate', 'activity.date'), + $qb->expr()->orX( + $qb->expr()->isNull('centerHistory.endDate'), + $qb->expr()->gt('centerHistory.endDate', 'activity.date') + ) + ) + ) + ->andWhere($qb->expr()->in('centerHistory.center', ':centers')) ->setParameter('centers', $centers); return $qb; diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/StatActivityDuration.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/StatActivityDuration.php index 9013b4648..f1228842f 100644 --- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/StatActivityDuration.php +++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/StatActivityDuration.php @@ -119,11 +119,24 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface $select = 'SUM(activity.durationTime) AS export_stat_activity'; } - return $qb->select($select) + $qb->select($select) ->join('activity.person', 'person') - ->join('actperson.center', 'actcenter') - ->where($qb->expr()->in('actcenter', ':centers')) - ->setParameter(':centers', $centers); + ->join('person.centerHistory', 'centerHistory'); + + $qb + ->where( + $qb->expr()->andX( + $qb->expr()->lte('centerHistory.startDate', 'activity.date'), + $qb->expr()->orX( + $qb->expr()->isNull('centerHistory.endDate'), + $qb->expr()->gt('centerHistory.endDate', 'activity.date') + ) + ) + ) + ->andWhere($qb->expr()->in('centerHistory.center', ':centers')) + ->setParameter('centers', $centers); + + return $qb; } public function requiredRole(): string diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityReasonAggregatorTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityReasonAggregatorTest.php deleted file mode 100644 index 79c0924f7..000000000 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityReasonAggregatorTest.php +++ /dev/null @@ -1,82 +0,0 @@ -getContainer(); - - $this->aggregator = $container->get('chill.activity.export.reason_aggregator'); - - // add a fake request with a default locale (used in translatable string) - $prophet = new \Prophecy\Prophet(); - $request = $prophet->prophesize(); - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - - $container->get('request_stack') - ->push($request->reveal()); - } - - public function getAggregator() - { - return $this->aggregator; - } - - public function getFormData() - { - return [ - ['level' => 'reasons'], - ['level' => 'categories'], - ]; - } - - public function getQueryBuilders() - { - if (null === self::$kernel) { - self::bootKernel(); - } - - $em = self::$kernel->getContainer() - ->get('doctrine.orm.entity_manager'); - - return [ - $em->createQueryBuilder() - ->select('count(activity.id)') - ->from('ChillActivityBundle:Activity', 'activity'), - $em->createQueryBuilder() - ->select('count(activity.id)') - ->from('ChillActivityBundle:Activity', 'activity') - ->join('activity.reasons', 'reasons'), - $em->createQueryBuilder() - ->select('count(activity.id)') - ->from('ChillActivityBundle:Activity', 'activity') - ->join('activity.reasons', 'reasons') - ->join('reasons.category', 'category'), - ]; - } -} diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityTypeAggregatorTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityTypeAggregatorTest.php index bd88a7d3b..435d1043e 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityTypeAggregatorTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityTypeAggregatorTest.php @@ -11,8 +11,10 @@ declare(strict_types=1); namespace Chill\ActivityBundle\Tests\Export\Aggregator; -use Chill\ActivityBundle\Export\Aggregator\PersonAggregators\ActivityTypeAggregator; +use Chill\ActivityBundle\Export\Aggregator\ActivityTypeAggregator; use Chill\MainBundle\Test\Export\AbstractAggregatorTest; +use Doctrine\ORM\EntityManagerInterface; +use Prophecy\PhpUnit\ProphecyTrait; /** * Add tests for ActivityTypeAggregator. @@ -22,23 +24,22 @@ use Chill\MainBundle\Test\Export\AbstractAggregatorTest; */ final class ActivityTypeAggregatorTest extends AbstractAggregatorTest { + use ProphecyTrait; + private ActivityTypeAggregator $aggregator; protected function setUp(): void { self::bootKernel(); - $container = self::$kernel->getContainer(); + $this->aggregator = self::$container->get('chill.activity.export.type_aggregator'); - $this->aggregator = $container->get('chill.activity.export.type_aggregator'); + $request = $this->prophesize() + ->willExtend(\Symfony\Component\HttpFoundation\Request::class); - // add a fake request with a default locale (used in translatable string) - $prophet = new \Prophecy\Prophet(); - $request = $prophet->prophesize(); - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); $request->getLocale()->willReturn('fr'); - $container->get('request_stack') + self::$container->get('request_stack') ->push($request->reveal()); } @@ -60,8 +61,7 @@ final class ActivityTypeAggregatorTest extends AbstractAggregatorTest self::bootKernel(); } - $em = self::$kernel->getContainer() - ->get('doctrine.orm.entity_manager'); + $em = self::$container->get(EntityManagerInterface::class); return [ $em->createQueryBuilder() @@ -70,12 +70,7 @@ final class ActivityTypeAggregatorTest extends AbstractAggregatorTest $em->createQueryBuilder() ->select('count(activity.id)') ->from('ChillActivityBundle:Activity', 'activity') - ->join('activity.reasons', 'reasons'), - $em->createQueryBuilder() - ->select('count(activity.id)') - ->from('ChillActivityBundle:Activity', 'activity') - ->join('activity.reasons', 'reasons') - ->join('reasons.category', 'category'), + ->join('activity.activityType', 'acttype'), ]; } } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityUserAggregatorTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityUserAggregatorTest.php index 0e620040f..ea76a362c 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityUserAggregatorTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityUserAggregatorTest.php @@ -13,6 +13,8 @@ namespace Chill\ActivityBundle\Tests\Export\Aggregator; use Chill\ActivityBundle\Export\Aggregator\ActivityUserAggregator; use Chill\MainBundle\Test\Export\AbstractAggregatorTest; +use Doctrine\ORM\EntityManagerInterface; +use Prophecy\PhpUnit\ProphecyTrait; /** * Add tests for ActivityUsernAggregator. @@ -22,23 +24,22 @@ use Chill\MainBundle\Test\Export\AbstractAggregatorTest; */ final class ActivityUserAggregatorTest extends AbstractAggregatorTest { + use ProphecyTrait; + private ActivityUserAggregator $aggregator; protected function setUp(): void { self::bootKernel(); - $container = self::$kernel->getContainer(); + $this->aggregator = self::$container->get('chill.activity.export.user_aggregator'); - $this->aggregator = $container->get('chill.activity.export.user_aggregator'); + $request = $this->prophesize() + ->willExtend(\Symfony\Component\HttpFoundation\Request::class); - // add a fake request with a default locale (used in translatable string) - $prophet = new \Prophecy\Prophet(); - $request = $prophet->prophesize(); - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); $request->getLocale()->willReturn('fr'); - $container->get('request_stack') + self::$container->get('request_stack') ->push($request->reveal()); } @@ -47,35 +48,25 @@ final class ActivityUserAggregatorTest extends AbstractAggregatorTest return $this->aggregator; } - public function getFormData() + public function getFormData(): array { return [ [], ]; } - public function getQueryBuilders() + public function getQueryBuilders(): array { if (null === self::$kernel) { self::bootKernel(); } - $em = self::$kernel->getContainer() - ->get('doctrine.orm.entity_manager'); + $em = self::$container->get(EntityManagerInterface::class); return [ $em->createQueryBuilder() ->select('count(activity.id)') ->from('ChillActivityBundle:Activity', 'activity'), - $em->createQueryBuilder() - ->select('count(activity.id)') - ->from('ChillActivityBundle:Activity', 'activity') - ->join('activity.reasons', 'reasons'), - $em->createQueryBuilder() - ->select('count(activity.id)') - ->from('ChillActivityBundle:Activity', 'activity') - ->join('activity.reasons', 'reasons') - ->join('reasons.category', 'category'), ]; } } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/PersonAggregators/ActivityReasonAggregatorTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/PersonAggregators/ActivityReasonAggregatorTest.php index 6de364ae7..f89c20e31 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/PersonAggregators/ActivityReasonAggregatorTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/PersonAggregators/ActivityReasonAggregatorTest.php @@ -15,9 +15,12 @@ use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Export\Aggregator\PersonAggregators\ActivityReasonAggregator; use Chill\MainBundle\Test\Export\AbstractAggregatorTest; use Doctrine\ORM\EntityManagerInterface; +use Prophecy\PhpUnit\ProphecyTrait; final class ActivityReasonAggregatorTest extends AbstractAggregatorTest { + use ProphecyTrait; + private ActivityReasonAggregator $aggregator; protected function setUp(): void @@ -25,6 +28,14 @@ final class ActivityReasonAggregatorTest extends AbstractAggregatorTest self::bootKernel(); $this->aggregator = self::$container->get('chill.activity.export.reason_aggregator'); + + $request = $this->prophesize() + ->willExtend(\Symfony\Component\HttpFoundation\Request::class); + + $request->getLocale()->willReturn('fr'); + + self::$container->get('request_stack') + ->push($request->reveal()); } public function getAggregator() @@ -35,12 +46,8 @@ final class ActivityReasonAggregatorTest extends AbstractAggregatorTest public function getFormData(): array { return [ - [ - 'level' => 'reasons', - ], - [ - 'level' => 'categories', - ] + ['level' => 'reasons'], + ['level' => 'categories'], ]; } @@ -55,11 +62,16 @@ final class ActivityReasonAggregatorTest extends AbstractAggregatorTest return [ $em->createQueryBuilder() ->select('count(activity.id)') - ->from(Activity::class, 'activity') - ->join('activity.person', 'actperson') - ->innerJoin('activity.reasons', 'actreasons') - ->join('actreasons.category', 'actreasoncat') - , + ->from('ChillActivityBundle:Activity', 'activity'), + $em->createQueryBuilder() + ->select('count(activity.id)') + ->from('ChillActivityBundle:Activity', 'activity') + ->join('activity.reasons', 'actreasons'), + $em->createQueryBuilder() + ->select('count(activity.id)') + ->from('ChillActivityBundle:Activity', 'activity') + ->join('activity.reasons', 'actreasons') + ->join('actreasons.category', 'actreasoncat'), ]; } } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/AvgActivityDurationTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/AvgActivityDurationTest.php new file mode 100644 index 000000000..b175c4f15 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/AvgActivityDurationTest.php @@ -0,0 +1,51 @@ +export = self::$container->get('chill.activity.export.avg_activity_duration_linked_to_acp'); + } + + public function getExport() + { + return $this->export; + } + + public function getFormData(): array + { + return [ + [], + ]; + } + + public function getModifiersCombination(): array + { + return [ + ['activity'], + ['activity', 'accompanying_period'], + ]; + } +} diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/AvgActivityVisitDurationTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/AvgActivityVisitDurationTest.php new file mode 100644 index 000000000..5d0e11be3 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/AvgActivityVisitDurationTest.php @@ -0,0 +1,51 @@ +export = self::$container->get('chill.activity.export.avg_activity_visit_duration_linked_to_acp'); + } + + public function getExport() + { + return $this->export; + } + + public function getFormData(): array + { + return [ + [], + ]; + } + + public function getModifiersCombination(): array + { + return [ + ['activity'], + ['activity', 'accompanying_period'], + ]; + } +} diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/CountActivityTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/CountActivityTest.php new file mode 100644 index 000000000..78f8556c1 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/CountActivityTest.php @@ -0,0 +1,51 @@ +export = self::$container->get('chill.activity.export.count_activity_linked_to_acp'); + } + + public function getExport() + { + return $this->export; + } + + public function getFormData(): array + { + return [ + [], + ]; + } + + public function getModifiersCombination(): array + { + return [ + ['activity'], + ['activity', 'accompanying_period'], + ]; + } +} diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/SumActivityDurationTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/SumActivityDurationTest.php new file mode 100644 index 000000000..939ca2a88 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/SumActivityDurationTest.php @@ -0,0 +1,51 @@ +export = self::$container->get('chill.activity.export.sum_activity_duration_linked_to_acp'); + } + + public function getExport() + { + return $this->export; + } + + public function getFormData(): array + { + return [ + [], + ]; + } + + public function getModifiersCombination(): array + { + return [ + ['activity'], + ['activity', 'accompanying_period'], + ]; + } +} diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/SumActivityVisitDurationTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/SumActivityVisitDurationTest.php new file mode 100644 index 000000000..7c0f79bc5 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/SumActivityVisitDurationTest.php @@ -0,0 +1,51 @@ +export = self::$container->get('chill.activity.export.sum_activity_visit_duration_linked_to_acp'); + } + + public function getExport() + { + return $this->export; + } + + public function getFormData(): array + { + return [ + [], + ]; + } + + public function getModifiersCombination(): array + { + return [ + ['activity'], + ['activity', 'accompanying_period'], + ]; + } +} diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Export/CountActivityTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToPerson/CountActivityTest.php similarity index 62% rename from src/Bundle/ChillActivityBundle/Tests/Export/Export/CountActivityTest.php rename to src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToPerson/CountActivityTest.php index cbf562dfa..f94ef3414 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Export/CountActivityTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToPerson/CountActivityTest.php @@ -9,8 +9,9 @@ declare(strict_types=1); -namespace Chill\ActivityBundle\Tests\Export\Export; +namespace Chill\ActivityBundle\Tests\Export\Export\LinkedToPerson; +use Chill\ActivityBundle\Export\Export\LinkedToPerson\CountActivity; use Chill\MainBundle\Test\Export\AbstractExportTest; /** @@ -19,19 +20,13 @@ use Chill\MainBundle\Test\Export\AbstractExportTest; */ final class CountActivityTest extends AbstractExportTest { - /** - * @var - */ - private $export; + private CountActivity $export; protected function setUp(): void { self::bootKernel(); - /** @var \Symfony\Component\DependencyInjection\ContainerInterface $container */ - $container = self::$kernel->getContainer(); - - $this->export = $container->get('chill.activity.export.count_activity'); + $this->export = self::$container->get('chill.activity.export.count_activity_linked_to_person'); } public function getExport() @@ -39,14 +34,14 @@ final class CountActivityTest extends AbstractExportTest return $this->export; } - public function getFormData() + public function getFormData(): array { return [ [], ]; } - public function getModifiersCombination() + public function getModifiersCombination(): array { return [ ['activity'], diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Export/ListActivityTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToPerson/ListActivityTest.php similarity index 65% rename from src/Bundle/ChillActivityBundle/Tests/Export/Export/ListActivityTest.php rename to src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToPerson/ListActivityTest.php index 46d23b023..a613bc083 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Export/ListActivityTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToPerson/ListActivityTest.php @@ -9,9 +9,11 @@ declare(strict_types=1); -namespace Chill\ActivityBundle\Tests\Export\Export; +namespace Chill\ActivityBundle\Tests\Export\Export\LinkedToPerson; +use Chill\ActivityBundle\Export\Export\LinkedToPerson\ListActivity; use Chill\MainBundle\Test\Export\AbstractExportTest; +use Prophecy\PhpUnit\ProphecyTrait; /** * @internal @@ -19,27 +21,22 @@ use Chill\MainBundle\Test\Export\AbstractExportTest; */ final class ListActivityTest extends AbstractExportTest { - /** - * @var \Chill\ActivityBundle\Export\Export\ListActivity - */ - private $export; + use ProphecyTrait; + + private ListActivity $export; protected function setUp(): void { self::bootKernel(); - /** @var \Symfony\Component\DependencyInjection\ContainerInterface $container */ - $container = self::$kernel->getContainer(); + $this->export = self::$container->get('chill.activity.export.list_activity_linked_to_person'); - $this->export = $container->get('chill.activity.export.list_activity'); + $request = $this->prophesize() + ->willExtend(\Symfony\Component\HttpFoundation\Request::class); - // add a fake request with a default locale (used in translatable string) - $prophet = new \Prophecy\Prophet(); - $request = $prophet->prophesize(); - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); $request->getLocale()->willReturn('fr'); - $container->get('request_stack') + self::$container->get('request_stack') ->push($request->reveal()); } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Export/StatActivityDurationSumTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToPerson/StatActivityDurationTest.php similarity index 55% rename from src/Bundle/ChillActivityBundle/Tests/Export/Export/StatActivityDurationSumTest.php rename to src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToPerson/StatActivityDurationTest.php index c69a31b5a..ae9e4f583 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Export/StatActivityDurationSumTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToPerson/StatActivityDurationTest.php @@ -9,8 +9,9 @@ declare(strict_types=1); -namespace Chill\ActivityBundle\Tests\Export\Export; +namespace Chill\ActivityBundle\Tests\Export\Export\LinkedToPerson; +use Chill\ActivityBundle\Export\Export\LinkedToPerson\StatActivityDuration; use Chill\MainBundle\Test\Export\AbstractExportTest; /** @@ -19,21 +20,15 @@ use Chill\MainBundle\Test\Export\AbstractExportTest; * @internal * @coversNothing */ -final class StatActivityDurationSumTest extends AbstractExportTest +final class StatActivityDurationTest extends AbstractExportTest { - /** - * @var \Chill\ActivityBundle\Export\Export\StatActivityDuration - */ - private $export; + private StatActivityDuration $export; protected function setUp(): void { self::bootKernel(); - /** @var \Symfony\Component\DependencyInjection\ContainerInterface $container */ - $container = self::$kernel->getContainer(); - - $this->export = $container->get('chill.activity.export.sum_activity_duration'); + $this->export = self::$container->get('chill.activity.export.sum_activity_duration_linked_to_person'); } public function getExport() @@ -41,14 +36,14 @@ final class StatActivityDurationSumTest extends AbstractExportTest return $this->export; } - public function getFormData() + public function getFormData(): array { return [ [], ]; } - public function getModifiersCombination() + public function getModifiersCombination(): array { return [ ['activity'], diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/ActivityTypeFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/ActivityTypeFilterTest.php index 10f16247e..e38d4cf5c 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/ActivityTypeFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/ActivityTypeFilterTest.php @@ -31,12 +31,6 @@ final class ActivityTypeFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.activity.export.filter_activitytype'); } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/BySocialActionFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/BySocialActionFilterTest.php index 1480e3569..d8091d068 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/BySocialActionFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/BySocialActionFilterTest.php @@ -29,12 +29,6 @@ final class BySocialActionFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.activity.export.bysocialaction_filter'); } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/BySocialIssueFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/BySocialIssueFilterTest.php index 6af3ea97c..61e5d4715 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/BySocialIssueFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/BySocialIssueFilterTest.php @@ -29,12 +29,6 @@ final class BySocialIssueFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.activity.export.bysocialissue_filter'); } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/ByUserFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/ByUserFilterTest.php index 93810433d..aaf852b14 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/ByUserFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/ByUserFilterTest.php @@ -29,12 +29,6 @@ final class ByUserFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.activity.export.byuser_filter'); } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/EmergencyFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/EmergencyFilterTest.php index d90523bed..07810efbe 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/EmergencyFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/EmergencyFilterTest.php @@ -28,12 +28,6 @@ final class EmergencyFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.activity.export.emergency_filter'); } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/LocationTypeFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/LocationTypeFilterTest.php index dcac884b9..6888e6cf7 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/LocationTypeFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/LocationTypeFilterTest.php @@ -29,12 +29,6 @@ final class LocationTypeFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.activity.export.locationtype_filter'); } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/SentReceivedFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/SentReceivedFilterTest.php index b40443ee4..d9a24dc27 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/SentReceivedFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/SentReceivedFilterTest.php @@ -28,12 +28,6 @@ final class SentReceivedFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.activity.export.sentreceived_filter'); } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/UserFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/UserFilterTest.php index cc1a1b81a..838973caa 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/UserFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/UserFilterTest.php @@ -29,12 +29,6 @@ final class UserFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.activity.export.user_filter'); } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/UserScopeFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/UserScopeFilterTest.php index 31ff8ca57..6b1040036 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/UserScopeFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ACPFilters/UserScopeFilterTest.php @@ -29,12 +29,6 @@ final class UserScopeFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.activity.export.userscope_filter'); } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ActivityDateFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ActivityDateFilterTest.php index b65d3808d..e95fd7c20 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ActivityDateFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ActivityDateFilterTest.php @@ -28,12 +28,6 @@ final class ActivityDateFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.activity.export.date_filter'); } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ActivityReasonFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ActivityReasonFilterTest.php index 72f052f54..d45ecfbb2 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ActivityReasonFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ActivityReasonFilterTest.php @@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Tests\Export\Filter; use Chill\ActivityBundle\Export\Filter\PersonFilters\ActivityReasonFilter; use Chill\MainBundle\Test\Export\AbstractFilterTest; use Doctrine\Common\Collections\ArrayCollection; +use Prophecy\PhpUnit\ProphecyTrait; /** * @internal @@ -21,23 +22,22 @@ use Doctrine\Common\Collections\ArrayCollection; */ final class ActivityReasonFilterTest extends AbstractFilterTest { + use ProphecyTrait; + private ActivityReasonFilter $filter; protected function setUp(): void { self::bootKernel(); - $container = self::$kernel->getContainer(); + $this->filter = self::$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) - $prophet = new \Prophecy\Prophet(); - $request = $prophet->prophesize(); - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); + $request = $this->prophesize() + ->willExtend(\Symfony\Component\HttpFoundation\Request::class); + $request->getLocale()->willReturn('fr'); - $container->get('request_stack') + self::$container->get('request_stack') ->push($request->reveal()); } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ActivityTypeFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ActivityTypeFilterTest.php index 12ace7c67..1bee8532e 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ActivityTypeFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ActivityTypeFilterTest.php @@ -29,12 +29,6 @@ final class ActivityTypeFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.activity.export.type_filter'); } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/PersonFilters/ActivityReasonFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/PersonFilters/ActivityReasonFilterTest.php index e6b14b44c..fc7dbbd00 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/PersonFilters/ActivityReasonFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/PersonFilters/ActivityReasonFilterTest.php @@ -29,12 +29,6 @@ final class ActivityReasonFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.activity.export.reason_filter'); } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/PersonFilters/PersonHavingActivityBetweenDateFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/PersonFilters/PersonHavingActivityBetweenDateFilterTest.php index 5cad68da4..42cf9d884 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/PersonFilters/PersonHavingActivityBetweenDateFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/PersonFilters/PersonHavingActivityBetweenDateFilterTest.php @@ -29,12 +29,6 @@ final class PersonHavingActivityBetweenDateFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.activity.export.person_having_an_activity_between_date_filter'); } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/PersonHavingActivityBetweenDateFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/PersonHavingActivityBetweenDateFilterTest.php index 507f03323..0e8199352 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/PersonHavingActivityBetweenDateFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/PersonHavingActivityBetweenDateFilterTest.php @@ -28,18 +28,14 @@ final class PersonHavingActivityBetweenDateFilterTest extends AbstractFilterTest { self::bootKernel(); - $container = self::$kernel->getContainer(); + $this->filter = self::$container->get('chill.activity.export.person_having_an_activity_between_date_filter'); - $this->filter = $container->get('chill.activity.export.' - . 'person_having_an_activity_between_date_filter'); + $request = $this->prophesize() + ->willExtend(\Symfony\Component\HttpFoundation\Request::class); - // add a fake request with a default locale (used in translatable string) - $prophet = new \Prophecy\Prophet(); - $request = $prophet->prophesize(); - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); $request->getLocale()->willReturn('fr'); - $container->get('request_stack') + self::$container->get('request_stack') ->push($request->reveal()); } diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php index 8e4dc5d25..b2750ae93 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person.php @@ -27,6 +27,8 @@ use Chill\MainBundle\Validation\Constraint\PhonenumberConstraint; use Chill\PersonBundle\Entity\Household\Household; use Chill\PersonBundle\Entity\Household\HouseholdMember; use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress; +use Chill\PersonBundle\Entity\Person\PersonCenterCurrent; +use Chill\PersonBundle\Entity\Person\PersonCenterHistory; use Chill\PersonBundle\Entity\Person\PersonCurrentAddress; use Chill\PersonBundle\Entity\Person\PersonResource; use Chill\PersonBundle\Validator\Constraints\Household\HouseholdMembershipSequential; @@ -188,9 +190,21 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * The person's center. * * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Center") + * @deprecated */ private ?Center $center = null; + /** + * @ORM\OneToMany(targetEntity=PersonCenterHistory::class, mappedBy="person", cascade={"persist"}) + * @var Collection|PersonCenterHistory[] + */ + private Collection $centerHistory; + + /** + * @ORM\OneToOne(targetEntity=PersonCenterCurrent::class, mappedBy="person") + */ + private ?PersonCenterCurrent $centerCurrent = null; + /** * Array where customfield's data are stored. * @@ -531,6 +545,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI $this->budgetResources = new ArrayCollection(); $this->budgetCharges = new ArrayCollection(); $this->resources = new ArrayCollection(); + $this->centerHistory = new ArrayCollection(); } /** @@ -903,9 +918,43 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI return $this->budgetResources; } + private function getCurrentCenterHistory(): ?PersonCenterHistory + { + if (0 === $this->centerHistory->count()) { + return null; + } + + $criteria = Criteria::create(); + $now = new DateTimeImmutable('now'); + $criteria->where(Criteria::expr()->lte('startDate', $now)) + ->andWhere(Criteria::expr()->orX( + Criteria::expr()->isNull('endDate'), + Criteria::expr()->gt('endDate', $now) + )); + + $histories = $this->centerHistory->matching($criteria); + + switch ($histories->count()) { + case 0: + return null; + case 1: + return $histories->first(); + default: + throw new \UnexpectedValueException('It should not contains more than one center at a time'); + } + } + public function getCenter(): ?Center { - return $this->center; + if (null !== $this->centerCurrent) { + return $this->centerCurrent->getCenter(); + } + + if (null === $currentCenterHistory = $this->getCurrentCenterHistory()) { + return null; + } + + return $currentCenterHistory->getCenter(); } public function getCFData(): ?array @@ -1518,17 +1567,67 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI return $this; } + /** + * Associate the center with the person. The association start on 'now'. + * + * @param Center $center + * @return $this + */ public function setCenter(Center $center): self { $this->center = $center; + $modification = new DateTimeImmutable('now'); + + foreach ($this->centerHistory as $centerHistory) { + if (null === $centerHistory->getEndDate()) { + $centerHistory->setEndDate($modification); + } + } + + $this->centerHistory[] = $new = new PersonCenterHistory($this, $center, $modification); + return $this; } /** - * @return Report + * @return Collection */ - public function setCFData(?array $cFData) + public function getCenterHistory(): Collection + { + return $this->centerHistory; + } + + /** + * @param Collection $centerHistory + * @return Person + */ + public function setCenterHistory(Collection $centerHistory): Person + { + $this->centerHistory = $centerHistory; + return $this; + } + + /** + * @return PersonCenterCurrent|null + */ + public function getCenterCurrent(): ?PersonCenterCurrent + { + if (null !== $this->centerCurrent) { + return $this->centerCurrent; + } + + if (null === $currentCenterHistory = $this->getCurrentCenterHistory()) { + return null; + } + + return new PersonCenterCurrent($currentCenterHistory); + } + + /** + * @return Person + */ + public function setCFData(?array $cFData): self { $this->cFData = $cFData; diff --git a/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterCurrent.php b/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterCurrent.php new file mode 100644 index 000000000..690ff025e --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterCurrent.php @@ -0,0 +1,112 @@ +person = $history->getPerson(); + $this->center = $history->getCenter(); + $this->startDate = $history->getStartDate(); + $this->endDate = $history->getEndDate(); + $this->id = $history->getId(); + } + + /** + * The id will be the same as the current @link{PersonCenterHistory::class} + * + * @return int + */ + public function getId(): int + { + return $this->id; + } + + /** + * @return Person + */ + public function getPerson(): Person + { + return $this->person; + } + + /** + * @return Center + */ + public function getCenter(): Center + { + return $this->center; + } + + /** + * @return \DateTimeImmutable + */ + public function getStartDate(): \DateTimeImmutable + { + return $this->startDate; + } + + /** + * @return \DateTimeImmutable|null + */ + public function getEndDate(): ?\DateTimeImmutable + { + return $this->endDate; + } + +} diff --git a/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterHistory.php b/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterHistory.php new file mode 100644 index 000000000..6bfb28cc6 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterHistory.php @@ -0,0 +1,142 @@ +person = $person; + $this->center = $center; + $this->startDate = $startDate; + } + + + /** + * @return int|null + */ + public function getId(): ?int + { + return $this->id; + } + + /** + * @return Person|null + */ + public function getPerson(): ?Person + { + return $this->person; + } + + /** + * @param Person|null $person + */ + public function setPerson(?Person $person): self + { + $this->person = $person; + + return $this; + } + + /** + * @return Center|null + */ + public function getCenter(): ?Center + { + return $this->center; + } + + /** + * @param Center|null $center + */ + public function setCenter(?Center $center): self + { + $this->center = $center; + + return $this; + } + + /** + * @return \DateTimeImmutable|null + */ + public function getStartDate(): ?\DateTimeImmutable + { + return $this->startDate; + } + + /** + * @param \DateTimeImmutable|null $startDate + */ + public function setStartDate(?\DateTimeImmutable $startDate): self + { + $this->startDate = $startDate; + return $this; + } + + /** + * @return \DateTimeImmutable|null + */ + public function getEndDate(): ?\DateTimeImmutable + { + return $this->endDate; + } + + /** + * @param \DateTimeImmutable|null $endDate + */ + public function setEndDate(?\DateTimeImmutable $endDate): self + { + $this->endDate = $endDate; + + return $this; + } +} diff --git a/src/Bundle/ChillPersonBundle/Export/Export/CountAccompanyingCourse.php b/src/Bundle/ChillPersonBundle/Export/Export/CountAccompanyingCourse.php index 11a10436e..02682c3a9 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/CountAccompanyingCourse.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/CountAccompanyingCourse.php @@ -15,6 +15,8 @@ use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\GroupedExportInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; +use Chill\PersonBundle\Entity\Person\PersonCenterHistory; use Chill\PersonBundle\Export\Declarations; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter; use Doctrine\ORM\EntityManagerInterface; @@ -90,9 +92,25 @@ class CountAccompanyingCourse implements ExportInterface, GroupedExportInterface public function initiateQuery(array $requiredModifiers, array $acl, array $data = []): QueryBuilder { + $centers = array_map(static function ($el) { + return $el['center']; + }, $acl); + $qb = $this->repository->createQueryBuilder('acp'); - $qb->select('COUNT(acp.id) AS export_result'); + $qb + ->andWhere( + $qb->expr()->exists( + 'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part + JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person) + WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers) + ' + ) + ) + ->setParameter('authorized_centers', $centers) + ; + + $qb->select('COUNT(DISTINCT acp.id) AS export_result'); return $qb; } diff --git a/src/Bundle/ChillPersonBundle/Export/Export/CountEvaluation.php b/src/Bundle/ChillPersonBundle/Export/Export/CountEvaluation.php index 634b351cf..7ff5349f6 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/CountEvaluation.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/CountEvaluation.php @@ -15,6 +15,8 @@ use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\GroupedExportInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; +use Chill\PersonBundle\Entity\Person\PersonCenterHistory; use Chill\PersonBundle\Export\Declarations; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter; use Doctrine\ORM\EntityManagerInterface; @@ -88,6 +90,10 @@ class CountEvaluation implements ExportInterface, GroupedExportInterface public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) { + $centers = array_map(static function ($el) { + return $el['center']; + }, $acl); + $qb = $this->repository->createQueryBuilder('acp'); if (!in_array('acpw', $qb->getAllAliases(), true)) { @@ -98,6 +104,18 @@ class CountEvaluation implements ExportInterface, GroupedExportInterface $qb->join('acpw.accompanyingPeriodWorkEvaluations', 'workeval'); } + $qb + ->andWhere( + $qb->expr()->exists( + 'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part + JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person) + WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers) + ' + ) + ) + ->setParameter('authorized_centers', $centers) + ; + $qb->select('COUNT(DISTINCT workeval.id) AS export_result'); return $qb; diff --git a/src/Bundle/ChillPersonBundle/Export/Export/CountHousehold.php b/src/Bundle/ChillPersonBundle/Export/Export/CountHousehold.php index 106084e4f..e1c7adf88 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/CountHousehold.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/CountHousehold.php @@ -15,6 +15,9 @@ use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\GroupedExportInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; +use Chill\PersonBundle\Entity\Household\HouseholdMember; +use Chill\PersonBundle\Entity\Person\PersonCenterHistory; use Chill\PersonBundle\Export\Declarations; use Chill\PersonBundle\Security\Authorization\HouseholdVoter; use Doctrine\ORM\EntityManagerInterface; @@ -88,23 +91,29 @@ class CountHousehold implements ExportInterface, GroupedExportInterface public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) { - $qb = $this->repository->createQueryBuilder('acp'); + $centers = array_map(static function ($el) { + return $el['center']; + }, $acl); - if (!in_array('acppart', $qb->getAllAliases(), true)) { - $qb->join('acp.participations', 'acppart'); - } + $qb = $this->repository + ->createQueryBuilder('acp') + ->join('acp.participations', 'acppart') + // little optimization: we remove joins and make a direct join between participations and household members + ->join(HouseholdMember::class, 'member', Query\Expr\Join::WITH, 'IDENTITY(acppart.person) = IDENTITY(member.person)') + ->join('member.household', 'household') + ; - if (!in_array('partperson', $qb->getAllAliases(), true)) { - $qb->join('acppart.person', 'partperson'); - } - - if (!in_array('member', $qb->getAllAliases(), true)) { - $qb->join('partperson.householdParticipations', 'member'); - } - - if (!in_array('household', $qb->getAllAliases(), true)) { - $qb->join('member.household', 'household'); - } + $qb + ->andWhere( + $qb->expr()->exists( + 'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part + JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person) + WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers) + ' + ) + ) + ->setParameter('authorized_centers', $centers) + ; $qb->select('COUNT(DISTINCT household.id) AS export_result'); diff --git a/src/Bundle/ChillPersonBundle/Export/Export/CountPerson.php b/src/Bundle/ChillPersonBundle/Export/Export/CountPerson.php index 18cefc6bb..3b2e47bdd 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/CountPerson.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/CountPerson.php @@ -14,9 +14,11 @@ namespace Chill\PersonBundle\Export\Export; use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\GroupedExportInterface; +use Chill\PersonBundle\Entity\Person\PersonCenterHistory; use Chill\PersonBundle\Export\Declarations; use Chill\PersonBundle\Repository\PersonRepository; use Chill\PersonBundle\Security\Authorization\PersonVoter; +use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Query; use Doctrine\ORM\QueryBuilder; use LogicException; @@ -100,9 +102,12 @@ class CountPerson implements ExportInterface, GroupedExportInterface $qb = $this->personRepository->createQueryBuilder('person'); $qb->select('COUNT(person.id) AS export_result') - ->join('person.center', 'center') - ->andWhere('center IN (:authorized_centers)') - ->setParameter('authorized_centers', $centers); + ->andWhere( + $qb->expr()->exists( + 'SELECT 1 FROM '.PersonCenterHistory::class.' pch WHERE pch.person = person.id AND pch.center IN (:authorized_centers)' + ) + ) + ->setParameter('authorized_centers', $centers); return $qb; } diff --git a/src/Bundle/ChillPersonBundle/Export/Export/CountPersonWithAccompanyingCourse.php b/src/Bundle/ChillPersonBundle/Export/Export/CountPersonWithAccompanyingCourse.php index 057611032..fa28e2abe 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/CountPersonWithAccompanyingCourse.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/CountPersonWithAccompanyingCourse.php @@ -15,6 +15,7 @@ use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\GroupedExportInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Chill\PersonBundle\Entity\Person\PersonCenterHistory; use Chill\PersonBundle\Export\Declarations; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter; use Doctrine\ORM\EntityManagerInterface; @@ -88,6 +89,10 @@ class CountPersonWithAccompanyingCourse implements ExportInterface, GroupedExpor public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) { + $centers = array_map(static function ($el) { + return $el['center']; + }, $acl); + $qb = $this->repository->createQueryBuilder('acp'); if (!in_array('acppart', $qb->getAllAliases(), true)) { @@ -98,6 +103,12 @@ class CountPersonWithAccompanyingCourse implements ExportInterface, GroupedExpor $qb->join('acppart.person', 'person'); } + $qb->andWhere( + $qb->expr()->exists( + 'SELECT 1 FROM '.PersonCenterHistory::class.' pch WHERE pch.person = person.id AND pch.center IN (:authorized_centers)' + ) + )->setParameter('authorized_centers', $centers); + $qb->select('COUNT(DISTINCT person.id) AS export_result'); return $qb; diff --git a/src/Bundle/ChillPersonBundle/Export/Export/CountSocialWorkActions.php b/src/Bundle/ChillPersonBundle/Export/Export/CountSocialWorkActions.php index 2ad6e9f1b..4ba071d3b 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/CountSocialWorkActions.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/CountSocialWorkActions.php @@ -15,6 +15,8 @@ use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\GroupedExportInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; +use Chill\PersonBundle\Entity\Person\PersonCenterHistory; use Chill\PersonBundle\Export\Declarations; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter; use Doctrine\ORM\EntityManagerInterface; @@ -90,13 +92,26 @@ class CountSocialWorkActions implements ExportInterface, GroupedExportInterface public function initiateQuery(array $requiredModifiers, array $acl, array $data = []): QueryBuilder { - $qb = $this->repository->createQueryBuilder('acp'); + $centers = array_map(static function ($el) { + return $el['center']; + }, $acl); - if (!in_array('acpw', $qb->getAllAliases(), true)) { - $qb->join('acp.works', 'acpw'); - } + $qb = $this->repository->createQueryBuilder('acp') + ->join('acp.works', 'acpw'); - $qb->select('COUNT(acpw.id) as export_result'); + $qb + ->andWhere( + $qb->expr()->exists( + 'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part + JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person) + WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers) + ' + ) + ) + ->setParameter('authorized_centers', $centers) + ; + + $qb->select('COUNT(DISTINCT acpw.id) as export_result'); return $qb; } diff --git a/src/Bundle/ChillPersonBundle/Export/Export/StatAccompanyingCourseDuration.php b/src/Bundle/ChillPersonBundle/Export/Export/StatAccompanyingCourseDuration.php index b805005be..3b2036797 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/StatAccompanyingCourseDuration.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/StatAccompanyingCourseDuration.php @@ -16,6 +16,8 @@ use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\GroupedExportInterface; use Chill\MainBundle\Form\Type\ChillDateType; use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; +use Chill\PersonBundle\Entity\Person\PersonCenterHistory; use Chill\PersonBundle\Export\Declarations; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter; use DateTime; @@ -94,15 +96,27 @@ class StatAccompanyingCourseDuration implements ExportInterface, GroupedExportIn public function initiateQuery(array $requiredModifiers, array $acl, array $data = []): QueryBuilder { + $centers = array_map(static function ($el) { + return $el['center']; + }, $acl); + $qb = $this->repository->createQueryBuilder('acp'); + $qb + ->andWhere( + $qb->expr()->exists( + 'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part + JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person) + WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers) + ' + ) + ) + ->setParameter('authorized_centers', $centers) + ; + $qb ->select('AVG( - ( CASE - WHEN acp.closingDate IS NOT NULL - THEN acp.closingDate - ELSE :force_closingDate - END ) - acp.openingDate + COALESCE(acp.closingDate, :force_closingDate) - acp.openingDate ) AS export_result') ->setParameter('force_closingDate', $data['closingdate']); diff --git a/src/Bundle/ChillPersonBundle/Repository/Person/PersonCenterHistoryInterface.php b/src/Bundle/ChillPersonBundle/Repository/Person/PersonCenterHistoryInterface.php new file mode 100644 index 000000000..089add06a --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Repository/Person/PersonCenterHistoryInterface.php @@ -0,0 +1,10 @@ +repository = $em->getRepository($this->getClassName()); + } + + public function find($id): ?PersonCenterHistory + { + return $this->repository->find($id); + } + + /** + * @return array|PersonCenterHistory[] + */ + public function findAll(): array + { + return $this->repository->findAll(); + } + + /** + * @return array|PersonCenterHistory[] + */ + public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array + { + return $this->repository->findBy($criteria, $orderBy, $limit, $offset); + } + + public function findOneBy(array $criteria): ?PersonCenterHistory + { + return $this->repository->findOneBy($criteria); + } + + public function getClassName(): string + { + return PersonCenterHistory::class; + } +} diff --git a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php index d5dc3cd7d..96662b66c 100644 --- a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php @@ -16,6 +16,7 @@ use Chill\MainBundle\Repository\CountryRepository; use Chill\MainBundle\Search\ParsingException; use Chill\MainBundle\Search\SearchApiQuery; use Chill\MainBundle\Security\Authorization\AuthorizationHelper; +use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Security\Authorization\PersonVoter; use DateTimeInterface; @@ -34,7 +35,7 @@ use function implode; final class PersonACLAwareRepository implements PersonACLAwareRepositoryInterface { - private AuthorizationHelper $authorizationHelper; + private AuthorizationHelperInterface $authorizationHelper; private CountryRepository $countryRepository; @@ -46,7 +47,7 @@ final class PersonACLAwareRepository implements PersonACLAwareRepositoryInterfac Security $security, EntityManagerInterface $em, CountryRepository $countryRepository, - AuthorizationHelper $authorizationHelper + AuthorizationHelperInterface $authorizationHelper ) { $this->security = $security; $this->em = $em; @@ -310,9 +311,10 @@ final class PersonACLAwareRepository implements PersonACLAwareRepositoryInterfac } return $query + ->setFromClause($query->getFromClause() . ' JOIN view_chill_person_person_center_history_current vcppchc ON vcppchc.person_id = person.id', $query->getFromParams()) ->andWhereClause( strtr( - 'person.center_id IN ({{ center_ids }})', + 'vcppchc.center_id IN ({{ center_ids }})', [ '{{ center_ids }}' => implode( ', ', diff --git a/src/Bundle/ChillPersonBundle/Tests/Entity/PersonTest.php b/src/Bundle/ChillPersonBundle/Tests/Entity/PersonTest.php index 18149c824..4633c3fcb 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Entity/PersonTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Entity/PersonTest.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\PersonBundle\Tests\Entity; +use Chill\MainBundle\Entity\Center; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\Household\Household; use Chill\PersonBundle\Entity\Household\HouseholdMember; @@ -191,4 +192,29 @@ final class PersonTest extends \PHPUnit\Framework\TestCase $this->assertEquals($r['result'], Person::ERROR_ADDIND_PERIOD_AFTER_AN_OPEN_PERIOD); } + + public function testSetCenter() + { + $person = new Person(); + $centerA = new Center(); + $centerB = new Center(); + + $this->assertCount(0, $person->getCenterHistory()); + $this->assertNull($person->getCenter()); + $this->assertNull($person->getCenterCurrent()); + + $person->setCenter($centerA); + + $this->assertCount(1, $person->getCenterHistory()); + $this->assertSame($centerA, $person->getCenter()); + $this->assertInstanceOf(Person\PersonCenterCurrent::class, $person->getCenterCurrent()); + $this->assertSame($centerA, $person->getCenterCurrent()->getCenter()); + + $person->setCenter($centerB); + + $this->assertCount(2, $person->getCenterHistory()); + $this->assertSame($centerB, $person->getCenter()); + $this->assertInstanceOf(Person\PersonCenterCurrent::class, $person->getCenterCurrent()); + $this->assertSame($centerB, $person->getCenterCurrent()->getCenter()); + } } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListPersonTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListPersonTest.php index f3408a064..d3564c0c6 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListPersonTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListPersonTest.php @@ -14,6 +14,7 @@ namespace Chill\PersonBundle\Tests\Export\Export; use Chill\MainBundle\Test\Export\AbstractExportTest; use Chill\PersonBundle\Export\Export\ListPerson; use DateTime; +use Prophecy\PhpUnit\ProphecyTrait; /** * Test the export "ListPerson". @@ -23,10 +24,9 @@ use DateTime; */ final class ListPersonTest extends AbstractExportTest { - /** - * @var ListPerson - */ - private $export; + use ProphecyTrait; + + private ListPerson $export; protected function setUp(): void { @@ -34,10 +34,9 @@ final class ListPersonTest extends AbstractExportTest $this->export = self::$container->get('chill.person.export.list_person'); - // add a fake request with a default locale (used in translatable string) - $prophet = new \Prophecy\Prophet(); - $request = $prophet->prophesize(); - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); + $request = $this->prophesize() + ->willExtend(\Symfony\Component\HttpFoundation\Request::class); + $request->getLocale()->willReturn('fr'); self::$container->get('request_stack') @@ -49,7 +48,7 @@ final class ListPersonTest extends AbstractExportTest return $this->export; } - public function getFormData() + public function getFormData(): array { return [ ['fields' => ['id', 'firstName', 'lastName']], @@ -65,7 +64,7 @@ final class ListPersonTest extends AbstractExportTest ]; } - public function getModifiersCombination() + public function getModifiersCombination(): array { return [ ['person'], diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ActiveOnDateFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ActiveOnDateFilterTest.php index 3a8160cd2..fa03315d2 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ActiveOnDateFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ActiveOnDateFilterTest.php @@ -30,12 +30,6 @@ final class ActiveOnDateFilterTest extends AbstractFilterTest //parent::setUp(); self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_activeondate'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ActiveOneDayBetweenDatesFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ActiveOneDayBetweenDatesFilterTest.php index 30957879e..44f55e69f 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ActiveOneDayBetweenDatesFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ActiveOneDayBetweenDatesFilterTest.php @@ -30,12 +30,6 @@ final class ActiveOneDayBetweenDatesFilterTest extends AbstractFilterTest //parent::setUp(); self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_activeonedaybetweendates'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/AdministrativeLocationFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/AdministrativeLocationFilterTest.php index c09c50fbc..3bd7518f2 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/AdministrativeLocationFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/AdministrativeLocationFilterTest.php @@ -30,12 +30,6 @@ final class AdministrativeLocationFilterTest extends AbstractFilterTest //parent::setUp(); self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_administrative_location'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ClosingMotiveFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ClosingMotiveFilterTest.php index 8ff47ac6c..02e0de4d2 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ClosingMotiveFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ClosingMotiveFilterTest.php @@ -28,12 +28,6 @@ final class ClosingMotiveFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_closingmotive'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ConfidentialFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ConfidentialFilterTest.php index db469bd49..c3e185e1f 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ConfidentialFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ConfidentialFilterTest.php @@ -27,12 +27,6 @@ final class ConfidentialFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_confidential'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/CurrentUserJobFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/CurrentUserJobFilterTest.php index ab2c703b6..0507333ab 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/CurrentUserJobFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/CurrentUserJobFilterTest.php @@ -27,12 +27,6 @@ final class CurrentUserJobFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_userjob'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/CurrentUserScopeFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/CurrentUserScopeFilterTest.php index d4f4712bc..12c3ce96f 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/CurrentUserScopeFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/CurrentUserScopeFilterTest.php @@ -27,12 +27,6 @@ final class CurrentUserScopeFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_userscope'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/EmergencyFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/EmergencyFilterTest.php index 5a7c1228f..7f5fe9f32 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/EmergencyFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/EmergencyFilterTest.php @@ -27,12 +27,6 @@ final class EmergencyFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_emergency'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/EvaluationFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/EvaluationFilterTest.php index c3c25870d..b1436f345 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/EvaluationFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/EvaluationFilterTest.php @@ -30,12 +30,6 @@ final class EvaluationFilterTest extends AbstractFilterTest //parent::setUp(); self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_evaluation'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/GeographicalUnitStatFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/GeographicalUnitStatFilterTest.php index 8baaf5df7..247cb870b 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/GeographicalUnitStatFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/GeographicalUnitStatFilterTest.php @@ -30,12 +30,6 @@ final class GeographicalUnitStatFilterTest extends AbstractFilterTest //parent::setUp(); self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_geographicalunitstat'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/IntensityFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/IntensityFilterTest.php index 6319b2acf..2f4c0caf8 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/IntensityFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/IntensityFilterTest.php @@ -27,12 +27,6 @@ final class IntensityFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_intensity'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/OpenBetweenDatesFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/OpenBetweenDatesFilterTest.php index 5334c17f8..a402b1f6a 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/OpenBetweenDatesFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/OpenBetweenDatesFilterTest.php @@ -30,12 +30,6 @@ final class OpenBetweenDatesFilterTest extends AbstractFilterTest //parent::setUp(); self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_openbetweendates'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/OriginFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/OriginFilterTest.php index 745e62ca6..3182d0063 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/OriginFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/OriginFilterTest.php @@ -28,12 +28,6 @@ final class OriginFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_origin'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ReferrerFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ReferrerFilterTest.php index 8d2c8ef5b..71cfd44da 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ReferrerFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/ReferrerFilterTest.php @@ -29,12 +29,6 @@ final class ReferrerFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_referrer'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/RequestorFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/RequestorFilterTest.php index d936f09ae..318bccf0a 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/RequestorFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/RequestorFilterTest.php @@ -26,15 +26,8 @@ final class RequestorFilterTest extends AbstractFilterTest protected function setUp(): void { - //parent::setUp(); self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_requestor'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/SocialActionFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/SocialActionFilterTest.php index 39321dad1..7b9a8b63e 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/SocialActionFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/SocialActionFilterTest.php @@ -30,12 +30,6 @@ final class SocialActionFilterTest extends AbstractFilterTest //parent::setUp(); self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_socialaction'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/SocialIssueFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/SocialIssueFilterTest.php index a7815d3ed..9b7eec446 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/SocialIssueFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/SocialIssueFilterTest.php @@ -28,12 +28,6 @@ final class SocialIssueFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_socialissue'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/StepFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/StepFilterTest.php index e9353b461..0dce61dc3 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/StepFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/StepFilterTest.php @@ -27,12 +27,6 @@ final class StepFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_step'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/EvaluationFilters/EvaluationTypeFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/EvaluationFilters/EvaluationTypeFilterTest.php index 8ba2b46c1..81c764c99 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/EvaluationFilters/EvaluationTypeFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/EvaluationFilters/EvaluationTypeFilterTest.php @@ -29,12 +29,6 @@ final class EvaluationTypeFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_evaluationtype'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/EvaluationFilters/MaxDateFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/EvaluationFilters/MaxDateFilterTest.php index 5c9533850..be4b3580a 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/EvaluationFilters/MaxDateFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/EvaluationFilters/MaxDateFilterTest.php @@ -29,12 +29,6 @@ final class MaxDateFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_maxdate'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/HouseholdFilters/CompositionFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/HouseholdFilters/CompositionFilterTest.php index 6892c0afc..e71949958 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/HouseholdFilters/CompositionFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/HouseholdFilters/CompositionFilterTest.php @@ -29,12 +29,6 @@ final class CompositionFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_household_composition'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/AgeFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/AgeFilterTest.php index 30ca43dfd..30c3ed86d 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/AgeFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/AgeFilterTest.php @@ -28,12 +28,6 @@ final class AgeFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_age'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/DeadOrAliveFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/DeadOrAliveFilterTest.php index ea2fa62cb..0cbb22be7 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/DeadOrAliveFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/DeadOrAliveFilterTest.php @@ -28,12 +28,6 @@ final class DeadOrAliveFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_dead_or_alive'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/DeathdateFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/DeathdateFilterTest.php index cb711af43..17742dcd6 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/DeathdateFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/DeathdateFilterTest.php @@ -28,12 +28,6 @@ final class DeathdateFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_deathdate'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/GenderFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/GenderFilterTest.php index 8ce02a653..9ebf99b6d 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/GenderFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/GenderFilterTest.php @@ -27,12 +27,6 @@ final class GenderFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $prophet = new \Prophecy\Prophet(); - $request = $prophet->prophesize(); - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_gender'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/MaritalStatusFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/MaritalStatusFilterTest.php index 8ce747f63..40fa814b1 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/MaritalStatusFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/MaritalStatusFilterTest.php @@ -29,12 +29,6 @@ final class MaritalStatusFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_marital_status'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/NationalityFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/NationalityFilterTest.php index 4ea2c44cc..6dd1a944e 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/NationalityFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/NationalityFilterTest.php @@ -29,12 +29,6 @@ final class NationalityFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_nationality'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/ResidentialAddressAtThirdpartyFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/ResidentialAddressAtThirdpartyFilterTest.php index 8bd07f75c..8444f6865 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/ResidentialAddressAtThirdpartyFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/ResidentialAddressAtThirdpartyFilterTest.php @@ -31,12 +31,6 @@ final class ResidentialAddressAtThirdpartyFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_residential_address_at_thirdparty'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/ResidentialAddressAtUserFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/ResidentialAddressAtUserFilterTest.php index 6a2cde4b0..ba3ededca 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/ResidentialAddressAtUserFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/PersonFilters/ResidentialAddressAtUserFilterTest.php @@ -31,12 +31,6 @@ final class ResidentialAddressAtUserFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_residential_address_at_user'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/JobFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/JobFilterTest.php index 5116af979..76462ebe5 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/JobFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/JobFilterTest.php @@ -27,12 +27,6 @@ final class JobFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_job'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ReferrerFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ReferrerFilterTest.php index c5cc9c523..dd4a17c72 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ReferrerFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ReferrerFilterTest.php @@ -29,12 +29,6 @@ final class ReferrerFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_treatingagent'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ScopeFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ScopeFilterTest.php index b12eb4e5b..2eb1301ca 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ScopeFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ScopeFilterTest.php @@ -27,12 +27,6 @@ final class ScopeFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_scope'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/SocialWorkTypeFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/SocialWorkTypeFilterTest.php index 2e3b392ae..b9def05cd 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/SocialWorkTypeFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/SocialWorkTypeFilterTest.php @@ -31,12 +31,6 @@ final class SocialWorkTypeFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.person.export.filter_social_work_type'); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Repository/PersonACLAwareRepositoryTest.php b/src/Bundle/ChillPersonBundle/Tests/Repository/PersonACLAwareRepositoryTest.php new file mode 100644 index 000000000..4540e3716 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Repository/PersonACLAwareRepositoryTest.php @@ -0,0 +1,79 @@ +entityManager = self::$container->get(EntityManagerInterface::class); + $this->countryRepository = self::$container->get(CountryRepository::class); + $this->centerRepository = self::$container->get(CenterRepositoryInterface::class); + + } + + public function testCountByCriteria() + { + $user = new User(); + + $authorizationHelper = $this->prophesize(AuthorizationHelperInterface::class); + $authorizationHelper->getReachableCenters(Argument::exact($user), Argument::exact(PersonVoter::SEE)) + ->willReturn($this->centerRepository->findAll()); + + $security = $this->prophesize(Security::class); + $security->getUser()->willReturn($user); + + $repository = new PersonACLAwareRepository($security->reveal(), $this->entityManager, $this->countryRepository, + $authorizationHelper->reveal()); + + $number = $repository->countBySearchCriteria('diallo'); + + $this->assertGreaterThan(0, $number); + } + + public function testFindByCriteria() + { + $user = new User(); + + $authorizationHelper = $this->prophesize(AuthorizationHelperInterface::class); + $authorizationHelper->getReachableCenters(Argument::exact($user), Argument::exact(PersonVoter::SEE)) + ->willReturn($this->centerRepository->findAll()); + + $security = $this->prophesize(Security::class); + $security->getUser()->willReturn($user); + + $repository = new PersonACLAwareRepository($security->reveal(), $this->entityManager, $this->countryRepository, + $authorizationHelper->reveal()); + + $results = $repository->findBySearchCriteria(0, 5, false, 'diallo'); + + $this->assertGreaterThan(0, count($results)); + $this->assertContainsOnlyInstancesOf(Person::class, $results); + foreach ($results as $person) { + $this->assertStringContainsString('diallo', strtolower($person->getFirstName() . ' ' . $person->getLastName())); + } + } +} diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20220926154347.php b/src/Bundle/ChillPersonBundle/migrations/Version20220926154347.php new file mode 100644 index 000000000..b308c22e3 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20220926154347.php @@ -0,0 +1,69 @@ +addSql('CREATE SEQUENCE chill_person_person_center_history_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_person_person_center_history ( + id INT NOT NULL, person_id INT DEFAULT NULL, center_id INT DEFAULT NULL, + startDate DATE NOT NULL, endDate DATE DEFAULT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, + updatedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, createdBy_id INT DEFAULT NULL, + updatedBy_id INT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_CACA67FA217BBB47 ON chill_person_person_center_history (person_id)'); + $this->addSql('CREATE INDEX IDX_CACA67FA5932F377 ON chill_person_person_center_history (center_id)'); + $this->addSql('CREATE INDEX IDX_CACA67FA3174800F ON chill_person_person_center_history (createdBy_id)'); + $this->addSql('CREATE INDEX IDX_CACA67FA65FF1AEC ON chill_person_person_center_history (updatedBy_id)'); + $this->addSql('COMMENT ON COLUMN chill_person_person_center_history.startDate IS \'(DC2Type:date_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_person_person_center_history.endDate IS \'(DC2Type:date_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_person_person_center_history.createdAt IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_person_person_center_history.updatedAt IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE chill_person_person_center_history ADD CONSTRAINT FK_CACA67FA217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_person_center_history ADD CONSTRAINT FK_CACA67FA5932F377 FOREIGN KEY (center_id) REFERENCES centers (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_person_center_history ADD CONSTRAINT FK_CACA67FA3174800F FOREIGN KEY (createdBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_person_center_history ADD CONSTRAINT FK_CACA67FA65FF1AEC FOREIGN KEY (updatedBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + + // check consistency of history on database side + $this->addSql('ALTER TABLE chill_person_person_center_history ADD CHECK (startdate <= enddate)'); + $this->addSql('ALTER TABLE chill_person_person_center_history ADD CONSTRAINT ' . + 'chill_internal_person_person_center_history_not_overlaps EXCLUDE USING GIST( + -- extension btree_gist required to include comparaison with integer + person_id WITH =, + daterange(startdate, enddate, \'[)\') WITH && + ) + INITIALLY DEFERRED'); + + // create index on search by person and date + $this->addSql('CREATE INDEX chill_internal_person_person_center_history_by_date ON chill_person_person_center_history (person_id DESC, startdate DESC, enddate DESC NULLS FIRST)'); + + // create a view to get the current center on a person + $this->addSql( + 'CREATE VIEW view_chill_person_person_center_history_current AS + SELECT id, person_id, center_id, startDate, endDate, createdAt, updatedAt, createdBy_id, updatedBy_id + FROM chill_person_person_center_history WHERE startDate <= NOW() AND (enddate IS NULL OR enddate > NOW())' + ); + + $this->addSql('INSERT INTO chill_person_person_center_history (id, person_id, center_id, startdate) + SELECT nextval(\'chill_person_person_center_history_id_seq\'), id, center_id, COALESCE(createdat, NOW()) + FROM chill_person_person WHERE center_id IS NOT NULL'); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP VIEW view_chill_person_person_center_history_current'); + $this->addSql('DROP SEQUENCE chill_person_person_center_history_id_seq CASCADE'); + $this->addSql('DROP TABLE chill_person_person_center_history'); + } +} diff --git a/src/Bundle/ChillReportBundle/Tests/Export/Filter/ReportDateFilterTest.php b/src/Bundle/ChillReportBundle/Tests/Export/Filter/ReportDateFilterTest.php index 27c107f9d..54291a02f 100644 --- a/src/Bundle/ChillReportBundle/Tests/Export/Filter/ReportDateFilterTest.php +++ b/src/Bundle/ChillReportBundle/Tests/Export/Filter/ReportDateFilterTest.php @@ -28,12 +28,6 @@ final class ReportDateFilterTest extends AbstractFilterTest { self::bootKernel(); - // add a fake request with a default locale (used in translatable string) - $request = $this->prophesize(); - - $request->willExtend(\Symfony\Component\HttpFoundation\Request::class); - $request->getLocale()->willReturn('fr'); - $this->filter = self::$container->get('chill.report.export.filter_date'); } diff --git a/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepository.php b/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepository.php index d2dd7fc18..dca83eb71 100644 --- a/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepository.php +++ b/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepository.php @@ -13,6 +13,7 @@ namespace Chill\TaskBundle\Repository; use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface; use Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface; +use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\Person; use Chill\TaskBundle\Entity\SingleTask; @@ -31,14 +32,14 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository { private AuthorizationHelperInterface $authorizationHelper; - private CenterResolverDispatcherInterface $centerResolverDispatcher; + private CenterResolverManagerInterface $centerResolverDispatcher; private EntityManagerInterface $em; private Security $security; public function __construct( - CenterResolverDispatcherInterface $centerResolverDispatcher, + CenterResolverManagerInterface $centerResolverDispatcher, EntityManagerInterface $em, Security $security, AuthorizationHelperInterface $authorizationHelper @@ -304,14 +305,18 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository QueryBuilder $qb, $entity ): QueryBuilder { - $scopes = $this->authorizationHelper->getReachableScopes( - $this->security->getUser(), - TaskVoter::SHOW, - $this->centerResolverDispatcher->resolveCenter($entity) - ); + foreach ($this->centerResolverDispatcher->resolveCenters($entity) as $center) { + $scopes = $this->authorizationHelper->getReachableScopes( + $this->security->getUser(), + TaskVoter::SHOW, + $center + ); - return $qb->andWhere($qb->expr()->in('t.circle', ':scopes')) - ->setParameter('scopes', $scopes); + $qb->andWhere($qb->expr()->in('t.circle', ':scopes')) + ->setParameter('scopes', $scopes); + } + + return $qb; } private function addACLGlobal( @@ -329,7 +334,10 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository $qb->leftJoin('t.person', 'person') ->leftJoin('t.course', 'course') ->leftJoin('course.participations', 'participation') - ->leftJoin('participation.person', 'person_p'); + ->leftJoin('participation.person', 'person_p') + ->leftJoin('person.centerCurrent', 'center_current_person') + ->leftJoin('person_p.centerCurrent', 'center_current_participation') + ; $qb->distinct(true); $k = 0; @@ -344,8 +352,8 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository $and = $qb->expr()->andX( $qb->expr()->orX( - $qb->expr()->eq('person.center', ':center_' . $k), - $qb->expr()->eq('person_p.center', ':center_' . $k) + $qb->expr()->eq('center_current_person.center', ':center_' . $k), + $qb->expr()->eq('center_current_participation.center', ':center_' . $k) ), $qb->expr()->in('t.circle', ':scopes_' . $k) ); diff --git a/src/Bundle/ChillTaskBundle/Tests/Repository/SingleTaskACLAwareRepositoryTest.php b/src/Bundle/ChillTaskBundle/Tests/Repository/SingleTaskACLAwareRepositoryTest.php new file mode 100644 index 000000000..f4c54b6cc --- /dev/null +++ b/src/Bundle/ChillTaskBundle/Tests/Repository/SingleTaskACLAwareRepositoryTest.php @@ -0,0 +1,211 @@ +em = self::$container->get(EntityManagerInterface::class); + $this->userRepository = self::$container->get(UserRepository::class); + $this->centerRepository = self::$container->get(CenterRepositoryInterface::class); + $this->scopeRepository = self::$container->get(ScopeRepository::class); + $this->personRepository = self::$container->get(PersonRepository::class); + } + + public function testCountByPerson(): void + { + $centerA = $this->centerRepository->findOneBy(['name' => 'Center A']); + $user = new User(); + $scopes = $this->scopeRepository->findAll(); + $person = $this->getRandomPerson($this->em); + + $security = $this->prophesize(Security::class); + $security->getUser()->willReturn($user); + + $centerResolverDispatcher = $this->prophesize(CenterResolverManagerInterface::class); + $centerResolverDispatcher->resolveCenters(Argument::type(Person::class), Argument::any()) + ->willReturn([$centerA]); + + $authorizationHelper = $this->prophesize(AuthorizationHelperInterface::class); + $authorizationHelper->getReachableScopes(Argument::exact($user), Argument::exact(TaskVoter::SHOW), Argument::exact($centerA)) + ->willReturn($scopes); + + $repository = new SingleTaskAclAwareRepository( + $centerResolverDispatcher->reveal(), + $this->em, + $security->reveal(), + $authorizationHelper->reveal() + ); + + $nb = $repository->countByPerson($person, null, []); + + $this->assertGreaterThanOrEqual(0, $nb); + } + + public function testFindByPerson(): void + { + $centerA = $this->centerRepository->findOneBy(['name' => 'Center A']); + $user = new User(); + $scopes = $this->scopeRepository->findAll(); + $person = $this->getRandomPerson($this->em); + + $security = $this->prophesize(Security::class); + $security->getUser()->willReturn($user); + + $centerResolverDispatcher = $this->prophesize(CenterResolverManagerInterface::class); + $centerResolverDispatcher->resolveCenters(Argument::type(Person::class), Argument::any()) + ->willReturn([$centerA]); + + $authorizationHelper = $this->prophesize(AuthorizationHelperInterface::class); + $authorizationHelper->getReachableScopes(Argument::exact($user), Argument::exact(TaskVoter::SHOW), Argument::exact($centerA)) + ->willReturn($scopes); + + $repository = new SingleTaskAclAwareRepository( + $centerResolverDispatcher->reveal(), + $this->em, + $security->reveal(), + $authorizationHelper->reveal() + ); + + $tasks = $repository->findByPerson($person, null, []); + + $this->assertGreaterThanOrEqual(0, count($tasks)); + } + + public function testFindByAllViewable(): void + { + $centerA = $this->centerRepository->findOneBy(['name' => 'Center A']); + $user = new User(); + $scopes = $this->scopeRepository->findAll(); + + $security = $this->prophesize(Security::class); + $security->getUser()->willReturn($user); + + $centerResolverDispatcher = $this->prophesize(CenterResolverManagerInterface::class); + $centerResolverDispatcher->resolveCenters(Argument::type(Person::class), Argument::any()) + ->willReturn([$centerA]); + + $authorizationHelper = $this->prophesize(AuthorizationHelperInterface::class); + $authorizationHelper->getReachableCenters(Argument::exact($user), Argument::exact(TaskVoter::SHOW)) + ->willReturn([$centerA]); + $authorizationHelper->getReachableScopes(Argument::exact($user), Argument::exact(TaskVoter::SHOW), Argument::exact($centerA)) + ->willReturn($scopes); + + $repository = new SingleTaskAclAwareRepository( + $centerResolverDispatcher->reveal(), + $this->em, + $security->reveal(), + $authorizationHelper->reveal() + ); + + $tasks = $repository->findByAllViewable(null, []); + + $this->assertGreaterThanOrEqual(0, count($tasks)); + } + + public function testCountByAllViewable(): void + { + $centerA = $this->centerRepository->findOneBy(['name' => 'Center A']); + $user = new User(); + $scopes = $this->scopeRepository->findAll(); + + $security = $this->prophesize(Security::class); + $security->getUser()->willReturn($user); + + $centerResolverDispatcher = $this->prophesize(CenterResolverManagerInterface::class); + $centerResolverDispatcher->resolveCenters(Argument::type(Person::class), Argument::any()) + ->willReturn([$centerA]); + + $authorizationHelper = $this->prophesize(AuthorizationHelperInterface::class); + $authorizationHelper->getReachableCenters(Argument::exact($user), Argument::exact(TaskVoter::SHOW)) + ->willReturn([$centerA]); + $authorizationHelper->getReachableScopes(Argument::exact($user), Argument::exact(TaskVoter::SHOW), Argument::exact($centerA)) + ->willReturn($scopes); + + $repository = new SingleTaskAclAwareRepository( + $centerResolverDispatcher->reveal(), + $this->em, + $security->reveal(), + $authorizationHelper->reveal() + ); + + $nb = $repository->countByAllViewable(null, []); + + $this->assertGreaterThanOrEqual(0, $nb); + } + + public function testFindByCourse(): void + { + $centerA = $this->centerRepository->findOneBy(['name' => 'Center A']); + $user = new User(); + $scopes = $this->scopeRepository->findAll(); + /** @var Person $person */ + $person = $this->em->createQuery( + 'SELECT p FROM '.Person::class.' p JOIN p.centerCurrent cc + WHERE SIZE(p.accompanyingPeriodParticipations) > 0 + AND cc.center = :center' + ) + ->setParameter('center', $centerA) + ->setMaxResults(1) + ->getSingleResult() + ; + $period = $person->getAccompanyingPeriodParticipations()->first()->getAccompanyingPeriod(); + + $security = $this->prophesize(Security::class); + $security->getUser()->willReturn($user); + + $centerResolverDispatcher = $this->prophesize(CenterResolverManagerInterface::class); + $centerResolverDispatcher->resolveCenters(Argument::type(AccompanyingPeriod::class), Argument::any()) + ->willReturn([$centerA]); + + $authorizationHelper = $this->prophesize(AuthorizationHelperInterface::class); + $authorizationHelper->getReachableScopes(Argument::exact($user), Argument::exact(TaskVoter::SHOW), Argument::any()) + ->willReturn($scopes); + + $repository = new SingleTaskAclAwareRepository( + $centerResolverDispatcher->reveal(), + $this->em, + $security->reveal(), + $authorizationHelper->reveal() + ); + + $tasks = $repository->findByCourse($period); + + $this->assertGreaterThanOrEqual(0, count($tasks)); + } +} \ No newline at end of file