Merge branch 'rector/rules-symfony' into 'master'

Rector: apply symfony rules "up to symfony 4.4"

See merge request Chill-Projet/chill-bundles!536
This commit is contained in:
Julien Fastré 2023-10-17 11:34:12 +00:00
commit 98cd0f3c00
1907 changed files with 18704 additions and 27763 deletions

View File

@ -0,0 +1,6 @@
kind: Feature
body: |
Add history to scopes and to jobs in administrator section. When user job or main scope of user is changed, automaticaly add a new row in history.
time: 2023-09-20T17:52:07.160601133+02:00
custom:
Issue: "147"

View File

@ -0,0 +1,6 @@
kind: Feature
body: Allow closing motives to be identified as 'canceling the accompanying period'
+ don't take canceled accompanying periods into account
time: 2023-10-04T12:08:57.586865276+02:00
custom:
Issue: "146"

View File

@ -0,0 +1,5 @@
kind: Feature
body: '[export] add an aggregator for activities: group by job scope aggregator'
time: 2023-10-11T15:51:15.022779832+02:00
custom:
Issue: ""

View File

@ -3,3 +3,39 @@
# Run tests from root to adapt your own environment # Run tests from root to adapt your own environment
KERNEL_CLASS='App\Kernel' KERNEL_CLASS='App\Kernel'
APP_SECRET='$ecretf0rt3st' APP_SECRET='$ecretf0rt3st'
ADMIN_PASSWORD=password
LOCALE=fr
REDIS_URL=redis
REDIS_PORT=6379
REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT}
JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem
JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
JWT_PASSPHRASE=2a30f6ba26521a2613821da35f28386e
TWILIO_SID=~
TWILIO_SECRET=~
DEFAULT_CARRIER_CODE=BE
ADD_ADDRESS_DEFAULT_COUNTRY=BE
ADD_ADDRESS_MAP_CENTER_X=50.8443
ADD_ADDRESS_MAP_CENTER_Y=4.3523
ADD_ADDRESS_MAP_CENTER_Z=15
SHORT_MESSAGE_DSN=null://null
MESSENGER_TRANSPORT_DSN=sync://
###< symfony/messenger ###
###> doctrine/doctrine-bundle ###
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
#
DATABASE_URL="postgresql://postgres:postgres@db:5432/test?serverVersion=14&charset=utf8"
###< doctrine/doctrine-bundle ###
ASYNC_UPLOAD_TEMP_URL_KEY=
ASYNC_UPLOAD_TEMP_URL_BASE_PATH=
ASYNC_UPLOAD_TEMP_URL_CONTAINER=

View File

@ -3,7 +3,7 @@
# Select what we should cache between builds # Select what we should cache between builds
cache: cache:
paths: paths:
- tests/app/vendor/ - /vendor/
- .cache - .cache
# Bring in any services we need http://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-a-service # Bring in any services we need http://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-a-service
@ -23,12 +23,10 @@ variables:
# configure database access # configure database access
DATABASE_URL: postgresql://postgres:postgres@db:5432/postgres?serverVersion=14&charset=utf8 DATABASE_URL: postgresql://postgres:postgres@db:5432/postgres?serverVersion=14&charset=utf8
# fetch the chill-app using git submodules # fetch the chill-app using git submodules
GIT_SUBMODULE_STRATEGY: recursive # GIT_SUBMODULE_STRATEGY: recursive
REDIS_HOST: redis REDIS_HOST: redis
REDIS_PORT: 6379 REDIS_PORT: 6379
REDIS_URL: redis://redis:6379 REDIS_URL: redis://redis:6379
# change vendor dir to make the app install into tests/apps
COMPOSER_VENDOR_DIR: tests/app/vendor
DEFAULT_CARRIER_CODE: BE DEFAULT_CARRIER_CODE: BE
stages: stages:
@ -50,7 +48,7 @@ build:
expire_in: 30 min expire_in: 30 min
paths: paths:
- bin - bin
- tests/app/vendor/ - vendor/
code_style: code_style:
stage: Tests stage: Tests
@ -64,7 +62,7 @@ code_style:
expire_in: 30 min expire_in: 30 min
paths: paths:
- bin - bin
- tests/app/vendor/ - vendor/
phpstan_tests: phpstan_tests:
stage: Tests stage: Tests
@ -78,13 +76,14 @@ phpstan_tests:
expire_in: 30 min expire_in: 30 min
paths: paths:
- bin - bin
- tests/app/vendor/ - vendor/
rector_tests: rector_tests:
stage: Tests stage: Tests
image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82 image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82
script: script:
- bin/rector --dry-run - tests/console cache:clear
- bin/rector process --dry-run
cache: cache:
paths: paths:
- .cache/ - .cache/
@ -92,7 +91,7 @@ rector_tests:
expire_in: 30 min expire_in: 30 min
paths: paths:
- bin - bin
- tests/app/vendor/ - vendor/
# psalm_tests: # psalm_tests:
# stage: Tests # stage: Tests
@ -109,19 +108,17 @@ rector_tests:
unit_tests: unit_tests:
stage: Tests stage: Tests
image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82 image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82
# until we fix testes
allow_failure: true
script: script:
- php tests/app/bin/console doctrine:migrations:migrate -n - php tests/console doctrine:migrations:migrate -n --env=test
- php -d memory_limit=2G tests/app/bin/console cache:clear --env=dev - php tests/console chill:db:sync-views --env=test
- php -d memory_limit=3G tests/app/bin/console doctrine:fixtures:load -n - php -d memory_limit=2G tests/console cache:clear --env=test
- php -d memory_limit=2G tests/app/bin/console cache:clear --env=test - php -d memory_limit=3G tests/console doctrine:fixtures:load -n
- php -d memory_limit=4G bin/phpunit --colors=never - php -d memory_limit=4G bin/phpunit --colors=never --exclude-group dbIntensive
artifacts: artifacts:
expire_in: 30 min expire_in: 30 min
paths: paths:
- bin - bin
- tests/app/vendor/ - vendor/
release: release:
stage: Deploy stage: Deploy

3
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "_exts/sphinx-php"] [submodule "_exts/sphinx-php"]
path = _exts/sphinx-php path = _exts/sphinx-php
url = https://github.com/fabpot/sphinx-php.git url = https://github.com/fabpot/sphinx-php.git
[submodule "tests/app"]
path = tests/app
url = https://gitlab.com/Chill-projet/chill-app.git

View File

@ -91,7 +91,7 @@ $rules = array_merge(
[ [
'@PhpCsFixer' => true, '@PhpCsFixer' => true,
'@PhpCsFixer:risky' => false, '@PhpCsFixer:risky' => false,
'@Symfony' => false, '@Symfony' => true,
'@Symfony:risky' => false, '@Symfony:risky' => false,
'ordered_class_elements' => [ 'ordered_class_elements' => [
'order' => [ 'order' => [
@ -111,13 +111,13 @@ $rules = array_merge(
'method_private', 'method_private',
], ],
'sort_algorithm' => 'alpha', 'sort_algorithm' => 'alpha',
] ],
], ],
$rules, $rules,
$riskyRules, $riskyRules,
$untilFullSwitchToPhp8, $untilFullSwitchToPhp8,
); );
$rules['header_comment']['header'] = trim(file_get_contents(__DIR__ . '/resource/header.txt')); $rules['header_comment']['header'] = trim(file_get_contents(__DIR__.'/resource/header.txt'));
return $config->setRules($rules); return $config->setRules($rules);

View File

@ -8,7 +8,7 @@
"social worker" "social worker"
], ],
"require": { "require": {
"php": "^7.4|^8.2", "php": "^8.2",
"ext-json": "*", "ext-json": "*",
"ext-openssl": "*", "ext-openssl": "*",
"ext-redis": "*", "ext-redis": "*",
@ -48,7 +48,6 @@
"symfony/monolog-bundle": "^3.5", "symfony/monolog-bundle": "^3.5",
"symfony/security-bundle": "^4.4", "symfony/security-bundle": "^4.4",
"symfony/serializer": "^5.3", "symfony/serializer": "^5.3",
"symfony/templating": "^4.4",
"symfony/translation": "^4.4", "symfony/translation": "^4.4",
"symfony/twig-bundle": "^4.4", "symfony/twig-bundle": "^4.4",
"symfony/validator": "^4.4", "symfony/validator": "^4.4",
@ -76,7 +75,7 @@
"phpunit/phpunit": ">= 7.5", "phpunit/phpunit": ">= 7.5",
"psalm/plugin-phpunit": "^0.18.4", "psalm/plugin-phpunit": "^0.18.4",
"psalm/plugin-symfony": "^4.0.2", "psalm/plugin-symfony": "^4.0.2",
"rector/rector": "^0.15.23", "rector/rector": "^0.17.7",
"symfony/debug-bundle": "^5.1", "symfony/debug-bundle": "^5.1",
"symfony/dotenv": "^4.4", "symfony/dotenv": "^4.4",
"symfony/maker-bundle": "^1.20", "symfony/maker-bundle": "^1.20",
@ -98,7 +97,6 @@
"Chill\\DocGeneratorBundle\\": "src/Bundle/ChillDocGeneratorBundle", "Chill\\DocGeneratorBundle\\": "src/Bundle/ChillDocGeneratorBundle",
"Chill\\DocStoreBundle\\": "src/Bundle/ChillDocStoreBundle", "Chill\\DocStoreBundle\\": "src/Bundle/ChillDocStoreBundle",
"Chill\\EventBundle\\": "src/Bundle/ChillEventBundle", "Chill\\EventBundle\\": "src/Bundle/ChillEventBundle",
"Chill\\FamilyMemberBundle\\": "src/Bundle/ChillFamilyMemberBundle",
"Chill\\MainBundle\\": "src/Bundle/ChillMainBundle", "Chill\\MainBundle\\": "src/Bundle/ChillMainBundle",
"Chill\\PersonBundle\\": "src/Bundle/ChillPersonBundle", "Chill\\PersonBundle\\": "src/Bundle/ChillPersonBundle",
"Chill\\ReportBundle\\": "src/Bundle/ChillReportBundle", "Chill\\ReportBundle\\": "src/Bundle/ChillReportBundle",
@ -110,7 +108,7 @@
}, },
"autoload-dev": { "autoload-dev": {
"psr-4": { "psr-4": {
"App\\": "tests/app/src/", "App\\": "tests/",
"Chill\\DocGeneratorBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests", "Chill\\DocGeneratorBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests",
"Chill\\WopiBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests", "Chill\\WopiBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests",
"Chill\\Utils\\Rector\\Tests\\": "utils/rector/tests" "Chill\\Utils\\Rector\\Tests\\": "utils/rector/tests"
@ -128,12 +126,10 @@
}, },
"bin-dir": "bin", "bin-dir": "bin",
"optimize-autoloader": true, "optimize-autoloader": true,
"sort-packages": true, "sort-packages": true
"vendor-dir": "tests/app/vendor"
}, },
"scripts": { "scripts": {
"auto-scripts": { "auto-scripts": {
"assets:install %PUBLIC_DIR%": "symfony-cmd",
"cache:clear": "symfony-cmd" "cache:clear": "symfony-cmd"
} }
} }

View File

@ -54,18 +54,9 @@ class CountPerson implements ExportInterface
public function getLabels($key, array $values, $data) public function getLabels($key, array $values, $data)
{ {
// the Closure which will be executed by the formatter. // the Closure which will be executed by the formatter.
return function ($value) { return fn($value) => match ($value) {
switch ($value) { '_header' => $this->getTitle(),
case '_header': default => $value,
// we have to process specifically the '_header' string,
// which will be used by the formatter to show a column title
return $this->getTitle();
default:
// for all value, we do not process them and return them
// immediatly
return $value;
}
}; };
} }

View File

@ -13,7 +13,7 @@ namespace Chill\MyBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class example extends Controller class example extends \Symfony\Bundle\FrameworkBundle\Controller\AbstractController
{ {
public function yourAction() public function yourAction()
{ {

View File

@ -16,7 +16,7 @@ use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\Role;
class ConsultationController extends Controller class ConsultationController extends \Symfony\Bundle\FrameworkBundle\Controller\AbstractController
{ {
/** /**
* @param int $id personId * @param int $id personId
@ -43,7 +43,7 @@ class ConsultationController extends Controller
$circles = $authorizationHelper->getReachableCircles( $circles = $authorizationHelper->getReachableCircles(
$this->getUser(), $this->getUser(),
new Role(ConsultationVoter::SEE), ConsultationVoter::SEE,
$person->getCenter() $person->getCenter()
); );

View File

@ -23,25 +23,18 @@ class ChillMainConfiguration implements ConfigurationInterface
{ {
use AddWidgetConfigurationTrait; use AddWidgetConfigurationTrait;
/**
* @var ContainerBuilder
*/
private $containerBuilder;
public function __construct( public function __construct(
array $widgetFactories, array $widgetFactories,
ContainerBuilder $containerBuilder private readonly ContainerBuilder $containerBuilder
) { ) {
// we register here widget factories (see below) // we register here widget factories (see below)
$this->setWidgetFactories($widgetFactories); $this->setWidgetFactories($widgetFactories);
// we will need the container builder later...
$this->containerBuilder = $containerBuilder;
} }
public function getConfigTreeBuilder() public function getConfigTreeBuilder()
{ {
$treeBuilder = new TreeBuilder(); $treeBuilder = new TreeBuilder('chill_main');
$rootNode = $treeBuilder->root('chill_main'); $rootNode = $treeBuilder->getRootNode();
$rootNode $rootNode
->children() ->children()

View File

@ -87,7 +87,7 @@ class ChillPersonAddAPersonWidget implements WidgetInterface
// show only the person from the authorized centers // show only the person from the authorized centers
$and = $qb->expr()->andX(); $and = $qb->expr()->andX();
$centers = $this->authorizationHelper $centers = $this->authorizationHelper
->getReachableCenters($this->getUser(), new Role(PersonVoter::SEE)); ->getReachableCenters($this->getUser(), PersonVoter::SEE);
$and->add($qb->expr()->in('person.center', ':centers')); $and->add($qb->expr()->in('person.center', ':centers'));
$qb->setParameter('centers', $centers); $qb->setParameter('centers', $centers);

View File

@ -1,63 +0,0 @@
Entity,Join,Attribute,Alias
AccompanyingPeriod::class,,,acp
,AccompanyingPeriodWork::class,acp.works,acpw
,AccompanyingPeriodParticipation::class,acp.participations,acppart
,Location::class,acp.administrativeLocation,acploc
,ClosingMotive::class,acp.closingMotive,acpmotive
,UserJob::class,acp.job,acpjob
,Origin::class,acp.origin,acporigin
,Scope::class,acp.scopes,acpscope
,SocialIssue::class,acp.socialIssues,acpsocialissue
,User::class,acp.user,acpuser
AccompanyingPeriodWork::class,,,acpw
,AccompanyingPeriodWorkEvaluation::class,acpw.accompanyingPeriodWorkEvaluations,workeval
,User::class,acpw.referrers,acpwuser
,SocialAction::class,acpw.socialAction,acpwsocialaction
,Goal::class,acpw.goals,goal
,Result::class,acpw.results,result
AccompanyingPeriodParticipation::class,,,acppart
,Person::class,acppart.person,partperson
AccompanyingPeriodWorkEvaluation::class,,,workeval
,Evaluation::class,workeval.evaluation,eval
Goal::class,,,goal
,Result::class,goal.results,goalresult
Person::class,,,person
,Center::class,person.center,center
,HouseholdMember::class,partperson.householdParticipations,householdmember
,MaritalStatus::class,person.maritalStatus,personmarital
,VendeePerson::class,,vp
,VendeePersonMineur::class,,vpm
ResidentialAddress::class,,,resaddr
,ThirdParty::class,resaddr.hostThirdParty,tparty
ThirdParty::class,,,tparty
,ThirdPartyCategory::class,tparty.categories,tpartycat
HouseholdMember::class,,,householdmember
,Household::class,householdmember.household,household
,Person::class,householdmember.person,memberperson
,,memberperson.center,membercenter
Household::class,,,household
,HouseholdComposition::class,household.compositions,composition
Activity::class,,,activity
,Person::class,activity.person,actperson
,AccompanyingPeriod::class,activity.accompanyingPeriod,acp
,Person::class,activity_person_having_activity.person,person_person_having_activity
,ActivityReason::class,activity_person_having_activity.reasons,reasons_person_having_activity
,ActivityType::class,activity.activityType,acttype
,Location::class,activity.location,actloc
,SocialAction::class,activity.socialActions,actsocialaction
,SocialIssue::class,activity.socialIssues,actsocialssue
,ThirdParty::class,activity.thirdParties,acttparty
,User::class,activity.user,actuser
,User::class,activity.users,actusers
,ActivityReason::class,activity.reasons,actreasons
,Center::class,actperson.center,actcenter
ActivityReason::class,,,actreasons
,ActivityReasonCategory::class,actreason.category,actreasoncat
Calendar::class,,,cal
,CancelReason::class,cal.cancelReason,calcancel
,Location::class,cal.location,calloc
,User::class,cal.user,caluser
VendeePerson::class,,,vp
,SituationProfessionelle::class,vp.situationProfessionelle,vpprof
,StatutLogement::class,vp.statutLogement,vplog
,TempsDeTravail::class,vp.tempsDeTravail,vptt
1 Entity Join Attribute Alias
2 AccompanyingPeriod::class acp
3 AccompanyingPeriodWork::class acp.works acpw
4 AccompanyingPeriodParticipation::class acp.participations acppart
5 Location::class acp.administrativeLocation acploc
6 ClosingMotive::class acp.closingMotive acpmotive
7 UserJob::class acp.job acpjob
8 Origin::class acp.origin acporigin
9 Scope::class acp.scopes acpscope
10 SocialIssue::class acp.socialIssues acpsocialissue
11 User::class acp.user acpuser
12 AccompanyingPeriodWork::class acpw
13 AccompanyingPeriodWorkEvaluation::class acpw.accompanyingPeriodWorkEvaluations workeval
14 User::class acpw.referrers acpwuser
15 SocialAction::class acpw.socialAction acpwsocialaction
16 Goal::class acpw.goals goal
17 Result::class acpw.results result
18 AccompanyingPeriodParticipation::class acppart
19 Person::class acppart.person partperson
20 AccompanyingPeriodWorkEvaluation::class workeval
21 Evaluation::class workeval.evaluation eval
22 Goal::class goal
23 Result::class goal.results goalresult
24 Person::class person
25 Center::class person.center center
26 HouseholdMember::class partperson.householdParticipations householdmember
27 MaritalStatus::class person.maritalStatus personmarital
28 VendeePerson::class vp
29 VendeePersonMineur::class vpm
30 ResidentialAddress::class resaddr
31 ThirdParty::class resaddr.hostThirdParty tparty
32 ThirdParty::class tparty
33 ThirdPartyCategory::class tparty.categories tpartycat
34 HouseholdMember::class householdmember
35 Household::class householdmember.household household
36 Person::class householdmember.person memberperson
37 memberperson.center membercenter
38 Household::class household
39 HouseholdComposition::class household.compositions composition
40 Activity::class activity
41 Person::class activity.person actperson
42 AccompanyingPeriod::class activity.accompanyingPeriod acp
43 Person::class activity_person_having_activity.person person_person_having_activity
44 ActivityReason::class activity_person_having_activity.reasons reasons_person_having_activity
45 ActivityType::class activity.activityType acttype
46 Location::class activity.location actloc
47 SocialAction::class activity.socialActions actsocialaction
48 SocialIssue::class activity.socialIssues actsocialssue
49 ThirdParty::class activity.thirdParties acttparty
50 User::class activity.user actuser
51 User::class activity.users actusers
52 ActivityReason::class activity.reasons actreasons
53 Center::class actperson.center actcenter
54 ActivityReason::class actreasons
55 ActivityReasonCategory::class actreason.category actreasoncat
56 Calendar::class cal
57 CancelReason::class cal.cancelReason calcancel
58 Location::class cal.location calloc
59 User::class cal.user caluser
60 VendeePerson::class vp
61 SituationProfessionelle::class vp.situationProfessionelle vpprof
62 StatutLogement::class vp.statutLogement vplog
63 TempsDeTravail::class vp.tempsDeTravail vptt

View File

@ -21,7 +21,6 @@ These are alias conventions :
| | AccompanyingPeriodInfo::class | not existing (using custom WITH clause) | acpinfo | | | AccompanyingPeriodInfo::class | not existing (using custom WITH clause) | acpinfo |
| AccompanyingPeriodWork::class | | | acpw | | AccompanyingPeriodWork::class | | | acpw |
| | AccompanyingPeriodWorkEvaluation::class | acpw.accompanyingPeriodWorkEvaluations | workeval | | | AccompanyingPeriodWorkEvaluation::class | acpw.accompanyingPeriodWorkEvaluations | workeval |
| | User::class | acpw.referrers | acpwuser |
| | SocialAction::class | acpw.socialAction | acpwsocialaction | | | SocialAction::class | acpw.socialAction | acpwsocialaction |
| | Goal::class | acpw.goals | goal | | | Goal::class | acpw.goals | goal |
| | Result::class | acpw.results | result | | | Result::class | acpw.results | result |

View File

@ -2,26 +2,51 @@
<!-- https://phpunit.readthedocs.io/en/latest/configuration.html --> <!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="tests/app/vendor/phpunit/phpunit/phpunit.xsd" xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
backupGlobals="false" backupGlobals="false"
colors="true" colors="true"
bootstrap="tests/app/tests/bootstrap.php" bootstrap="tests/bootstrap.php"
> >
<php> <php>
<ini name="error_reporting" value="-1" /> <ini name="error_reporting" value="-1" />
<server name="APP_ENV" value="test" force="true" /> <server name="APP_ENV" value="test" force="true" />
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" /> <env name="SYMFONY_DEPRECATIONS_HELPER" value="max[direct]=0&amp;max[indirect]=999999" />
<server name="SHELL_VERBOSITY" value="-1" /> <server name="SHELL_VERBOSITY" value="-1" />
<env name="KERNEL_CLASS" value="\App\Kernel" />
</php> </php>
<testsuites> <testsuites>
<!--
<testsuite name="ActivityBundle">
<directory suffix="Test.php">src/Bundle/ChillActivityBundle/Tests/</directory>
</testsuite>
-->
<testsuite name="AsideActivityBundle">
<directory suffix="Test.php">src/Bundle/ChillAsideActivityBundle/src/Tests/</directory>
</testsuite>
<testsuite name="BudgetBundle">
<directory suffix="Test.php">src/Bundle/ChillBudgetBundle/Tests/</directory>
</testsuite>
<testsuite name="CalendarBundle">
<directory suffix="Test.php">src/Bundle/ChillCalendarBundle/Tests/</directory>
</testsuite>
<!-- Missing CustomFieldBundle -->
<testsuite name="DocGeneratorBundle">
<directory suffix="Test.php">src/Bundle/ChillDocGeneratorBundle/tests/</directory>
</testsuite>
<testsuite name="DocStoreBundle">
<directory suffix="Test.php">src/Bundle/ChillDocStoreBundle/Tests/</directory>
</testsuite>
<!--
<testsuite name="EventBundle">
<directory suffix="Test.php">src/Bundle/ChillEventBundle/tests/</directory>
</testsuite>
-->
<testsuite name="MainBundle"> <testsuite name="MainBundle">
<directory suffix="Test.php">src/Bundle/ChillMainBundle/Tests/</directory> <directory suffix="Test.php">src/Bundle/ChillMainBundle/Tests/</directory>
</testsuite> </testsuite>
<testsuite name="PersonBundle"> <testsuite name="PersonBundle">
<directory suffix="Test.php">src/Bundle/ChillPersonBundle/Tests/</directory> <directory suffix="Test.php">src/Bundle/ChillPersonBundle/Tests/</directory>
<!-- test for export will be runned later -->
<exclude>src/Bundle/ChillPersonBundle/Tests/Export/*</exclude>
<!-- we are rewriting accompanying periods... Work in progress --> <!-- we are rewriting accompanying periods... Work in progress -->
<exclude>src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingPeriodControllerTest.php</exclude> <exclude>src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingPeriodControllerTest.php</exclude>
<!-- we are rewriting address, Work in progress --> <!-- we are rewriting address, Work in progress -->
@ -31,14 +56,18 @@
<!-- temporarily removed, the time to find a fix --> <!-- temporarily removed, the time to find a fix -->
<exclude>src/Bundle/ChillPersonBundle/Tests/Controller/PersonDuplicateControllerViewTest.php</exclude> <exclude>src/Bundle/ChillPersonBundle/Tests/Controller/PersonDuplicateControllerViewTest.php</exclude>
</testsuite> </testsuite>
<testsuite name="AsideActivityBundle"> <!--
<directory suffix="Test.php">src/Bundle/ChillAsideActivityBundle/src/Tests/</directory> <testsuite name="ReportBundle">
<directory suffix="Test.php">src/Bundle/ChillReportBundle/Tests/</directory>
</testsuite> </testsuite>
<testsuite name="CalendarBundle"> -->
<directory suffix="Test.php">src/Bundle/ChillCalendarBundle/Tests/</directory> <!--
<testsuite name="TaskBundle">
<directory suffix="Test.php">src/Bundle/ChillTaskBundle/Tests</directory>
</testsuite> </testsuite>
<testsuite name="DocGeneratorBundle"> -->
<directory suffix="Test.php">src/Bundle/ChillDocGeneratorBundle/tests/</directory> <testsuite name="ThirdPartyBundle">
<directory suffix="Test.php">src/Bundle/ChillThirdPartyBundle/Tests</directory>
</testsuite> </testsuite>
<testsuite name="WopiBundle"> <testsuite name="WopiBundle">
<directory suffix="Test.php">src/Bundle/ChillWopiBundle/tests/</directory> <directory suffix="Test.php">src/Bundle/ChillWopiBundle/tests/</directory>

View File

@ -19,6 +19,9 @@ return static function (RectorConfig $rectorConfig): void {
__DIR__ . '/src', __DIR__ . '/src',
]); ]);
$rectorConfig->symfonyContainerXml(__DIR__ . '/var/cache/dev/testsApp_KernelDevDebugContainer.xml');
$rectorConfig->symfonyContainerPhp(__DIR__ . '/tests/symfony-container.php');
//$rectorConfig->cacheClass(\Rector\Caching\ValueObject\Storage\FileCacheStorage::class); //$rectorConfig->cacheClass(\Rector\Caching\ValueObject\Storage\FileCacheStorage::class);
//$rectorConfig->cacheDirectory(__DIR__ . '/.cache/rector'); //$rectorConfig->cacheDirectory(__DIR__ . '/.cache/rector');
@ -28,43 +31,25 @@ return static function (RectorConfig $rectorConfig): void {
//define sets of rules //define sets of rules
$rectorConfig->sets([ $rectorConfig->sets([
LevelSetList::UP_TO_PHP_74 LevelSetList::UP_TO_PHP_82,
\Rector\Symfony\Set\SymfonyLevelSetList::UP_TO_SYMFONY_44,
\Rector\Doctrine\Set\DoctrineSetList::DOCTRINE_CODE_QUALITY,
\Rector\PHPUnit\Set\PHPUnitLevelSetList::UP_TO_PHPUNIT_90,
]); ]);
// some routes are added twice if it remains activated
// $rectorConfig->rule(\Rector\Symfony\Configs\Rector\ClassMethod\AddRouteAnnotationRector::class);
// chill rules // chill rules
$rectorConfig->rule(\Chill\Utils\Rector\Rector\ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector::class); //$rectorConfig->rule(\Chill\Utils\Rector\Rector\ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector::class);
// skip some path... // skip some path...
$rectorConfig->skip([ $rectorConfig->skip([
// make rector stuck for some files
\Rector\Php56\Rector\FunctionLike\AddDefaultValueForUndefinedVariableRector::class,
// we need to discuss this: are we going to have FALSE in tests instead of an error ? // we need to discuss this: are we going to have FALSE in tests instead of an error ?
\Rector\Php71\Rector\FuncCall\CountOnNullRector::class, \Rector\Php71\Rector\FuncCall\CountOnNullRector::class,
// must merge MR500 and review a typing of "ArrayCollection" in entities // we must adapt service definition
\Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class, \Rector\Symfony\Symfony28\Rector\MethodCall\GetToConstructorInjectionRector::class,
\Rector\Symfony\Symfony34\Rector\Closure\ContainerGetNameToTypeInTestsRector::class,
// remove all PHP80 rules, in order to activate them one by one
\Rector\Php80\Rector\ClassMethod\AddParamBasedOnParentClassMethodRector::class,
\Rector\Php80\Rector\Class_\AnnotationToAttributeRector::class,
\Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
\Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
\Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
\Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
\Rector\Php80\Rector\Class_\DoctrineAnnotationClassToAttributeRector::class,
\Rector\Php80\Rector\ClassMethod\FinalPrivateToPrivateVisibilityRector::class,
\Rector\Php80\Rector\Ternary\GetDebugTypeRector::class,
\Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
\Rector\Php80\Rector\Property\NestedAnnotationToAttributeRector::class,
\Rector\Php80\Rector\FuncCall\Php8ResourceReturnToObjectRector::class,
\Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
\Rector\Php80\Rector\ClassMethod\SetStateToStaticRector::class,
\Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
\Rector\Php80\Rector\Identical\StrEndsWithRector::class,
\Rector\Php80\Rector\Identical\StrStartsWithRector::class,
\Rector\Php80\Rector\Class_\StringableForToStringRector::class,
\Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
\Rector\Php80\Rector\FunctionLike\UnionTypesRector::class
]); ]);
}; };

View File

@ -18,7 +18,6 @@ use Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface;
use Chill\ActivityBundle\Repository\ActivityRepository; use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\ActivityBundle\Repository\ActivityTypeCategoryRepository; use Chill\ActivityBundle\Repository\ActivityTypeCategoryRepository;
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface; use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
use Chill\ActivityBundle\Repository\ActivityUserJobRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter; use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable; use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Entity\UserJob;
@ -35,11 +34,8 @@ use Chill\PersonBundle\Privacy\PrivacyEvent;
use Chill\PersonBundle\Repository\AccompanyingPeriodRepository; use Chill\PersonBundle\Repository\AccompanyingPeriodRepository;
use Chill\PersonBundle\Repository\PersonRepository; use Chill\PersonBundle\Repository\PersonRepository;
use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository; use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
use DateTime;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use RuntimeException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\Extension\Core\Type\HiddenType;
@ -49,7 +45,6 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
use function array_key_exists;
final class ActivityController extends AbstractController final class ActivityController extends AbstractController
{ {
@ -77,9 +72,9 @@ final class ActivityController extends AbstractController
/** /**
* Deletes a Activity entity. * Deletes a Activity entity.
* *
* @param mixed $id * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/{id}/delete", name="chill_activity_activity_delete", methods={"GET", "POST", "DELETE"})
*/ */
public function deleteAction(Request $request, $id) public function deleteAction(Request $request, mixed $id)
{ {
$view = null; $view = null;
@ -92,10 +87,10 @@ final class ActivityController extends AbstractController
} }
if ($activity->getAccompanyingPeriod() instanceof AccompanyingPeriod) { if ($activity->getAccompanyingPeriod() instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:confirm_deleteAccompanyingCourse.html.twig'; $view = '@ChillActivity/Activity/confirm_deleteAccompanyingCourse.html.twig';
$accompanyingPeriod = $activity->getAccompanyingPeriod(); $accompanyingPeriod = $activity->getAccompanyingPeriod();
} else { } else {
$view = 'ChillActivityBundle:Activity:confirm_deletePerson.html.twig'; $view = '@ChillActivity/Activity/confirm_deletePerson.html.twig';
} }
// TODO // TODO
@ -103,7 +98,7 @@ final class ActivityController extends AbstractController
$form = $this->createDeleteForm($activity->getId(), $person, $accompanyingPeriod); $form = $this->createDeleteForm($activity->getId(), $person, $accompanyingPeriod);
if ($request->getMethod() === Request::METHOD_DELETE) { if (Request::METHOD_DELETE === $request->getMethod()) {
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isValid()) { if ($form->isValid()) {
@ -136,10 +131,6 @@ final class ActivityController extends AbstractController
} }
} }
if (null === $view) {
throw $this->createNotFoundException('Template not found');
}
return $this->render($view, [ return $this->render($view, [
'activity' => $activity, 'activity' => $activity,
'delete_form' => $form->createView(), 'delete_form' => $form->createView(),
@ -150,6 +141,8 @@ final class ActivityController extends AbstractController
/** /**
* Displays a form to edit an existing Activity entity. * Displays a form to edit an existing Activity entity.
*
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/{id}/edit", name="chill_activity_activity_edit", methods={"GET", "POST", "PUT"})
*/ */
public function editAction(int $id, Request $request): Response public function editAction(int $id, Request $request): Response
{ {
@ -165,10 +158,10 @@ final class ActivityController extends AbstractController
$person = $entity->getPerson(); $person = $entity->getPerson();
if ($entity->getAccompanyingPeriod() instanceof AccompanyingPeriod) { if ($entity->getAccompanyingPeriod() instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:editAccompanyingCourse.html.twig'; $view = '@ChillActivity/Activity/editAccompanyingCourse.html.twig';
$accompanyingPeriod = $entity->getAccompanyingPeriod(); $accompanyingPeriod = $entity->getAccompanyingPeriod();
} else { } else {
$view = 'ChillActivityBundle:Activity:editPerson.html.twig'; $view = '@ChillActivity/Activity/editPerson.html.twig';
} }
// TODO // TODO
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity); // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity);
@ -229,10 +222,6 @@ final class ActivityController extends AbstractController
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
*/ */
if (null === $view) {
throw $this->createNotFoundException('Template not found');
}
$activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); $activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']);
return $this->render($view, [ return $this->render($view, [
@ -247,6 +236,8 @@ final class ActivityController extends AbstractController
/** /**
* Lists all Activity entities. * Lists all Activity entities.
*
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/", name="chill_activity_activity_list")
*/ */
public function listAction(Request $request): Response public function listAction(Request $request): Response
{ {
@ -282,9 +273,9 @@ final class ActivityController extends AbstractController
'element_class' => Activity::class, 'element_class' => Activity::class,
'action' => 'list', 'action' => 'list',
]); ]);
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); $this->eventDispatcher->dispatch($event, PrivacyEvent::PERSON_PRIVACY_EVENT);
$view = 'ChillActivityBundle:Activity:listPerson.html.twig'; $view = '@ChillActivity/Activity/listPerson.html.twig';
} elseif ($accompanyingPeriod instanceof AccompanyingPeriod) { } elseif ($accompanyingPeriod instanceof AccompanyingPeriod) {
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $accompanyingPeriod); $this->denyAccessUnlessGranted(ActivityVoter::SEE, $accompanyingPeriod);
@ -300,9 +291,9 @@ final class ActivityController extends AbstractController
$filterArgs $filterArgs
); );
$view = 'ChillActivityBundle:Activity:listAccompanyingCourse.html.twig'; $view = '@ChillActivity/Activity/listAccompanyingCourse.html.twig';
} else { } else {
throw new \LogicException("Unsupported"); throw new \LogicException('Unsupported');
} }
return $this->render( return $this->render(
@ -332,25 +323,28 @@ final class ActivityController extends AbstractController
->addEntityChoice('activity_types', 'activity_filter.Types', \Chill\ActivityBundle\Entity\ActivityType::class, $types, [ ->addEntityChoice('activity_types', 'activity_filter.Types', \Chill\ActivityBundle\Entity\ActivityType::class, $types, [
'choice_label' => function (\Chill\ActivityBundle\Entity\ActivityType $activityType) { 'choice_label' => function (\Chill\ActivityBundle\Entity\ActivityType $activityType) {
$text = match ($activityType->hasCategory()) { $text = match ($activityType->hasCategory()) {
true => $this->translatableStringHelper->localize($activityType->getCategory()->getName()) . ' > ', true => $this->translatableStringHelper->localize($activityType->getCategory()->getName()).' > ',
false => '', false => '',
}; };
return $text . $this->translatableStringHelper->localize($activityType->getName()); return $text.$this->translatableStringHelper->localize($activityType->getName());
} },
]); ]);
} }
if (1 < count($jobs)) { if (1 < count($jobs)) {
$filterBuilder $filterBuilder
->addEntityChoice('jobs', 'activity_filter.Jobs', UserJob::class, $jobs, [ ->addEntityChoice('jobs', 'activity_filter.Jobs', UserJob::class, $jobs, [
'choice_label' => fn (UserJob $u) => $this->translatableStringHelper->localize($u->getLabel()) 'choice_label' => fn (UserJob $u) => $this->translatableStringHelper->localize($u->getLabel()),
]); ]);
} }
return $filterBuilder->build(); return $filterBuilder->build();
} }
/**
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/new", name="chill_activity_activity_new", methods={"POST", "GET"})
*/
public function newAction(Request $request): Response public function newAction(Request $request): Response
{ {
$view = null; $view = null;
@ -358,16 +352,16 @@ final class ActivityController extends AbstractController
[$person, $accompanyingPeriod] = $this->getEntity($request); [$person, $accompanyingPeriod] = $this->getEntity($request);
if ($accompanyingPeriod instanceof AccompanyingPeriod) { if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:newAccompanyingCourse.html.twig'; $view = '@ChillActivity/Activity/newAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) { } elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:newPerson.html.twig'; $view = '@ChillActivity/Activity/newPerson.html.twig';
} }
$activityType_id = $request->get('activityType_id', 0); $activityType_id = $request->get('activityType_id', 0);
$activityType = $this->activityTypeRepository->find($activityType_id); $activityType = $this->activityTypeRepository->find($activityType_id);
if (isset($activityType) && !$activityType->isActive()) { if (isset($activityType) && !$activityType->isActive()) {
throw new InvalidArgumentException('Activity type must be active'); throw new \InvalidArgumentException('Activity type must be active');
} }
$activityData = null; $activityData = null;
@ -402,45 +396,45 @@ final class ActivityController extends AbstractController
} }
$entity->setActivityType($activityType); $entity->setActivityType($activityType);
$entity->setDate(new DateTime('now')); $entity->setDate(new \DateTime('now'));
if ($request->query->has('activityData')) { if ($request->query->has('activityData')) {
$activityData = $request->query->get('activityData'); $activityData = $request->query->get('activityData');
if (array_key_exists('durationTime', $activityData) && $activityType->getDurationTimeVisible() > 0) { if (\array_key_exists('durationTime', $activityData) && $activityType->getDurationTimeVisible() > 0) {
$durationTimeInMinutes = $activityData['durationTime']; $durationTimeInMinutes = $activityData['durationTime'];
$hours = floor($durationTimeInMinutes / 60); $hours = floor($durationTimeInMinutes / 60);
$minutes = $durationTimeInMinutes % 60; $minutes = $durationTimeInMinutes % 60;
$duration = DateTime::createFromFormat('H:i', $hours . ':' . $minutes); $duration = \DateTime::createFromFormat('H:i', $hours.':'.$minutes);
if ($duration) { if ($duration) {
$entity->setDurationTime($duration); $entity->setDurationTime($duration);
} }
} }
if (array_key_exists('date', $activityData)) { if (\array_key_exists('date', $activityData)) {
$date = DateTime::createFromFormat('Y-m-d', $activityData['date']); $date = \DateTime::createFromFormat('Y-m-d', $activityData['date']);
if ($date) { if ($date) {
$entity->setDate($date); $entity->setDate($date);
} }
} }
if (array_key_exists('personsId', $activityData) && $activityType->getPersonsVisible() > 0) { if (\array_key_exists('personsId', $activityData) && $activityType->getPersonsVisible() > 0) {
foreach ($activityData['personsId'] as $personId) { foreach ($activityData['personsId'] as $personId) {
$concernedPerson = $this->personRepository->find($personId); $concernedPerson = $this->personRepository->find($personId);
$entity->addPerson($concernedPerson); $entity->addPerson($concernedPerson);
} }
} }
if (array_key_exists('professionalsId', $activityData) && $activityType->getThirdPartiesVisible() > 0) { if (\array_key_exists('professionalsId', $activityData) && $activityType->getThirdPartiesVisible() > 0) {
foreach ($activityData['professionalsId'] as $professionalsId) { foreach ($activityData['professionalsId'] as $professionalsId) {
$professional = $this->thirdPartyRepository->find($professionalsId); $professional = $this->thirdPartyRepository->find($professionalsId);
$entity->addThirdParty($professional); $entity->addThirdParty($professional);
} }
} }
if (array_key_exists('usersId', $activityData) && $activityType->getUsersVisible() > 0) { if (\array_key_exists('usersId', $activityData) && $activityType->getUsersVisible() > 0) {
foreach ($activityData['usersId'] as $userId) { foreach ($activityData['usersId'] as $userId) {
$user = $this->userRepository->find($userId); $user = $this->userRepository->find($userId);
@ -450,16 +444,16 @@ final class ActivityController extends AbstractController
} }
} }
if (array_key_exists('location', $activityData) && $activityType->getLocationVisible() > 0) { if (\array_key_exists('location', $activityData) && $activityType->getLocationVisible() > 0) {
$location = $this->locationRepository->find($activityData['location']); $location = $this->locationRepository->find($activityData['location']);
$entity->setLocation($location); $entity->setLocation($location);
} }
if (array_key_exists('comment', $activityData) && $activityType->getCommentVisible() > 0) { if (\array_key_exists('comment', $activityData) && $activityType->getCommentVisible() > 0) {
$comment = new CommentEmbeddable(); $comment = new CommentEmbeddable();
$comment->setComment($activityData['comment']); $comment->setComment($activityData['comment']);
$comment->setUserId($this->getUser()->getid()); $comment->setUserId($this->getUser()->getid());
$comment->setDate(new DateTime('now')); $comment->setDate(new \DateTime('now'));
$entity->setComment($comment); $entity->setComment($comment);
} }
} }
@ -531,6 +525,9 @@ final class ActivityController extends AbstractController
]); ]);
} }
/**
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/select-type", name="chill_activity_activity_select_type")
*/
public function selectTypeAction(Request $request): Response public function selectTypeAction(Request $request): Response
{ {
$view = null; $view = null;
@ -538,9 +535,9 @@ final class ActivityController extends AbstractController
[$person, $accompanyingPeriod] = $this->getEntity($request); [$person, $accompanyingPeriod] = $this->getEntity($request);
if ($accompanyingPeriod instanceof AccompanyingPeriod) { if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:selectTypeAccompanyingCourse.html.twig'; $view = '@ChillActivity/Activity/selectTypeAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) { } elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:selectTypePerson.html.twig'; $view = '@ChillActivity/Activity/selectTypePerson.html.twig';
} }
$data = []; $data = [];
@ -575,6 +572,9 @@ final class ActivityController extends AbstractController
]); ]);
} }
/**
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/{id}/show", name="chill_activity_activity_show")
*/
public function showAction(Request $request, int $id): Response public function showAction(Request $request, int $id): Response
{ {
$entity = $this->activityRepository->find($id); $entity = $this->activityRepository->find($id);
@ -587,11 +587,11 @@ final class ActivityController extends AbstractController
$person = $entity->getPerson(); $person = $entity->getPerson();
if ($accompanyingPeriod instanceof AccompanyingPeriod) { if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:showAccompanyingCourse.html.twig'; $view = '@ChillActivity/Activity/showAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) { } elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:showPerson.html.twig'; $view = '@ChillActivity/Activity/showPerson.html.twig';
} else { } else {
throw new RuntimeException('the activity should be linked with a period or person'); throw new \RuntimeException('the activity should be linked with a period or person');
} }
if (null !== $accompanyingPeriod) { if (null !== $accompanyingPeriod) {
@ -614,10 +614,6 @@ final class ActivityController extends AbstractController
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
*/ */
if (null === $view) {
throw $this->createNotFoundException('Template not found');
}
return $this->render($view, [ return $this->render($view, [
'person' => $person, 'person' => $person,
'accompanyingCourse' => $accompanyingPeriod, 'accompanyingCourse' => $accompanyingPeriod,

View File

@ -24,6 +24,8 @@ class ActivityReasonCategoryController extends AbstractController
{ {
/** /**
* Creates a new ActivityReasonCategory entity. * Creates a new ActivityReasonCategory entity.
*
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/create", name="chill_activity_activityreasoncategory_create", methods={"POST"})
*/ */
public function createAction(Request $request) public function createAction(Request $request)
{ {
@ -31,15 +33,15 @@ class ActivityReasonCategoryController extends AbstractController
$form = $this->createCreateForm($entity); $form = $this->createCreateForm($entity);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
$em->persist($entity); $em->persist($entity);
$em->flush(); $em->flush();
return $this->redirect($this->generateUrl('chill_activity_activityreasoncategory_show', ['id' => $entity->getId()])); return $this->redirectToRoute('chill_activity_activityreasoncategory_show', ['id' => $entity->getId()]);
} }
return $this->render('ChillActivityBundle:ActivityReasonCategory:new.html.twig', [ return $this->render('@ChillActivity/ActivityReasonCategory/new.html.twig', [
'entity' => $entity, 'entity' => $entity,
'form' => $form->createView(), 'form' => $form->createView(),
]); ]);
@ -48,9 +50,9 @@ class ActivityReasonCategoryController extends AbstractController
/** /**
* Displays a form to edit an existing ActivityReasonCategory entity. * Displays a form to edit an existing ActivityReasonCategory entity.
* *
* @param mixed $id * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/{id}/edit", name="chill_activity_activityreasoncategory_edit")
*/ */
public function editAction($id) public function editAction(mixed $id)
{ {
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
@ -62,7 +64,7 @@ class ActivityReasonCategoryController extends AbstractController
$editForm = $this->createEditForm($entity); $editForm = $this->createEditForm($entity);
return $this->render('ChillActivityBundle:ActivityReasonCategory:edit.html.twig', [ return $this->render('@ChillActivity/ActivityReasonCategory/edit.html.twig', [
'entity' => $entity, 'entity' => $entity,
'edit_form' => $editForm->createView(), 'edit_form' => $editForm->createView(),
]); ]);
@ -70,6 +72,8 @@ class ActivityReasonCategoryController extends AbstractController
/** /**
* Lists all ActivityReasonCategory entities. * Lists all ActivityReasonCategory entities.
*
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/", name="chill_activity_activityreasoncategory")
*/ */
public function indexAction() public function indexAction()
{ {
@ -77,20 +81,22 @@ class ActivityReasonCategoryController extends AbstractController
$entities = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReasonCategory::class)->findAll(); $entities = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReasonCategory::class)->findAll();
return $this->render('ChillActivityBundle:ActivityReasonCategory:index.html.twig', [ return $this->render('@ChillActivity/ActivityReasonCategory/index.html.twig', [
'entities' => $entities, 'entities' => $entities,
]); ]);
} }
/** /**
* Displays a form to create a new ActivityReasonCategory entity. * Displays a form to create a new ActivityReasonCategory entity.
*
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/new", name="chill_activity_activityreasoncategory_new")
*/ */
public function newAction() public function newAction()
{ {
$entity = new ActivityReasonCategory(); $entity = new ActivityReasonCategory();
$form = $this->createCreateForm($entity); $form = $this->createCreateForm($entity);
return $this->render('ChillActivityBundle:ActivityReasonCategory:new.html.twig', [ return $this->render('@ChillActivity/ActivityReasonCategory/new.html.twig', [
'entity' => $entity, 'entity' => $entity,
'form' => $form->createView(), 'form' => $form->createView(),
]); ]);
@ -99,9 +105,9 @@ class ActivityReasonCategoryController extends AbstractController
/** /**
* Finds and displays a ActivityReasonCategory entity. * Finds and displays a ActivityReasonCategory entity.
* *
* @param mixed $id * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/{id}/show", name="chill_activity_activityreasoncategory_show")
*/ */
public function showAction($id) public function showAction(mixed $id)
{ {
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
@ -111,7 +117,7 @@ class ActivityReasonCategoryController extends AbstractController
throw $this->createNotFoundException('Unable to find ActivityReasonCategory entity.'); throw $this->createNotFoundException('Unable to find ActivityReasonCategory entity.');
} }
return $this->render('ChillActivityBundle:ActivityReasonCategory:show.html.twig', [ return $this->render('@ChillActivity/ActivityReasonCategory/show.html.twig', [
'entity' => $entity, 'entity' => $entity,
]); ]);
} }
@ -119,9 +125,9 @@ class ActivityReasonCategoryController extends AbstractController
/** /**
* Edits an existing ActivityReasonCategory entity. * Edits an existing ActivityReasonCategory entity.
* *
* @param mixed $id * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/{id}/update", name="chill_activity_activityreasoncategory_update", methods={"POST", "PUT"})
*/ */
public function updateAction(Request $request, $id) public function updateAction(Request $request, mixed $id)
{ {
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
@ -134,13 +140,13 @@ class ActivityReasonCategoryController extends AbstractController
$editForm = $this->createEditForm($entity); $editForm = $this->createEditForm($entity);
$editForm->handleRequest($request); $editForm->handleRequest($request);
if ($editForm->isValid()) { if ($editForm->isSubmitted() && $editForm->isValid()) {
$em->flush(); $em->flush();
return $this->redirect($this->generateUrl('chill_activity_activityreasoncategory_edit', ['id' => $id])); return $this->redirectToRoute('chill_activity_activityreasoncategory_edit', ['id' => $id]);
} }
return $this->render('ChillActivityBundle:ActivityReasonCategory:edit.html.twig', [ return $this->render('@ChillActivity/ActivityReasonCategory/edit.html.twig', [
'entity' => $entity, 'entity' => $entity,
'edit_form' => $editForm->createView(), 'edit_form' => $editForm->createView(),
]); ]);

View File

@ -24,15 +24,12 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
*/ */
class ActivityReasonController extends AbstractController class ActivityReasonController extends AbstractController
{ {
private ActivityReasonRepository $activityReasonRepository; public function __construct(private readonly ActivityReasonRepository $activityReasonRepository) {}
public function __construct(ActivityReasonRepository $activityReasonRepository)
{
$this->activityReasonRepository = $activityReasonRepository;
}
/** /**
* Creates a new ActivityReason entity. * Creates a new ActivityReason entity.
*
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/create", name="chill_activity_activityreason_create", methods={"POST"})
*/ */
public function createAction(Request $request) public function createAction(Request $request)
{ {
@ -40,15 +37,15 @@ class ActivityReasonController extends AbstractController
$form = $this->createCreateForm($entity); $form = $this->createCreateForm($entity);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
$em->persist($entity); $em->persist($entity);
$em->flush(); $em->flush();
return $this->redirect($this->generateUrl('chill_activity_activityreason', ['id' => $entity->getId()])); return $this->redirectToRoute('chill_activity_activityreason', ['id' => $entity->getId()]);
} }
return $this->render('ChillActivityBundle:ActivityReason:new.html.twig', [ return $this->render('@ChillActivity/ActivityReason/new.html.twig', [
'entity' => $entity, 'entity' => $entity,
'form' => $form->createView(), 'form' => $form->createView(),
]); ]);
@ -57,9 +54,9 @@ class ActivityReasonController extends AbstractController
/** /**
* Displays a form to edit an existing ActivityReason entity. * Displays a form to edit an existing ActivityReason entity.
* *
* @param mixed $id * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/{id}/edit", name="chill_activity_activityreason_edit")
*/ */
public function editAction($id) public function editAction(mixed $id)
{ {
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
@ -71,7 +68,7 @@ class ActivityReasonController extends AbstractController
$editForm = $this->createEditForm($entity); $editForm = $this->createEditForm($entity);
return $this->render('ChillActivityBundle:ActivityReason:edit.html.twig', [ return $this->render('@ChillActivity/ActivityReason/edit.html.twig', [
'entity' => $entity, 'entity' => $entity,
'edit_form' => $editForm->createView(), 'edit_form' => $editForm->createView(),
]); ]);
@ -79,6 +76,8 @@ class ActivityReasonController extends AbstractController
/** /**
* Lists all ActivityReason entities. * Lists all ActivityReason entities.
*
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/", name="chill_activity_activityreason")
*/ */
public function indexAction() public function indexAction()
{ {
@ -86,20 +85,22 @@ class ActivityReasonController extends AbstractController
$entities = $this->activityReasonRepository->findAll(); $entities = $this->activityReasonRepository->findAll();
return $this->render('ChillActivityBundle:ActivityReason:index.html.twig', [ return $this->render('@ChillActivity/ActivityReason/index.html.twig', [
'entities' => $entities, 'entities' => $entities,
]); ]);
} }
/** /**
* Displays a form to create a new ActivityReason entity. * Displays a form to create a new ActivityReason entity.
*
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/new", name="chill_activity_activityreason_new")
*/ */
public function newAction() public function newAction()
{ {
$entity = new ActivityReason(); $entity = new ActivityReason();
$form = $this->createCreateForm($entity); $form = $this->createCreateForm($entity);
return $this->render('ChillActivityBundle:ActivityReason:new.html.twig', [ return $this->render('@ChillActivity/ActivityReason/new.html.twig', [
'entity' => $entity, 'entity' => $entity,
'form' => $form->createView(), 'form' => $form->createView(),
]); ]);
@ -108,9 +109,9 @@ class ActivityReasonController extends AbstractController
/** /**
* Finds and displays a ActivityReason entity. * Finds and displays a ActivityReason entity.
* *
* @param mixed $id * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/{id}/show", name="chill_activity_activityreason_show")
*/ */
public function showAction($id) public function showAction(mixed $id)
{ {
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
@ -120,7 +121,7 @@ class ActivityReasonController extends AbstractController
throw $this->createNotFoundException('Unable to find ActivityReason entity.'); throw $this->createNotFoundException('Unable to find ActivityReason entity.');
} }
return $this->render('ChillActivityBundle:ActivityReason:show.html.twig', [ return $this->render('@ChillActivity/ActivityReason/show.html.twig', [
'entity' => $entity, 'entity' => $entity,
]); ]);
} }
@ -128,9 +129,9 @@ class ActivityReasonController extends AbstractController
/** /**
* Edits an existing ActivityReason entity. * Edits an existing ActivityReason entity.
* *
* @param mixed $id * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/{id}/update", name="chill_activity_activityreason_update", methods={"POST", "PUT"})
*/ */
public function updateAction(Request $request, $id) public function updateAction(Request $request, mixed $id)
{ {
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
@ -143,13 +144,13 @@ class ActivityReasonController extends AbstractController
$editForm = $this->createEditForm($entity); $editForm = $this->createEditForm($entity);
$editForm->handleRequest($request); $editForm->handleRequest($request);
if ($editForm->isValid()) { if ($editForm->isSubmitted() && $editForm->isValid()) {
$em->flush(); $em->flush();
return $this->redirect($this->generateUrl('chill_activity_activityreason', ['id' => $id])); return $this->redirectToRoute('chill_activity_activityreason', ['id' => $id]);
} }
return $this->render('ChillActivityBundle:ActivityReason:edit.html.twig', [ return $this->render('@ChillActivity/ActivityReason/edit.html.twig', [
'entity' => $entity, 'entity' => $entity,
'edit_form' => $editForm->createView(), 'edit_form' => $editForm->createView(),
]); ]);

View File

@ -24,7 +24,7 @@ class AdminActivityPresenceController extends CRUDController
*/ */
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator) protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
{ {
/** @var \Doctrine\ORM\QueryBuilder $query */ /* @var \Doctrine\ORM\QueryBuilder $query */
return $query->orderBy('e.id', 'ASC'); return $query->orderBy('e.id', 'ASC');
} }
} }

View File

@ -24,7 +24,7 @@ class AdminActivityTypeCategoryController extends CRUDController
*/ */
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator) protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
{ {
/** @var \Doctrine\ORM\QueryBuilder $query */ /* @var \Doctrine\ORM\QueryBuilder $query */
return $query->orderBy('e.ordering', 'ASC'); return $query->orderBy('e.ordering', 'ASC');
} }
} }

View File

@ -24,7 +24,7 @@ class AdminActivityTypeController extends CRUDController
*/ */
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator) protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
{ {
/** @var \Doctrine\ORM\QueryBuilder $query */ /* @var \Doctrine\ORM\QueryBuilder $query */
return $query->orderBy('e.ordering', 'ASC') return $query->orderBy('e.ordering', 'ASC')
->addOrderBy('e.id', 'ASC'); ->addOrderBy('e.id', 'ASC');
} }

View File

@ -18,11 +18,18 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
*/ */
class AdminController extends AbstractController class AdminController extends AbstractController
{ {
/**
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activity", name="chill_activity_admin_index")
*/
public function indexActivityAction() public function indexActivityAction()
{ {
return $this->render('ChillActivityBundle:Admin:layout_activity.html.twig'); return $this->render('@ChillActivity/Admin/layout_activity.html.twig');
} }
/**
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activity_redirect_to_main", name="chill_admin_aside_activity_redirect_to_admin_index", options={null})
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activity_redirect_to_main", name="chill_admin_activity_redirect_to_admin_index")
*/
public function redirectToAdminIndexAction() public function redirectToAdminIndexAction()
{ {
return $this->redirectToRoute('chill_main_admin_central'); return $this->redirectToRoute('chill_main_admin_central');

View File

@ -25,17 +25,11 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface
{ {
use \Symfony\Component\DependencyInjection\ContainerAwareTrait; use \Symfony\Component\DependencyInjection\ContainerAwareTrait;
private EntityManagerInterface $em; private readonly \Faker\Generator $faker;
/** public function __construct(private readonly EntityManagerInterface $em)
* @var \Faker\Generator
*/
private $faker;
public function __construct(EntityManagerInterface $em)
{ {
$this->faker = FakerFactory::create('fr_FR'); $this->faker = FakerFactory::create('fr_FR');
$this->em = $em;
} }
public function getOrder() public function getOrder()

View File

@ -52,13 +52,13 @@ class LoadActivityReason extends AbstractFixture implements OrderedFixtureInterf
]; ];
foreach ($reasons as $r) { foreach ($reasons as $r) {
echo 'Creating activity reason : ' . $r['name']['en'] . "\n"; echo 'Creating activity reason : '.$r['name']['en']."\n";
$activityReason = (new ActivityReason()) $activityReason = (new ActivityReason())
->setName(($r['name'])) ->setName($r['name'])
->setActive(true) ->setActive(true)
->setCategory($this->getReference($r['category'])); ->setCategory($this->getReference($r['category']));
$manager->persist($activityReason); $manager->persist($activityReason);
$reference = 'activity_reason_' . $r['name']['en']; $reference = 'activity_reason_'.$r['name']['en'];
$this->addReference($reference, $activityReason); $this->addReference($reference, $activityReason);
static::$references[] = $reference; static::$references[] = $reference;
} }

View File

@ -34,13 +34,13 @@ class LoadActivityReasonCategory extends AbstractFixture implements OrderedFixtu
]; ];
foreach ($categs as $c) { foreach ($categs as $c) {
echo 'Creating activity reason category : ' . $c['name']['en'] . "\n"; echo 'Creating activity reason category : '.$c['name']['en']."\n";
$activityReasonCategory = (new ActivityReasonCategory()) $activityReasonCategory = (new ActivityReasonCategory())
->setName(($c['name'])) ->setName($c['name'])
->setActive(true); ->setActive(true);
$manager->persist($activityReasonCategory); $manager->persist($activityReasonCategory);
$this->addReference( $this->addReference(
'cat_' . $c['name']['en'], 'cat_'.$c['name']['en'],
$activityReasonCategory $activityReasonCategory
); );
} }

View File

@ -54,14 +54,14 @@ class LoadActivityType extends Fixture implements OrderedFixtureInterface
]; ];
foreach ($types as $t) { foreach ($types as $t) {
echo 'Creating activity type : ' . $t['name']['fr'] . ' (cat:' . $t['category'] . " \n"; echo 'Creating activity type : '.$t['name']['fr'].' (cat:'.$t['category']." \n";
$activityType = (new ActivityType()) $activityType = (new ActivityType())
->setName(($t['name'])) ->setName($t['name'])
->setCategory($this->getReference('activity_type_cat_' . $t['category'])) ->setCategory($this->getReference('activity_type_cat_'.$t['category']))
->setSocialIssuesVisible(1) ->setSocialIssuesVisible(1)
->setSocialActionsVisible(1); ->setSocialActionsVisible(1);
$manager->persist($activityType); $manager->persist($activityType);
$reference = 'activity_type_' . $t['name']['fr']; $reference = 'activity_type_'.$t['name']['fr'];
$this->addReference($reference, $activityType); $this->addReference($reference, $activityType);
static::$references[] = $reference; static::$references[] = $reference;
} }

View File

@ -42,13 +42,13 @@ class LoadActivityTypeCategory extends Fixture implements OrderedFixtureInterfac
]; ];
foreach ($categories as $cat) { foreach ($categories as $cat) {
echo 'Creating activity type category : ' . $cat['ref'] . "\n"; echo 'Creating activity type category : '.$cat['ref']."\n";
$newCat = (new ActivityTypeCategory()) $newCat = (new ActivityTypeCategory())
->setName(($cat['name'])); ->setName($cat['name']);
$manager->persist($newCat); $manager->persist($newCat);
$reference = 'activity_type_cat_' . $cat['ref']; $reference = 'activity_type_cat_'.$cat['ref'];
$this->addReference($reference, $newCat); $this->addReference($reference, $newCat);
static::$references[] = $reference; static::$references[] = $reference;

View File

@ -20,8 +20,6 @@ use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectManager;
use function in_array;
/** /**
* Add a role CHILL_ACTIVITY_UPDATE & CHILL_ACTIVITY_CREATE for all groups except administrative, * Add a role CHILL_ACTIVITY_UPDATE & CHILL_ACTIVITY_CREATE for all groups except administrative,
* and a role CHILL_ACTIVITY_SEE for administrative. * and a role CHILL_ACTIVITY_SEE for administrative.
@ -40,10 +38,10 @@ class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterfac
foreach (LoadScopes::$references as $scopeRef) { foreach (LoadScopes::$references as $scopeRef) {
$scope = $this->getReference($scopeRef); $scope = $this->getReference($scopeRef);
//create permission group // create permission group
switch ($permissionsGroup->getName()) { switch ($permissionsGroup->getName()) {
case 'social': case 'social':
if ($scope->getName()['en'] === 'administrative') { if ('administrative' === $scope->getName()['en']) {
break 2; // we do not want any power on administrative break 2; // we do not want any power on administrative
} }
@ -51,7 +49,7 @@ class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterfac
case 'administrative': case 'administrative':
case 'direction': case 'direction':
if (in_array($scope->getName()['en'], ['administrative', 'social'], true)) { if (\in_array($scope->getName()['en'], ['administrative', 'social'], true)) {
break 2; // we do not want any power on social or administrative break 2; // we do not want any power on social or administrative
} }
@ -60,7 +58,7 @@ class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterfac
printf( printf(
'Adding CHILL_ACTIVITY_UPDATE & CHILL_ACTIVITY_CREATE & CHILL_ACTIVITY_DELETE, and stats and list permissions to %s ' 'Adding CHILL_ACTIVITY_UPDATE & CHILL_ACTIVITY_CREATE & CHILL_ACTIVITY_DELETE, and stats and list permissions to %s '
. "permission group, scope '%s' \n", ."permission group, scope '%s' \n",
$permissionsGroup->getName(), $permissionsGroup->getName(),
$scope->getName()['en'] $scope->getName()['en']
); );

View File

@ -32,7 +32,7 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
$container->setParameter('chill_activity.form.time_duration', $config['form']['time_duration']); $container->setParameter('chill_activity.form.time_duration', $config['form']['time_duration']);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../config')); $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config'));
$loader->load('services.yaml'); $loader->load('services.yaml');
$loader->load('services/export.yaml'); $loader->load('services/export.yaml');
$loader->load('services/repositories.yaml'); $loader->load('services/repositories.yaml');
@ -73,7 +73,7 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
*/ */
public function prependRoutes(ContainerBuilder $container) public function prependRoutes(ContainerBuilder $container)
{ {
//add routes for custom bundle // add routes for custom bundle
$container->prependExtensionConfig('chill_main', [ $container->prependExtensionConfig('chill_main', [
'routing' => [ 'routing' => [
'resources' => [ 'resources' => [

View File

@ -13,7 +13,6 @@ namespace Chill\ActivityBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\ConfigurationInterface;
use function is_int; use function is_int;
/** /**
@ -59,7 +58,7 @@ class Configuration implements ConfigurationInterface
->info('The number of seconds of this duration. Must be an integer.') ->info('The number of seconds of this duration. Must be an integer.')
->cannotBeEmpty() ->cannotBeEmpty()
->validate() ->validate()
->ifTrue(static fn ($data) => !is_int($data))->thenInvalid('The value %s is not a valid integer') ->ifTrue(static fn ($data) => !\is_int($data))->thenInvalid('The value %s is not a valid integer')
->end() ->end()
->end() ->end()
->scalarNode('label') ->scalarNode('label')

View File

@ -36,7 +36,6 @@ use DateTime;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Serializer\Annotation\DiscriminatorMap; use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName; use Symfony\Component\Serializer\Annotation\SerializedName;
@ -46,11 +45,15 @@ use Symfony\Component\Validator\Constraints as Assert;
* Class Activity. * Class Activity.
* *
* @ORM\Entity(repositoryClass="Chill\ActivityBundle\Repository\ActivityRepository") * @ORM\Entity(repositoryClass="Chill\ActivityBundle\Repository\ActivityRepository")
*
* @ORM\Table(name="activity") * @ORM\Table(name="activity")
*
* @ORM\HasLifecycleCallbacks * @ORM\HasLifecycleCallbacks
*
* @DiscriminatorMap(typeProperty="type", mapping={ * @DiscriminatorMap(typeProperty="type", mapping={
* "activity": Activity::class * "activity": Activity::class
* }) * })
*
* @ActivityValidator\ActivityValidity * @ActivityValidator\ActivityValidity
* *
* TODO see if necessary * TODO see if necessary
@ -65,69 +68,84 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
use TrackUpdateTrait; use TrackUpdateTrait;
public const SENTRECEIVED_RECEIVED = 'received'; final public const SENTRECEIVED_RECEIVED = 'received';
public const SENTRECEIVED_SENT = 'sent'; final public const SENTRECEIVED_SENT = 'sent';
/** /**
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod") * @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod")
*
* @Groups({"read"}) * @Groups({"read"})
*/ */
private ?AccompanyingPeriod $accompanyingPeriod = null; private ?AccompanyingPeriod $accompanyingPeriod = null;
/** /**
* @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityType") * @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityType")
*
* @Groups({"read", "docgen:read"}) * @Groups({"read", "docgen:read"})
*
* @SerializedName("activityType") * @SerializedName("activityType")
*
* @ORM\JoinColumn(name="type_id") * @ORM\JoinColumn(name="type_id")
*/ */
private ActivityType $activityType; private ActivityType $activityType;
/** /**
* @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityPresence") * @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityPresence")
*
* @Groups({"docgen:read"}) * @Groups({"docgen:read"})
*/ */
private ?ActivityPresence $attendee = null; private ?ActivityPresence $attendee = null;
/** /**
* @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\CommentEmbeddable", columnPrefix="comment_") * @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\CommentEmbeddable", columnPrefix="comment_")
*
* @Groups({"docgen:read"}) * @Groups({"docgen:read"})
*/ */
private CommentEmbeddable $comment; private CommentEmbeddable $comment;
/** /**
* @ORM\Column(type="datetime") * @ORM\Column(type="datetime")
*
* @Groups({"docgen:read"}) * @Groups({"docgen:read"})
*/ */
private DateTime $date; private \DateTime $date;
/** /**
* @ORM\ManyToMany(targetEntity="Chill\DocStoreBundle\Entity\StoredObject", cascade={"persist"}) * @ORM\ManyToMany(targetEntity="Chill\DocStoreBundle\Entity\StoredObject", cascade={"persist"})
*
* @Assert\Valid(traverse=true) * @Assert\Valid(traverse=true)
*
* @var Collection<StoredObject>
*/ */
private Collection $documents; private Collection $documents;
/** /**
* @ORM\Column(type="time", nullable=true) * @ORM\Column(type="time", nullable=true)
*/ */
private ?DateTime $durationTime = null; private ?\DateTime $durationTime = null;
/** /**
* @ORM\Column(type="boolean", options={"default": false}) * @ORM\Column(type="boolean", options={"default": false})
*
* @Groups({"docgen:read"}) * @Groups({"docgen:read"})
*/ */
private bool $emergency = false; private bool $emergency = false;
/** /**
* @ORM\Id * @ORM\Id
*
* @ORM\Column(name="id", type="integer") * @ORM\Column(name="id", type="integer")
*
* @ORM\GeneratedValue(strategy="AUTO") * @ORM\GeneratedValue(strategy="AUTO")
*
* @Groups({"read", "docgen:read"}) * @Groups({"read", "docgen:read"})
*/ */
private ?int $id = null; private ?int $id = null;
/** /**
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Location") * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Location")
*
* @groups({"read", "docgen:read"}) * @groups({"read", "docgen:read"})
*/ */
private ?Location $location = null; private ?Location $location = null;
@ -139,9 +157,12 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
/** /**
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\Person") * @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\Person")
*
* @Groups({"read", "docgen:read"}) * @Groups({"read", "docgen:read"})
*
* @var Collection<Person>
*/ */
private ?Collection $persons = null; private Collection $persons;
/** /**
* @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\PrivateCommentEmbeddable", columnPrefix="privateComment_") * @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\PrivateCommentEmbeddable", columnPrefix="privateComment_")
@ -150,58 +171,78 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
/** /**
* @ORM\ManyToMany(targetEntity="Chill\ActivityBundle\Entity\ActivityReason") * @ORM\ManyToMany(targetEntity="Chill\ActivityBundle\Entity\ActivityReason")
*
* @Groups({"docgen:read"}) * @Groups({"docgen:read"})
*
* @var Collection<ActivityReason>
*/ */
private Collection $reasons; private Collection $reasons;
/** /**
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Scope") * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Scope")
*
* @Groups({"docgen:read"}) * @Groups({"docgen:read"})
*/ */
private ?Scope $scope = null; private ?Scope $scope = null;
/** /**
* @ORM\Column(type="string", options={"default": ""}) * @ORM\Column(type="string", options={"default": ""})
*
* @Groups({"docgen:read"}) * @Groups({"docgen:read"})
*/ */
private string $sentReceived = ''; private string $sentReceived = '';
/** /**
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialAction") * @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialAction")
*
* @ORM\JoinTable(name="chill_activity_activity_chill_person_socialaction") * @ORM\JoinTable(name="chill_activity_activity_chill_person_socialaction")
*
* @Groups({"read", "docgen:read"}) * @Groups({"read", "docgen:read"})
*
* @var Collection<SocialAction>
*/ */
private Collection $socialActions; private Collection $socialActions;
/** /**
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialIssue") * @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialIssue")
*
* @ORM\JoinTable(name="chill_activity_activity_chill_person_socialissue") * @ORM\JoinTable(name="chill_activity_activity_chill_person_socialissue")
*
* @Groups({"read", "docgen:read"}) * @Groups({"read", "docgen:read"})
*
* @var Collection<SocialIssue>
*/ */
private Collection $socialIssues; private Collection $socialIssues;
/** /**
* @ORM\ManyToMany(targetEntity="Chill\ThirdPartyBundle\Entity\ThirdParty") * @ORM\ManyToMany(targetEntity="Chill\ThirdPartyBundle\Entity\ThirdParty")
*
* @Groups({"read", "docgen:read"}) * @Groups({"read", "docgen:read"})
*
* @var Collection<ThirdParty>
*/ */
private ?Collection $thirdParties = null; private Collection $thirdParties;
/** /**
* @ORM\Column(type="time", nullable=true) * @ORM\Column(type="time", nullable=true)
*/ */
private ?DateTime $travelTime = null; private ?\DateTime $travelTime = null;
/** /**
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User") * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
*
* @Groups({"docgen:read"}) * @Groups({"docgen:read"})
*/ */
private ?User $user = null; private ?User $user = null;
/** /**
* @ORM\ManyToMany(targetEntity="Chill\MainBundle\Entity\User") * @ORM\ManyToMany(targetEntity="Chill\MainBundle\Entity\User")
*
* @Groups({"read", "docgen:read"}) * @Groups({"read", "docgen:read"})
*
* @var Collection<User>
*/ */
private ?Collection $users = null; private Collection $users;
public function __construct() public function __construct()
{ {
@ -268,7 +309,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
$this->socialIssues[] = $socialIssue; $this->socialIssues[] = $socialIssue;
} }
if ($this->getAccompanyingPeriod() !== null) { if (null !== $this->getAccompanyingPeriod()) {
$this->getAccompanyingPeriod()->addSocialIssue($socialIssue); $this->getAccompanyingPeriod()->addSocialIssue($socialIssue);
} }
@ -334,7 +375,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
return $this->comment; return $this->comment;
} }
public function getDate(): DateTime public function getDate(): \DateTime
{ {
return $this->date; return $this->date;
} }
@ -356,7 +397,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
return (int) round(($this->durationTime->getTimestamp() + $this->durationTime->getOffset()) / 60.0, 0); return (int) round(($this->durationTime->getTimestamp() + $this->durationTime->getOffset()) / 60.0, 0);
} }
public function getDurationTime(): ?DateTime public function getDurationTime(): ?\DateTime
{ {
return $this->durationTime; return $this->durationTime;
} }
@ -410,7 +451,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
// TODO better semantic with: return $this->persons->filter(...); // TODO better semantic with: return $this->persons->filter(...);
foreach ($this->persons as $person) { foreach ($this->persons as $person) {
if ($this->accompanyingPeriod->getOpenParticipationContainsPerson($person) === null) { if (null === $this->accompanyingPeriod->getOpenParticipationContainsPerson($person)) {
$personsNotAssociated[] = $person; $personsNotAssociated[] = $person;
} }
} }
@ -469,7 +510,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
return $this->thirdParties; return $this->thirdParties;
} }
public function getTravelTime(): ?DateTime public function getTravelTime(): ?\DateTime
{ {
return $this->travelTime; return $this->travelTime;
} }
@ -580,7 +621,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
return $this; return $this;
} }
public function setDate(DateTime $date): self public function setDate(\DateTime $date): self
{ {
$this->date = $date; $this->date = $date;
@ -594,7 +635,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
return $this; return $this;
} }
public function setDurationTime(?DateTime $durationTime): self public function setDurationTime(?\DateTime $durationTime): self
{ {
$this->durationTime = $durationTime; $this->durationTime = $durationTime;
@ -664,7 +705,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
return $this; return $this;
} }
public function setTravelTime(DateTime $travelTime): self public function setTravelTime(\DateTime $travelTime): self
{ {
$this->travelTime = $travelTime; $this->travelTime = $travelTime;

View File

@ -18,7 +18,9 @@ use Symfony\Component\Serializer\Annotation as Serializer;
* Class ActivityPresence. * Class ActivityPresence.
* *
* @ORM\Entity * @ORM\Entity
*
* @ORM\Table(name="activitytpresence") * @ORM\Table(name="activitytpresence")
*
* @ORM\HasLifecycleCallbacks * @ORM\HasLifecycleCallbacks
*/ */
class ActivityPresence class ActivityPresence
@ -30,15 +32,20 @@ class ActivityPresence
/** /**
* @ORM\Id * @ORM\Id
*
* @ORM\Column(name="id", type="integer") * @ORM\Column(name="id", type="integer")
*
* @ORM\GeneratedValue(strategy="AUTO") * @ORM\GeneratedValue(strategy="AUTO")
*
* @Serializer\Groups({"docgen:read"}) * @Serializer\Groups({"docgen:read"})
*/ */
private ?int $id = null; private ?int $id = null;
/** /**
* @ORM\Column(type="json") * @ORM\Column(type="json")
*
* @Serializer\Groups({"docgen:read"}) * @Serializer\Groups({"docgen:read"})
*
* @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"})
*/ */
private array $name = []; private array $name = [];

View File

@ -17,39 +17,38 @@ use Doctrine\ORM\Mapping as ORM;
* Class ActivityReason. * Class ActivityReason.
* *
* @ORM\Entity * @ORM\Entity
*
* @ORM\Table(name="activityreason") * @ORM\Table(name="activityreason")
*
* @ORM\HasLifecycleCallbacks * @ORM\HasLifecycleCallbacks
*/ */
class ActivityReason class ActivityReason
{ {
/** /**
* @var bool
* @ORM\Column(type="boolean") * @ORM\Column(type="boolean")
*/ */
private $active = true; private bool $active = true;
/** /**
* @var ActivityReasonCategory
* @ORM\ManyToOne( * @ORM\ManyToOne(
* targetEntity="Chill\ActivityBundle\Entity\ActivityReasonCategory", * targetEntity="Chill\ActivityBundle\Entity\ActivityReasonCategory",
* inversedBy="reasons") * inversedBy="reasons")
*/ */
private $category; private ?ActivityReasonCategory $category = null;
/** /**
* @var int
*
* @ORM\Id * @ORM\Id
*
* @ORM\Column(name="id", type="integer") * @ORM\Column(name="id", type="integer")
*
* @ORM\GeneratedValue(strategy="AUTO") * @ORM\GeneratedValue(strategy="AUTO")
*/ */
private $id; private ?int $id = null;
/** /**
* @var array
* @ORM\Column(type="json") * @ORM\Column(type="json")
*/ */
private $name; private array $name;
/** /**
* Get active. * Get active.
@ -81,27 +80,9 @@ class ActivityReason
/** /**
* Get name. * Get name.
*
* @param mixed|null $locale
*
* @return array | string
*/ */
public function getName($locale = null) public function getName(): array
{ {
if ($locale) {
if (isset($this->name[$locale])) {
return $this->name[$locale];
}
foreach ($this->name as $name) {
if (!empty($name)) {
return $name;
}
}
return '';
}
return $this->name; return $this->name;
} }

View File

@ -12,34 +12,37 @@ declare(strict_types=1);
namespace Chill\ActivityBundle\Entity; namespace Chill\ActivityBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
/** /**
* Class ActivityReasonCategory. * Class ActivityReasonCategory.
* *
* @ORM\Entity * @ORM\Entity
*
* @ORM\Table(name="activityreasoncategory") * @ORM\Table(name="activityreasoncategory")
*
* @ORM\HasLifecycleCallbacks * @ORM\HasLifecycleCallbacks
*/ */
class ActivityReasonCategory class ActivityReasonCategory implements \Stringable
{ {
/** /**
* @var bool
* @ORM\Column(type="boolean") * @ORM\Column(type="boolean")
*/ */
private $active = true; private bool $active = true;
/** /**
* @var int
*
* @ORM\Id * @ORM\Id
*
* @ORM\Column(name="id", type="integer") * @ORM\Column(name="id", type="integer")
*
* @ORM\GeneratedValue(strategy="AUTO") * @ORM\GeneratedValue(strategy="AUTO")
*/ */
private $id; private ?int $id = null;
/** /**
* @var string * @var string
*
* @ORM\Column(type="json") * @ORM\Column(type="json")
*/ */
private $name; private $name;
@ -47,12 +50,13 @@ class ActivityReasonCategory
/** /**
* Array of ActivityReason. * Array of ActivityReason.
* *
* @var ArrayCollection * @var Collection<ActivityReason>
*
* @ORM\OneToMany( * @ORM\OneToMany(
* targetEntity="Chill\ActivityBundle\Entity\ActivityReason", * targetEntity="Chill\ActivityBundle\Entity\ActivityReason",
* mappedBy="category") * mappedBy="category")
*/ */
private $reasons; private Collection $reasons;
/** /**
* ActivityReasonCategory constructor. * ActivityReasonCategory constructor.
@ -62,12 +66,9 @@ class ActivityReasonCategory
$this->reasons = new ArrayCollection(); $this->reasons = new ArrayCollection();
} }
/** public function __toString(): string
* @return string
*/
public function __toString()
{ {
return 'ActivityReasonCategory(' . $this->getName('x') . ')'; return 'ActivityReasonCategory('.$this->getName('x').')';
} }
/** /**
@ -121,11 +122,9 @@ class ActivityReasonCategory
* as unactive, all the reason have this entity as category is also * as unactive, all the reason have this entity as category is also
* set as unactive. * set as unactive.
* *
* @param bool $active
*
* @return ActivityReasonCategory * @return ActivityReasonCategory
*/ */
public function setActive($active) public function setActive(bool $active)
{ {
if ($this->active !== $active && !$active) { if ($this->active !== $active && !$active) {
foreach ($this->reasons as $reason) { foreach ($this->reasons as $reason) {

View File

@ -12,7 +12,6 @@ declare(strict_types=1);
namespace Chill\ActivityBundle\Entity; namespace Chill\ActivityBundle\Entity;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use InvalidArgumentException;
use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Serializer\Annotation as Serializer;
use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Constraints as Assert;
@ -22,31 +21,36 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
* Class ActivityType. * Class ActivityType.
* *
* @ORM\Entity * @ORM\Entity
*
* @ORM\Table(name="activitytype") * @ORM\Table(name="activitytype")
*
* @ORM\HasLifecycleCallbacks * @ORM\HasLifecycleCallbacks
*/ */
class ActivityType class ActivityType
{ {
public const FIELD_INVISIBLE = 0; final public const FIELD_INVISIBLE = 0;
public const FIELD_OPTIONAL = 1; final public const FIELD_OPTIONAL = 1;
public const FIELD_REQUIRED = 2; final public const FIELD_REQUIRED = 2;
/** /**
* @deprecated not in use * @deprecated not in use
*
* @ORM\Column(type="string", nullable=false, options={"default": ""}) * @ORM\Column(type="string", nullable=false, options={"default": ""})
*/ */
private string $accompanyingPeriodLabel = ''; private string $accompanyingPeriodLabel = '';
/** /**
* @deprecated not in use * @deprecated not in use
*
* @ORM\Column(type="smallint", nullable=false, options={"default": 1}) * @ORM\Column(type="smallint", nullable=false, options={"default": 1})
*/ */
private int $accompanyingPeriodVisible = self::FIELD_INVISIBLE; private int $accompanyingPeriodVisible = self::FIELD_INVISIBLE;
/** /**
* @ORM\Column(type="boolean") * @ORM\Column(type="boolean")
*
* @Groups({"read"}) * @Groups({"read"})
*/ */
private bool $active = true; private bool $active = true;
@ -118,8 +122,11 @@ class ActivityType
/** /**
* @ORM\Id * @ORM\Id
*
* @ORM\Column(name="id", type="integer") * @ORM\Column(name="id", type="integer")
*
* @ORM\GeneratedValue(strategy="AUTO") * @ORM\GeneratedValue(strategy="AUTO")
*
* @Groups({"docgen:read"}) * @Groups({"docgen:read"})
*/ */
private ?int $id = null; private ?int $id = null;
@ -136,7 +143,9 @@ class ActivityType
/** /**
* @ORM\Column(type="json") * @ORM\Column(type="json")
*
* @Groups({"read", "docgen:read"}) * @Groups({"read", "docgen:read"})
*
* @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"})
*/ */
private array $name = []; private array $name = [];
@ -158,6 +167,7 @@ class ActivityType
/** /**
* @ORM\Column(type="smallint", nullable=false, options={"default": 1}) * @ORM\Column(type="smallint", nullable=false, options={"default": 1})
*
* @Groups({"read"}) * @Groups({"read"})
*/ */
private int $personsVisible = self::FIELD_OPTIONAL; private int $personsVisible = self::FIELD_OPTIONAL;
@ -238,6 +248,7 @@ class ActivityType
/** /**
* @ORM\Column(type="smallint", nullable=false, options={"default": 1}) * @ORM\Column(type="smallint", nullable=false, options={"default": 1})
*
* @Groups({"read"}) * @Groups({"read"})
*/ */
private int $thirdPartiesVisible = self::FIELD_INVISIBLE; private int $thirdPartiesVisible = self::FIELD_INVISIBLE;
@ -264,6 +275,7 @@ class ActivityType
/** /**
* @ORM\Column(type="smallint", nullable=false, options={"default": 1}) * @ORM\Column(type="smallint", nullable=false, options={"default": 1})
*
* @Groups({"read"}) * @Groups({"read"})
*/ */
private int $usersVisible = self::FIELD_OPTIONAL; private int $usersVisible = self::FIELD_OPTIONAL;
@ -275,10 +287,8 @@ class ActivityType
/** /**
* @Assert\Callback * @Assert\Callback
*
* @param mixed $payload
*/ */
public function checkSocialActionsVisibility(ExecutionContextInterface $context, $payload) public function checkSocialActionsVisibility(ExecutionContextInterface $context, mixed $payload)
{ {
if ($this->socialIssuesVisible !== $this->socialActionsVisible) { if ($this->socialIssuesVisible !== $this->socialActionsVisible) {
if (!(2 === $this->socialIssuesVisible && 1 === $this->socialActionsVisible)) { if (!(2 === $this->socialIssuesVisible && 1 === $this->socialActionsVisible)) {
@ -374,13 +384,13 @@ class ActivityType
public function getLabel(string $field): ?string public function getLabel(string $field): ?string
{ {
$property = $field . 'Label'; $property = $field.'Label';
if (!property_exists($this, $property)) { if (!property_exists($this, $property)) {
throw new InvalidArgumentException('Field "' . $field . '" not found'); throw new \InvalidArgumentException('Field "'.$field.'" not found');
} }
/** @phpstan-ignore-next-line */ /* @phpstan-ignore-next-line */
return $this->{$property}; return $this->{$property};
} }
@ -533,25 +543,25 @@ class ActivityType
public function isRequired(string $field): bool public function isRequired(string $field): bool
{ {
$property = $field . 'Visible'; $property = $field.'Visible';
if (!property_exists($this, $property)) { if (!property_exists($this, $property)) {
throw new InvalidArgumentException('Field "' . $field . '" not found'); throw new \InvalidArgumentException('Field "'.$field.'" not found');
} }
/** @phpstan-ignore-next-line */ /* @phpstan-ignore-next-line */
return self::FIELD_REQUIRED === $this->{$property}; return self::FIELD_REQUIRED === $this->{$property};
} }
public function isVisible(string $field): bool public function isVisible(string $field): bool
{ {
$property = $field . 'Visible'; $property = $field.'Visible';
if (!property_exists($this, $property)) { if (!property_exists($this, $property)) {
throw new InvalidArgumentException('Field "' . $field . '" not found'); throw new \InvalidArgumentException('Field "'.$field.'" not found');
} }
/** @phpstan-ignore-next-line */ /* @phpstan-ignore-next-line */
return self::FIELD_INVISIBLE !== $this->{$property}; return self::FIELD_INVISIBLE !== $this->{$property};
} }

View File

@ -15,7 +15,9 @@ use Doctrine\ORM\Mapping as ORM;
/** /**
* @ORM\Entity * @ORM\Entity
*
* @ORM\Table(name="activitytypecategory") * @ORM\Table(name="activitytypecategory")
*
* @ORM\HasLifecycleCallbacks * @ORM\HasLifecycleCallbacks
*/ */
class ActivityTypeCategory class ActivityTypeCategory
@ -27,7 +29,9 @@ class ActivityTypeCategory
/** /**
* @ORM\Id * @ORM\Id
*
* @ORM\Column(name="id", type="integer") * @ORM\Column(name="id", type="integer")
*
* @ORM\GeneratedValue(strategy="AUTO") * @ORM\GeneratedValue(strategy="AUTO")
*/ */
private ?int $id = null; private ?int $id = null;

View File

@ -15,22 +15,11 @@ use Chill\ActivityBundle\Entity\Activity;
use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository; use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use function in_array;
class ActivityEntityListener class ActivityEntityListener
{ {
private EntityManagerInterface $em; public function __construct(private readonly EntityManagerInterface $em, private readonly AccompanyingPeriodWorkRepository $workRepository) {}
private AccompanyingPeriodWorkRepository $workRepository;
public function __construct(EntityManagerInterface $em, AccompanyingPeriodWorkRepository $workRepository)
{
$this->em = $em;
$this->workRepository = $workRepository;
}
public function persistActionToCourse(Activity $activity) public function persistActionToCourse(Activity $activity)
{ {
@ -39,11 +28,11 @@ class ActivityEntityListener
$accompanyingCourseWorks = $this->workRepository->findByAccompanyingPeriod($period); $accompanyingCourseWorks = $this->workRepository->findByAccompanyingPeriod($period);
$periodActions = []; $periodActions = [];
$now = new DateTimeImmutable(); $now = new \DateTimeImmutable();
foreach ($accompanyingCourseWorks as $key => $work) { foreach ($accompanyingCourseWorks as $key => $work) {
// take only the actions which are still opened // take only the actions which are still opened
if ($work->getEndDate() === null || $work->getEndDate() > ($activity->getDate() ?? $now)) { if (null === $work->getEndDate() || $work->getEndDate() > ($activity->getDate() ?? $now)) {
$periodActions[$key] = spl_object_hash($work->getSocialAction()); $periodActions[$key] = spl_object_hash($work->getSocialAction());
} }
} }
@ -52,14 +41,14 @@ class ActivityEntityListener
$associatedThirdparties = $activity->getThirdParties(); $associatedThirdparties = $activity->getThirdParties();
foreach ($activity->getSocialActions() as $action) { foreach ($activity->getSocialActions() as $action) {
if (in_array(spl_object_hash($action), $periodActions, true)) { if (\in_array(spl_object_hash($action), $periodActions, true)) {
continue; continue;
} }
$newAction = new AccompanyingPeriodWork(); $newAction = new AccompanyingPeriodWork();
$newAction->setSocialAction($action); $newAction->setSocialAction($action);
$period->addWork($newAction); $period->addWork($newAction);
$date = DateTimeImmutable::createFromMutable($activity->getDate()); $date = \DateTimeImmutable::createFromMutable($activity->getDate());
$newAction->setStartDate($date); $newAction->setStartDate($date);
foreach ($associatedPersons as $person) { foreach ($associatedPersons as $person) {

View File

@ -27,7 +27,7 @@ class ByActivityNumberAggregator implements AggregatorInterface
public function alterQuery(QueryBuilder $qb, $data): void public function alterQuery(QueryBuilder $qb, $data): void
{ {
$qb $qb
->addSelect('(SELECT COUNT(activity.id) FROM ' . Activity::class . ' activity WHERE activity.accompanyingPeriod = acp) AS activity_by_number_aggregator') ->addSelect('(SELECT COUNT(activity.id) FROM '.Activity::class.' activity WHERE activity.accompanyingPeriod = acp) AS activity_by_number_aggregator')
->addGroupBy('activity_by_number_aggregator'); ->addGroupBy('activity_by_number_aggregator');
} }
@ -40,6 +40,7 @@ class ByActivityNumberAggregator implements AggregatorInterface
{ {
// No form needed // No form needed
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];

View File

@ -17,21 +17,10 @@ use Chill\PersonBundle\Repository\SocialWork\SocialActionRepository;
use Chill\PersonBundle\Templating\Entity\SocialActionRender; use Chill\PersonBundle\Templating\Entity\SocialActionRender;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
class BySocialActionAggregator implements AggregatorInterface class BySocialActionAggregator implements AggregatorInterface
{ {
private SocialActionRender $actionRender; public function __construct(private readonly SocialActionRender $actionRender, private readonly SocialActionRepository $actionRepository) {}
private SocialActionRepository $actionRepository;
public function __construct(
SocialActionRender $actionRender,
SocialActionRepository $actionRepository
) {
$this->actionRender = $actionRender;
$this->actionRepository = $actionRepository;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -40,7 +29,7 @@ class BySocialActionAggregator implements AggregatorInterface
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
if (!in_array('actsocialaction', $qb->getAllAliases(), true)) { if (!\in_array('actsocialaction', $qb->getAllAliases(), true)) {
$qb->leftJoin('activity.socialActions', 'actsocialaction'); $qb->leftJoin('activity.socialActions', 'actsocialaction');
} }
@ -57,6 +46,7 @@ class BySocialActionAggregator implements AggregatorInterface
{ {
// no form // no form
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];

View File

@ -17,21 +17,10 @@ use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
use Chill\PersonBundle\Templating\Entity\SocialIssueRender; use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
class BySocialIssueAggregator implements AggregatorInterface class BySocialIssueAggregator implements AggregatorInterface
{ {
private SocialIssueRender $issueRender; public function __construct(private readonly SocialIssueRepository $issueRepository, private readonly SocialIssueRender $issueRender) {}
private SocialIssueRepository $issueRepository;
public function __construct(
SocialIssueRepository $issueRepository,
SocialIssueRender $issueRender
) {
$this->issueRepository = $issueRepository;
$this->issueRender = $issueRender;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -40,7 +29,7 @@ class BySocialIssueAggregator implements AggregatorInterface
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
if (!in_array('actsocialissue', $qb->getAllAliases(), true)) { if (!\in_array('actsocialissue', $qb->getAllAliases(), true)) {
$qb->leftJoin('activity.socialIssues', 'actsocialissue'); $qb->leftJoin('activity.socialIssues', 'actsocialissue');
} }
@ -57,6 +46,7 @@ class BySocialIssueAggregator implements AggregatorInterface
{ {
// no form // no form
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];

View File

@ -12,14 +12,9 @@ declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator; namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Repository\LocationRepository;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Closure;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
final readonly class ActivityLocationAggregator implements AggregatorInterface final readonly class ActivityLocationAggregator implements AggregatorInterface
{ {
@ -32,7 +27,7 @@ final readonly class ActivityLocationAggregator implements AggregatorInterface
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
if (!in_array('actloc', $qb->getAllAliases(), true)) { if (!\in_array('actloc', $qb->getAllAliases(), true)) {
$qb->leftJoin('activity.location', 'actloc'); $qb->leftJoin('activity.location', 'actloc');
} }
$qb->addSelect(sprintf('actloc.name AS %s', self::KEY)); $qb->addSelect(sprintf('actloc.name AS %s', self::KEY));
@ -48,12 +43,13 @@ final readonly class ActivityLocationAggregator implements AggregatorInterface
{ {
// no form required for this aggregator // no form required for this aggregator
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
} }
public function getLabels($key, array $values, $data): Closure public function getLabels($key, array $values, $data): \Closure
{ {
return function ($value): string { return function ($value): string {
if ('_header' === $value) { if ('_header' === $value) {

View File

@ -15,26 +15,14 @@ use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface; use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Closure;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
class ActivityTypeAggregator implements AggregatorInterface class ActivityTypeAggregator implements AggregatorInterface
{ {
public const KEY = 'activity_type_aggregator'; final public const KEY = 'activity_type_aggregator';
protected ActivityTypeRepositoryInterface $activityTypeRepository; public function __construct(protected ActivityTypeRepositoryInterface $activityTypeRepository, protected TranslatableStringHelperInterface $translatableStringHelper) {}
protected TranslatableStringHelperInterface $translatableStringHelper;
public function __construct(
ActivityTypeRepositoryInterface $activityTypeRepository,
TranslatableStringHelperInterface $translatableStringHelper
) {
$this->activityTypeRepository = $activityTypeRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -43,7 +31,7 @@ class ActivityTypeAggregator implements AggregatorInterface
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
if (!in_array('acttype', $qb->getAllAliases(), true)) { if (!\in_array('acttype', $qb->getAllAliases(), true)) {
$qb->leftJoin('activity.activityType', 'acttype'); $qb->leftJoin('activity.activityType', 'acttype');
} }
@ -60,12 +48,13 @@ class ActivityTypeAggregator implements AggregatorInterface
{ {
// no form required for this aggregator // no form required for this aggregator
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
} }
public function getLabels($key, array $values, $data): Closure public function getLabels($key, array $values, $data): \Closure
{ {
// for performance reason, we load data from db only once // for performance reason, we load data from db only once
$this->activityTypeRepository->findBy(['id' => $values]); $this->activityTypeRepository->findBy(['id' => $values]);

View File

@ -15,25 +15,14 @@ use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Repository\UserRepository; use Chill\MainBundle\Repository\UserRepository;
use Chill\MainBundle\Templating\Entity\UserRender; use Chill\MainBundle\Templating\Entity\UserRender;
use Closure;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
class ActivityUserAggregator implements AggregatorInterface class ActivityUserAggregator implements AggregatorInterface
{ {
public const KEY = 'activity_user_id'; final public const KEY = 'activity_user_id';
private UserRender $userRender; public function __construct(private readonly UserRepository $userRepository, private readonly UserRender $userRender) {}
private UserRepository $userRepository;
public function __construct(
UserRepository $userRepository,
UserRender $userRender
) {
$this->userRepository = $userRepository;
$this->userRender = $userRender;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -58,12 +47,13 @@ class ActivityUserAggregator implements AggregatorInterface
{ {
// nothing to add // nothing to add
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
} }
public function getLabels($key, $values, $data): Closure public function getLabels($key, $values, $data): \Closure
{ {
return function ($value) { return function ($value) {
if ('_header' === $value) { if ('_header' === $value) {

View File

@ -17,19 +17,10 @@ use Chill\MainBundle\Repository\UserRepositoryInterface;
use Chill\MainBundle\Templating\Entity\UserRender; use Chill\MainBundle\Templating\Entity\UserRender;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
class ActivityUsersAggregator implements AggregatorInterface class ActivityUsersAggregator implements AggregatorInterface
{ {
private UserRender $userRender; public function __construct(private readonly UserRepositoryInterface $userRepository, private readonly UserRender $userRender) {}
private UserRepositoryInterface $userRepository;
public function __construct(UserRepositoryInterface $userRepository, UserRender $userRender)
{
$this->userRepository = $userRepository;
$this->userRender = $userRender;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -38,7 +29,7 @@ class ActivityUsersAggregator implements AggregatorInterface
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
if (!in_array('actusers', $qb->getAllAliases(), true)) { if (!\in_array('actusers', $qb->getAllAliases(), true)) {
$qb->leftJoin('activity.users', 'actusers'); $qb->leftJoin('activity.users', 'actusers');
} }
@ -56,6 +47,7 @@ class ActivityUsersAggregator implements AggregatorInterface
{ {
// nothing to add on the form // nothing to add on the form
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];

View File

@ -12,23 +12,22 @@ declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator; namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Entity\User\UserJobHistory;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Repository\UserJobRepositoryInterface; use Chill\MainBundle\Repository\UserJobRepositoryInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorInterface class ActivityUsersJobAggregator implements AggregatorInterface
{ {
private TranslatableStringHelperInterface $translatableStringHelper; private const PREFIX = 'act_agg_user_job';
private UserJobRepositoryInterface $userJobRepository; public function __construct(
private readonly UserJobRepositoryInterface $userJobRepository,
public function __construct(UserJobRepositoryInterface $userJobRepository, TranslatableStringHelperInterface $translatableStringHelper) private readonly TranslatableStringHelperInterface $translatableStringHelper
{ ) {}
$this->userJobRepository = $userJobRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -37,24 +36,37 @@ class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorI
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
if (!in_array('actusers', $qb->getAllAliases(), true)) { $p = self::PREFIX;
$qb->leftJoin('activity.users', 'actusers');
}
$qb $qb
->addSelect('IDENTITY(actusers.userJob) AS activity_users_job_aggregator') ->leftJoin('activity.users', "{$p}_user")
->addGroupBy('activity_users_job_aggregator'); ->leftJoin(
UserJobHistory::class,
"{$p}_history",
Expr\Join::WITH,
$qb->expr()->eq("{$p}_history.user", "{$p}_user")
)
// job_at based on activity.date
->andWhere(
$qb->expr()->andX(
$qb->expr()->lte("{$p}_history.startDate", 'activity.date'),
$qb->expr()->orX(
$qb->expr()->isNull("{$p}_history.endDate"),
$qb->expr()->gt("{$p}_history.endDate", 'activity.date')
)
)
)
->addSelect("IDENTITY({$p}_history.job) AS {$p}_select")
->addGroupBy("{$p}_select");
} }
public function applyOn() public function applyOn(): string
{ {
return Declarations::ACTIVITY; return Declarations::ACTIVITY;
} }
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder) {}
{
// nothing to add in the form
}
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
@ -81,11 +93,11 @@ class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorI
public function getQueryKeys($data): array public function getQueryKeys($data): array
{ {
return ['activity_users_job_aggregator']; return [self::PREFIX.'_select'];
} }
public function getTitle() public function getTitle(): string
{ {
return 'Aggregate by users job'; return 'export.aggregator.activity.by_user_job.Aggregate by users job';
} }
} }

View File

@ -12,23 +12,22 @@ declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator; namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Entity\User\UserScopeHistory;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Repository\ScopeRepositoryInterface; use Chill\MainBundle\Repository\ScopeRepositoryInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\AggregatorInterface class ActivityUsersScopeAggregator implements AggregatorInterface
{ {
private ScopeRepositoryInterface $scopeRepository; private const PREFIX = 'act_agg_user_scope';
private TranslatableStringHelperInterface $translatableStringHelper; public function __construct(
private readonly ScopeRepositoryInterface $scopeRepository,
public function __construct(ScopeRepositoryInterface $scopeRepository, TranslatableStringHelperInterface $translatableStringHelper) private readonly TranslatableStringHelperInterface $translatableStringHelper
{ ) {}
$this->scopeRepository = $scopeRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -37,24 +36,37 @@ class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\Aggregato
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
if (!in_array('actusers', $qb->getAllAliases(), true)) { $p = self::PREFIX;
$qb->leftJoin('activity.users', 'actusers');
}
$qb $qb
->addSelect('IDENTITY(actusers.mainScope) AS activity_users_main_scope_aggregator') ->leftJoin('activity.users', "{$p}_user")
->addGroupBy('activity_users_main_scope_aggregator'); ->leftJoin(
UserScopeHistory::class,
"{$p}_history",
Expr\Join::WITH,
$qb->expr()->eq("{$p}_history.user", "{$p}_user")
)
// scope_at based on activity.date
->andWhere(
$qb->expr()->andX(
$qb->expr()->lte("{$p}_history.startDate", 'activity.date'),
$qb->expr()->orX(
$qb->expr()->isNull("{$p}_history.endDate"),
$qb->expr()->gt("{$p}_history.endDate", 'activity.date')
)
)
)
->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select")
->addGroupBy("{$p}_select");
} }
public function applyOn() public function applyOn(): string
{ {
return Declarations::ACTIVITY; return Declarations::ACTIVITY;
} }
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder) {}
{
// nothing to add in the form
}
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
@ -81,11 +93,11 @@ class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\Aggregato
public function getQueryKeys($data): array public function getQueryKeys($data): array
{ {
return ['activity_users_main_scope_aggregator']; return [self::PREFIX.'_select'];
} }
public function getTitle() public function getTitle(): string
{ {
return 'Aggregate by users scope'; return 'export.aggregator.activity.by_user_scope.Aggregate by users scope';
} }
} }

View File

@ -20,17 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface;
class ByCreatorAggregator implements AggregatorInterface class ByCreatorAggregator implements AggregatorInterface
{ {
private UserRender $userRender; public function __construct(private readonly UserRepositoryInterface $userRepository, private readonly UserRender $userRender) {}
private UserRepositoryInterface $userRepository;
public function __construct(
UserRepositoryInterface $userRepository,
UserRender $userRender
) {
$this->userRepository = $userRepository;
$this->userRender = $userRender;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -52,6 +42,7 @@ class ByCreatorAggregator implements AggregatorInterface
{ {
// no form // no form
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];

View File

@ -17,21 +17,10 @@ use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
use Chill\ThirdPartyBundle\Templating\Entity\ThirdPartyRender; use Chill\ThirdPartyBundle\Templating\Entity\ThirdPartyRender;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
class ByThirdpartyAggregator implements AggregatorInterface class ByThirdpartyAggregator implements AggregatorInterface
{ {
private ThirdPartyRender $thirdPartyRender; public function __construct(private readonly ThirdPartyRepository $thirdPartyRepository, private readonly ThirdPartyRender $thirdPartyRender) {}
private ThirdPartyRepository $thirdPartyRepository;
public function __construct(
ThirdPartyRepository $thirdPartyRepository,
ThirdPartyRender $thirdPartyRender
) {
$this->thirdPartyRepository = $thirdPartyRepository;
$this->thirdPartyRender = $thirdPartyRender;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -40,7 +29,7 @@ class ByThirdpartyAggregator implements AggregatorInterface
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
if (!in_array('acttparty', $qb->getAllAliases(), true)) { if (!\in_array('acttparty', $qb->getAllAliases(), true)) {
$qb->leftJoin('activity.thirdParties', 'acttparty'); $qb->leftJoin('activity.thirdParties', 'acttparty');
} }
@ -57,6 +46,7 @@ class ByThirdpartyAggregator implements AggregatorInterface
{ {
// no form // no form
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];

View File

@ -12,26 +12,22 @@ declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator; namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Entity\User\UserScopeHistory;
use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Repository\ScopeRepository; use Chill\MainBundle\Repository\ScopeRepository;
use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
class CreatorScopeAggregator implements AggregatorInterface class CreatorScopeAggregator implements AggregatorInterface
{ {
private ScopeRepository $scopeRepository; private const PREFIX = 'acp_agg_creator_scope';
private TranslatableStringHelper $translatableStringHelper;
public function __construct( public function __construct(
ScopeRepository $scopeRepository, private readonly ScopeRepository $scopeRepository,
TranslatableStringHelper $translatableStringHelper private readonly TranslatableStringHelper $translatableStringHelper
) { ) {}
$this->scopeRepository = $scopeRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -40,12 +36,28 @@ class CreatorScopeAggregator implements AggregatorInterface
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
if (!in_array('actcreator', $qb->getAllAliases(), true)) { $p = self::PREFIX;
$qb->leftJoin('activity.createdBy', 'actcreator');
}
$qb->addSelect('IDENTITY(actcreator.mainScope) AS creatorscope_aggregator'); $qb
$qb->addGroupBy('creatorscope_aggregator'); ->leftJoin('activity.createdBy', "{$p}_user")
->leftJoin(
UserScopeHistory::class,
"{$p}_history",
Join::WITH,
$qb->expr()->eq("{$p}_history.user", "{$p}_user")
)
// scope_at based on activity.date
->andWhere(
$qb->expr()->andX(
$qb->expr()->lte("{$p}_history.startDate", 'activity.date'),
$qb->expr()->orX(
$qb->expr()->isNull("{$p}_history.endDate"),
$qb->expr()->gt("{$p}_history.endDate", 'activity.date')
)
)
)
->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select")
->addGroupBy("{$p}_select");
} }
public function applyOn(): string public function applyOn(): string
@ -53,10 +65,8 @@ class CreatorScopeAggregator implements AggregatorInterface
return Declarations::ACTIVITY; return Declarations::ACTIVITY;
} }
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder) {}
{
// no form
}
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
@ -83,11 +93,11 @@ class CreatorScopeAggregator implements AggregatorInterface
public function getQueryKeys($data): array public function getQueryKeys($data): array
{ {
return ['creatorscope_aggregator']; return [self::PREFIX.'_select'];
} }
public function getTitle(): string public function getTitle(): string
{ {
return 'Group activity by creator scope'; return 'export.aggregator.activity.by_creator_scope.Group activity by creator scope';
} }
} }

View File

@ -14,10 +14,8 @@ namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Export\AggregatorInterface;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use RuntimeException;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class DateAggregator implements AggregatorInterface class DateAggregator implements AggregatorInterface
{ {
@ -56,7 +54,7 @@ class DateAggregator implements AggregatorInterface
break; // order DESC does not works ! break; // order DESC does not works !
default: default:
throw new RuntimeException(sprintf("The frequency data '%s' is invalid.", $data['frequency'])); throw new \RuntimeException(sprintf("The frequency data '%s' is invalid.", $data['frequency']));
} }
$qb->addSelect(sprintf("TO_CHAR(activity.date, '%s') AS date_aggregator", $fmt)); $qb->addSelect(sprintf("TO_CHAR(activity.date, '%s') AS date_aggregator", $fmt));
@ -78,6 +76,7 @@ class DateAggregator implements AggregatorInterface
'empty_data' => self::DEFAULT_CHOICE, 'empty_data' => self::DEFAULT_CHOICE,
]); ]);
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return ['frequency' => self::DEFAULT_CHOICE]; return ['frequency' => self::DEFAULT_CHOICE];
@ -87,24 +86,16 @@ class DateAggregator implements AggregatorInterface
{ {
return static function ($value) use ($data): string { return static function ($value) use ($data): string {
if ('_header' === $value) { if ('_header' === $value) {
return 'by ' . $data['frequency']; return 'by '.$data['frequency'];
} }
if (null === $value) { if (null === $value) {
return ''; return '';
} }
switch ($data['frequency']) { return match ($data['frequency']) {
case 'month': default => $value,
case 'week': };
//return $this->translator->trans('for week') .' '. $value ;
case 'year':
//return $this->translator->trans('in year') .' '. $value ;
default:
return $value;
}
}; };
} }

View File

@ -0,0 +1,103 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Entity\User\UserJobHistory;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Repository\ScopeRepository;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
class JobScopeAggregator implements AggregatorInterface
{
private const PREFIX = 'acp_agg_creator_job';
public function __construct(
private readonly ScopeRepository $scopeRepository,
private readonly TranslatableStringHelper $translatableStringHelper
) {}
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$p = self::PREFIX;
$qb
->leftJoin('activity.createdBy', "{$p}_user")
->leftJoin(
UserJobHistory::class,
"{$p}_history",
Join::WITH,
$qb->expr()->eq("{$p}_history.user", "{$p}_user")
)
// job_at based on activity.date
->andWhere(
$qb->expr()->andX(
$qb->expr()->lte("{$p}_history.startDate", 'activity.date'),
$qb->expr()->orX(
$qb->expr()->isNull("{$p}_history.endDate"),
$qb->expr()->gt("{$p}_history.endDate", 'activity.date')
)
)
)
->addSelect("IDENTITY({$p}_history.job) AS {$p}_select")
->addGroupBy("{$p}_select");
}
public function applyOn(): string
{
return Declarations::ACTIVITY;
}
public function buildForm(FormBuilderInterface $builder) {}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{
return function ($value): string {
if ('_header' === $value) {
return 'Scope';
}
if (null === $value || '' === $value) {
return '';
}
$s = $this->scopeRepository->find($value);
return $this->translatableStringHelper->localize(
$s->getName()
);
};
}
public function getQueryKeys($data): array
{
return [self::PREFIX.'_select'];
}
public function getTitle(): string
{
return 'export.aggregator.activity.by_creator_job.Group activity by creator job';
}
}

View File

@ -17,21 +17,10 @@ use Chill\MainBundle\Repository\LocationTypeRepository;
use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
class LocationTypeAggregator implements AggregatorInterface class LocationTypeAggregator implements AggregatorInterface
{ {
private LocationTypeRepository $locationTypeRepository; public function __construct(private readonly LocationTypeRepository $locationTypeRepository, private readonly TranslatableStringHelper $translatableStringHelper) {}
private TranslatableStringHelper $translatableStringHelper;
public function __construct(
LocationTypeRepository $locationTypeRepository,
TranslatableStringHelper $translatableStringHelper
) {
$this->locationTypeRepository = $locationTypeRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -40,7 +29,7 @@ class LocationTypeAggregator implements AggregatorInterface
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
if (!in_array('actloc', $qb->getAllAliases(), true)) { if (!\in_array('actloc', $qb->getAllAliases(), true)) {
$qb->leftJoin('activity.location', 'actloc'); $qb->leftJoin('activity.location', 'actloc');
} }
@ -57,6 +46,7 @@ class LocationTypeAggregator implements AggregatorInterface
{ {
// no form // no form
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];

View File

@ -17,34 +17,15 @@ use Chill\ActivityBundle\Repository\ActivityReasonRepository;
use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Export\ExportElementValidatedInterface; use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use RuntimeException;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface;
use function count;
use function in_array;
class ActivityReasonAggregator implements AggregatorInterface, ExportElementValidatedInterface class ActivityReasonAggregator implements AggregatorInterface, ExportElementValidatedInterface
{ {
protected ActivityReasonCategoryRepository $activityReasonCategoryRepository; public function __construct(protected ActivityReasonCategoryRepository $activityReasonCategoryRepository, protected ActivityReasonRepository $activityReasonRepository, protected TranslatableStringHelper $translatableStringHelper) {}
protected ActivityReasonRepository $activityReasonRepository;
protected TranslatableStringHelperInterface $translatableStringHelper;
public function __construct(
ActivityReasonCategoryRepository $activityReasonCategoryRepository,
ActivityReasonRepository $activityReasonRepository,
TranslatableStringHelper $translatableStringHelper
) {
$this->activityReasonCategoryRepository = $activityReasonCategoryRepository;
$this->activityReasonRepository = $activityReasonRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -61,20 +42,20 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
$elem = 'actreasoncat.id'; $elem = 'actreasoncat.id';
$alias = 'activity_categories_id'; $alias = 'activity_categories_id';
} else { } else {
throw new RuntimeException('The data provided are not recognized.'); throw new \RuntimeException('The data provided are not recognized.');
} }
$qb->addSelect($elem . ' as ' . $alias); $qb->addSelect($elem.' as '.$alias);
// make a jointure only if needed // make a jointure only if needed
if (!in_array('actreasons', $qb->getAllAliases(), true)) { if (!\in_array('actreasons', $qb->getAllAliases(), true)) {
$qb->innerJoin('activity.reasons', 'actreasons'); $qb->innerJoin('activity.reasons', 'actreasons');
} }
// join category if necessary // join category if necessary
if ('activity_categories_id' === $alias) { if ('activity_categories_id' === $alias) {
// add join only if needed // add join only if needed
if (!in_array('actreasoncat', $qb->getAllAliases(), true)) { if (!\in_array('actreasoncat', $qb->getAllAliases(), true)) {
$qb->join('actreasons.category', 'actreasoncat'); $qb->join('actreasons.category', 'actreasoncat');
} }
} }
@ -82,7 +63,7 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
// add the "group by" part // add the "group by" part
$groupBy = $qb->getDQLPart('groupBy'); $groupBy = $qb->getDQLPart('groupBy');
if (count($groupBy) > 0) { if (\count($groupBy) > 0) {
$qb->addGroupBy($alias); $qb->addGroupBy($alias);
} else { } else {
$qb->groupBy($alias); $qb->groupBy($alias);
@ -110,6 +91,7 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
] ]
); );
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
@ -117,21 +99,11 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
public function getLabels($key, array $values, $data) public function getLabels($key, array $values, $data)
{ {
// for performance reason, we load data from db only once match ($data['level']) {
switch ($data['level']) { 'reasons' => $this->activityReasonRepository->findBy(['id' => $values]),
case 'reasons': 'categories' => $this->activityReasonCategoryRepository->findBy(['id' => $values]),
$this->activityReasonRepository->findBy(['id' => $values]); default => throw new \RuntimeException(sprintf("The level data '%s' is invalid.", $data['level'])),
};
break;
case 'categories':
$this->activityReasonCategoryRepository->findBy(['id' => $values]);
break;
default:
throw new RuntimeException(sprintf("The level data '%s' is invalid.", $data['level']));
}
return function ($value) use ($data) { return function ($value) use ($data) {
if ('_header' === $value) { if ('_header' === $value) {
@ -171,7 +143,7 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
return ['activity_categories_id']; return ['activity_categories_id'];
} }
throw new RuntimeException('The data provided are not recognised.'); throw new \RuntimeException('The data provided are not recognised.');
} }
public function getTitle() public function getTitle()

View File

@ -14,18 +14,12 @@ namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Export\AggregatorInterface;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
class SentReceivedAggregator implements AggregatorInterface class SentReceivedAggregator implements AggregatorInterface
{ {
private TranslatorInterface $translator; public function __construct(private readonly TranslatorInterface $translator) {}
public function __construct(TranslatorInterface $translator)
{
$this->translator = $translator;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -47,6 +41,7 @@ class SentReceivedAggregator implements AggregatorInterface
{ {
// No form needed // No form needed
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
@ -71,7 +66,7 @@ class SentReceivedAggregator implements AggregatorInterface
return $this->translator->trans('export.aggregator.activity.by_sent_received.is received'); return $this->translator->trans('export.aggregator.activity.by_sent_received.is received');
default: default:
throw new LogicException(sprintf('The value %s is not valid', $value)); throw new \LogicException(sprintf('The value %s is not valid', $value));
} }
}; };
} }

View File

@ -16,9 +16,9 @@ namespace Chill\ActivityBundle\Export;
*/ */
abstract class Declarations abstract class Declarations
{ {
public const ACTIVITY = 'activity'; final public const ACTIVITY = 'activity';
public const ACTIVITY_ACP = 'activity_linked_to_acp'; final public const ACTIVITY_ACP = 'activity_linked_to_acp';
public const ACTIVITY_PERSON = 'activity_linked_to_person'; final public const ACTIVITY_PERSON = 'activity_linked_to_person';
} }

View File

@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter; use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface; use Chill\MainBundle\Export\GroupedExportInterface;
@ -23,7 +24,6 @@ use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository; use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query; use Doctrine\ORM\Query;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
class AvgActivityDuration implements ExportInterface, GroupedExportInterface class AvgActivityDuration implements ExportInterface, GroupedExportInterface
@ -31,12 +31,13 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface
protected EntityRepository $repository; protected EntityRepository $repository;
public function __construct( public function __construct(
EntityManagerInterface $em EntityManagerInterface $em,
) { ) {
$this->repository = $em->getRepository(Activity::class); $this->repository = $em->getRepository(Activity::class);
} }
public function buildForm(FormBuilderInterface $builder) {} public function buildForm(FormBuilderInterface $builder) {}
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
@ -60,7 +61,7 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface
public function getLabels($key, array $values, $data) public function getLabels($key, array $values, $data)
{ {
if ('export_avg_activity_duration' !== $key) { if ('export_avg_activity_duration' !== $key) {
throw new LogicException("the key {$key} is not used by this export"); throw new \LogicException("the key {$key} is not used by this export");
} }
return static fn ($value) => '_header' === $value ? 'Average activities linked to an accompanying period duration' : $value; return static fn ($value) => '_header' === $value ? 'Average activities linked to an accompanying period duration' : $value;
@ -100,14 +101,16 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface
$qb $qb
->andWhere( ->andWhere(
$qb->expr()->exists( $qb->expr()->exists(
'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part '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) 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) WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
' '
) )
) )
->setParameter('authorized_centers', $centers); ->setParameter('authorized_centers', $centers);
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
return $qb; return $qb;
} }

View File

@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter; use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface; use Chill\MainBundle\Export\GroupedExportInterface;
@ -23,7 +24,6 @@ use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository; use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query; use Doctrine\ORM\Query;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterface class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterface
@ -31,7 +31,7 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac
protected EntityRepository $repository; protected EntityRepository $repository;
public function __construct( public function __construct(
EntityManagerInterface $em EntityManagerInterface $em,
) { ) {
$this->repository = $em->getRepository(Activity::class); $this->repository = $em->getRepository(Activity::class);
} }
@ -40,6 +40,7 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac
{ {
// TODO: Implement buildForm() method. // TODO: Implement buildForm() method.
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
@ -63,7 +64,7 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac
public function getLabels($key, array $values, $data) public function getLabels($key, array $values, $data)
{ {
if ('export_avg_activity_visit_duration' !== $key) { if ('export_avg_activity_visit_duration' !== $key) {
throw new LogicException("the key {$key} is not used by this export"); throw new \LogicException("the key {$key} is not used by this export");
} }
return static fn ($value) => '_header' === $value ? 'Average activities linked to an accompanying period visit duration' : $value; return static fn ($value) => '_header' === $value ? 'Average activities linked to an accompanying period visit duration' : $value;
@ -103,14 +104,16 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac
$qb $qb
->andWhere( ->andWhere(
$qb->expr()->exists( $qb->expr()->exists(
'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part '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) 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) WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
' '
) )
) )
->setParameter('authorized_centers', $centers); ->setParameter('authorized_centers', $centers);
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
return $qb; return $qb;
} }

View File

@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter; use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface; use Chill\MainBundle\Export\GroupedExportInterface;
@ -23,7 +24,6 @@ use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository; use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query; use Doctrine\ORM\Query;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
class CountActivity implements ExportInterface, GroupedExportInterface class CountActivity implements ExportInterface, GroupedExportInterface
@ -31,12 +31,13 @@ class CountActivity implements ExportInterface, GroupedExportInterface
protected EntityRepository $repository; protected EntityRepository $repository;
public function __construct( public function __construct(
EntityManagerInterface $em EntityManagerInterface $em,
) { ) {
$this->repository = $em->getRepository(Activity::class); $this->repository = $em->getRepository(Activity::class);
} }
public function buildForm(FormBuilderInterface $builder) {} public function buildForm(FormBuilderInterface $builder) {}
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
@ -60,7 +61,7 @@ class CountActivity implements ExportInterface, GroupedExportInterface
public function getLabels($key, array $values, $data) public function getLabels($key, array $values, $data)
{ {
if ('export_count_activity' !== $key) { if ('export_count_activity' !== $key) {
throw new LogicException("the key {$key} is not used by this export"); throw new \LogicException("the key {$key} is not used by this export");
} }
return static fn ($value) => '_header' === $value ? 'Number of activities linked to an accompanying period' : $value; return static fn ($value) => '_header' === $value ? 'Number of activities linked to an accompanying period' : $value;
@ -97,14 +98,16 @@ class CountActivity implements ExportInterface, GroupedExportInterface
$qb $qb
->andWhere( ->andWhere(
$qb->expr()->exists( $qb->expr()->exists(
'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part '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) 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) WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
' '
) )
) )
->setParameter('authorized_centers', $centers); ->setParameter('authorized_centers', $centers);
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
$qb->select('COUNT(DISTINCT activity.id) as export_count_activity'); $qb->select('COUNT(DISTINCT activity.id) as export_count_activity');
return $qb; return $qb;

View File

@ -16,6 +16,7 @@ use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Export\Export\ListActivityHelper; use Chill\ActivityBundle\Export\Export\ListActivityHelper;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter; use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
use Chill\MainBundle\Export\GroupedExportInterface; use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\MainBundle\Export\Helper\TranslatableStringExportLabelHelper; use Chill\MainBundle\Export\Helper\TranslatableStringExportLabelHelper;
use Chill\MainBundle\Export\ListInterface; use Chill\MainBundle\Export\ListInterface;
@ -25,26 +26,13 @@ use Symfony\Component\Form\FormBuilderInterface;
class ListActivity implements ListInterface, GroupedExportInterface class ListActivity implements ListInterface, GroupedExportInterface
{ {
private EntityManagerInterface $entityManager; public function __construct(private readonly ListActivityHelper $helper, private readonly EntityManagerInterface $entityManager, private readonly TranslatableStringExportLabelHelper $translatableStringExportLabelHelper) {}
private ListActivityHelper $helper;
private TranslatableStringExportLabelHelper $translatableStringExportLabelHelper;
public function __construct(
ListActivityHelper $helper,
EntityManagerInterface $entityManager,
TranslatableStringExportLabelHelper $translatableStringExportLabelHelper
) {
$this->helper = $helper;
$this->entityManager = $entityManager;
$this->translatableStringExportLabelHelper = $translatableStringExportLabelHelper;
}
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)
{ {
$this->helper->buildForm($builder); $this->helper->buildForm($builder);
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
@ -57,7 +45,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
public function getDescription() public function getDescription()
{ {
return ListActivityHelper::MSG_KEY . 'List activities linked to an accompanying course'; return ListActivityHelper::MSG_KEY.'List activities linked to an accompanying course';
} }
public function getGroup(): string public function getGroup(): string
@ -67,22 +55,17 @@ class ListActivity implements ListInterface, GroupedExportInterface
public function getLabels($key, array $values, $data) public function getLabels($key, array $values, $data)
{ {
switch ($key) { return match ($key) {
case 'acpId': 'acpId' => static function ($value) {
return static function ($value) { if ('_header' === $value) {
if ('_header' === $value) { return ListActivityHelper::MSG_KEY.'accompanying course id';
return ListActivityHelper::MSG_KEY . 'accompanying course id'; }
}
return $value ?? ''; return $value ?? '';
}; },
'scopesNames' => $this->translatableStringExportLabelHelper->getLabelMulti($key, $values, ListActivityHelper::MSG_KEY.'course circles'),
case 'scopesNames': default => $this->helper->getLabels($key, $values, $data),
return $this->translatableStringExportLabelHelper->getLabelMulti($key, $values, ListActivityHelper::MSG_KEY . 'course circles'); };
default:
return $this->helper->getLabels($key, $values, $data);
}
} }
public function getQueryKeys($data) public function getQueryKeys($data)
@ -104,7 +87,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
public function getTitle() public function getTitle()
{ {
return ListActivityHelper::MSG_KEY . 'List activity linked to a course'; return ListActivityHelper::MSG_KEY.'List activity linked to a course';
} }
public function getType() public function getType()
@ -128,7 +111,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
->andWhere( ->andWhere(
$qb->expr()->exists( $qb->expr()->exists(
'SELECT 1 'SELECT 1
FROM ' . PersonCenterHistory::class . ' acl_count_person_history FROM '.PersonCenterHistory::class.' acl_count_person_history
WHERE acl_count_person_history.person = person WHERE acl_count_person_history.person = person
AND acl_count_person_history.center IN (:authorized_centers) AND acl_count_person_history.center IN (:authorized_centers)
' '
@ -145,9 +128,11 @@ class ListActivity implements ListInterface, GroupedExportInterface
// add select for this step // add select for this step
$qb $qb
->addSelect('acp.id AS acpId') ->addSelect('acp.id AS acpId')
->addSelect('(SELECT AGGREGATE(acpScope.name) FROM ' . Scope::class . ' acpScope WHERE acpScope MEMBER OF acp.scopes) AS scopesNames') ->addSelect('(SELECT AGGREGATE(acpScope.name) FROM '.Scope::class.' acpScope WHERE acpScope MEMBER OF acp.scopes) AS scopesNames')
->addGroupBy('scopesNames'); ->addGroupBy('scopesNames');
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
return $qb; return $qb;
} }

View File

@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter; use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface; use Chill\MainBundle\Export\GroupedExportInterface;
@ -23,7 +24,6 @@ use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository; use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query; use Doctrine\ORM\Query;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
class SumActivityDuration implements ExportInterface, GroupedExportInterface class SumActivityDuration implements ExportInterface, GroupedExportInterface
@ -31,7 +31,7 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface
protected EntityRepository $repository; protected EntityRepository $repository;
public function __construct( public function __construct(
EntityManagerInterface $em EntityManagerInterface $em,
) { ) {
$this->repository = $em->getRepository(Activity::class); $this->repository = $em->getRepository(Activity::class);
} }
@ -40,6 +40,7 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface
{ {
// TODO: Implement buildForm() method. // TODO: Implement buildForm() method.
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
@ -63,7 +64,7 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface
public function getLabels($key, array $values, $data) public function getLabels($key, array $values, $data)
{ {
if ('export_sum_activity_duration' !== $key) { if ('export_sum_activity_duration' !== $key) {
throw new LogicException("the key {$key} is not used by this export"); throw new \LogicException("the key {$key} is not used by this export");
} }
return static fn ($value) => '_header' === $value ? 'Sum activities linked to an accompanying period duration' : $value; return static fn ($value) => '_header' === $value ? 'Sum activities linked to an accompanying period duration' : $value;
@ -103,14 +104,16 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface
$qb $qb
->andWhere( ->andWhere(
$qb->expr()->exists( $qb->expr()->exists(
'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part '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) 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) WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
' '
) )
) )
->setParameter('authorized_centers', $centers); ->setParameter('authorized_centers', $centers);
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
return $qb; return $qb;
} }

View File

@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter; use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface; use Chill\MainBundle\Export\GroupedExportInterface;
@ -23,7 +24,6 @@ use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository; use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query; use Doctrine\ORM\Query;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
class SumActivityVisitDuration implements ExportInterface, GroupedExportInterface class SumActivityVisitDuration implements ExportInterface, GroupedExportInterface
@ -31,7 +31,7 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac
protected EntityRepository $repository; protected EntityRepository $repository;
public function __construct( public function __construct(
EntityManagerInterface $em EntityManagerInterface $em,
) { ) {
$this->repository = $em->getRepository(Activity::class); $this->repository = $em->getRepository(Activity::class);
} }
@ -40,6 +40,7 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac
{ {
// TODO: Implement buildForm() method. // TODO: Implement buildForm() method.
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
@ -63,7 +64,7 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac
public function getLabels($key, array $values, $data) public function getLabels($key, array $values, $data)
{ {
if ('export_sum_activity_visit_duration' !== $key) { if ('export_sum_activity_visit_duration' !== $key) {
throw new LogicException("the key {$key} is not used by this export"); throw new \LogicException("the key {$key} is not used by this export");
} }
return static fn ($value) => '_header' === $value ? 'Sum activities linked to an accompanying period visit duration' : $value; return static fn ($value) => '_header' === $value ? 'Sum activities linked to an accompanying period visit duration' : $value;
@ -103,14 +104,16 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac
$qb $qb
->andWhere( ->andWhere(
$qb->expr()->exists( $qb->expr()->exists(
'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part '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) 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) WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
' '
) )
) )
->setParameter('authorized_centers', $centers); ->setParameter('authorized_centers', $centers);
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
return $qb; return $qb;
} }

View File

@ -19,20 +19,14 @@ use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface; use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\PersonBundle\Export\Declarations as PersonDeclarations; use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
use Doctrine\ORM\Query; use Doctrine\ORM\Query;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
class CountActivity implements ExportInterface, GroupedExportInterface class CountActivity implements ExportInterface, GroupedExportInterface
{ {
protected ActivityRepository $activityRepository; public function __construct(protected ActivityRepository $activityRepository) {}
public function __construct(
ActivityRepository $activityRepository
) {
$this->activityRepository = $activityRepository;
}
public function buildForm(FormBuilderInterface $builder) {} public function buildForm(FormBuilderInterface $builder) {}
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
@ -56,7 +50,7 @@ class CountActivity implements ExportInterface, GroupedExportInterface
public function getLabels($key, array $values, $data) public function getLabels($key, array $values, $data)
{ {
if ('export_count_activity' !== $key) { if ('export_count_activity' !== $key) {
throw new LogicException("the key {$key} is not used by this export"); throw new \LogicException("the key {$key} is not used by this export");
} }
return static fn ($value) => '_header' === $value ? 'Number of activities linked to a person' : $value; return static fn ($value) => '_header' === $value ? 'Number of activities linked to a person' : $value;

View File

@ -20,7 +20,6 @@ use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\MainBundle\Export\ListInterface; use Chill\MainBundle\Export\ListInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Export\Declarations as PersonDeclarations; use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
use DateTime;
use Doctrine\DBAL\Exception\InvalidArgumentException; use Doctrine\DBAL\Exception\InvalidArgumentException;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query; use Doctrine\ORM\Query;
@ -30,14 +29,8 @@ use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
use function array_key_exists;
use function count;
use function in_array;
class ListActivity implements ListInterface, GroupedExportInterface class ListActivity implements ListInterface, GroupedExportInterface
{ {
protected EntityManagerInterface $entityManager;
protected array $fields = [ protected array $fields = [
'id', 'id',
'date', 'date',
@ -52,23 +45,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
'person_id', 'person_id',
]; ];
protected TranslatableStringHelperInterface $translatableStringHelper; public function __construct(protected EntityManagerInterface $entityManager, protected TranslatorInterface $translator, protected TranslatableStringHelperInterface $translatableStringHelper, private readonly ActivityRepository $activityRepository) {}
protected TranslatorInterface $translator;
private ActivityRepository $activityRepository;
public function __construct(
EntityManagerInterface $em,
TranslatorInterface $translator,
TranslatableStringHelperInterface $translatableStringHelper,
ActivityRepository $activityRepository
) {
$this->entityManager = $em;
$this->translator = $translator;
$this->translatableStringHelper = $translatableStringHelper;
$this->activityRepository = $activityRepository;
}
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)
{ {
@ -79,7 +56,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
'label' => 'Fields to include in export', 'label' => 'Fields to include in export',
'constraints' => [new Callback([ 'constraints' => [new Callback([
'callback' => static function ($selected, ExecutionContextInterface $context) { 'callback' => static function ($selected, ExecutionContextInterface $context) {
if (count($selected) === 0) { if (0 === \count($selected)) {
$context->buildViolation('You must select at least one element') $context->buildViolation('You must select at least one element')
->atPath('fields') ->atPath('fields')
->addViolation(); ->addViolation();
@ -88,6 +65,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
])], ])],
]); ]);
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
@ -117,7 +95,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
return 'date'; return 'date';
} }
$date = DateTime::createFromFormat('Y-m-d H:i:s', $value); $date = \DateTime::createFromFormat('Y-m-d H:i:s', $value);
return $date->format('d-m-Y'); return $date->format('d-m-Y');
}; };
@ -141,11 +119,11 @@ class ListActivity implements ListInterface, GroupedExportInterface
$activity = $activityRepository->find($value); $activity = $activityRepository->find($value);
return implode(', ', array_map(fn (ActivityReason $r) => '"' . return implode(', ', array_map(fn (ActivityReason $r) => '"'.
$this->translatableStringHelper->localize($r->getCategory()->getName()) $this->translatableStringHelper->localize($r->getCategory()->getName())
. ' > ' . .' > '.
$this->translatableStringHelper->localize($r->getName()) $this->translatableStringHelper->localize($r->getName())
. '"', $activity->getReasons()->toArray())); .'"', $activity->getReasons()->toArray()));
}; };
case 'circle_name': case 'circle_name':
@ -154,7 +132,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
return 'circle'; return 'circle';
} }
return $this->translatableStringHelper->localize(json_decode($value, true, 512, JSON_THROW_ON_ERROR)); return $this->translatableStringHelper->localize(json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR));
}; };
case 'type_name': case 'type_name':
@ -163,7 +141,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
return 'activity type'; return 'activity type';
} }
return $this->translatableStringHelper->localize(json_decode($value, true, 512, JSON_THROW_ON_ERROR)); return $this->translatableStringHelper->localize(json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR));
}; };
default: default:
@ -202,7 +180,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
$centers = array_map(static fn ($el) => $el['center'], $acl); $centers = array_map(static fn ($el) => $el['center'], $acl);
// throw an error if any fields are present // throw an error if any fields are present
if (!array_key_exists('fields', $data)) { if (!\array_key_exists('fields', $data)) {
throw new InvalidArgumentException('Any fields have been checked.'); throw new InvalidArgumentException('Any fields have been checked.');
} }
@ -226,7 +204,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
->setParameter('centers', $centers); ->setParameter('centers', $centers);
foreach ($this->fields as $f) { foreach ($this->fields as $f) {
if (in_array($f, $data['fields'], true)) { if (\in_array($f, $data['fields'], true)) {
switch ($f) { switch ($f) {
case 'id': case 'id':
$qb->addSelect('activity.id AS id'); $qb->addSelect('activity.id AS id');

View File

@ -20,7 +20,6 @@ use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface; use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\PersonBundle\Export\Declarations as PersonDeclarations; use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
use Doctrine\ORM\Query; use Doctrine\ORM\Query;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
/** /**
@ -30,27 +29,21 @@ use Symfony\Component\Form\FormBuilderInterface;
*/ */
class StatActivityDuration implements ExportInterface, GroupedExportInterface class StatActivityDuration implements ExportInterface, GroupedExportInterface
{ {
public const SUM = 'sum'; final public const SUM = 'sum';
/**
* The action for this report.
*/
protected string $action;
private ActivityRepository $activityRepository;
/** /**
* @param string $action the stat to perform * @param string $action the stat to perform
*/ */
public function __construct( public function __construct(
ActivityRepository $activityRepository, private readonly ActivityRepository $activityRepository,
string $action = 'sum' /**
) { * The action for this report.
$this->action = $action; */
$this->activityRepository = $activityRepository; protected string $action = 'sum'
} ) {}
public function buildForm(FormBuilderInterface $builder) {} public function buildForm(FormBuilderInterface $builder) {}
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
@ -67,7 +60,7 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
return 'Sum activities linked to a person duration by various parameters.'; return 'Sum activities linked to a person duration by various parameters.';
} }
throw new LogicException('this action is not supported: ' . $this->action); throw new \LogicException('this action is not supported: '.$this->action);
} }
public function getGroup(): string public function getGroup(): string
@ -78,7 +71,7 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
public function getLabels($key, array $values, $data) public function getLabels($key, array $values, $data)
{ {
if ('export_stat_activity' !== $key) { if ('export_stat_activity' !== $key) {
throw new LogicException(sprintf('The key %s is not used by this export', $key)); throw new \LogicException(sprintf('The key %s is not used by this export', $key));
} }
$header = self::SUM === $this->action ? 'Sum activities linked to a person duration' : false; $header = self::SUM === $this->action ? 'Sum activities linked to a person duration' : false;
@ -102,7 +95,7 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
return 'Sum activity linked to a person duration'; return 'Sum activity linked to a person duration';
} }
throw new LogicException('This action is not supported: ' . $this->action); throw new \LogicException('This action is not supported: '.$this->action);
} }
public function getType(): string public function getType(): string

View File

@ -23,54 +23,24 @@ use Chill\PersonBundle\Export\Helper\LabelPersonHelper;
use Chill\ThirdPartyBundle\Export\Helper\LabelThirdPartyHelper; use Chill\ThirdPartyBundle\Export\Helper\LabelThirdPartyHelper;
use Doctrine\ORM\AbstractQuery; use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
use const SORT_NUMERIC;
class ListActivityHelper class ListActivityHelper
{ {
public const MSG_KEY = 'export.list.activity.'; final public const MSG_KEY = 'export.list.activity.';
private ActivityPresenceRepositoryInterface $activityPresenceRepository;
private ActivityTypeRepositoryInterface $activityTypeRepository;
private DateTimeHelper $dateTimeHelper;
private LabelPersonHelper $labelPersonHelper;
private LabelThirdPartyHelper $labelThirdPartyHelper;
private TranslatableStringHelperInterface $translatableStringHelper;
private TranslatableStringExportLabelHelper $translatableStringLabelHelper;
private TranslatorInterface $translator;
private UserHelper $userHelper;
public function __construct( public function __construct(
ActivityPresenceRepositoryInterface $activityPresenceRepository, private readonly ActivityPresenceRepositoryInterface $activityPresenceRepository,
ActivityTypeRepositoryInterface $activityTypeRepository, private readonly ActivityTypeRepositoryInterface $activityTypeRepository,
DateTimeHelper $dateTimeHelper, private readonly DateTimeHelper $dateTimeHelper,
LabelPersonHelper $labelPersonHelper, private readonly LabelPersonHelper $labelPersonHelper,
LabelThirdPartyHelper $labelThirdPartyHelper, private readonly LabelThirdPartyHelper $labelThirdPartyHelper,
TranslatorInterface $translator, private readonly TranslatorInterface $translator,
TranslatableStringHelperInterface $translatableStringHelper, private readonly TranslatableStringHelperInterface $translatableStringHelper,
TranslatableStringExportLabelHelper $translatableStringLabelHelper, private readonly TranslatableStringExportLabelHelper $translatableStringLabelHelper,
UserHelper $userHelper private readonly UserHelper $userHelper
) { ) {}
$this->activityPresenceRepository = $activityPresenceRepository;
$this->activityTypeRepository = $activityTypeRepository;
$this->dateTimeHelper = $dateTimeHelper;
$this->labelPersonHelper = $labelPersonHelper;
$this->labelThirdPartyHelper = $labelThirdPartyHelper;
$this->translator = $translator;
$this->translatableStringHelper = $translatableStringHelper;
$this->translatableStringLabelHelper = $translatableStringLabelHelper;
$this->userHelper = $userHelper;
}
public function addSelect(QueryBuilder $qb): void public function addSelect(QueryBuilder $qb): void
{ {
@ -85,7 +55,7 @@ class ListActivityHelper
->addSelect('AGGREGATE(actPerson.id) AS personsNames') ->addSelect('AGGREGATE(actPerson.id) AS personsNames')
->leftJoin('activity.users', 'users_u') ->leftJoin('activity.users', 'users_u')
->addSelect('AGGREGATE(users_u.id) AS usersIds') ->addSelect('AGGREGATE(users_u.id) AS usersIds')
->addSelect('AGGREGATE(users_u.id) AS usersNames') ->addSelect('AGGREGATE(JSON_BUILD_OBJECT(\'uid\', users_u.id, \'d\', activity.date)) AS usersNames')
->leftJoin('activity.thirdParties', 'thirdparty') ->leftJoin('activity.thirdParties', 'thirdparty')
->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesIds') ->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesIds')
->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesNames') ->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesNames')
@ -96,9 +66,9 @@ class ListActivityHelper
->leftJoin('activity.location', 'location') ->leftJoin('activity.location', 'location')
->addSelect('location.name AS locationName') ->addSelect('location.name AS locationName')
->addSelect('activity.sentReceived') ->addSelect('activity.sentReceived')
->addSelect('IDENTITY(activity.createdBy) AS createdBy') ->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(activity.createdBy), \'d\', activity.createdAt) AS createdBy')
->addSelect('activity.createdAt') ->addSelect('activity.createdAt')
->addSelect('IDENTITY(activity.updatedBy) AS updatedBy') ->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(activity.updatedBy), \'d\', activity.updatedAt) AS updatedBy')
->addSelect('activity.updatedAt') ->addSelect('activity.updatedAt')
->addGroupBy('activity.id') ->addGroupBy('activity.id')
->addGroupBy('location.id'); ->addGroupBy('location.id');
@ -113,113 +83,78 @@ class ListActivityHelper
public function getLabels($key, array $values, $data) public function getLabels($key, array $values, $data)
{ {
switch ($key) { return match ($key) {
case 'createdAt': 'createdAt', 'updatedAt' => $this->dateTimeHelper->getLabel($key),
case 'updatedAt': 'createdBy', 'updatedBy' => $this->userHelper->getLabel($key, $values, $key),
return $this->dateTimeHelper->getLabel($key); 'date' => $this->dateTimeHelper->getLabel(self::MSG_KEY.$key),
'attendeeName' => function ($value) {
if ('_header' === $value) {
return 'Attendee';
}
case 'createdBy': if (null === $value || null === $presence = $this->activityPresenceRepository->find($value)) {
case 'updatedBy': return '';
return $this->userHelper->getLabel($key, $values, $key); }
case 'date': return $this->translatableStringHelper->localize($presence->getName());
return $this->dateTimeHelper->getLabel(self::MSG_KEY . $key); },
'listReasons' => $this->translatableStringLabelHelper->getLabelMulti($key, $values, 'Activity Reasons'),
'typeName' => function ($value) {
if ('_header' === $value) {
return 'Activity type';
}
case 'attendeeName': if (null === $value || null === $type = $this->activityTypeRepository->find($value)) {
return function ($value) { return '';
if ('_header' === $value) { }
return 'Attendee';
}
if (null === $value || null === $presence = $this->activityPresenceRepository->find($value)) { return $this->translatableStringHelper->localize($type->getName());
return ''; },
} 'usersNames' => $this->userHelper->getLabelMulti($key, $values, self::MSG_KEY.'users name'),
'usersIds', 'thirdPartiesIds', 'personsIds' => static function ($value) use ($key) {
if ('_header' === $value) {
return match ($key) {
'usersIds' => self::MSG_KEY.'users ids',
'thirdPartiesIds' => self::MSG_KEY.'third parties ids',
'personsIds' => self::MSG_KEY.'persons ids',
};
}
return $this->translatableStringHelper->localize($presence->getName()); $decoded = json_decode((string) $value, null, 512, JSON_THROW_ON_ERROR);
};
case 'listReasons': return implode(
return $this->translatableStringLabelHelper->getLabelMulti($key, $values, 'Activity Reasons'); '|',
array_unique(
array_filter($decoded, static fn (?int $id) => null !== $id),
\SORT_NUMERIC
)
);
},
'personsNames' => $this->labelPersonHelper->getLabelMulti($key, $values, self::MSG_KEY.'persons name'),
'thirdPartiesNames' => $this->labelThirdPartyHelper->getLabelMulti($key, $values, self::MSG_KEY.'thirds parties'),
'sentReceived' => function ($value) {
if ('_header' === $value) {
return self::MSG_KEY.'sent received';
}
case 'typeName': if (null === $value) {
return function ($value) { return '';
if ('_header' === $value) { }
return 'Activity type';
}
if (null === $value || null === $type = $this->activityTypeRepository->find($value)) { return $this->translator->trans($value);
return ''; },
} default => function ($value) use ($key) {
if ('_header' === $value) {
return self::MSG_KEY.$key;
}
return $this->translatableStringHelper->localize($type->getName()); if (null === $value) {
}; return '';
}
case 'usersNames': return $this->translator->trans($value);
return $this->userHelper->getLabelMulti($key, $values, self::MSG_KEY . 'users name'); },
};
case 'usersIds':
case 'thirdPartiesIds':
case 'personsIds':
return static function ($value) use ($key) {
if ('_header' === $value) {
switch ($key) {
case 'usersIds':
return self::MSG_KEY . 'users ids';
case 'thirdPartiesIds':
return self::MSG_KEY . 'third parties ids';
case 'personsIds':
return self::MSG_KEY . 'persons ids';
default:
throw new LogicException('key not supported');
}
}
$decoded = json_decode($value, null, 512, JSON_THROW_ON_ERROR);
return implode(
'|',
array_unique(
array_filter($decoded, static fn (?int $id) => null !== $id),
SORT_NUMERIC
)
);
};
case 'personsNames':
return $this->labelPersonHelper->getLabelMulti($key, $values, self::MSG_KEY . 'persons name');
case 'thirdPartiesNames':
return $this->labelThirdPartyHelper->getLabelMulti($key, $values, self::MSG_KEY . 'thirds parties');
case 'sentReceived':
return function ($value) {
if ('_header' === $value) {
return self::MSG_KEY . 'sent received';
}
if (null === $value) {
return '';
}
return $this->translator->trans($value);
};
default:
return function ($value) use ($key) {
if ('_header' === $value) {
return self::MSG_KEY . $key;
}
if (null === $value) {
return '';
}
return $this->translator->trans($value);
};
}
} }
public function getQueryKeys($data) public function getQueryKeys($data)

View File

@ -21,9 +21,6 @@ use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
/**
* Filter accompanying period to keep only the one having at list one activity from the given ActivityType.
*/
class ActivityTypeFilter implements FilterInterface class ActivityTypeFilter implements FilterInterface
{ {
public function __construct( public function __construct(
@ -40,7 +37,7 @@ class ActivityTypeFilter implements FilterInterface
{ {
$qb->andWhere( $qb->andWhere(
$qb->expr()->exists( $qb->expr()->exists(
'SELECT 1 FROM ' . Activity::class . ' act_type_filter_activity 'SELECT 1 FROM '.Activity::class.' act_type_filter_activity
WHERE act_type_filter_activity.activityType IN (:act_type_filter_activity_types) AND act_type_filter_activity.accompanyingPeriod = acp' WHERE act_type_filter_activity.activityType IN (:act_type_filter_activity_types) AND act_type_filter_activity.accompanyingPeriod = acp'
) )
); );
@ -57,13 +54,14 @@ class ActivityTypeFilter implements FilterInterface
$builder->add('accepted_activitytypes', EntityType::class, [ $builder->add('accepted_activitytypes', EntityType::class, [
'class' => ActivityType::class, 'class' => ActivityType::class,
'choices' => $this->activityTypeRepository->findAllActive(), 'choices' => $this->activityTypeRepository->findAllActive(),
'choice_label' => fn (ActivityType $aty) => ($aty->hasCategory() ? $this->translatableStringHelper->localize($aty->getCategory()->getName()) . ' > ' : '') 'choice_label' => fn (ActivityType $aty) => ($aty->hasCategory() ? $this->translatableStringHelper->localize($aty->getCategory()->getName()).' > ' : '')
. .
$this->translatableStringHelper->localize($aty->getName()), $this->translatableStringHelper->localize($aty->getName()),
'multiple' => true, 'multiple' => true,
'expanded' => true, 'expanded' => true,
]); ]);
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];

View File

@ -18,16 +18,10 @@ use Chill\PersonBundle\Form\Type\PickSocialActionType;
use Chill\PersonBundle\Templating\Entity\SocialActionRender; use Chill\PersonBundle\Templating\Entity\SocialActionRender;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
class BySocialActionFilter implements FilterInterface class BySocialActionFilter implements FilterInterface
{ {
private SocialActionRender $actionRender; public function __construct(private readonly SocialActionRender $actionRender) {}
public function __construct(SocialActionRender $actionRender)
{
$this->actionRender = $actionRender;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -36,7 +30,7 @@ class BySocialActionFilter implements FilterInterface
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
if (!in_array('actsocialaction', $qb->getAllAliases(), true)) { if (!\in_array('actsocialaction', $qb->getAllAliases(), true)) {
$qb->join('activity.socialActions', 'actsocialaction'); $qb->join('activity.socialActions', 'actsocialaction');
} }
@ -60,6 +54,7 @@ class BySocialActionFilter implements FilterInterface
'multiple' => true, 'multiple' => true,
]); ]);
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];

View File

@ -18,16 +18,10 @@ use Chill\PersonBundle\Form\Type\PickSocialIssueType;
use Chill\PersonBundle\Templating\Entity\SocialIssueRender; use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
class BySocialIssueFilter implements FilterInterface class BySocialIssueFilter implements FilterInterface
{ {
private SocialIssueRender $issueRender; public function __construct(private readonly SocialIssueRender $issueRender) {}
public function __construct(SocialIssueRender $issueRender)
{
$this->issueRender = $issueRender;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -36,7 +30,7 @@ class BySocialIssueFilter implements FilterInterface
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
if (!in_array('actsocialissue', $qb->getAllAliases(), true)) { if (!\in_array('actsocialissue', $qb->getAllAliases(), true)) {
$qb->join('activity.socialIssues', 'actsocialissue'); $qb->join('activity.socialIssues', 'actsocialissue');
} }
@ -60,6 +54,7 @@ class BySocialIssueFilter implements FilterInterface
'multiple' => true, 'multiple' => true,
]); ]);
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];

View File

@ -18,7 +18,7 @@ use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
/** /**
* Filter accompanying periods to keep only the one without any activity * Filter accompanying periods to keep only the one without any activity.
*/ */
class HasNoActivityFilter implements FilterInterface class HasNoActivityFilter implements FilterInterface
{ {
@ -32,7 +32,7 @@ class HasNoActivityFilter implements FilterInterface
$qb $qb
->andWhere(' ->andWhere('
NOT EXISTS ( NOT EXISTS (
SELECT 1 FROM ' . Activity::class . ' activity SELECT 1 FROM '.Activity::class.' activity
WHERE activity.accompanyingPeriod = acp WHERE activity.accompanyingPeriod = acp
) )
'); ');
@ -45,8 +45,9 @@ class HasNoActivityFilter implements FilterInterface
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)
{ {
//no form needed // no form needed
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];

View File

@ -34,10 +34,10 @@ final readonly class PeriodHavingActivityBetweenDatesFilter implements FilterInt
{ {
$builder $builder
->add('start_date', PickRollingDateType::class, [ ->add('start_date', PickRollingDateType::class, [
'label' => 'export.filter.activity.course_having_activity_between_date.Receiving an activity after' 'label' => 'export.filter.activity.course_having_activity_between_date.Receiving an activity after',
]) ])
->add('end_date', PickRollingDateType::class, [ ->add('end_date', PickRollingDateType::class, [
'label' => 'export.filter.activity.course_having_activity_between_date.Receiving an activity before' 'label' => 'export.filter.activity.course_having_activity_between_date.Receiving an activity before',
]); ]);
} }
@ -45,7 +45,7 @@ final readonly class PeriodHavingActivityBetweenDatesFilter implements FilterInt
{ {
return [ return [
'start_date' => new RollingDate(RollingDate::T_YEAR_CURRENT_START), 'start_date' => new RollingDate(RollingDate::T_YEAR_CURRENT_START),
'end_date' => new RollingDate(RollingDate::T_TODAY) 'end_date' => new RollingDate(RollingDate::T_TODAY),
]; ];
} }
@ -56,7 +56,7 @@ final readonly class PeriodHavingActivityBetweenDatesFilter implements FilterInt
[ [
'from' => $this->rollingDateConverter->convert($data['start_date']), 'from' => $this->rollingDateConverter->convert($data['start_date']),
'to' => $this->rollingDateConverter->convert($data['end_date']), 'to' => $this->rollingDateConverter->convert($data['end_date']),
] ],
]; ];
} }
@ -73,7 +73,7 @@ final readonly class PeriodHavingActivityBetweenDatesFilter implements FilterInt
$qb->andWhere( $qb->andWhere(
$qb->expr()->exists( $qb->expr()->exists(
'SELECT 1 FROM ' . Activity::class . " {$alias} WHERE {$alias}.date >= :{$from} AND {$alias}.date < :{$to} AND {$alias}.accompanyingPeriod = acp" 'SELECT 1 FROM '.Activity::class." {$alias} WHERE {$alias}.date >= :{$from} AND {$alias}.date < :{$to} AND {$alias}.accompanyingPeriod = acp"
) )
); );

View File

@ -27,17 +27,7 @@ use Symfony\Contracts\Translation\TranslatorInterface;
class ActivityDateFilter implements FilterInterface class ActivityDateFilter implements FilterInterface
{ {
protected TranslatorInterface $translator; public function __construct(protected TranslatorInterface $translator, private readonly RollingDateConverterInterface $rollingDateConverter) {}
private RollingDateConverterInterface $rollingDateConverter;
public function __construct(
TranslatorInterface $translator,
RollingDateConverterInterface $rollingDateConverter
) {
$this->translator = $translator;
$this->rollingDateConverter = $rollingDateConverter;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -100,14 +90,14 @@ class ActivityDateFilter implements FilterInterface
if (null === $date_from) { if (null === $date_from) {
$form->get('date_from')->addError(new FormError( $form->get('date_from')->addError(new FormError(
$this->translator->trans('This field ' $this->translator->trans('This field '
. 'should not be empty') .'should not be empty')
)); ));
} }
if (null === $date_to) { if (null === $date_to) {
$form->get('date_to')->addError(new FormError( $form->get('date_to')->addError(new FormError(
$this->translator->trans('This field ' $this->translator->trans('This field '
. 'should not be empty') .'should not be empty')
)); ));
} }
@ -118,13 +108,14 @@ class ActivityDateFilter implements FilterInterface
) { ) {
$form->get('date_to')->addError(new FormError( $form->get('date_to')->addError(new FormError(
$this->translator->trans('This date should be after ' $this->translator->trans('This date should be after '
. 'the date given in "Implied in an activity after ' .'the date given in "Implied in an activity after '
. 'this date" field') .'this date" field')
)); ));
} }
} }
}); });
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return ['date_from' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), 'date_to' => new RollingDate(RollingDate::T_TODAY)]; return ['date_from' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), 'date_to' => new RollingDate(RollingDate::T_TODAY)];

View File

@ -22,21 +22,12 @@ use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface;
use function count;
class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInterface class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInterface
{ {
protected ActivityTypeRepositoryInterface $activityTypeRepository;
protected TranslatableStringHelperInterface $translatableStringHelper;
public function __construct( public function __construct(
TranslatableStringHelperInterface $translatableStringHelper, protected TranslatableStringHelperInterface $translatableStringHelper,
ActivityTypeRepositoryInterface $activityTypeRepository protected ActivityTypeRepositoryInterface $activityTypeRepository
) { ) {}
$this->translatableStringHelper = $translatableStringHelper;
$this->activityTypeRepository = $activityTypeRepository;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -61,7 +52,7 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
$builder->add('types', EntityType::class, [ $builder->add('types', EntityType::class, [
'choices' => $this->activityTypeRepository->findAllActive(), 'choices' => $this->activityTypeRepository->findAllActive(),
'class' => ActivityType::class, 'class' => ActivityType::class,
'choice_label' => fn (ActivityType $aty) => ($aty->hasCategory() ? $this->translatableStringHelper->localize($aty->getCategory()->getName()) . ' > ' : '') 'choice_label' => fn (ActivityType $aty) => ($aty->hasCategory() ? $this->translatableStringHelper->localize($aty->getCategory()->getName()).' > ' : '')
. .
$this->translatableStringHelper->localize($aty->getName()), $this->translatableStringHelper->localize($aty->getName()),
'group_by' => function (ActivityType $type) { 'group_by' => function (ActivityType $type) {
@ -78,6 +69,7 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
], ],
]); ]);
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
@ -103,7 +95,7 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
public function validateForm($data, ExecutionContextInterface $context) public function validateForm($data, ExecutionContextInterface $context)
{ {
if (null === $data['types'] || count($data['types']) === 0) { if (null === $data['types'] || 0 === \count($data['types'])) {
$context $context
->buildViolation('At least one type must be chosen') ->buildViolation('At least one type must be chosen')
->addViolation(); ->addViolation();

View File

@ -20,12 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface;
class ActivityUsersFilter implements FilterInterface class ActivityUsersFilter implements FilterInterface
{ {
private UserRender $userRender; public function __construct(private readonly UserRender $userRender) {}
public function __construct(UserRender $userRender)
{
$this->userRender = $userRender;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -37,8 +32,8 @@ class ActivityUsersFilter implements FilterInterface
$orX = $qb->expr()->orX(); $orX = $qb->expr()->orX();
foreach ($data['accepted_users'] as $key => $user) { foreach ($data['accepted_users'] as $key => $user) {
$orX->add($qb->expr()->isMemberOf(':activity_users_filter_u' . $key, 'activity.users')); $orX->add($qb->expr()->isMemberOf(':activity_users_filter_u'.$key, 'activity.users'));
$qb->setParameter('activity_users_filter_u' . $key, $user); $qb->setParameter('activity_users_filter_u'.$key, $user);
} }
$qb->andWhere($orX); $qb->andWhere($orX);
@ -56,6 +51,7 @@ class ActivityUsersFilter implements FilterInterface
'label' => 'Users', 'label' => 'Users',
]); ]);
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];

View File

@ -20,12 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface;
class ByCreatorFilter implements FilterInterface class ByCreatorFilter implements FilterInterface
{ {
private UserRender $userRender; public function __construct(private readonly UserRender $userRender) {}
public function __construct(UserRender $userRender)
{
$this->userRender = $userRender;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -52,6 +47,7 @@ class ByCreatorFilter implements FilterInterface
'multiple' => true, 'multiple' => true,
]); ]);
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];

View File

@ -28,12 +28,7 @@ class EmergencyFilter implements FilterInterface
private const DEFAULT_CHOICE = 'false'; private const DEFAULT_CHOICE = 'false';
private TranslatorInterface $translator; public function __construct(private readonly TranslatorInterface $translator) {}
public function __construct(TranslatorInterface $translator)
{
$this->translator = $translator;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -70,6 +65,7 @@ class EmergencyFilter implements FilterInterface
'empty_data' => self::DEFAULT_CHOICE, 'empty_data' => self::DEFAULT_CHOICE,
]); ]);
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return ['accepted_emergency' => self::DEFAULT_CHOICE]; return ['accepted_emergency' => self::DEFAULT_CHOICE];

View File

@ -14,7 +14,6 @@ namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\PickUserLocationType; use Chill\MainBundle\Form\Type\PickUserLocationType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
@ -46,6 +45,7 @@ class LocationFilter implements FilterInterface
'label' => 'pick location', 'label' => 'pick location',
]); ]);
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];

View File

@ -18,16 +18,10 @@ use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\Query\Expr\Andx; use Doctrine\ORM\Query\Expr\Andx;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
class LocationTypeFilter implements FilterInterface class LocationTypeFilter implements FilterInterface
{ {
private TranslatableStringHelper $translatableStringHelper; public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) {}
public function __construct(TranslatableStringHelper $translatableStringHelper)
{
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -36,7 +30,7 @@ class LocationTypeFilter implements FilterInterface
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
if (!in_array('actloc', $qb->getAllAliases(), true)) { if (!\in_array('actloc', $qb->getAllAliases(), true)) {
$qb->join('activity.location', 'actloc'); $qb->join('activity.location', 'actloc');
} }
@ -62,9 +56,10 @@ class LocationTypeFilter implements FilterInterface
{ {
$builder->add('accepted_locationtype', PickLocationTypeType::class, [ $builder->add('accepted_locationtype', PickLocationTypeType::class, [
'multiple' => true, 'multiple' => true,
//'label' => false, // 'label' => false,
]); ]);
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];

View File

@ -17,29 +17,15 @@ use Chill\ActivityBundle\Repository\ActivityReasonRepository;
use Chill\MainBundle\Export\ExportElementValidatedInterface; use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\Query\Expr; use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface;
use function count;
use function in_array;
class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInterface class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInterface
{ {
protected ActivityReasonRepository $activityReasonRepository; public function __construct(protected TranslatableStringHelper $translatableStringHelper, protected ActivityReasonRepository $activityReasonRepository) {}
protected TranslatableStringHelperInterface $translatableStringHelper;
public function __construct(
TranslatableStringHelper $helper,
ActivityReasonRepository $activityReasonRepository
) {
$this->translatableStringHelper = $helper;
$this->activityReasonRepository = $activityReasonRepository;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -52,7 +38,7 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
$join = $qb->getDQLPart('join'); $join = $qb->getDQLPart('join');
$clause = $qb->expr()->in('actreasons', ':selected_activity_reasons'); $clause = $qb->expr()->in('actreasons', ':selected_activity_reasons');
if (!in_array('actreasons', $qb->getAllAliases(), true)) { if (!\in_array('actreasons', $qb->getAllAliases(), true)) {
$qb->join('activity.reasons', 'actreasons'); $qb->join('activity.reasons', 'actreasons');
} }
@ -82,6 +68,7 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
'expanded' => false, 'expanded' => false,
]); ]);
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];
@ -91,7 +78,7 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
{ {
// collect all the reasons'name used in this filter in one array // collect all the reasons'name used in this filter in one array
$reasonsNames = array_map( $reasonsNames = array_map(
fn (ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"', fn (ActivityReason $r): string => '"'.$this->translatableStringHelper->localize($r->getName()).'"',
$this->activityReasonRepository->findBy(['id' => $data['reasons']->toArray()]) $this->activityReasonRepository->findBy(['id' => $data['reasons']->toArray()])
); );
@ -110,7 +97,7 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
public function validateForm($data, ExecutionContextInterface $context) public function validateForm($data, ExecutionContextInterface $context)
{ {
if (null === $data['reasons'] || count($data['reasons']) === 0) { if (null === $data['reasons'] || 0 === \count($data['reasons'])) {
$context $context
->buildViolation('At least one reason must be chosen') ->buildViolation('At least one reason must be chosen')
->addViolation(); ->addViolation();

View File

@ -16,46 +16,23 @@ use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Repository\ActivityReasonRepository; use Chill\ActivityBundle\Repository\ActivityReasonRepository;
use Chill\MainBundle\Export\ExportElementValidatedInterface; use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\Export\FilterType;
use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface; use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Export\Declarations; use Chill\PersonBundle\Export\Declarations;
use DateTime;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use function count; final readonly class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInterface, FilterInterface
class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInterface, FilterInterface
{ {
protected ActivityReasonRepository $activityReasonRepository;
protected TranslatableStringHelperInterface $translatableStringHelper;
protected TranslatorInterface $translator;
public function __construct( public function __construct(
TranslatableStringHelper $translatableStringHelper, private TranslatableStringHelper $translatableStringHelper,
ActivityReasonRepository $activityReasonRepository, private ActivityReasonRepository $activityReasonRepository,
TranslatorInterface $translator, private RollingDateConverterInterface $rollingDateConverter,
private readonly RollingDateConverterInterface $rollingDateConverter, ) {}
) {
$this->translatableStringHelper = $translatableStringHelper;
$this->activityReasonRepository = $activityReasonRepository;
$this->translator = $translator;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -72,11 +49,11 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
// add clause between date // add clause between date
$sqb->where('activity_person_having_activity.date BETWEEN ' $sqb->where('activity_person_having_activity.date BETWEEN '
. ':person_having_activity_between_date_from' .':person_having_activity_between_date_from'
. ' AND ' .' AND '
. ':person_having_activity_between_date_to' .':person_having_activity_between_date_to'
. ' AND ' .' AND '
. '(person_person_having_activity.id = person.id OR person MEMBER OF activity_person_having_activity.persons)'); .'(person_person_having_activity.id = person.id OR person MEMBER OF activity_person_having_activity.persons)');
if (isset($data['reasons']) && [] !== $data['reasons']) { if (isset($data['reasons']) && [] !== $data['reasons']) {
// add clause activity reason // add clause activity reason
@ -134,6 +111,7 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
]); ]);
} }
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return [ return [
@ -155,7 +133,7 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
'reasons' => implode( 'reasons' => implode(
', ', ', ',
array_map( array_map(
fn (ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"', fn (ActivityReason $r): string => '"'.$this->translatableStringHelper->localize($r->getName()).'"',
$data['reasons'] $data['reasons']
) )
), ),

View File

@ -29,12 +29,7 @@ class SentReceivedFilter implements FilterInterface
private const DEFAULT_CHOICE = Activity::SENTRECEIVED_SENT; private const DEFAULT_CHOICE = Activity::SENTRECEIVED_SENT;
private TranslatorInterface $translator; public function __construct(private readonly TranslatorInterface $translator) {}
public function __construct(TranslatorInterface $translator)
{
$this->translator = $translator;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -71,6 +66,7 @@ class SentReceivedFilter implements FilterInterface
'empty_data' => self::DEFAULT_CHOICE, 'empty_data' => self::DEFAULT_CHOICE,
]); ]);
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return ['accepted_sentreceived' => self::DEFAULT_CHOICE]; return ['accepted_sentreceived' => self::DEFAULT_CHOICE];

View File

@ -21,12 +21,7 @@ use Symfony\Component\Form\FormBuilderInterface;
class UserFilter implements FilterInterface class UserFilter implements FilterInterface
{ {
private UserRender $userRender; public function __construct(private readonly UserRender $userRender) {}
public function __construct(UserRender $userRender)
{
$this->userRender = $userRender;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -61,6 +56,7 @@ class UserFilter implements FilterInterface
'label' => 'Creators', 'label' => 'Creators',
]); ]);
} }
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];

View File

@ -13,22 +13,21 @@ namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User\UserScopeHistory;
use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\Query\Expr\Andx; use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
class UserScopeFilter implements FilterInterface class UserScopeFilter implements FilterInterface
{ {
private TranslatableStringHelper $translatableStringHelper; private const PREFIX = 'acp_act_filter_user_scope'; // creator ? cfr translation
public function __construct(TranslatableStringHelper $translatableStringHelper) public function __construct(
{ private readonly TranslatableStringHelper $translatableStringHelper
$this->translatableStringHelper = $translatableStringHelper; ) {}
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -37,22 +36,33 @@ class UserScopeFilter implements FilterInterface
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
if (!in_array('actuser', $qb->getAllAliases(), true)) { $p = self::PREFIX;
$qb->join('activity.user', 'actuser');
}
$where = $qb->getDQLPart('where'); $qb
->leftJoin('activity.user', "{$p}_user") // createdBy ? cfr translation
$clause = $qb->expr()->in('actuser.mainScope', ':userscope'); ->leftJoin(
UserScopeHistory::class,
if ($where instanceof Andx) { "{$p}_history",
$where->add($clause); Join::WITH,
} else { $qb->expr()->eq("{$p}_history.user", "{$p}_user")
$where = $qb->expr()->andX($clause); )
} // scope_at based on activity.date
->andWhere(
$qb->add('where', $where); $qb->expr()->andX(
$qb->setParameter('userscope', $data['accepted_userscope']); $qb->expr()->lte("{$p}_history.startDate", 'activity.date'),
$qb->expr()->orX(
$qb->expr()->isNull("{$p}_history.endDate"),
$qb->expr()->gt("{$p}_history.endDate", 'activity.date')
)
)
)
->andWhere(
$qb->expr()->in("{$p}_history.scope", ":{$p}_scopes")
)
->setParameter(
"{$p}_scopes",
$data['scopes'],
);
} }
public function applyOn(): string public function applyOn(): string
@ -62,37 +72,41 @@ class UserScopeFilter implements FilterInterface
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)
{ {
$builder->add('accepted_userscope', EntityType::class, [ $builder
'class' => Scope::class, ->add('scopes', EntityType::class, [
'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize( 'class' => Scope::class,
$s->getName() 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize(
), $s->getName()
'multiple' => true, ),
'expanded' => true, 'multiple' => true,
]); 'expanded' => true,
} ]);
public function getFormDefaultData(): array
{
return [];
} }
public function describeAction($data, $format = 'string'): array public function describeAction($data, $format = 'string'): array
{ {
$scopes = []; $scopes = [];
foreach ($data['accepted_userscope'] as $s) { foreach ($data['scopes'] as $s) {
$scopes[] = $this->translatableStringHelper->localize( $scopes[] = $this->translatableStringHelper->localize(
$s->getName() $s->getName()
); );
} }
return ['Filtered activity by userscope: only %scopes%', [ return ['export.filter.activity.by_creator_scope.Filtered activity by user scope: only %scopes%', [
'%scopes%' => implode(', ', $scopes), '%scopes%' => implode(', ', $scopes),
]]; ]];
} }
public function getFormDefaultData(): array
{
return [
'scopes' => [],
];
}
public function getTitle(): string public function getTitle(): string
{ {
return 'Filter activity by userscope'; return 'export.filter.activity.by_creator_scope.Filter activity by user scope';
} }
} }

View File

@ -13,6 +13,7 @@ namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Entity\User\UserJobHistory;
use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Entity\UserJob;
use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
@ -22,12 +23,11 @@ use Symfony\Component\Form\FormBuilderInterface;
class UsersJobFilter implements FilterInterface class UsersJobFilter implements FilterInterface
{ {
private TranslatableStringHelperInterface $translatableStringHelper; private const PREFIX = 'act_filter_user_job';
public function __construct(TranslatableStringHelperInterface $translatableStringHelper) public function __construct(
{ private readonly TranslatableStringHelperInterface $translatableStringHelper
$this->translatableStringHelper = $translatableStringHelper; ) {}
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -36,14 +36,25 @@ class UsersJobFilter implements FilterInterface
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
$p = self::PREFIX;
$qb $qb
->andWhere( ->andWhere(
$qb->expr()->exists( $qb->expr()->exists(
'SELECT 1 FROM ' . Activity::class . ' activity_users_job_filter_act 'SELECT 1 FROM '.Activity::class." {$p}_act "
JOIN activity_users_job_filter_act.users users WHERE users.userJob IN (:activity_users_job_filter_jobs) AND activity_users_job_filter_act = activity ' ."JOIN {$p}_act.users {$p}_user "
.'JOIN '.UserJobHistory::class." {$p}_history WITH {$p}_history.user = {$p}_user "
."WHERE {$p}_act = activity "
// job_at based on activity.date
."AND {$p}_history.startDate <= activity.date "
."AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > activity.date) "
."AND {$p}_history.job IN ( :{$p}_jobs )"
) )
) )
->setParameter('activity_users_job_filter_jobs', $data['jobs']); ->setParameter(
"{$p}_jobs",
$data['jobs']
);
} }
public function applyOn() public function applyOn()
@ -53,21 +64,18 @@ class UsersJobFilter implements FilterInterface
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)
{ {
$builder->add('jobs', EntityType::class, [ $builder
'class' => UserJob::class, ->add('jobs', EntityType::class, [
'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize($j->getLabel()), 'class' => UserJob::class,
'multiple' => true, 'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize($j->getLabel()),
'expanded' => true, 'multiple' => true,
]); 'expanded' => true,
} ]);
public function getFormDefaultData(): array
{
return [];
} }
public function describeAction($data, $format = 'string') public function describeAction($data, $format = 'string')
{ {
return ['export.filter.activity.by_usersjob.Filtered activity by users job: only %jobs%', [ return ['export.filter.activity.by_users_job.Filtered activity by users job: only %jobs%', [
'%jobs%' => implode( '%jobs%' => implode(
', ', ', ',
array_map( array_map(
@ -78,8 +86,15 @@ class UsersJobFilter implements FilterInterface
]]; ]];
} }
public function getFormDefaultData(): array
{
return [
'jobs' => [],
];
}
public function getTitle() public function getTitle()
{ {
return 'export.filter.activity.by_usersjob.Filter by users job'; return 'export.filter.activity.by_users_job.Filter by users job';
} }
} }

View File

@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User\UserScopeHistory;
use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Repository\ScopeRepositoryInterface; use Chill\MainBundle\Repository\ScopeRepositoryInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
@ -23,17 +24,12 @@ use Symfony\Component\Form\FormBuilderInterface;
class UsersScopeFilter implements FilterInterface class UsersScopeFilter implements FilterInterface
{ {
private ScopeRepositoryInterface $scopeRepository; private const PREFIX = 'act_filter_user_scope';
private TranslatableStringHelperInterface $translatableStringHelper;
public function __construct( public function __construct(
ScopeRepositoryInterface $scopeRepository, private readonly ScopeRepositoryInterface $scopeRepository,
TranslatableStringHelperInterface $translatableStringHelper private readonly TranslatableStringHelperInterface $translatableStringHelper
) { ) {}
$this->scopeRepository = $scopeRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -42,39 +38,47 @@ class UsersScopeFilter implements FilterInterface
public function alterQuery(QueryBuilder $qb, $data) public function alterQuery(QueryBuilder $qb, $data)
{ {
$p = self::PREFIX;
$qb $qb
->andWhere( ->andWhere(
$qb->expr()->exists( $qb->expr()->exists(
'SELECT 1 FROM ' . Activity::class . ' activity_users_scope_filter_act 'SELECT 1 FROM '.Activity::class." {$p}_act "
JOIN activity_users_scope_filter_act.users users WHERE users.mainScope IN (:activity_users_scope_filter_scopes) AND activity_users_scope_filter_act = activity ' ."JOIN {$p}_act.users {$p}_user "
.'JOIN '.UserScopeHistory::class." {$p}_history WITH {$p}_history.user = {$p}_user "
."WHERE {$p}_act = activity "
// scope_at based on activity.date
."AND {$p}_history.startDate <= activity.date "
."AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > activity.date) "
."AND {$p}_history.scope IN ( :{$p}_scopes )"
) )
) )
->setParameter('activity_users_scope_filter_scopes', $data['scopes']); ->setParameter(
"{$p}_scopes",
$data['scopes']
);
} }
public function applyOn() public function applyOn(): string
{ {
return Declarations::ACTIVITY; return Declarations::ACTIVITY;
} }
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)
{ {
$builder->add('scopes', EntityType::class, [ $builder
'class' => Scope::class, ->add('scopes', EntityType::class, [
'choices' => $this->scopeRepository->findAllActive(), 'class' => Scope::class,
'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), 'choices' => $this->scopeRepository->findAllActive(),
'multiple' => true, 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()),
'expanded' => true, 'multiple' => true,
]); 'expanded' => true,
} ]);
public function getFormDefaultData(): array
{
return [];
} }
public function describeAction($data, $format = 'string') public function describeAction($data, $format = 'string'): array
{ {
return ['export.filter.activity.by_usersscope.Filtered activity by users scope: only %scopes%', [ return ['export.filter.activity.by_users_scope.Filtered activity by users scope: only %scopes%', [
'%scopes%' => implode( '%scopes%' => implode(
', ', ', ',
array_map( array_map(
@ -85,8 +89,15 @@ class UsersScopeFilter implements FilterInterface
]]; ]];
} }
public function getTitle() public function getFormDefaultData(): array
{ {
return 'export.filter.activity.by_usersscope.Filter by users scope'; return [
'scopes' => [],
];
}
public function getTitle(): string
{
return 'export.filter.activity.by_users_scope.Filter by users scope';
} }
} }

View File

@ -34,12 +34,8 @@ use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
use Chill\PersonBundle\Templating\Entity\SocialActionRender; use Chill\PersonBundle\Templating\Entity\SocialActionRender;
use Chill\PersonBundle\Templating\Entity\SocialIssueRender; use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
use Chill\ThirdPartyBundle\Entity\ThirdParty; use Chill\ThirdPartyBundle\Entity\ThirdParty;
use DateInterval;
use DateTime;
use DateTimeZone;
use Doctrine\ORM\EntityRepository; use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectManager;
use RuntimeException;
use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\CallbackTransformer;
@ -53,45 +49,24 @@ use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Role\Role;
use function in_array;
class ActivityType extends AbstractType class ActivityType extends AbstractType
{ {
protected AuthorizationHelper $authorizationHelper;
protected ObjectManager $om;
protected SocialActionRender $socialActionRender;
protected SocialIssueRender $socialIssueRender;
protected array $timeChoices;
protected TranslatableStringHelper $translatableStringHelper;
protected User $user; protected User $user;
public function __construct( public function __construct(
TokenStorageInterface $tokenStorage, TokenStorageInterface $tokenStorage,
AuthorizationHelper $authorizationHelper, protected AuthorizationHelper $authorizationHelper,
ObjectManager $om, protected ObjectManager $om,
TranslatableStringHelper $translatableStringHelper, protected TranslatableStringHelper $translatableStringHelper,
array $timeChoices, protected array $timeChoices,
SocialIssueRender $socialIssueRender, protected SocialIssueRender $socialIssueRender,
SocialActionRender $socialActionRender protected SocialActionRender $socialActionRender
) { ) {
if (!$tokenStorage->getToken()->getUser() instanceof User) { if (!$tokenStorage->getToken()->getUser() instanceof User) {
throw new RuntimeException('you should have a valid user'); throw new \RuntimeException('you should have a valid user');
} }
$this->user = $tokenStorage->getToken()->getUser(); $this->user = $tokenStorage->getToken()->getUser();
$this->authorizationHelper = $authorizationHelper;
$this->om = $om;
$this->translatableStringHelper = $translatableStringHelper;
$this->timeChoices = $timeChoices;
$this->socialIssueRender = $socialIssueRender;
$this->socialActionRender = $socialActionRender;
} }
public function buildForm(FormBuilderInterface $builder, array $options): void public function buildForm(FormBuilderInterface $builder, array $options): void
@ -121,16 +96,16 @@ class ActivityType extends AbstractType
]); ]);
} }
/** @var ? \Chill\PersonBundle\Entity\AccompanyingPeriod $accompanyingPeriod */ /** @var \Chill\PersonBundle\Entity\AccompanyingPeriod|null $accompanyingPeriod */
$accompanyingPeriod = null; $accompanyingPeriod = null;
if ($options['accompanyingPeriod'] instanceof AccompanyingPeriod) { if ($options['accompanyingPeriod'] instanceof AccompanyingPeriod) {
$accompanyingPeriod = $options['accompanyingPeriod']; $accompanyingPeriod = $options['accompanyingPeriod'];
} }
if ($activityType->isVisible('socialIssues') && $accompanyingPeriod) { if ($activityType->isVisible('socialIssues') && null !== $accompanyingPeriod) {
$builder->add('socialIssues', HiddenType::class, [ $builder->add('socialIssues', HiddenType::class, [
'required' => $activityType->getSocialIssuesVisible() === 2, 'required' => 2 === $activityType->getSocialIssuesVisible(),
]); ]);
$builder->get('socialIssues') $builder->get('socialIssues')
->addModelTransformer(new CallbackTransformer( ->addModelTransformer(new CallbackTransformer(
@ -156,9 +131,9 @@ class ActivityType extends AbstractType
)); ));
} }
if ($activityType->isVisible('socialActions') && $accompanyingPeriod) { if ($activityType->isVisible('socialActions') && null !== $accompanyingPeriod) {
$builder->add('socialActions', HiddenType::class, [ $builder->add('socialActions', HiddenType::class, [
'required' => $activityType->getSocialActionsVisible() === 2, 'required' => 2 === $activityType->getSocialActionsVisible(),
]); ]);
$builder->get('socialActions') $builder->get('socialActions')
->addModelTransformer(new CallbackTransformer( ->addModelTransformer(new CallbackTransformer(
@ -342,7 +317,7 @@ class ActivityType extends AbstractType
if ($activityType->isVisible('location')) { if ($activityType->isVisible('location')) {
$builder->add('location', HiddenType::class, [ $builder->add('location', HiddenType::class, [
'required' => $activityType->getLocationVisible() === 2, 'required' => 2 === $activityType->getLocationVisible(),
]) ])
->get('location') ->get('location')
->addModelTransformer(new CallbackTransformer( ->addModelTransformer(new CallbackTransformer(
@ -393,16 +368,16 @@ class ActivityType extends AbstractType
) { ) {
// set the timezone to GMT, and fix the difference between current and GMT // set the timezone to GMT, and fix the difference between current and GMT
// the datetimetransformer will then handle timezone as GMT // the datetimetransformer will then handle timezone as GMT
$timezoneUTC = new DateTimeZone('GMT'); $timezoneUTC = new \DateTimeZone('GMT');
/** @var DateTime $data */ /** @var \DateTime $data */
$data = $formEvent->getData() ?? DateTime::createFromFormat('U', '300'); $data = $formEvent->getData() ?? \DateTime::createFromFormat('U', '300');
$seconds = $data->getTimezone()->getOffset($data); $seconds = $data->getTimezone()->getOffset($data);
$data->setTimeZone($timezoneUTC); $data->setTimeZone($timezoneUTC);
$data->add(new DateInterval('PT' . $seconds . 'S')); $data->add(new \DateInterval('PT'.$seconds.'S'));
// test if the timestamp is in the choices. // test if the timestamp is in the choices.
// If not, recreate the field with the new timestamp // If not, recreate the field with the new timestamp
if (!in_array($data->getTimestamp(), $timeChoices, true)) { if (!\in_array($data->getTimestamp(), $timeChoices, true)) {
// the data are not in the possible values. add them // the data are not in the possible values. add them
$timeChoices[$data->format('H:i')] = $data->getTimestamp(); $timeChoices[$data->format('H:i')] = $data->getTimestamp();
$form = $builder->create($fieldName, ChoiceType::class, array_merge( $form = $builder->create($fieldName, ChoiceType::class, array_merge(
@ -428,7 +403,7 @@ class ActivityType extends AbstractType
$resolver $resolver
->setRequired(['center', 'role', 'activityType', 'accompanyingPeriod']) ->setRequired(['center', 'role', 'activityType', 'accompanyingPeriod'])
->setAllowedTypes('center', ['null', Center::class]) ->setAllowedTypes('center', ['null', Center::class])
->setAllowedTypes('role', [Role::class, 'string']) ->setAllowedTypes('role', ['string'])
->setAllowedTypes('activityType', \Chill\ActivityBundle\Entity\ActivityType::class) ->setAllowedTypes('activityType', \Chill\ActivityBundle\Entity\ActivityType::class)
->setAllowedTypes('accompanyingPeriod', [\Chill\PersonBundle\Entity\AccompanyingPeriod::class, 'null']); ->setAllowedTypes('accompanyingPeriod', [\Chill\PersonBundle\Entity\AccompanyingPeriod::class, 'null']);
} }

View File

@ -25,12 +25,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
class ActivityTypeType extends AbstractType class ActivityTypeType extends AbstractType
{ {
private TranslatableStringHelper $translatableStringHelper; public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) {}
public function __construct(TranslatableStringHelper $translatableStringHelper)
{
$this->translatableStringHelper = $translatableStringHelper;
}
public function buildForm(FormBuilderInterface $builder, array $options) public function buildForm(FormBuilderInterface $builder, array $options)
{ {
@ -61,8 +56,8 @@ class ActivityTypeType extends AbstractType
foreach ($fields as $field) { foreach ($fields as $field) {
$builder $builder
->add($field . 'Visible', ActivityFieldPresence::class) ->add($field.'Visible', ActivityFieldPresence::class)
->add($field . 'Label', TextType::class, [ ->add($field.'Label', TextType::class, [
'required' => false, 'required' => false,
'empty_data' => '', 'empty_data' => '',
]); ]);

View File

@ -24,21 +24,11 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/ */
class PickActivityReasonType extends AbstractType class PickActivityReasonType extends AbstractType
{ {
private ActivityReasonRepository $activityReasonRepository;
private ActivityReasonRender $reasonRender;
private TranslatableStringHelperInterface $translatableStringHelper;
public function __construct( public function __construct(
ActivityReasonRepository $activityReasonRepository, private readonly ActivityReasonRepository $activityReasonRepository,
ActivityReasonRender $reasonRender, private readonly ActivityReasonRender $reasonRender,
TranslatableStringHelperInterface $translatableStringHelper private readonly TranslatableStringHelperInterface $translatableStringHelper
) { ) {}
$this->activityReasonRepository = $activityReasonRepository;
$this->reasonRender = $reasonRender;
$this->translatableStringHelper = $translatableStringHelper;
}
public function configureOptions(OptionsResolver $resolver) public function configureOptions(OptionsResolver $resolver)
{ {

View File

@ -23,15 +23,7 @@ use Symfony\Contracts\Translation\TranslatorInterface;
*/ */
class TranslatableActivityReasonCategoryType extends AbstractType class TranslatableActivityReasonCategoryType extends AbstractType
{ {
private TranslatableStringHelperInterface $translatableStringHelper; public function __construct(private readonly TranslatableStringHelperInterface $translatableStringHelper, private readonly TranslatorInterface $translator) {}
private TranslatorInterface $translator;
public function __construct(TranslatableStringHelperInterface $translatableStringHelper, TranslatorInterface $translator)
{
$this->translatableStringHelper = $translatableStringHelper;
$this->translator = $translator;
}
public function configureOptions(OptionsResolver $resolver) public function configureOptions(OptionsResolver $resolver)
{ {
@ -39,16 +31,11 @@ class TranslatableActivityReasonCategoryType extends AbstractType
[ [
'class' => ActivityReasonCategory::class, 'class' => ActivityReasonCategory::class,
'choice_label' => fn (ActivityReasonCategory $category) => $this->translatableStringHelper->localize($category->getName()) 'choice_label' => fn (ActivityReasonCategory $category) => $this->translatableStringHelper->localize($category->getName())
. (!$category->getActive() ? ' (' . $this->translator->trans('inactive') . ')' : ''), .(!$category->getActive() ? ' ('.$this->translator->trans('inactive').')' : ''),
] ]
); );
} }
public function getBlockPrefix()
{
return 'translatable_activity_reason_category';
}
public function getParent() public function getParent()
{ {
return EntityType::class; return EntityType::class;

View File

@ -20,17 +20,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
class TranslatableActivityType extends AbstractType class TranslatableActivityType extends AbstractType
{ {
protected ActivityTypeRepositoryInterface $activityTypeRepository; public function __construct(protected TranslatableStringHelperInterface $translatableStringHelper, protected ActivityTypeRepositoryInterface $activityTypeRepository) {}
protected TranslatableStringHelperInterface $translatableStringHelper;
public function __construct(
TranslatableStringHelperInterface $helper,
ActivityTypeRepositoryInterface $activityTypeRepository
) {
$this->translatableStringHelper = $helper;
$this->activityTypeRepository = $activityTypeRepository;
}
public function configureOptions(OptionsResolver $resolver) public function configureOptions(OptionsResolver $resolver)
{ {

View File

@ -23,17 +23,7 @@ use Symfony\Contracts\Translation\TranslatorInterface;
*/ */
class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
{ {
protected Security $security; public function __construct(protected Security $security, protected TranslatorInterface $translator) {}
protected TranslatorInterface $translator;
public function __construct(
Security $security,
TranslatorInterface $translator
) {
$this->security = $security;
$this->translator = $translator;
}
public function buildMenu($menuId, MenuItem $menu, array $parameters) public function buildMenu($menuId, MenuItem $menu, array $parameters)
{ {

View File

@ -18,14 +18,9 @@ use Symfony\Component\Security\Core\Security;
/** /**
* @implements LocalMenuBuilderInterface<array> * @implements LocalMenuBuilderInterface<array>
*/ */
final class AdminMenuBuilder implements LocalMenuBuilderInterface final readonly class AdminMenuBuilder implements LocalMenuBuilderInterface
{ {
private Security $security; public function __construct(private Security $security) {}
public function __construct(Security $security)
{
$this->security = $security;
}
public function buildMenu($menuId, MenuItem $menu, array $parameters) public function buildMenu($menuId, MenuItem $menu, array $parameters)
{ {

View File

@ -21,25 +21,9 @@ use Symfony\Contracts\Translation\TranslatorInterface;
/** /**
* @implements LocalMenuBuilderInterface<array{person: Person}> * @implements LocalMenuBuilderInterface<array{person: Person}>
*/ */
final class PersonMenuBuilder implements LocalMenuBuilderInterface final readonly class PersonMenuBuilder implements LocalMenuBuilderInterface
{ {
/** public function __construct(private AuthorizationCheckerInterface $authorizationChecker, private TranslatorInterface $translator) {}
* @var AuthorizationCheckerInterface
*/
private $authorizationChecker;
/**
* @var TranslatorInterface
*/
private $translator;
public function __construct(
AuthorizationCheckerInterface $authorizationChecker,
TranslatorInterface $translator
) {
$this->translator = $translator;
$this->authorizationChecker = $authorizationChecker;
}
public function buildMenu($menuId, MenuItem $menu, array $parameters) public function buildMenu($menuId, MenuItem $menu, array $parameters)
{ {

View File

@ -16,14 +16,9 @@ use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\MainBundle\Entity\Notification; use Chill\MainBundle\Entity\Notification;
use Chill\MainBundle\Notification\NotificationHandlerInterface; use Chill\MainBundle\Notification\NotificationHandlerInterface;
final class ActivityNotificationHandler implements NotificationHandlerInterface final readonly class ActivityNotificationHandler implements NotificationHandlerInterface
{ {
private ActivityRepository $activityRepository; public function __construct(private ActivityRepository $activityRepository) {}
public function __construct(ActivityRepository $activityRepository)
{
$this->activityRepository = $activityRepository;
}
public function getTemplate(Notification $notification, array $options = []): string public function getTemplate(Notification $notification, array $options = []): string
{ {
@ -40,6 +35,6 @@ final class ActivityNotificationHandler implements NotificationHandlerInterface
public function supports(Notification $notification, array $options = []): bool public function supports(Notification $notification, array $options = []): bool
{ {
return $notification->getRelatedEntityClass() === Activity::class; return Activity::class === $notification->getRelatedEntityClass();
} }
} }

View File

@ -35,9 +35,6 @@ use Doctrine\ORM\QueryBuilder;
use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
use function count;
use function in_array;
final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInterface final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInterface
{ {
public function __construct( public function __construct(
@ -75,7 +72,6 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
return $qb->getQuery()->getSingleScalarResult(); return $qb->getQuery()->getSingleScalarResult();
} }
public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): array public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): array
{ {
$qb = $this->buildBaseQuery($filters); $qb = $this->buildBaseQuery($filters);
@ -83,7 +79,7 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
$qb->andWhere('a.accompanyingPeriod = :period')->setParameter('period', $period); $qb->andWhere('a.accompanyingPeriod = :period')->setParameter('period', $period);
foreach ($orderBy as $field => $order) { foreach ($orderBy as $field => $order) {
$qb->addOrderBy('a.' . $field, $order); $qb->addOrderBy('a.'.$field, $order);
} }
if (null !== $start) { if (null !== $start) {
@ -122,9 +118,30 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
->leftJoin('a.user', 'activity_u') ->leftJoin('a.user', 'activity_u')
->andWhere( ->andWhere(
$qb->expr()->orX( $qb->expr()->orX(
'creator.userJob IN (:jobs)', $qb->expr()->exists(
'activity_u.userJob IN (:jobs)', sprintf(
'EXISTS (SELECT 1 FROM ' . User::class . ' activity_user WHERE activity_user MEMBER OF a.users AND activity_user.userJob IN (:jobs))' 'SELECT 1 FROM %s ujh_creator WHERE ujh_creator.user = a.createdBy '
.'AND ujh_creator.job IN (:jobs) AND a.createdAt > ujh_creator.startDate '
.'AND (ujh_creator.endDate IS NULL or ujh_creator.endDate > a.date)',
User\UserJobHistory::class
)
),
$qb->expr()->exists(
sprintf(
'SELECT 1 FROM %s ujh_u WHERE ujh_u.user = a.user '
.'AND ujh_u.job IN (:jobs) AND a.createdAt > ujh_u.startDate '
.'AND (ujh_u.endDate IS NULL or ujh_u.endDate > a.date)',
User\UserJobHistory::class
)
),
$qb->expr()->exists(
sprintf(
'SELECT 1 FROM %s ujh_users WHERE ujh_users.user MEMBER OF a.users '
.'AND ujh_users.job IN (:jobs) AND a.createdAt > ujh_users.startDate '
.'AND (ujh_users.endDate IS NULL or ujh_users.endDate > a.date)',
User\UserJobHistory::class
)
),
) )
) )
->setParameter('jobs', $jobs); ->setParameter('jobs', $jobs);
@ -142,7 +159,6 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
} }
/** /**
* @param AccompanyingPeriod|Person $associated
* @return array<ActivityType> * @return array<ActivityType>
*/ */
public function findActivityTypeByAssociated(AccompanyingPeriod|Person $associated): array public function findActivityTypeByAssociated(AccompanyingPeriod|Person $associated): array
@ -172,16 +188,17 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
return $qb->getQuery()->getResult(); return $qb->getQuery()->getResult();
} }
public function findUserJobByAssociated(Person|AccompanyingPeriod $associated): array public function findUserJobByAssociated(AccompanyingPeriod|Person $associated): array
{ {
$in = $this->em->createQueryBuilder(); $in = $this->em->createQueryBuilder();
$in->select('IDENTITY(u.userJob)') $in->select('IDENTITY(u.job)')
->from(User::class, 'u') ->distinct()
->from(User\UserJobHistory::class, 'u')
->join( ->join(
Activity::class, Activity::class,
'a', 'a',
Join::WITH, Join::WITH,
'a.createdBy = u OR a.user = u OR u MEMBER OF a.users' 'a.createdBy = u.user OR a.user = u.user OR u.user MEMBER OF a.users AND a.date >= u.startDate ANd (u.endDate IS NULL or u.endDate > a.date)'
); );
if ($associated instanceof Person) { if ($associated instanceof Person) {
@ -203,7 +220,6 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
return $qb->getQuery()->getResult(); return $qb->getQuery()->getResult();
} }
public function findByAccompanyingPeriodSimplified(AccompanyingPeriod $period, ?int $limit = 1000): array public function findByAccompanyingPeriodSimplified(AccompanyingPeriod $period, ?int $limit = 1000): array
{ {
$rsm = new ResultSetMappingBuilder($this->em); $rsm = new ResultSetMappingBuilder($this->em);
@ -291,7 +307,7 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
$qb = $this->filterBaseQueryByPerson($qb, $person, $role); $qb = $this->filterBaseQueryByPerson($qb, $person, $role);
foreach ($orderBy as $field => $direction) { foreach ($orderBy as $field => $direction) {
$qb->addOrderBy('a.' . $field, $direction); $qb->addOrderBy('a.'.$field, $direction);
} }
if (null !== $start) { if (null !== $start) {
@ -318,7 +334,7 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
$orX->add(sprintf('a.person = :person AND a.scope IN (:scopes_%d)', $counter)); $orX->add(sprintf('a.person = :person AND a.scope IN (:scopes_%d)', $counter));
$qb->setParameter(sprintf('scopes_%d', $counter), $scopes); $qb->setParameter(sprintf('scopes_%d', $counter), $scopes);
$qb->setParameter('person', $person); $qb->setParameter('person', $person);
$counter++; ++$counter;
} }
foreach ($person->getAccompanyingPeriodParticipations() as $participation) { foreach ($person->getAccompanyingPeriodParticipations() as $participation) {
@ -341,7 +357,7 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
->setParameter(sprintf('participation_end_%d', $counter), $participation->getEndDate()); ->setParameter(sprintf('participation_end_%d', $counter), $participation->getEndDate());
} }
$orX->add($and); $orX->add($and);
$counter++; ++$counter;
} }
if (0 === $orX->count()) { if (0 === $orX->count()) {
@ -362,10 +378,10 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
return [ return [
'id' => $metadataActivity->getTableName() 'id' => $metadataActivity->getTableName()
. '.' . $metadataActivity->getColumnName('id'), .'.'.$metadataActivity->getColumnName('id'),
'type' => 'activity', 'type' => 'activity',
'date' => $metadataActivity->getTableName() 'date' => $metadataActivity->getTableName()
. '.' . $metadataActivity->getColumnName('date'), .'.'.$metadataActivity->getColumnName('date'),
'FROM' => $from, 'FROM' => $from,
'WHERE' => $where, 'WHERE' => $where,
'parameters' => $parameters, 'parameters' => $parameters,
@ -378,12 +394,12 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
$metadataPerson = $this->em->getClassMetadata(Person::class); $metadataPerson = $this->em->getClassMetadata(Person::class);
$associationMapping = $metadataActivity->getAssociationMapping('person'); $associationMapping = $metadataActivity->getAssociationMapping('person');
return $metadataActivity->getTableName() . ' JOIN ' return $metadataActivity->getTableName().' JOIN '
. $metadataPerson->getTableName() . ' ON ' .$metadataPerson->getTableName().' ON '
. $metadataPerson->getTableName() . '.' . .$metadataPerson->getTableName().'.'.
$associationMapping['joinColumns'][0]['referencedColumnName'] $associationMapping['joinColumns'][0]['referencedColumnName']
. ' = ' .' = '
. $associationMapping['joinColumns'][0]['name']; .$associationMapping['joinColumns'][0]['name'];
} }
private function getWhereClause(string $context, array $args): array private function getWhereClause(string $context, array $args): array
@ -402,7 +418,7 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
ActivityVoter::SEE ActivityVoter::SEE
); );
if (count($reachableCenters) === 0) { if (0 === \count($reachableCenters)) {
// insert a dummy condition // insert a dummy condition
return 'FALSE = TRUE'; return 'FALSE = TRUE';
} }
@ -419,7 +435,7 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
foreach ($reachableCenters as $center) { foreach ($reachableCenters as $center) {
// we pass if not in centers // we pass if not in centers
if (!in_array($center, $args['centers'], true)) { if (!\in_array($center, $args['centers'], true)) {
continue; continue;
} }
// we get all the reachable scopes for this center // we get all the reachable scopes for this center
@ -441,7 +457,7 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
// begin loop for scopes // begin loop for scopes
$where .= ' AND ('; $where .= ' AND (';
$scopesI = 0; //like scope#i $scopesI = 0; // like scope#i
foreach ($reachablesScopesId as $scopeId) { foreach ($reachablesScopesId as $scopeId) {
if (0 < $scopesI) { if (0 < $scopesI) {

View File

@ -22,8 +22,8 @@ interface ActivityACLAwareRepositoryInterface
/** /**
* Return all the activities associated to an accompanying period and that the user is allowed to apply the given role. * Return all the activities associated to an accompanying period and that the user is allowed to apply the given role.
* *
*
* @param array{my_activities?: bool, types?: array<ActivityType>, jobs?: array<UserJob>, after?: \DateTimeImmutable|null, before?: \DateTimeImmutable|null} $filters * @param array{my_activities?: bool, types?: array<ActivityType>, jobs?: array<UserJob>, after?: \DateTimeImmutable|null, before?: \DateTimeImmutable|null} $filters
*
* @return array<Activity> * @return array<Activity>
*/ */
public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): array; public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): array;
@ -49,20 +49,20 @@ interface ActivityACLAwareRepositoryInterface
/** /**
* @param array{my_activities?: bool, types?: array<ActivityType>, jobs?: array<UserJob>, after?: \DateTimeImmutable|null, before?: \DateTimeImmutable|null} $filters * @param array{my_activities?: bool, types?: array<ActivityType>, jobs?: array<UserJob>, after?: \DateTimeImmutable|null, before?: \DateTimeImmutable|null} $filters
*
* @return array<Activity> * @return array<Activity>
*/ */
public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): array; public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): array;
/** /**
* Return a list of the type for the activities associated to person or accompanying period * Return a list of the type for the activities associated to person or accompanying period.
* *
* @return array<ActivityType> * @return array<ActivityType>
*/ */
public function findActivityTypeByAssociated(AccompanyingPeriod|Person $associated): array; public function findActivityTypeByAssociated(AccompanyingPeriod|Person $associated): array;
/** /**
* Return a list of the user job for the activities associated to person or accompanying period * Return a list of the user job for the activities associated to person or accompanying period.
* *
* Associated mean the job: * Associated mean the job:
* - of the creator; * - of the creator;

View File

@ -15,25 +15,15 @@ use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter; use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Chill\ActivityBundle\Service\GenericDoc\Providers\AccompanyingPeriodActivityGenericDocProvider; use Chill\ActivityBundle\Service\GenericDoc\Providers\AccompanyingPeriodActivityGenericDocProvider;
use Chill\ActivityBundle\Service\GenericDoc\Providers\PersonActivityGenericDocProvider; use Chill\ActivityBundle\Service\GenericDoc\Providers\PersonActivityGenericDocProvider;
use Chill\DocStoreBundle\Entity\PersonDocument;
use Chill\DocStoreBundle\Entity\StoredObject; use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\GenericDoc\FetchQuery; use Chill\DocStoreBundle\GenericDoc\FetchQuery;
use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface; use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface;
use Chill\DocStoreBundle\GenericDoc\Providers\PersonDocumentGenericDocProvider;
use Chill\DocStoreBundle\Repository\PersonDocumentACLAwareRepositoryInterface;
use Chill\DocStoreBundle\Security\Authorization\PersonDocumentVoter;
use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Security\Authorization\AuthorizationHelperForCurrentUserInterface; use Chill\MainBundle\Security\Authorization\AuthorizationHelperForCurrentUserInterface;
use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface; use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter;
use DateTimeImmutable;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\MappingException;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\HttpKernel\HttpCache\Store;
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
final readonly class ActivityDocumentACLAwareRepository implements ActivityDocumentACLAwareRepositoryInterface final readonly class ActivityDocumentACLAwareRepository implements ActivityDocumentACLAwareRepositoryInterface
@ -45,14 +35,14 @@ final readonly class ActivityDocumentACLAwareRepository implements ActivityDocum
private Security $security private Security $security
) {} ) {}
public function buildFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQueryInterface public function buildFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, \DateTimeImmutable $startDate = null, \DateTimeImmutable $endDate = null, string $content = null): FetchQueryInterface
{ {
$query = $this->buildBaseFetchQueryActivityDocumentLinkedToPersonFromPersonContext($person, $startDate, $endDate, $content); $query = $this->buildBaseFetchQueryActivityDocumentLinkedToPersonFromPersonContext($person, $startDate, $endDate, $content);
return $this->addFetchQueryByPersonACL($query, $person); return $this->addFetchQueryByPersonACL($query, $person);
} }
public function buildBaseFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery public function buildBaseFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, \DateTimeImmutable $startDate = null, \DateTimeImmutable $endDate = null, string $content = null): FetchQuery
{ {
$storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class); $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class);
$activityMetadata = $this->em->getClassMetadata(Activity::class); $activityMetadata = $this->em->getClassMetadata(Activity::class);
@ -81,7 +71,7 @@ final readonly class ActivityDocumentACLAwareRepository implements ActivityDocum
return $this->addWhereClauses($query, $startDate, $endDate, $content); return $this->addWhereClauses($query, $startDate, $endDate, $content);
} }
public function buildFetchQueryActivityDocumentLinkedToAccompanyingPeriodFromPersonContext(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery public function buildFetchQueryActivityDocumentLinkedToAccompanyingPeriodFromPersonContext(Person $person, \DateTimeImmutable $startDate = null, \DateTimeImmutable $endDate = null, string $content = null): FetchQuery
{ {
$storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class); $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class);
$activityMetadata = $this->em->getClassMetadata(Activity::class); $activityMetadata = $this->em->getClassMetadata(Activity::class);
@ -116,8 +106,8 @@ final readonly class ActivityDocumentACLAwareRepository implements ActivityDocum
$storedObjectMetadata->getColumnName('createdAt') $storedObjectMetadata->getColumnName('createdAt')
); );
$orParams = [...$orParams, $participation->getAccompanyingPeriod()->getId(), $orParams = [...$orParams, $participation->getAccompanyingPeriod()->getId(),
DateTimeImmutable::createFromInterface($participation->getStartDate()), \DateTimeImmutable::createFromInterface($participation->getStartDate()),
null === $participation->getEndDate() ? null : DateTimeImmutable::createFromInterface($participation->getEndDate())]; null === $participation->getEndDate() ? null : \DateTimeImmutable::createFromInterface($participation->getEndDate())];
$orTypes = [...$orTypes, Types::INTEGER, Types::DATE_IMMUTABLE, Types::DATE_IMMUTABLE]; $orTypes = [...$orTypes, Types::INTEGER, Types::DATE_IMMUTABLE, Types::DATE_IMMUTABLE];
} }
@ -132,7 +122,7 @@ final readonly class ActivityDocumentACLAwareRepository implements ActivityDocum
return $this->addWhereClauses($query, $startDate, $endDate, $content); return $this->addWhereClauses($query, $startDate, $endDate, $content);
} }
private function addWhereClauses(FetchQuery $query, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery private function addWhereClauses(FetchQuery $query, \DateTimeImmutable $startDate = null, \DateTimeImmutable $endDate = null, string $content = null): FetchQuery
{ {
$storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class); $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class);
@ -155,7 +145,7 @@ final readonly class ActivityDocumentACLAwareRepository implements ActivityDocum
if (null !== $content and '' !== $content) { if (null !== $content and '' !== $content) {
$query->addWhereClause( $query->addWhereClause(
'stored_obj.title ilike ?', 'stored_obj.title ilike ?',
['%' . $content . '%'], ['%'.$content.'%'],
[Types::STRING] [Types::STRING]
); );
} }
@ -172,7 +162,7 @@ final readonly class ActivityDocumentACLAwareRepository implements ActivityDocum
foreach ($this->centerResolverManager->resolveCenters($person) as $center) { foreach ($this->centerResolverManager->resolveCenters($person) as $center) {
$reachableScopes = [ $reachableScopes = [
...$reachableScopes, ...$reachableScopes,
...$this->authorizationHelperForCurrentUser->getReachableScopes(ActivityVoter::SEE, $center) ...$this->authorizationHelperForCurrentUser->getReachableScopes(ActivityVoter::SEE, $center),
]; ];
} }

View File

@ -14,24 +14,23 @@ namespace Chill\ActivityBundle\Repository;
use Chill\DocStoreBundle\GenericDoc\FetchQuery; use Chill\DocStoreBundle\GenericDoc\FetchQuery;
use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface; use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface;
use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\Person;
use DateTimeImmutable;
/** /**
* Gives queries usable for fetching documents, with ACL aware * Gives queries usable for fetching documents, with ACL aware.
*/ */
interface ActivityDocumentACLAwareRepositoryInterface interface ActivityDocumentACLAwareRepositoryInterface
{ {
/** /**
* Return a fetch query for querying document's activities for a person * Return a fetch query for querying document's activities for a person.
* *
* This method must check the rights to see a document: the user must be allowed to see the given activities * This method must check the rights to see a document: the user must be allowed to see the given activities
*/ */
public function buildFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQueryInterface; public function buildFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, \DateTimeImmutable $startDate = null, \DateTimeImmutable $endDate = null, string $content = null): FetchQueryInterface;
/** /**
* Return a fetch query for querying document's activities for an activity in accompanying periods, but for a given person * Return a fetch query for querying document's activities for an activity in accompanying periods, but for a given person.
* *
* This method must check the rights to see a document: the user must be allowed to see the given accompanying periods * This method must check the rights to see a document: the user must be allowed to see the given accompanying periods
*/ */
public function buildFetchQueryActivityDocumentLinkedToAccompanyingPeriodFromPersonContext(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery; public function buildFetchQueryActivityDocumentLinkedToAccompanyingPeriodFromPersonContext(Person $person, \DateTimeImmutable $startDate = null, \DateTimeImmutable $endDate = null, string $content = null): FetchQuery;
} }

View File

@ -17,7 +17,7 @@ use Doctrine\ORM\EntityRepository;
class ActivityPresenceRepository implements ActivityPresenceRepositoryInterface class ActivityPresenceRepository implements ActivityPresenceRepositoryInterface
{ {
private EntityRepository $repository; private readonly EntityRepository $repository;
public function __construct(EntityManagerInterface $entityManager) public function __construct(EntityManagerInterface $entityManager)
{ {
@ -34,7 +34,7 @@ class ActivityPresenceRepository implements ActivityPresenceRepositoryInterface
return $this->repository->findAll(); return $this->repository->findAll();
} }
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array public function findBy(array $criteria, array $orderBy = null, int $limit = null, int $offset = null): array
{ {
return $this->findBy($criteria, $orderBy, $limit, $offset); return $this->findBy($criteria, $orderBy, $limit, $offset);
} }

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