mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-07-01 06:26:15 +00:00
Merge remote-tracking branch 'origin/master' into doc/authorizaton-documentation-update
This commit is contained in:
commit
98760bc5e8
45
CHANGELOG.md
45
CHANGELOG.md
@ -12,12 +12,45 @@ and this project adheres to
|
||||
|
||||
<!-- write down unreleased development here -->
|
||||
|
||||
* [task] Select2 field in task form to allow search for a user (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/167)
|
||||
* remove "search by phone configuration option": search by phone is now executed by default
|
||||
* remplacer le classement par ordre alphabétique par un classement par ordre de pertinence, qui tient compte:
|
||||
* de la présence d'une string avec le nom de la ville;
|
||||
* de la similarité;
|
||||
* du fait que la recherche commence par une partie du mot recherché
|
||||
* ajouter la recherche par numéro de téléphone directement dans la barre de recherche et dans le formulaire recherche avancée;
|
||||
* ajouter la recherche par date de naissance directement dans la barre de recherche;
|
||||
* ajouter la recherche par ville dans la recherche avancée
|
||||
* ajouter un lien vers le ménage dans les résultats de recherche
|
||||
* ajouter l'id du parcours dans les résultats de recherche
|
||||
* ajouter le demandeur dans les résultats de recherche
|
||||
* ajout d'un bouton "recherche avancée" sur la page d'accueil
|
||||
* [person] create an accompanying course: add client-side validation if no origin (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/210)
|
||||
* [person] fix bounds for computing current person address: the new address appears immediatly
|
||||
* [docgen] create a normalizer and serializer for normalization on doc format
|
||||
|
||||
|
||||
## Test releases
|
||||
|
||||
### Test release 2021-11-15
|
||||
|
||||
* [main] fix adding multiple AddresseDeRelais (combine PickAddressType with ChillCollection)
|
||||
* [person]: do not suggest the current household of the person (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/51)
|
||||
* [person]: display other phone numbers in view + add message in case no others phone numbers (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/184)
|
||||
* unnecessary whitespace removed from person banner after person-id + double parentheses removed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/290)
|
||||
* [person]: delete accompanying period work, including related objects (cascade) (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/36)
|
||||
* [address]: Display of incomplete address adjusted.
|
||||
* [household]: improve relationship graph
|
||||
* add form to create/edit/delete relationship link,
|
||||
* improve graph refresh mechanism
|
||||
* add feature to export canvas as image (png)
|
||||
* [person suggest] In widget "add person", improve the pertinence of persons when one of the names starts with the pattern;
|
||||
* [person] do not ask for center any more on person creation
|
||||
* [3party] do not ask for center any more on 3party creation
|
||||
|
||||
### Test release 2021-11-08
|
||||
|
||||
* [person]: Display the name of a user when searching after a User (TMS)
|
||||
* [person]: Add civility to the person
|
||||
* [person]: Various improvements on the edit person form
|
||||
* [person]: Set available_languages and available_countries as parameters for use in the edit person form
|
||||
@ -42,10 +75,9 @@ and this project adheres to
|
||||
* [tasks]: different layout for task list / my tasks, and fix link to tasks in alert or in warning
|
||||
* [admin]: links to activity admin section added again.
|
||||
* [household]: household addresses ordered by ValidFrom date and by id to show the last created address on top.
|
||||
* [socialWorkAction]: display of social issue and parent issues + banner context added.
|
||||
* [socialWorkAction]: display of social issue and parent issues + banner context added.
|
||||
* [DBAL dependencies] Upgrade to DBAL 3.1
|
||||
|
||||
|
||||
### Test release 2021-10-27
|
||||
|
||||
* [person]: delete double actions buttons on search person page
|
||||
@ -63,7 +95,10 @@ and this project adheres to
|
||||
* [3party]: fix address creation
|
||||
* [household members editor] finalisation of editor
|
||||
* [AccompanyingCourse banner]: replace translation referrer (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/70)
|
||||
* [Location]: add location system in activity and RV (calendar). User can choose in location list or create a new location.
|
||||
* [Location]: add location system in activity and RV (calendar). User can choose in location list or create a new location.
|
||||
* [household]: add relationship page with dynamic data visualisation graph
|
||||
|
||||
## Test releases
|
||||
|
||||
### Test release 2021-10-11
|
||||
|
||||
@ -130,7 +165,7 @@ and this project adheres to
|
||||
|
||||
## Test released
|
||||
|
||||
<!--
|
||||
<!--
|
||||
|
||||
Coming soon...
|
||||
|
||||
@ -143,4 +178,4 @@ DO NOT ADD unreleased items here. Add them under "Unreleased" title
|
||||
## Stable releases
|
||||
|
||||
No stable releases for v2+
|
||||
|
||||
|
||||
|
@ -54,6 +54,9 @@
|
||||
"doctrine/doctrine-fixtures-bundle": "^3.3",
|
||||
"fakerphp/faker": "^1.13",
|
||||
"nelmio/alice": "^3.8",
|
||||
"phpstan/extension-installer": "^1.1",
|
||||
"phpstan/phpstan": "^1.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.0",
|
||||
"phpunit/phpunit": "^7.0",
|
||||
"symfony/debug-bundle": "^5.1",
|
||||
"symfony/dotenv": "^5.1",
|
||||
@ -88,7 +91,8 @@
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"App\\": "tests/app/src/"
|
||||
"App\\": "tests/app/src/",
|
||||
"Chill\\DocGeneratorBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
|
111
phpstan-baseline.neon
Normal file
111
phpstan-baseline.neon
Normal file
@ -0,0 +1,111 @@
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
-
|
||||
message: "#^Variable property access on \\$this\\(Chill\\\\ActivityBundle\\\\Entity\\\\ActivityType\\)\\.$#"
|
||||
count: 3
|
||||
path: src/Bundle/ChillActivityBundle/Entity/ActivityType.php
|
||||
|
||||
-
|
||||
message: "#^Foreach overwrites \\$key with its key variable\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/Controller/CustomFieldsGroupController.php
|
||||
|
||||
-
|
||||
message: "#^Instantiated class PhpOffice\\\\PhpWord\\\\TemplateProcessor not found\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorController.php
|
||||
|
||||
-
|
||||
message: "#^Instantiated class PhpOffice\\\\PhpWord\\\\TemplateProcessor not found\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorTemplateController.php
|
||||
|
||||
-
|
||||
message: "#^Variable \\$participation might not be defined\\.$#"
|
||||
count: 3
|
||||
path: src/Bundle/ChillEventBundle/Controller/ParticipationController.php
|
||||
|
||||
-
|
||||
message: "#^Foreach overwrites \\$value with its value variable\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillEventBundle/Form/ChoiceLoader/EventChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Variable method call on object\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillMainBundle/CRUD/Controller/ApiController.php
|
||||
|
||||
-
|
||||
message: "#^Cannot unset offset '_token' on array\\{formatter\\: mixed, export\\: mixed, centers\\: mixed, alias\\: string\\}\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Controller/ExportController.php
|
||||
|
||||
-
|
||||
message: "#^Foreach overwrites \\$line with its value variable\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillMainBundle/Export/Formatter/CSVFormatter.php
|
||||
|
||||
-
|
||||
message: "#^Foreach overwrites \\$key with its key variable\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Export/Formatter/SpreadSheetFormatter.php
|
||||
|
||||
-
|
||||
message: "#^Foreach overwrites \\$key with its value variable\\.$#"
|
||||
count: 3
|
||||
path: src/Bundle/ChillMainBundle/Export/Formatter/SpreadSheetFormatter.php
|
||||
|
||||
-
|
||||
message: "#^Foreach overwrites \\$value with its value variable\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Form/ChoiceLoader/PostalCodeChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Variable \\$message on left side of \\?\\? always exists and is not nullable\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Templating/ChillTwigHelper.php
|
||||
|
||||
-
|
||||
message: "#^Variable \\$sqls on left side of \\?\\? always exists and is not nullable\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php
|
||||
|
||||
-
|
||||
message: "#^Class Chill\\\\PersonBundle\\\\Entity\\\\Person constructor invoked with 1 parameter, 0 required\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
||||
|
||||
-
|
||||
message: "#^Variable \\$street1Value might not be defined\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
||||
|
||||
-
|
||||
message: "#^Variable method call on mixed\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php
|
||||
|
||||
-
|
||||
message: "#^Foreach overwrites \\$value with its value variable\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Form/ChoiceLoader/PersonChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Foreach overwrites \\$action with its value variable\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
|
||||
|
||||
-
|
||||
message: "#^Foreach overwrites \\$action with its value variable\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Repository/SocialWork/GoalRepository.php
|
||||
|
||||
-
|
||||
message: "#^Foreach overwrites \\$action with its value variable\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Repository/SocialWork/ResultRepository.php
|
||||
|
||||
-
|
||||
message: "#^Foreach overwrites \\$value with its value variable\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillThirdPartyBundle/Form/ChoiceLoader/ThirdPartyChoiceLoader.php
|
131
phpstan-critical.neon
Normal file
131
phpstan-critical.neon
Normal file
@ -0,0 +1,131 @@
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
-
|
||||
message: "#^Implicit array creation is not allowed \\- variable \\$centers might not exist\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php
|
||||
|
||||
-
|
||||
message: "#^Access to an undefined property Chill\\\\PersonBundle\\\\Entity\\\\Person\\:\\:\\$currentHouseholdParticipationAt\\.$#"
|
||||
count: 3
|
||||
path: src/Bundle/ChillPersonBundle/Entity/Person.php
|
||||
|
||||
-
|
||||
message: "#^Access to an undefined property Chill\\\\PersonBundle\\\\Entity\\\\Household\\\\PersonHouseholdAddress\\:\\:\\$relation\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Entity/Household/PersonHouseholdAddress.php
|
||||
|
||||
-
|
||||
message: "#^Access to an undefined property Chill\\\\PersonBundle\\\\Entity\\\\AccompanyingPeriod\\:\\:\\$work\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php
|
||||
|
||||
-
|
||||
message: "#^Undefined variable\\: \\$person$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php
|
||||
|
||||
-
|
||||
message: "#^Access to an undefined property Chill\\\\PersonBundle\\\\Household\\\\MembersEditorFactory\\:\\:\\$validator\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillPersonBundle/Household/MembersEditorFactory.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\$action of method Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\AccompanyingPeriodWorkRepository\\:\\:buildQueryBySocialActionWithDescendants\\(\\) has invalid type Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\SocialAction\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\$action of method Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\AccompanyingPeriodWorkRepository\\:\\:countBySocialActionWithDescendants\\(\\) has invalid type Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\SocialAction\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
|
||||
|
||||
-
|
||||
message: "#^Undefined variable\\: \\$action$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
|
||||
|
||||
-
|
||||
message: "#^Undefined variable\\: \\$limit$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
|
||||
|
||||
-
|
||||
message: "#^Undefined variable\\: \\$offset$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
|
||||
|
||||
-
|
||||
message: "#^Undefined variable\\: \\$orderBy$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
|
||||
|
||||
-
|
||||
message: "#^Variable variables are not allowed\\.$#"
|
||||
count: 4
|
||||
path: src/Bundle/ChillPersonBundle/Search/PersonSearch.php
|
||||
|
||||
-
|
||||
message: "#^Function Chill\\\\PersonBundle\\\\Serializer\\\\Normalizer\\\\·\\\\is_array not found\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Serializer/Normalizer/MembersEditorNormalizer.php
|
||||
|
||||
-
|
||||
message: "#^Undefined variable\\: \\$value$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Validator/Constraints/AccompanyingPeriod/LocationValidityValidator.php
|
||||
|
||||
-
|
||||
message: "#^Undefined variable\\: \\$choiceSlug$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php
|
||||
|
||||
-
|
||||
message: "#^Undefined variable\\: \\$choiceSlug$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillReportBundle/Export/Export/ReportList.php
|
||||
|
||||
-
|
||||
message: "#^Undefined variable\\: \\$type$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillTaskBundle/Controller/TaskController.php
|
||||
|
||||
-
|
||||
message: "#^Call to an undefined method Chill\\\\MainBundle\\\\CRUD\\\\Controller\\\\AbstractCRUDController\\:\\:getRoleFor\\(\\)\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/CRUD/Controller/AbstractCRUDController.php
|
||||
|
||||
-
|
||||
message: "#^Call to an undefined method Chill\\\\MainBundle\\\\Controller\\\\UserController\\:\\:createEditForm\\(\\)\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Controller/UserController.php
|
||||
|
||||
-
|
||||
message: "#^Undefined variable\\: \\$current$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Pagination/PageGenerator.php
|
||||
|
||||
-
|
||||
message: "#^Call to an undefined method Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AbstractChillVoter\\:\\:getSupportedAttributes\\(\\)\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Security/Authorization/AbstractChillVoter.php
|
||||
|
||||
-
|
||||
message: "#^Call to an undefined method Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AbstractChillVoter\\:\\:getSupportedClasses\\(\\)\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Security/Authorization/AbstractChillVoter.php
|
||||
|
||||
-
|
||||
message: "#^Call to an undefined method Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AbstractChillVoter\\:\\:isGranted\\(\\)\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Security/Authorization/AbstractChillVoter.php
|
||||
|
||||
-
|
||||
message: "#^Access to an undefined property Chill\\\\PersonBundle\\\\Controller\\\\PersonController\\:\\:\\$security\\.$#"
|
||||
count: 3
|
||||
path: src/Bundle/ChillPersonBundle/Controller/PersonController.php
|
||||
|
||||
-
|
||||
message: "#^Call to an undefined method Chill\\\\ThirdPartyBundle\\\\Form\\\\Type\\\\PickThirdPartyTypeCategoryType\\:\\:transform\\(\\)\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillThirdPartyBundle/Form/Type/PickThirdPartyTypeCategoryType.php
|
852
phpstan-types.neon
Normal file
852
phpstan-types.neon
Normal file
@ -0,0 +1,852 @@
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/DataFixtures/ORM/LoadActivitytACL.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Entity/Activity.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Entity/ActivityReason.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Entity/ActivityReasonCategory.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Export/ListActivity.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\ActivityBundle\\\\Export\\\\Export\\\\StatActivityDuration\\:\\:getDescription\\(\\) should return string but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Export/StatActivityDuration.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\ActivityBundle\\\\Export\\\\Export\\\\StatActivityDuration\\:\\:getTitle\\(\\) should return string but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Export/StatActivityDuration.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Form/ActivityType.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Form/ActivityType.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in &&, mixed given on the right side\\.$#"
|
||||
count: 3
|
||||
path: src/Bundle/ChillActivityBundle/Form/ActivityType.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillActivityBundle/Form/ActivityType.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Menu/AdminMenuBuilder.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Security/Authorization/ActivityStatsVoter.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillActivityBundle/Timeline/TimelineActivityProvider.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillAsideActivityBundle/src/Form/AsideActivityFormType.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillAsideActivityBundle/src/Menu/AdminMenuBuilder.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 3
|
||||
path: src/Bundle/ChillBudgetBundle/Form/ChargeType.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillBudgetBundle/Form/ResourceType.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillBudgetBundle/Security/Authorization/BudgetElementVoter.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCalendarBundle/Entity/Calendar.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/Command/CreateFieldsOnGroupCommand.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/Controller/CustomFieldsGroupController.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/AbstractCustomField.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 3
|
||||
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldChoice.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 4
|
||||
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldChoice.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldChoice\\:\\:buildForm\\(\\) should return Symfony\\\\Component\\\\Form\\\\FormTypeInterface but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldChoice.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldDate.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldDate\\:\\:buildForm\\(\\) should return Symfony\\\\Component\\\\Form\\\\FormTypeInterface but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldDate.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldLongChoice\\:\\:buildForm\\(\\) should return Symfony\\\\Component\\\\Form\\\\FormTypeInterface but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldLongChoice.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldNumber.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldNumber\\:\\:buildForm\\(\\) should return Symfony\\\\Component\\\\Form\\\\FormTypeInterface but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldNumber.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldText\\:\\:buildForm\\(\\) should return Symfony\\\\Component\\\\Form\\\\FormTypeInterface but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldText.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldTitle\\:\\:buildForm\\(\\) should return Symfony\\\\Component\\\\Form\\\\FormTypeInterface but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldTitle.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/Entity/CustomField.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/Entity/CustomFieldsGroup.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in a negated boolean, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/Form/CustomFieldType.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillDocStoreBundle/Entity/DocumentCategory.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillEventBundle/Entity/Participation.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\EventBundle\\\\Entity\\\\Participation\\:\\:offsetGet\\(\\) should return mixed but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillEventBundle/Entity/Participation.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillEventBundle/Form/ChoiceLoader/EventChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillEventBundle/Form/ChoiceLoader/EventChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\$resolver of method Chill\\\\EventBundle\\\\Form\\\\EventTypeType\\:\\:setDefaultOptions\\(\\) has invalid type Symfony\\\\Component\\\\OptionsResolver\\\\OptionsResolverInterface\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillEventBundle/Form/EventTypeType.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\$resolver of method Chill\\\\EventBundle\\\\Form\\\\RoleType\\:\\:setDefaultOptions\\(\\) has invalid type Symfony\\\\Component\\\\OptionsResolver\\\\OptionsResolverInterface\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillEventBundle/Form/RoleType.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\$resolver of method Chill\\\\EventBundle\\\\Form\\\\StatusType\\:\\:setDefaultOptions\\(\\) has invalid type Symfony\\\\Component\\\\OptionsResolver\\\\OptionsResolverInterface\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillEventBundle/Form/StatusType.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillEventBundle/Form/Type/PickEventType.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillEventBundle/Search/EventSearch.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\EventBundle\\\\Search\\\\EventSearch\\:\\:renderResult\\(\\) should return string but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillEventBundle/Search/EventSearch.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillEventBundle/Security/Authorization/EventVoter.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillEventBundle/Security/Authorization/ParticipationVoter.php
|
||||
|
||||
-
|
||||
message: "#^Casting to string something that's already string\\.$#"
|
||||
count: 5
|
||||
path: src/Bundle/ChillFamilyMembersBundle/Entity/AbstractFamilyMember.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillFamilyMembersBundle/Form/FamilyMemberType.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillFamilyMembersBundle/Security/Voter/FamilyMemberVoter.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/CRUD/Controller/CRUDController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\$scope of method Chill\\\\MainBundle\\\\CRUD\\\\Controller\\\\CRUDController\\:\\:getReachableCenters\\(\\) has invalid type Chill\\\\MainBundle\\\\CRUD\\\\Controller\\\\Scope\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/CRUD/Controller/CRUDController.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/CRUD/Resolver/Resolver.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\MainBundle\\\\CRUD\\\\Resolver\\\\Resolver\\:\\:getConfigValue\\(\\) should return string but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/CRUD/Resolver/Resolver.php
|
||||
|
||||
-
|
||||
message: "#^Call to function array_search\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/CRUD/Routing/CRUDRoutesLoader.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillMainBundle/CRUD/Routing/CRUDRoutesLoader.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\MainBundle\\\\Command\\\\ChillImportUsersCommand\\:\\:execute\\(\\) should return int but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Command/ChillImportUsersCommand.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Command/ChillImportUsersCommand.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillMainBundle/Command/ChillUserSendRenewPasswordCodeCommand.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Command/ChillUserSendRenewPasswordCodeCommand.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\MainBundle\\\\Command\\\\ChillUserSendRenewPasswordCodeCommand\\:\\:execute\\(\\) should return int but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Command/ChillUserSendRenewPasswordCodeCommand.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillMainBundle/Command/LoadAndUpdateLanguagesCommand.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\MainBundle\\\\Command\\\\LoadAndUpdateLanguagesCommand\\:\\:execute\\(\\) should return int but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Command/LoadAndUpdateLanguagesCommand.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in a negated boolean, mixed given\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillMainBundle/Command/LoadAndUpdateLanguagesCommand.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\MainBundle\\\\Command\\\\LoadCountriesCommand\\:\\:execute\\(\\) should return int but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Command/LoadCountriesCommand.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\MainBundle\\\\Command\\\\LoadPostalCodesCommand\\:\\:execute\\(\\) should return int but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Command/LoadPostalCodesCommand.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\MainBundle\\\\Command\\\\SetPasswordCommand\\:\\:execute\\(\\) should return int but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Command/SetPasswordCommand.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Controller/PasswordController.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Controller/PostalCodeController.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadLanguages.php
|
||||
|
||||
-
|
||||
message: "#^Call to function array_search\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 5
|
||||
path: src/Bundle/ChillMainBundle/DependencyInjection/CompilerPass/ExportsCompilerPass.php
|
||||
|
||||
-
|
||||
message: "#^Call to function array_search\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/DependencyInjection/CompilerPass/SearchableServicesCompilerPass.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php
|
||||
|
||||
-
|
||||
message: "#^Call to function array_search\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/DependencyInjection/Widget/AbstractWidgetsCompilerPass.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/DependencyInjection/Widget/AbstractWidgetsCompilerPass.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/DependencyInjection/Widget/AbstractWidgetsCompilerPass.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Entity/Address.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Entity/Embeddable/CommentEmbeddable.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Entity/User.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Entity/User.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 6
|
||||
path: src/Bundle/ChillMainBundle/Export/ExportManager.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in a ternary operator condition, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Export/Formatter/SpreadsheetListFormatter.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Form/ChoiceLoader/PostalCodeChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Form/DataMapper/AddressDataMapper.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in a negated boolean, mixed given\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillMainBundle/Form/Type/AddressType.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillMainBundle/Form/Type/AddressType.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in a negated boolean, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Form/Type/ChillTextareaType.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Form/Type/ComposedRoleScopeType.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 3
|
||||
path: src/Bundle/ChillMainBundle/Form/Type/DataTransformer/DateIntervalTransformer.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in a negated boolean, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ObjectToIdTransformer.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Form/Type/Export/PickCenterType.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Form/Type/TranslatableStringFormType.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillMainBundle/Phonenumber/PhonenumberHelper.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillMainBundle/Phonenumber/PhonenumberHelper.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Search/Entity/SearchUserApiProvider.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillMainBundle/Security/Authorization/AbstractChillVoter.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelper.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillMainBundle/Security/ParentRoleHelper.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverEvent.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverVoter.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Security/PasswordRecover/TokenManager.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 3
|
||||
path: src/Bundle/ChillMainBundle/Templating/Entity/AddressRender.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Timeline/TimelineBuilder.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\MainBundle\\\\Timeline\\\\TimelineBuilder\\:\\:getTemplateData\\(\\) should return array but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Timeline/TimelineBuilder.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillMainBundle/Validation/Validator/RoleScopeScopePresence.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Validation/Validator/ValidPhonenumber.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/CRUD/Controller/OneToOneEntityPersonCRUDController.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Command/ChillPersonMoveCommand.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\PersonBundle\\\\Command\\\\ChillPersonMoveCommand\\:\\:execute\\(\\) should return int but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Command/ChillPersonMoveCommand.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Command/ChillPersonMoveCommand.php
|
||||
|
||||
-
|
||||
message: "#^Call to function array_search\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 3
|
||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 3
|
||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 6
|
||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Controller/PersonController.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/DependencyInjection/CompilerPass/AccompanyingPeriodTimelineCompilerPass.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Entity/Person.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillPersonBundle/Entity/PersonPhone.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillPersonBundle/Export/AbstractAccompanyingPeriodExportElement.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Aggregator/CountryOfBirthAggregator.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Aggregator/NationalityAggregator.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 3
|
||||
path: src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Filter/GenderFilter.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Form/ChoiceLoader/PersonChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Form/ChoiceLoader/PersonChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Form/DataMapper/PersonAltNameDataMapper.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in a ternary operator condition, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Form/Type/PersonAltNameType.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Form/Type/PersonPhoneType.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Form/Type/PickPersonType.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Household/MembersEditor.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\AccompanyingPeriodWorkRepository\\:\\:buildQueryBySocialActionWithDescendants\\(\\) has invalid return type Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\QueryBuilder\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillPersonBundle/Repository/PersonRepository.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 3
|
||||
path: src/Bundle/ChillPersonBundle/Search/PersonSearch.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\PersonBundle\\\\Search\\\\PersonSearch\\:\\:renderResult\\(\\) should return string but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Search/PersonSearch.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Search/SearchPersonApiProvider.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Serializer/Normalizer/AccompanyingPeriodWorkDenormalizer.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillPersonBundle/Templating/Entity/ClosingMotiveRender.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Timeline/AbstractTimelineAccompanyingPeriod.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillReportBundle/DataFixtures/ORM/LoadReportACL.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillReportBundle/DataFixtures/ORM/LoadReports.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\ReportBundle\\\\DataFixtures\\\\ORM\\\\LoadReports\\:\\:getRandomChoice\\(\\) should return array\\<string\\>\\|string but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillReportBundle/DataFixtures/ORM/LoadReports.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 4
|
||||
path: src/Bundle/ChillReportBundle/Export/Export/ReportList.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillReportBundle/Export/Export/ReportList.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillReportBundle/Security/Authorization/ReportVoter.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\ReportBundle\\\\Security\\\\Authorization\\\\ReportVoter\\:\\:supports\\(\\) should return bool but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillReportBundle/Security/Authorization/ReportVoter.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 4
|
||||
path: src/Bundle/ChillReportBundle/Timeline/TimelineReportProvider.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillTaskBundle/DataFixtures/ORM/LoadTaskACL.php
|
||||
|
||||
-
|
||||
message: "#^Casting to string something that's already string\\.$#"
|
||||
count: 3
|
||||
path: src/Bundle/ChillTaskBundle/Entity/AbstractTask.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillTaskBundle/Form/SingleTaskListType.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepository.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 5
|
||||
path: src/Bundle/ChillTaskBundle/Repository/SingleTaskRepository.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\TaskBundle\\\\Timeline\\\\SingleTaskTaskLifeCycleEventTimelineProvider\\:\\:getTransitionByName\\(\\) should return Symfony\\\\Component\\\\Workflow\\\\Transition but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillTaskBundle/Timeline/SingleTaskTaskLifeCycleEventTimelineProvider.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillTaskBundle/Timeline/TaskLifeCycleEventTimelineProvider.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\TaskBundle\\\\Timeline\\\\TaskLifeCycleEventTimelineProvider\\:\\:getTransitionByName\\(\\) should return Symfony\\\\Component\\\\Workflow\\\\Transition but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillTaskBundle/Timeline/TaskLifeCycleEventTimelineProvider.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillThirdPartyBundle/DependencyInjection/CompilerPass/ThirdPartyTypeCompilerPass.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 4
|
||||
path: src/Bundle/ChillThirdPartyBundle/Entity/ThirdParty.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillThirdPartyBundle/Form/ChoiceLoader/ThirdPartyChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillThirdPartyBundle/Form/ChoiceLoader/ThirdPartyChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillThirdPartyBundle/Repository/ThirdPartyRepository.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillThirdPartyBundle/Search/ThirdPartyApiSearch.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillThirdPartyBundle/Search/ThirdPartyApiSearch.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\ThirdPartyBundle\\\\Search\\\\ThirdPartySearch\\:\\:renderResult\\(\\) should return string but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillThirdPartyBundle/Search/ThirdPartySearch.php
|
||||
|
||||
-
|
||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillThirdPartyBundle/Security/Voter/ThirdPartyVoter.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillThirdPartyBundle/Templating/Entity/ThirdPartyRender.php
|
||||
|
24
phpstan.neon.dist
Normal file
24
phpstan.neon.dist
Normal file
@ -0,0 +1,24 @@
|
||||
parameters:
|
||||
level: 1
|
||||
paths:
|
||||
- src/
|
||||
excludePaths:
|
||||
- src/Bundle/*/Tests/*
|
||||
- src/Bundle/*/tests/*
|
||||
- src/Bundle/*/Test/*
|
||||
- src/Bundle/*/config/*
|
||||
- src/Bundle/*/migrations/*
|
||||
- src/Bundle/*/translations/*
|
||||
- src/Bundle/*/Resources/*
|
||||
- src/Bundle/*/src/Tests/*
|
||||
- src/Bundle/*/src/Test/*
|
||||
- src/Bundle/*/src/config/*
|
||||
- src/Bundle/*/src/migrations/*
|
||||
- src/Bundle/*/src/translations/*
|
||||
- src/Bundle/*/src/Resources/*
|
||||
|
||||
includes:
|
||||
- phpstan-types.neon
|
||||
- phpstan-critical.neon
|
||||
- phpstan-baseline.neon
|
||||
|
@ -37,6 +37,9 @@
|
||||
<testsuite name="CalendarBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillCalendarBundle/Tests/</directory>
|
||||
</testsuite>
|
||||
<testsuite name="DocGeneratorBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillDocGeneratorBundle/tests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<listeners>
|
||||
|
@ -1,37 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
||||
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Controller;
|
||||
|
||||
use Chill\ActivityBundle\Repository\ActivityACLAwareRepository;
|
||||
use Chill\ActivityBundle\Entity\ActivityReason;
|
||||
use Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface;
|
||||
use Chill\ActivityBundle\Repository\ActivityRepository;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeCategoryRepository;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Chill\MainBundle\Repository\LocationRepository;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Privacy\PrivacyEvent;
|
||||
use Chill\PersonBundle\Repository\AccompanyingPeriodRepository;
|
||||
use Chill\PersonBundle\Repository\PersonRepository;
|
||||
use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\Form;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
@ -42,33 +31,56 @@ use Chill\ActivityBundle\Form\ActivityType;
|
||||
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
|
||||
/**
|
||||
* Class ActivityController
|
||||
*
|
||||
* @package Chill\ActivityBundle\Controller
|
||||
*/
|
||||
class ActivityController extends AbstractController
|
||||
final class ActivityController extends AbstractController
|
||||
{
|
||||
protected EventDispatcherInterface $eventDispatcher;
|
||||
private EventDispatcherInterface $eventDispatcher;
|
||||
|
||||
protected AuthorizationHelper $authorizationHelper;
|
||||
private LoggerInterface $logger;
|
||||
|
||||
protected LoggerInterface $logger;
|
||||
private SerializerInterface $serializer;
|
||||
|
||||
protected SerializerInterface $serializer;
|
||||
private ActivityACLAwareRepositoryInterface $activityACLAwareRepository;
|
||||
|
||||
protected ActivityACLAwareRepositoryInterface $activityACLAwareRepository;
|
||||
private ActivityTypeRepository $activityTypeRepository;
|
||||
|
||||
private ThirdPartyRepository $thirdPartyRepository;
|
||||
|
||||
private PersonRepository $personRepository;
|
||||
|
||||
private LocationRepository $locationRepository;
|
||||
|
||||
private EntityManagerInterface $entityManager;
|
||||
|
||||
private ActivityRepository $activityRepository;
|
||||
|
||||
private AccompanyingPeriodRepository $accompanyingPeriodRepository;
|
||||
|
||||
private ActivityTypeCategoryRepository $activityTypeCategoryRepository;
|
||||
|
||||
public function __construct(
|
||||
ActivityACLAwareRepositoryInterface $activityACLAwareRepository,
|
||||
ActivityTypeRepository $activityTypeRepository,
|
||||
ActivityTypeCategoryRepository $activityTypeCategoryRepository,
|
||||
PersonRepository $personRepository,
|
||||
ThirdPartyRepository $thirdPartyRepository,
|
||||
LocationRepository $locationRepository,
|
||||
ActivityRepository $activityRepository,
|
||||
AccompanyingPeriodRepository $accompanyingPeriodRepository,
|
||||
EntityManagerInterface $entityManager,
|
||||
EventDispatcherInterface $eventDispatcher,
|
||||
AuthorizationHelper $authorizationHelper,
|
||||
LoggerInterface $logger,
|
||||
SerializerInterface $serializer
|
||||
) {
|
||||
$this->activityACLAwareRepository = $activityACLAwareRepository;
|
||||
$this->activityTypeRepository = $activityTypeRepository;
|
||||
$this->activityTypeCategoryRepository = $activityTypeCategoryRepository;
|
||||
$this->personRepository = $personRepository;
|
||||
$this->thirdPartyRepository = $thirdPartyRepository;
|
||||
$this->locationRepository = $locationRepository;
|
||||
$this->activityRepository = $activityRepository;
|
||||
$this->accompanyingPeriodRepository = $accompanyingPeriodRepository;
|
||||
$this->entityManager = $entityManager;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->authorizationHelper = $authorizationHelper;
|
||||
$this->logger = $logger;
|
||||
$this->serializer = $serializer;
|
||||
}
|
||||
@ -78,8 +90,8 @@ class ActivityController extends AbstractController
|
||||
*/
|
||||
public function listAction(Request $request): Response
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$view = null;
|
||||
$activities = [];
|
||||
// TODO: add pagination
|
||||
|
||||
[$person, $accompanyingPeriod] = $this->getEntity($request);
|
||||
@ -89,10 +101,10 @@ class ActivityController extends AbstractController
|
||||
$activities = $this->activityACLAwareRepository
|
||||
->findByPerson($person, ActivityVoter::SEE, 0, null);
|
||||
|
||||
$event = new PrivacyEvent($person, array(
|
||||
$event = new PrivacyEvent($person, [
|
||||
'element_class' => Activity::class,
|
||||
'action' => 'list'
|
||||
));
|
||||
]);
|
||||
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
|
||||
|
||||
$view = 'ChillActivityBundle:Activity:listPerson.html.twig';
|
||||
@ -105,16 +117,18 @@ class ActivityController extends AbstractController
|
||||
$view = 'ChillActivityBundle:Activity:listAccompanyingCourse.html.twig';
|
||||
}
|
||||
|
||||
return $this->render($view, array(
|
||||
'activities' => $activities,
|
||||
'person' => $person,
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
));
|
||||
return $this->render(
|
||||
$view,
|
||||
[
|
||||
'activities' => $activities,
|
||||
'person' => $person,
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function selectTypeAction(Request $request): Response
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$view = null;
|
||||
|
||||
[$person, $accompanyingPeriod] = $this->getEntity($request);
|
||||
@ -127,12 +141,17 @@ class ActivityController extends AbstractController
|
||||
|
||||
$data = [];
|
||||
|
||||
$activityTypeCategories = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityTypeCategory::class)
|
||||
$activityTypeCategories = $this
|
||||
->activityTypeCategoryRepository
|
||||
->findBy(['active' => true], ['ordering' => 'ASC']);
|
||||
|
||||
foreach ($activityTypeCategories as $activityTypeCategory) {
|
||||
$activityTypes = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityType::class)
|
||||
->findBy(['active' => true, 'category' => $activityTypeCategory], ['ordering' => 'ASC']);
|
||||
$activityTypes = $this
|
||||
->activityTypeRepository
|
||||
->findBy(
|
||||
['active' => true, 'category' => $activityTypeCategory],
|
||||
['ordering' => 'ASC']
|
||||
);
|
||||
|
||||
$data[] = [
|
||||
'activityTypeCategory' => $activityTypeCategory,
|
||||
@ -140,12 +159,6 @@ class ActivityController extends AbstractController
|
||||
];
|
||||
}
|
||||
|
||||
if ($request->query->has('activityData')) {
|
||||
$activityData = $request->query->get('activityData');
|
||||
} else {
|
||||
$activityData = [];
|
||||
}
|
||||
|
||||
if ($view === null) {
|
||||
throw $this->createNotFoundException('Template not found');
|
||||
}
|
||||
@ -154,13 +167,13 @@ class ActivityController extends AbstractController
|
||||
'person' => $person,
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
'data' => $data,
|
||||
'activityData' => $activityData
|
||||
'activityData' => $request->query->get('activityData', []),
|
||||
]);
|
||||
}
|
||||
|
||||
public function newAction(Request $request): Response
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$view = null;
|
||||
|
||||
[$person, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
@ -171,8 +184,7 @@ class ActivityController extends AbstractController
|
||||
}
|
||||
|
||||
$activityType_id = $request->get('activityType_id', 0);
|
||||
$activityType = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityType::class)
|
||||
->find($activityType_id);
|
||||
$activityType = $this->activityTypeRepository->find($activityType_id);
|
||||
|
||||
if (isset($activityType) && !$activityType->isActive()) {
|
||||
throw new \InvalidArgumentException('Activity type must be active');
|
||||
@ -230,23 +242,23 @@ class ActivityController extends AbstractController
|
||||
|
||||
if (array_key_exists('personsId', $activityData)) {
|
||||
foreach($activityData['personsId'] as $personId){
|
||||
$concernedPerson = $em->getRepository(\Chill\PersonBundle\Entity\Person::class)->find($personId);
|
||||
$concernedPerson = $this->personRepository->find($personId);
|
||||
$entity->addPerson($concernedPerson);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('professionalsId', $activityData)) {
|
||||
foreach($activityData['professionalsId'] as $professionalsId){
|
||||
$professional = $em->getRepository(\Chill\ThirdPartyBundle\Entity\ThirdParty::class)->find($professionalsId);
|
||||
$professional = $this->thirdPartyRepository->find($professionalsId);
|
||||
$entity->addThirdParty($professional);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('location', $activityData)) {
|
||||
$location = $em->getRepository(\Chill\MainBundle\Entity\Location::class)->find($activityData['location']);
|
||||
$location = $this->locationRepository->find($activityData['location']);
|
||||
$entity->setLocation($location);
|
||||
}
|
||||
|
||||
|
||||
if (array_key_exists('comment', $activityData)) {
|
||||
$comment = new CommentEmbeddable();
|
||||
$comment->setComment($activityData['comment']);
|
||||
@ -268,8 +280,8 @@ class ActivityController extends AbstractController
|
||||
])->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$em->persist($entity);
|
||||
$em->flush();
|
||||
$this->entityManager->persist($entity);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', $this->get('translator')->trans('Success : activity created!'));
|
||||
|
||||
@ -297,7 +309,7 @@ class ActivityController extends AbstractController
|
||||
|
||||
public function showAction(Request $request, $id): Response
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$view = null;
|
||||
|
||||
[$person, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
@ -307,13 +319,14 @@ class ActivityController extends AbstractController
|
||||
$view = 'ChillActivityBundle:Activity:showPerson.html.twig';
|
||||
}
|
||||
|
||||
$entity = $em->getRepository('ChillActivityBundle:Activity')->find($id);
|
||||
$entity = $this->activityRepository->find($id);
|
||||
|
||||
if (!$entity) {
|
||||
if (null === $entity) {
|
||||
throw $this->createNotFoundException('Unable to find Activity entity.');
|
||||
}
|
||||
|
||||
if (null !== $accompanyingPeriod) {
|
||||
// @TODO: Properties created dynamically.
|
||||
$entity->personsAssociated = $entity->getPersonsAssociated();
|
||||
$entity->personsNotAssociated = $entity->getPersonsNotAssociated();
|
||||
}
|
||||
@ -321,7 +334,7 @@ class ActivityController extends AbstractController
|
||||
// TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période
|
||||
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_SEE', $entity);
|
||||
|
||||
$deleteForm = $this->createDeleteForm($id, $person, $accompanyingPeriod);
|
||||
$deleteForm = $this->createDeleteForm($entity->getId(), $person, $accompanyingPeriod);
|
||||
|
||||
// TODO
|
||||
/*
|
||||
@ -337,21 +350,20 @@ class ActivityController extends AbstractController
|
||||
throw $this->createNotFoundException('Template not found');
|
||||
}
|
||||
|
||||
return $this->render($view, array(
|
||||
return $this->render($view, [
|
||||
'person' => $person,
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
'entity' => $entity,
|
||||
'delete_form' => $deleteForm->createView(),
|
||||
));
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a form to edit an existing Activity entity.
|
||||
*
|
||||
*/
|
||||
public function editAction($id, Request $request): Response
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$view = null;
|
||||
|
||||
[$person, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
@ -361,9 +373,9 @@ class ActivityController extends AbstractController
|
||||
$view = 'ChillActivityBundle:Activity:editPerson.html.twig';
|
||||
}
|
||||
|
||||
$entity = $em->getRepository('ChillActivityBundle:Activity')->find($id);
|
||||
$entity = $this->activityRepository->find($id);
|
||||
|
||||
if (!$entity) {
|
||||
if (null === $entity) {
|
||||
throw $this->createNotFoundException('Unable to find Activity entity.');
|
||||
}
|
||||
|
||||
@ -378,17 +390,18 @@ class ActivityController extends AbstractController
|
||||
])->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$em->persist($entity);
|
||||
$em->flush();
|
||||
$this->entityManager->persist($entity);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', $this->get('translator')->trans('Success : activity updated!'));
|
||||
|
||||
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
|
||||
$params['id'] = $id;
|
||||
$params['id'] = $entity->getId();
|
||||
|
||||
return $this->redirectToRoute('chill_activity_activity_show', $params);
|
||||
}
|
||||
|
||||
$deleteForm = $this->createDeleteForm($id, $person, $accompanyingPeriod);
|
||||
$deleteForm = $this->createDeleteForm($entity->getId(), $person, $accompanyingPeriod);
|
||||
|
||||
/*
|
||||
* TODO
|
||||
@ -406,23 +419,22 @@ class ActivityController extends AbstractController
|
||||
|
||||
$activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']);
|
||||
|
||||
return $this->render($view, array(
|
||||
return $this->render($view, [
|
||||
'entity' => $entity,
|
||||
'edit_form' => $form->createView(),
|
||||
'delete_form' => $deleteForm->createView(),
|
||||
'person' => $person,
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
'activity_json' => $activity_array
|
||||
));
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a Activity entity.
|
||||
*
|
||||
*/
|
||||
public function deleteAction(Request $request, $id)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$view = null;
|
||||
|
||||
[$person, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
@ -432,8 +444,7 @@ class ActivityController extends AbstractController
|
||||
$view = 'ChillActivityBundle:Activity:confirm_deletePerson.html.twig';
|
||||
}
|
||||
|
||||
/* @var $activity Activity */
|
||||
$activity = $em->getRepository('ChillActivityBundle:Activity')->find($id);
|
||||
$activity = $this->activityRepository->find($id);
|
||||
|
||||
if (!$activity) {
|
||||
throw $this->createNotFoundException('Unable to find Activity entity.');
|
||||
@ -442,35 +453,37 @@ class ActivityController extends AbstractController
|
||||
// TODO
|
||||
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_DELETE', $activity);
|
||||
|
||||
$form = $this->createDeleteForm($id, $person, $accompanyingPeriod);
|
||||
$form = $this->createDeleteForm($activity->getId(), $person, $accompanyingPeriod);
|
||||
|
||||
if ($request->getMethod() === Request::METHOD_DELETE) {
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isValid()) {
|
||||
|
||||
$this->logger->notice("An activity has been removed", array(
|
||||
$this->logger->notice("An activity has been removed", [
|
||||
'by_user' => $this->getUser()->getUsername(),
|
||||
'activity_id' => $activity->getId(),
|
||||
'person_id' => $activity->getPerson() ? $activity->getPerson()->getId() : null,
|
||||
'comment' => $activity->getComment()->getComment(),
|
||||
'scope_id' => $activity->getScope() ? $activity->getScope()->getId() : null,
|
||||
'reasons_ids' => $activity->getReasons()
|
||||
->map(function ($ar) { return $ar->getId(); })
|
||||
->map(
|
||||
static fn (ActivityReason $ar): int => $ar->getId()
|
||||
)
|
||||
->toArray(),
|
||||
'type_id' => $activity->getType()->getId(),
|
||||
'duration' => $activity->getDurationTime() ? $activity->getDurationTime()->format('U') : null,
|
||||
'date' => $activity->getDate()->format('Y-m-d'),
|
||||
'attendee' => $activity->getAttendee()
|
||||
));
|
||||
]);
|
||||
|
||||
$em->remove($activity);
|
||||
$em->flush();
|
||||
$this->entityManager->remove($activity);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', $this->get('translator')
|
||||
->trans("The activity has been successfully removed."));
|
||||
|
||||
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
|
||||
|
||||
return $this->redirectToRoute('chill_activity_activity_list', $params);
|
||||
}
|
||||
}
|
||||
@ -479,18 +492,18 @@ class ActivityController extends AbstractController
|
||||
throw $this->createNotFoundException('Template not found');
|
||||
}
|
||||
|
||||
return $this->render($view, array(
|
||||
return $this->render($view, [
|
||||
'activity' => $activity,
|
||||
'delete_form' => $form->createView(),
|
||||
'person' => $person,
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
));
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a form to delete a Activity entity by id.
|
||||
*/
|
||||
private function createDeleteForm(int $id, ?Person $person, ?AccompanyingPeriod $accompanyingPeriod): Form
|
||||
private function createDeleteForm(int $id, ?Person $person, ?AccompanyingPeriod $accompanyingPeriod): FormInterface
|
||||
{
|
||||
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
|
||||
$params['id'] = $id;
|
||||
@ -498,19 +511,17 @@ class ActivityController extends AbstractController
|
||||
return $this->createFormBuilder()
|
||||
->setAction($this->generateUrl('chill_activity_activity_delete', $params))
|
||||
->setMethod('DELETE')
|
||||
->add('submit', SubmitType::class, array('label' => 'Delete'))
|
||||
->getForm()
|
||||
;
|
||||
->add('submit', SubmitType::class, ['label' => 'Delete'])
|
||||
->getForm();
|
||||
}
|
||||
|
||||
private function getEntity(Request $request): array
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$person = $accompanyingPeriod = null;
|
||||
|
||||
if ($request->query->has('person_id')) {
|
||||
$person_id = $request->get('person_id');
|
||||
$person = $em->getRepository(Person::class)->find($person_id);
|
||||
$person = $this->personRepository->find($person_id);
|
||||
|
||||
if ($person === null) {
|
||||
throw $this->createNotFoundException('Person not found');
|
||||
@ -519,7 +530,7 @@ class ActivityController extends AbstractController
|
||||
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
|
||||
} elseif ($request->query->has('accompanying_period_id')) {
|
||||
$accompanying_period_id = $request->get('accompanying_period_id');
|
||||
$accompanyingPeriod = $em->getRepository(AccompanyingPeriod::class)->find($accompanying_period_id);
|
||||
$accompanyingPeriod = $this->accompanyingPeriodRepository->find($accompanying_period_id);
|
||||
|
||||
if ($accompanyingPeriod === null) {
|
||||
throw $this->createNotFoundException('Accompanying Period not found');
|
||||
@ -532,21 +543,20 @@ class ActivityController extends AbstractController
|
||||
}
|
||||
|
||||
return [
|
||||
$person, $accompanyingPeriod
|
||||
$person,
|
||||
$accompanyingPeriod
|
||||
];
|
||||
}
|
||||
|
||||
private function buildParamsToUrl(
|
||||
?Person $person,
|
||||
?AccompanyingPeriod $accompanyingPeriod
|
||||
): array {
|
||||
private function buildParamsToUrl(?Person $person, ?AccompanyingPeriod $accompanyingPeriod): array
|
||||
{
|
||||
$params = [];
|
||||
|
||||
if ($person) {
|
||||
if (null !== $person) {
|
||||
$params['person_id'] = $person->getId();
|
||||
}
|
||||
|
||||
if ($accompanyingPeriod) {
|
||||
if (null !== $accompanyingPeriod) {
|
||||
$params['accompanying_period_id'] = $accompanyingPeriod->getId();
|
||||
}
|
||||
|
||||
|
@ -22,9 +22,10 @@
|
||||
|
||||
namespace Chill\ActivityBundle\DataFixtures\ORM;
|
||||
|
||||
use Chill\PersonBundle\DataFixtures\Helper\RandomPersonHelperTrait;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Faker\Factory as FakerFactory;
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
@ -32,26 +33,21 @@ use Chill\MainBundle\DataFixtures\ORM\LoadUsers;
|
||||
use Chill\ActivityBundle\DataFixtures\ORM\LoadActivityReason;
|
||||
use Chill\ActivityBundle\DataFixtures\ORM\LoadActivityType;
|
||||
use Chill\MainBundle\DataFixtures\ORM\LoadScopes;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
|
||||
/**
|
||||
* Load reports into DB
|
||||
*
|
||||
* @author Champs-Libres Coop
|
||||
*/
|
||||
class LoadActivity extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface
|
||||
class LoadActivity extends AbstractFixture implements OrderedFixtureInterface
|
||||
{
|
||||
use \Symfony\Component\DependencyInjection\ContainerAwareTrait;
|
||||
use RandomPersonHelperTrait;
|
||||
|
||||
/**
|
||||
* @var \Faker\Generator
|
||||
*/
|
||||
private $faker;
|
||||
private EntityManagerInterface $em;
|
||||
|
||||
public function __construct()
|
||||
public function __construct(EntityManagerInterface $em)
|
||||
{
|
||||
$this->faker = FakerFactory::create('fr_FR');
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
public function getOrder()
|
||||
@ -86,15 +82,10 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface, C
|
||||
*
|
||||
* @return \Chill\ActivityBundle\Entity\ActivityReason
|
||||
*/
|
||||
private function getRandomActivityReason(array $excludingIds)
|
||||
private function getRandomActivityReason()
|
||||
{
|
||||
$reasonRef = LoadActivityReason::$references[array_rand(LoadActivityReason::$references)];
|
||||
|
||||
if (in_array($this->getReference($reasonRef)->getId(), $excludingIds)) {
|
||||
// we have a reason which should be excluded. Find another...
|
||||
return $this->getRandomActivityReason($excludingIds);
|
||||
}
|
||||
|
||||
return $this->getReference($reasonRef);
|
||||
}
|
||||
|
||||
@ -109,7 +100,7 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface, C
|
||||
return $this->getReference($userRef);
|
||||
}
|
||||
|
||||
public function newRandomActivity($person)
|
||||
public function newRandomActivity($person): ?Activity
|
||||
{
|
||||
$activity = (new Activity())
|
||||
->setUser($this->getRandomUser())
|
||||
@ -122,11 +113,13 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface, C
|
||||
|
||||
// ->setAttendee($this->faker->boolean())
|
||||
|
||||
$usedId = array();
|
||||
for ($i = 0; $i < rand(0, 4); $i++) {
|
||||
$reason = $this->getRandomActivityReason($usedId);
|
||||
$usedId[] = $reason->getId();
|
||||
$activity->addReason($reason);
|
||||
$reason = $this->getRandomActivityReason();
|
||||
if (null !== $reason) {
|
||||
$activity->addReason($reason);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return $activity;
|
||||
@ -134,20 +127,19 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface, C
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
$persons = $this->container->get('doctrine.orm.entity_manager')
|
||||
->getRepository('ChillPersonBundle:Person')
|
||||
$persons = $this->em
|
||||
->getRepository(Person::class)
|
||||
->findAll();
|
||||
|
||||
foreach($persons as $person) {
|
||||
foreach ($persons as $person) {
|
||||
$activityNbr = rand(0,3);
|
||||
$ref = 'activity_'.$person->getFullnameCanonical();
|
||||
|
||||
for($i = 0; $i < $activityNbr; $i ++) {
|
||||
for ($i = 0; $i < $activityNbr; $i ++) {
|
||||
$activity = $this->newRandomActivity($person);
|
||||
$manager->persist($activity);
|
||||
if (null !== $activity) {
|
||||
$manager->persist($activity);
|
||||
}
|
||||
}
|
||||
|
||||
$this->setReference($ref, $activity);
|
||||
}
|
||||
$manager->flush();
|
||||
}
|
||||
|
@ -1,27 +1,8 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2015, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Entity;
|
||||
|
||||
use Chill\DocStoreBundle\Entity\Document;
|
||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
|
||||
use Chill\MainBundle\Entity\Location;
|
||||
use Chill\PersonBundle\AccompanyingPeriod\SocialIssueConsistency\AccompanyingPeriodLinkedWithSocialIssuesEntityInterface;
|
||||
@ -38,7 +19,7 @@ use Chill\MainBundle\Entity\HasCenterInterface;
|
||||
use Chill\MainBundle\Entity\HasScopeInterface;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Chill\MainBundle\Validator\Constraints\Entity\UserCircleConsistency;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||
|
||||
@ -202,7 +183,7 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setUser(User $user): self
|
||||
public function setUser(UserInterface $user): self
|
||||
{
|
||||
$this->user = $user;
|
||||
|
||||
|
@ -1,31 +1,12 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2015, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* Class ActivityTypeCateogry
|
||||
*
|
||||
* @package Chill\ActivityBundle\Entity
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="activitytypecategory")
|
||||
* @ORM\HasLifecycleCallbacks()
|
||||
@ -37,7 +18,7 @@ class ActivityTypeCategory
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private ?int $id;
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="json")
|
||||
@ -54,10 +35,7 @@ class ActivityTypeCategory
|
||||
*/
|
||||
private float $ordering = 0.0;
|
||||
|
||||
/**
|
||||
* Get id
|
||||
*/
|
||||
public function getId(): int
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
@ -1,70 +1,39 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Champs-Libres <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Aggregator;
|
||||
|
||||
use Chill\ActivityBundle\Repository\ActivityReasonCategoryRepository;
|
||||
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class ActivityReasonAggregator implements AggregatorInterface,
|
||||
ExportElementValidatedInterface
|
||||
class ActivityReasonAggregator implements AggregatorInterface, ExportElementValidatedInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var EntityRepository
|
||||
*/
|
||||
protected $categoryRepository;
|
||||
protected ActivityReasonCategoryRepository $activityReasonCategoryRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var EntityRepository
|
||||
*/
|
||||
protected $reasonRepository;
|
||||
protected ActivityReasonRepository $activityReasonRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
protected $stringHelper;
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
EntityRepository $categoryRepository,
|
||||
EntityRepository $reasonRepository,
|
||||
TranslatableStringHelper $stringHelper
|
||||
ActivityReasonCategoryRepository $activityReasonCategoryRepository,
|
||||
ActivityReasonRepository $activityReasonRepository,
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
) {
|
||||
$this->categoryRepository = $categoryRepository;
|
||||
$this->reasonRepository = $reasonRepository;
|
||||
$this->stringHelper = $stringHelper;
|
||||
$this->activityReasonCategoryRepository = $activityReasonCategoryRepository;
|
||||
$this->activityReasonRepository = $activityReasonRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
@ -77,7 +46,7 @@ class ActivityReasonAggregator implements AggregatorInterface,
|
||||
$elem = 'category.id';
|
||||
$alias = 'activity_categories_id';
|
||||
} else {
|
||||
throw new \RuntimeException('the data provided are not recognized');
|
||||
throw new \RuntimeException('The data provided are not recognized.');
|
||||
}
|
||||
|
||||
$qb->addSelect($elem.' as '.$alias);
|
||||
@ -93,11 +62,12 @@ class ActivityReasonAggregator implements AggregatorInterface,
|
||||
(! array_key_exists('activity', $join))
|
||||
) {
|
||||
$qb->add(
|
||||
'join',
|
||||
array('activity' =>
|
||||
new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons')
|
||||
),
|
||||
true);
|
||||
'join',
|
||||
[
|
||||
'activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons')
|
||||
],
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
// join category if necessary
|
||||
@ -143,28 +113,33 @@ class ActivityReasonAggregator implements AggregatorInterface,
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('level', ChoiceType::class, array(
|
||||
'choices' => array(
|
||||
'By reason' => 'reasons',
|
||||
'By category of reason' => 'categories'
|
||||
),
|
||||
'multiple' => false,
|
||||
'expanded' => true,
|
||||
'label' => 'Reason\'s level'
|
||||
));
|
||||
$builder->add(
|
||||
'level',
|
||||
ChoiceType::class,
|
||||
[
|
||||
'choices' => [
|
||||
'By reason' => 'reasons',
|
||||
'By category of reason' => 'categories'
|
||||
],
|
||||
'multiple' => false,
|
||||
'expanded' => true,
|
||||
'label' => "Reason's level"
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function validateForm($data, ExecutionContextInterface $context)
|
||||
{
|
||||
if ($data['level'] === null) {
|
||||
$context->buildViolation("The reasons's level should not be empty")
|
||||
$context
|
||||
->buildViolation("The reasons's level should not be empty.")
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
public function getTitle()
|
||||
{
|
||||
return "Aggregate by activity reason";
|
||||
return 'Aggregate by activity reason';
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
@ -177,41 +152,33 @@ class ActivityReasonAggregator implements AggregatorInterface,
|
||||
// for performance reason, we load data from db only once
|
||||
switch ($data['level']) {
|
||||
case 'reasons':
|
||||
$this->reasonRepository->findBy(array('id' => $values));
|
||||
$this->activityReasonRepository->findBy(['id' => $values]);
|
||||
break;
|
||||
case 'categories':
|
||||
$this->categoryRepository->findBy(array('id' => $values));
|
||||
$this->activityReasonCategoryRepository->findBy(['id' => $values]);
|
||||
break;
|
||||
default:
|
||||
throw new \RuntimeException(sprintf("the level data '%s' is invalid",
|
||||
$data['level']));
|
||||
throw new \RuntimeException(sprintf("The level data '%s' is invalid.", $data['level']));
|
||||
}
|
||||
|
||||
return function($value) use ($data) {
|
||||
if ($value === '_header') {
|
||||
return $data['level'] === 'reasons' ?
|
||||
'Group by reasons'
|
||||
:
|
||||
'Group by categories of reason'
|
||||
;
|
||||
return $data['level'] === 'reasons' ? 'Group by reasons' : 'Group by categories of reason';
|
||||
}
|
||||
|
||||
switch ($data['level']) {
|
||||
case 'reasons':
|
||||
/* @var $r \Chill\ActivityBundle\Entity\ActivityReason */
|
||||
$r = $this->reasonRepository->find($value);
|
||||
$r = $this->activityReasonRepository->find($value);
|
||||
|
||||
return $this->stringHelper->localize($r->getCategory()->getName())
|
||||
." > "
|
||||
. $this->stringHelper->localize($r->getName());
|
||||
;
|
||||
break;
|
||||
return sprintf(
|
||||
"%s > %s",
|
||||
$this->translatableStringHelper->localize($r->getCategory()->getName()),
|
||||
$this->translatableStringHelper->localize($r->getName())
|
||||
);
|
||||
case 'categories':
|
||||
$c = $this->categoryRepository->find($value);
|
||||
$c = $this->activityReasonCategoryRepository->find($value);
|
||||
|
||||
return $this->stringHelper->localize($c->getName());
|
||||
break;
|
||||
// no need for a default : the default was already set above
|
||||
return $this->translatableStringHelper->localize($c->getName());
|
||||
}
|
||||
};
|
||||
|
||||
@ -222,12 +189,14 @@ class ActivityReasonAggregator implements AggregatorInterface,
|
||||
// add select element
|
||||
if ($data['level'] === 'reasons') {
|
||||
return array('activity_reasons_id');
|
||||
} elseif ($data['level'] === 'categories') {
|
||||
return array ('activity_categories_id');
|
||||
} else {
|
||||
throw new \RuntimeException('the data provided are not recognised');
|
||||
}
|
||||
|
||||
if ($data['level'] === 'categories') {
|
||||
return array ('activity_categories_id');
|
||||
}
|
||||
|
||||
throw new \RuntimeException('The data provided are not recognised.');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,75 +1,46 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Champs-Libres <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Aggregator;
|
||||
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class ActivityTypeAggregator implements AggregatorInterface
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* @var EntityRepository
|
||||
*/
|
||||
protected $typeRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
protected $stringHelper;
|
||||
|
||||
const KEY = 'activity_type_aggregator';
|
||||
|
||||
protected ActivityTypeRepository $activityTypeRepository;
|
||||
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public const KEY = 'activity_type_aggregator';
|
||||
|
||||
public function __construct(
|
||||
EntityRepository $typeRepository,
|
||||
TranslatableStringHelper $stringHelper
|
||||
ActivityTypeRepository $activityTypeRepository,
|
||||
TranslatableStringHelperInterface $translatableStringHelper
|
||||
) {
|
||||
$this->typeRepository = $typeRepository;
|
||||
$this->stringHelper = $stringHelper;
|
||||
$this->activityTypeRepository = $activityTypeRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
// add select element
|
||||
// add select element
|
||||
$qb->addSelect(sprintf('IDENTITY(activity.type) AS %s', self::KEY));
|
||||
|
||||
|
||||
// add the "group by" part
|
||||
$groupBy = $qb->addGroupBy(self::KEY);
|
||||
$qb->addGroupBy(self::KEY);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if a join between Activity and another alias
|
||||
*
|
||||
*
|
||||
* @param Join[] $joins
|
||||
* @param string $alias the alias to search for
|
||||
* @return boolean
|
||||
@ -81,7 +52,7 @@ class ActivityTypeAggregator implements AggregatorInterface
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -97,35 +68,33 @@ class ActivityTypeAggregator implements AggregatorInterface
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return "Aggregate by activity type";
|
||||
return 'Aggregate by activity type';
|
||||
}
|
||||
|
||||
|
||||
public function addRole()
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
public function getLabels($key, array $values, $data): \Closure
|
||||
{
|
||||
// for performance reason, we load data from db only once
|
||||
$this->typeRepository->findBy(array('id' => $values));
|
||||
|
||||
return function($value) use ($data) {
|
||||
$this->activityTypeRepository->findBy(['id' => $values]);
|
||||
|
||||
return function($value): string {
|
||||
if ($value === '_header') {
|
||||
return 'Activity type';
|
||||
}
|
||||
|
||||
/* @var $r \Chill\ActivityBundle\Entity\ActivityType */
|
||||
$t = $this->typeRepository->find($value);
|
||||
$t = $this->activityTypeRepository->find($value);
|
||||
|
||||
return $this->stringHelper->localize($t->getName());
|
||||
return $this->translatableStringHelper->localize($t->getName());
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return array(self::KEY);
|
||||
return [self::KEY];
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,51 +1,26 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2019 Champs Libres Cooperative <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Aggregator;
|
||||
|
||||
use Chill\MainBundle\Repository\UserRepository;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class ActivityUserAggregator implements AggregatorInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
protected $em;
|
||||
|
||||
const KEY = 'activity_user_id';
|
||||
|
||||
function __construct(EntityManagerInterface $em)
|
||||
{
|
||||
$this->em = $em;
|
||||
public const KEY = 'activity_user_id';
|
||||
|
||||
private UserRepository $userRepository;
|
||||
|
||||
public function __construct(
|
||||
UserRepository $userRepository
|
||||
) {
|
||||
$this->userRepository = $userRepository;
|
||||
}
|
||||
|
||||
|
||||
public function addRole()
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
@ -53,9 +28,9 @@ class ActivityUserAggregator implements AggregatorInterface
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
// add select element
|
||||
// add select element
|
||||
$qb->addSelect(sprintf('IDENTITY(activity.user) AS %s', self::KEY));
|
||||
|
||||
|
||||
// add the "group by" part
|
||||
$qb->addGroupBy(self::KEY);
|
||||
}
|
||||
@ -73,17 +48,14 @@ class ActivityUserAggregator implements AggregatorInterface
|
||||
public function getLabels($key, $values, $data): \Closure
|
||||
{
|
||||
// preload users at once
|
||||
$this->em->getRepository(User::class)
|
||||
->findBy(['id' => $values]);
|
||||
|
||||
$this->userRepository->findBy(['id' => $values]);
|
||||
|
||||
return function($value) {
|
||||
switch ($value) {
|
||||
case '_header':
|
||||
return 'activity user';
|
||||
default:
|
||||
return $this->em->getRepository(User::class)->find($value)
|
||||
->getUsername();
|
||||
if ($value === '_header') {
|
||||
return 'activity user';
|
||||
}
|
||||
|
||||
return $this->userRepository->find($value)->getUsername();
|
||||
};
|
||||
}
|
||||
|
||||
@ -94,6 +66,6 @@ class ActivityUserAggregator implements AggregatorInterface
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return "Aggregate by activity user";
|
||||
return 'Aggregate by activity user';
|
||||
}
|
||||
}
|
||||
|
@ -1,64 +1,40 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Champs-Libres <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Export;
|
||||
|
||||
use Chill\ActivityBundle\Repository\ActivityRepository;
|
||||
use Chill\MainBundle\Export\ExportInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Doctrine\ORM\Query;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class CountActivity implements ExportInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
protected ActivityRepository $activityRepository;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em
|
||||
)
|
||||
{
|
||||
$this->entityManager = $em;
|
||||
ActivityRepository $activityRepository
|
||||
) {
|
||||
$this->activityRepository = $activityRepository;
|
||||
}
|
||||
|
||||
public function buildForm(\Symfony\Component\Form\FormBuilderInterface $builder)
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function getDescription()
|
||||
{
|
||||
return "Count activities by various parameters.";
|
||||
return 'Count activities by various parameters.';
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return "Count activities";
|
||||
return 'Count activities';
|
||||
}
|
||||
|
||||
public function getType()
|
||||
@ -68,26 +44,26 @@ class CountActivity implements ExportInterface
|
||||
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = array())
|
||||
{
|
||||
$qb = $this->entityManager->createQueryBuilder();
|
||||
$centers = array_map(function($el) { return $el['center']; }, $acl);
|
||||
|
||||
$qb->select('COUNT(activity.id) as export_count_activity')
|
||||
->from('ChillActivityBundle:Activity', 'activity')
|
||||
->join('activity.person', 'person')
|
||||
;
|
||||
|
||||
$qb->where($qb->expr()->in('person.center', ':centers'))
|
||||
->setParameter('centers', $centers)
|
||||
;
|
||||
|
||||
$centers = array_map(static fn($el) => $el['center'], $acl);
|
||||
|
||||
$qb = $this
|
||||
->activityRepository
|
||||
->createQueryBuilder('activity')
|
||||
->select('COUNT(activity.id) as export_count_activity')
|
||||
->join('activity.person', 'person');
|
||||
|
||||
$qb
|
||||
->where($qb->expr()->in('person.center', ':centers'))
|
||||
->setParameter('centers', $centers);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
|
||||
public function supportsModifiers()
|
||||
{
|
||||
return array('person', 'activity');
|
||||
return ['person', 'activity'];
|
||||
}
|
||||
|
||||
|
||||
public function requiredRole()
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
@ -95,7 +71,7 @@ class CountActivity implements ExportInterface
|
||||
|
||||
public function getAllowedFormattersTypes()
|
||||
{
|
||||
return array(\Chill\MainBundle\Export\FormatterInterface::TYPE_TABULAR);
|
||||
return [FormatterInterface::TYPE_TABULAR];
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
@ -103,19 +79,13 @@ class CountActivity implements ExportInterface
|
||||
if ($key !== 'export_count_activity') {
|
||||
throw new \LogicException("the key $key is not used by this export");
|
||||
}
|
||||
|
||||
return function($value) {
|
||||
return $value === '_header' ?
|
||||
'Number of activities'
|
||||
:
|
||||
$value
|
||||
;
|
||||
};
|
||||
|
||||
return static fn($value) => $value === '_header' ? 'Number of activities' : $value;
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
return array('export_count_activity');
|
||||
return ['export_count_activity'];
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
|
@ -1,31 +1,14 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 Champs-Libres <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Export;
|
||||
|
||||
use Chill\ActivityBundle\Repository\ActivityRepository;
|
||||
use Chill\MainBundle\Export\ListInterface;
|
||||
use Chill\ActivityBundle\Entity\ActivityReason;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\ActivityBundle\Entity\ActivityType;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\DBAL\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
@ -37,33 +20,17 @@ use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
/**
|
||||
* Create a list for all activities
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class ListActivity implements ListInterface
|
||||
{
|
||||
private ActivityRepository $activityRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
protected EntityManagerInterface $entityManager;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
protected TranslatorInterface $translator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
protected $translatableStringHelper;
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
protected $fields = array(
|
||||
protected array $fields = [
|
||||
'id',
|
||||
'date',
|
||||
'durationTime',
|
||||
@ -75,32 +42,28 @@ class ListActivity implements ListInterface
|
||||
'person_firstname',
|
||||
'person_lastname',
|
||||
'person_id'
|
||||
);
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
TranslatorInterface $translator,
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
)
|
||||
{
|
||||
EntityManagerInterface $em,
|
||||
TranslatorInterface $translator,
|
||||
TranslatableStringHelperInterface $translatableStringHelper,
|
||||
ActivityRepository $activityRepository
|
||||
) {
|
||||
$this->entityManager = $em;
|
||||
$this->translator = $translator;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->activityRepository = $activityRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @param FormBuilderInterface $builder
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('fields', ChoiceType::class, array(
|
||||
$builder->add('fields', ChoiceType::class, [
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
'choices' => array_combine($this->fields, $this->fields),
|
||||
'label' => 'Fields to include in export',
|
||||
'constraints' => [new Callback(array(
|
||||
'constraints' => [new Callback([
|
||||
'callback' => function($selected, ExecutionContextInterface $context) {
|
||||
if (count($selected) === 0) {
|
||||
$context->buildViolation('You must select at least one element')
|
||||
@ -108,19 +71,14 @@ class ListActivity implements ListInterface
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
))]
|
||||
));
|
||||
])]
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return type
|
||||
*/
|
||||
public function getAllowedFormattersTypes()
|
||||
{
|
||||
return array(FormatterInterface::TYPE_LIST);
|
||||
return [FormatterInterface::TYPE_LIST];
|
||||
}
|
||||
|
||||
public function getDescription()
|
||||
@ -133,29 +91,32 @@ class ListActivity implements ListInterface
|
||||
switch ($key)
|
||||
{
|
||||
case 'date' :
|
||||
return function($value) {
|
||||
if ($value === '_header') return 'date';
|
||||
return static function($value) {
|
||||
if ($value === '_header') {
|
||||
return 'date';
|
||||
}
|
||||
|
||||
$date = \DateTime::createFromFormat('Y-m-d H:i:s', $value);
|
||||
|
||||
return $date->format('d-m-Y');
|
||||
};
|
||||
case 'attendee':
|
||||
return function($value) {
|
||||
if ($value === '_header') return 'attendee';
|
||||
return static function($value) {
|
||||
if ($value === '_header') {
|
||||
return 'attendee';
|
||||
}
|
||||
|
||||
return $value ? 1 : 0;
|
||||
};
|
||||
case 'list_reasons' :
|
||||
/* @var $activityReasonsRepository EntityRepository */
|
||||
$activityRepository = $this->entityManager
|
||||
->getRepository('ChillActivityBundle:Activity');
|
||||
$activityRepository = $this->activityRepository;
|
||||
|
||||
return function($value) use ($activityRepository) {
|
||||
if ($value === '_header') return 'activity reasons';
|
||||
return function($value) use ($activityRepository): string {
|
||||
if ($value === '_header') {
|
||||
return 'activity reasons';
|
||||
}
|
||||
|
||||
$activity = $activityRepository
|
||||
->find($value);
|
||||
$activity = $activityRepository->find($value);
|
||||
|
||||
return implode(", ", array_map(function(ActivityReason $r) {
|
||||
|
||||
@ -168,21 +129,25 @@ class ListActivity implements ListInterface
|
||||
};
|
||||
case 'circle_name' :
|
||||
return function($value) {
|
||||
if ($value === '_header') return 'circle';
|
||||
if ($value === '_header') {
|
||||
return 'circle';
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper
|
||||
->localize(json_decode($value, true));
|
||||
return $this->translatableStringHelper->localize(json_decode($value, true));
|
||||
};
|
||||
case 'type_name' :
|
||||
return function($value) {
|
||||
if ($value === '_header') return 'activity type';
|
||||
if ($value === '_header') {
|
||||
return 'activity type';
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper
|
||||
->localize(json_decode($value, true));
|
||||
return $this->translatableStringHelper->localize(json_decode($value, true));
|
||||
};
|
||||
default:
|
||||
return function($value) use ($key) {
|
||||
if ($value === '_header') return $key;
|
||||
return static function($value) use ($key) {
|
||||
if ($value === '_header') {
|
||||
return $key;
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
@ -209,14 +174,13 @@ class ListActivity implements ListInterface
|
||||
return 'activity';
|
||||
}
|
||||
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = array())
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
||||
{
|
||||
$centers = array_map(function($el) { return $el['center']; }, $acl);
|
||||
|
||||
// throw an error if any fields are present
|
||||
if (!\array_key_exists('fields', $data)) {
|
||||
throw new \Doctrine\DBAL\Exception\InvalidArgumentException("any fields "
|
||||
. "have been checked");
|
||||
throw new InvalidArgumentException('Any fields have been checked.');
|
||||
}
|
||||
|
||||
$qb = $this->entityManager->createQueryBuilder();
|
||||
@ -227,7 +191,6 @@ class ListActivity implements ListInterface
|
||||
->join('person.center', 'center')
|
||||
->andWhere('center IN (:authorized_centers)')
|
||||
->setParameter('authorized_centers', $centers);
|
||||
;
|
||||
|
||||
foreach ($this->fields as $f) {
|
||||
if (in_array($f, $data['fields'])) {
|
||||
@ -269,8 +232,6 @@ class ListActivity implements ListInterface
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
@ -281,7 +242,7 @@ class ListActivity implements ListInterface
|
||||
|
||||
public function supportsModifiers()
|
||||
{
|
||||
return array('activity', 'person');
|
||||
return ['activity', 'person'];
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,89 +1,62 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Champs-Libres <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Export;
|
||||
|
||||
use Chill\ActivityBundle\Repository\ActivityRepository;
|
||||
use Chill\MainBundle\Export\ExportInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Doctrine\ORM\Query;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
/**
|
||||
* This export allow to compute stats on activity duration.
|
||||
*
|
||||
*
|
||||
* The desired stat must be given in constructor.
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class StatActivityDuration implements ExportInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
const SUM = 'sum';
|
||||
|
||||
private ActivityRepository $activityRepository;
|
||||
|
||||
public const SUM = 'sum';
|
||||
|
||||
/**
|
||||
* The action for this report.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $action;
|
||||
|
||||
protected string $action;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*
|
||||
* @param EntityManagerInterface $em
|
||||
* @param string $action the stat to perform
|
||||
*/
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
$action = 'sum'
|
||||
)
|
||||
{
|
||||
$this->entityManager = $em;
|
||||
ActivityRepository $activityRepository,
|
||||
string $action = 'sum'
|
||||
) {
|
||||
$this->action = $action;
|
||||
$this->activityRepository = $activityRepository;
|
||||
}
|
||||
|
||||
public function buildForm(\Symfony\Component\Form\FormBuilderInterface $builder)
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function getDescription()
|
||||
{
|
||||
if ($this->action === self::SUM) {
|
||||
return "Sum activities duration by various parameters.";
|
||||
return 'Sum activities duration by various parameters.';
|
||||
}
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
if ($this->action === self::SUM) {
|
||||
return "Sum activity duration";
|
||||
return 'Sum activity duration';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function getType()
|
||||
@ -91,31 +64,33 @@ class StatActivityDuration implements ExportInterface
|
||||
return 'activity';
|
||||
}
|
||||
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = array())
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
||||
{
|
||||
$centers = array_map(function($el) { return $el['center']; }, $acl);
|
||||
$qb = $this->entityManager->createQueryBuilder();
|
||||
|
||||
$centers = array_map(
|
||||
static fn(array $el): string => $el['center'],
|
||||
$acl
|
||||
);
|
||||
|
||||
$qb = $this->activityRepository->createQueryBuilder('activity');
|
||||
|
||||
$select = null;
|
||||
|
||||
if ($this->action === self::SUM) {
|
||||
$select = "SUM(activity.durationTime) AS export_stat_activity";
|
||||
$select = 'SUM(activity.durationTime) AS export_stat_activity';
|
||||
}
|
||||
|
||||
$qb->select($select)
|
||||
->from('ChillActivityBundle:Activity', 'activity')
|
||||
->join('activity.person', 'person')
|
||||
->join('person.center', 'center')
|
||||
->where($qb->expr()->in('center', ':centers'))
|
||||
->setParameter(':centers', $centers)
|
||||
;
|
||||
|
||||
return $qb;
|
||||
|
||||
return $qb->select($select)
|
||||
->join('activity.person', 'person')
|
||||
->join('person.center', 'center')
|
||||
->where($qb->expr()->in('center', ':centers'))
|
||||
->setParameter(':centers', $centers);
|
||||
}
|
||||
|
||||
|
||||
public function supportsModifiers()
|
||||
{
|
||||
return array('person', 'activity');
|
||||
return ['person', 'activity'];
|
||||
}
|
||||
|
||||
|
||||
public function requiredRole()
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
@ -123,32 +98,23 @@ class StatActivityDuration implements ExportInterface
|
||||
|
||||
public function getAllowedFormattersTypes()
|
||||
{
|
||||
return array(\Chill\MainBundle\Export\FormatterInterface::TYPE_TABULAR);
|
||||
return [FormatterInterface::TYPE_TABULAR];
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
if ($key !== 'export_stat_activity') {
|
||||
throw new \LogicException("the key $key is not used by this export");
|
||||
throw new \LogicException(sprintf('The key %s is not used by this export', $key));
|
||||
}
|
||||
|
||||
switch ($this->action) {
|
||||
case self::SUM:
|
||||
$header = "Sum of activities duration";
|
||||
}
|
||||
|
||||
return function($value) use ($header) {
|
||||
return $value === '_header' ?
|
||||
$header
|
||||
:
|
||||
$value
|
||||
;
|
||||
};
|
||||
|
||||
$header = $this->action === self::SUM ? 'Sum of activities duration' : false;
|
||||
|
||||
return static fn(string $value) => $value === '_header' ? $header : $value;
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
return array('export_stat_activity');
|
||||
return ['export_stat_activity'];
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
|
@ -1,25 +1,12 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 Champs-Libres <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Filter;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
|
||||
@ -28,34 +15,24 @@ use Chill\MainBundle\Form\Type\Export\FilterType;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class ActivityDateFilter implements FilterInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
|
||||
protected TranslatorInterface $translator;
|
||||
|
||||
function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
|
||||
public function addRole()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(\Doctrine\ORM\QueryBuilder $qb, $data)
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->between('activity.date', ':date_from',
|
||||
$clause = $qb->expr()->between('activity.date', ':date_from',
|
||||
':date_to');
|
||||
|
||||
if ($where instanceof Expr\Andx) {
|
||||
@ -63,7 +40,7 @@ class ActivityDateFilter implements FilterInterface
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('date_from', $data['date_from']);
|
||||
$qb->setParameter('date_to', $data['date_to']);
|
||||
@ -74,35 +51,43 @@ class ActivityDateFilter implements FilterInterface
|
||||
return 'activity';
|
||||
}
|
||||
|
||||
public function buildForm(\Symfony\Component\Form\FormBuilderInterface $builder)
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('date_from', DateType::class, array(
|
||||
'label' => "Activities after this date",
|
||||
'data' => new \DateTime(),
|
||||
'attr' => array('class' => 'datepicker'),
|
||||
'widget'=> 'single_text',
|
||||
'format' => 'dd-MM-yyyy',
|
||||
));
|
||||
|
||||
$builder->add('date_to', DateType::class, array(
|
||||
'label' => "Activities before this date",
|
||||
'data' => new \DateTime(),
|
||||
'attr' => array('class' => 'datepicker'),
|
||||
'widget'=> 'single_text',
|
||||
'format' => 'dd-MM-yyyy',
|
||||
));
|
||||
|
||||
$builder->add(
|
||||
'date_from',
|
||||
DateType::class,
|
||||
[
|
||||
'label' => 'Activities after this date',
|
||||
'data' => new \DateTime(),
|
||||
'attr' => ['class' => 'datepicker'],
|
||||
'widget'=> 'single_text',
|
||||
'format' => 'dd-MM-yyyy',
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'date_to',
|
||||
DateType::class,
|
||||
[
|
||||
'label' => 'Activities before this date',
|
||||
'data' => new \DateTime(),
|
||||
'attr' => ['class' => 'datepicker'],
|
||||
'widget'=> 'single_text',
|
||||
'format' => 'dd-MM-yyyy',
|
||||
]
|
||||
);
|
||||
|
||||
$builder->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
|
||||
/* @var $filterForm \Symfony\Component\Form\FormInterface */
|
||||
$filterForm = $event->getForm()->getParent();
|
||||
$enabled = $filterForm->get(FilterType::ENABLED_FIELD)->getData();
|
||||
|
||||
|
||||
if ($enabled === true) {
|
||||
// if the filter is enabled, add some validation
|
||||
$form = $event->getForm();
|
||||
$date_from = $form->get('date_from')->getData();
|
||||
$date_to = $form->get('date_to')->getData();
|
||||
|
||||
|
||||
// check that fields are not empty
|
||||
if ($date_from === null) {
|
||||
$form->get('date_from')->addError(new FormError(
|
||||
@ -113,8 +98,8 @@ class ActivityDateFilter implements FilterInterface
|
||||
$form->get('date_to')->addError(new FormError(
|
||||
$this->translator->trans('This field '
|
||||
. 'should not be empty')));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// check that date_from is before date_to
|
||||
if (
|
||||
($date_from !== null && $date_to !== null)
|
||||
@ -132,17 +117,18 @@ class ActivityDateFilter implements FilterInterface
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
return array(
|
||||
"Filtered by date of activity: only between %date_from% and %date_to%",
|
||||
array(
|
||||
"%date_from%" => $data['date_from']->format('d-m-Y'),
|
||||
'%date_to%' => $data['date_to']->format('d-m-Y')
|
||||
));
|
||||
return [
|
||||
'Filtered by date of activity: only between %date_from% and %date_to%',
|
||||
[
|
||||
'%date_from%' => $data['date_from']->format('d-m-Y'),
|
||||
'%date_to%' => $data['date_to']->format('d-m-Y')
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return "Filtered by date activity";
|
||||
return 'Filtered by date activity';
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,25 +1,12 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Champs-Libres <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Filter;
|
||||
|
||||
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
@ -28,41 +15,24 @@ use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class ActivityReasonFilter implements FilterInterface,
|
||||
ExportElementValidatedInterface
|
||||
class ActivityReasonFilter implements FilterInterface, ExportElementValidatedInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
protected $translatableStringHelper;
|
||||
|
||||
/**
|
||||
* The repository for activity reasons
|
||||
*
|
||||
* @var EntityRepository
|
||||
*/
|
||||
protected $reasonRepository;
|
||||
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
protected ActivityReasonRepository $activityReasonRepository;
|
||||
|
||||
public function __construct(
|
||||
TranslatableStringHelper $helper,
|
||||
EntityRepository $reasonRepository
|
||||
TranslatableStringHelper $helper,
|
||||
ActivityReasonRepository $activityReasonRepository
|
||||
) {
|
||||
$this->translatableStringHelper = $helper;
|
||||
$this->reasonRepository = $reasonRepository;
|
||||
$this->activityReasonRepository = $activityReasonRepository;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
@ -75,12 +45,12 @@ class ActivityReasonFilter implements FilterInterface,
|
||||
&&
|
||||
!$this->checkJoinAlreadyDefined($join['activity'], 'reasons')
|
||||
)
|
||||
OR
|
||||
||
|
||||
(! array_key_exists('activity', $join))
|
||||
) {
|
||||
$qb->add(
|
||||
'join',
|
||||
array('activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons')),
|
||||
'join',
|
||||
array('activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons')),
|
||||
true
|
||||
);
|
||||
}
|
||||
@ -90,25 +60,25 @@ class ActivityReasonFilter implements FilterInterface,
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('selected_activity_reasons', $data['reasons']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if a join between Activity and Reason is already defined
|
||||
*
|
||||
*
|
||||
* @param Join[] $joins
|
||||
* @return boolean
|
||||
*/
|
||||
private function checkJoinAlreadyDefined(array $joins, $alias)
|
||||
private function checkJoinAlreadyDefined(array $joins, $alias): bool
|
||||
{
|
||||
foreach ($joins as $join) {
|
||||
if ($join->getAlias() === $alias) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -119,51 +89,47 @@ class ActivityReasonFilter implements FilterInterface,
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
//create a local copy of translatableStringHelper
|
||||
$helper = $this->translatableStringHelper;
|
||||
|
||||
$builder->add('reasons', EntityType::class, array(
|
||||
'class' => 'ChillActivityBundle:ActivityReason',
|
||||
'choice_label' => function (ActivityReason $reason) use ($helper) {
|
||||
return $helper->localize($reason->getName());
|
||||
},
|
||||
'group_by' => function(ActivityReason $reason) use ($helper) {
|
||||
return $helper->localize($reason->getCategory()->getName());
|
||||
},
|
||||
$builder->add('reasons', EntityType::class, [
|
||||
'class' => ActivityReason::class,
|
||||
'choice_label' => fn(ActivityReason $reason) => $this->translatableStringHelper->localize($reason->getName()),
|
||||
'group_by' => fn(ActivityReason $reason) => $this->translatableStringHelper->localize($reason->getCategory()->getName()),
|
||||
'multiple' => true,
|
||||
'expanded' => false
|
||||
));
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function validateForm($data, ExecutionContextInterface $context)
|
||||
{
|
||||
if ($data['reasons'] === null || count($data['reasons']) === 0) {
|
||||
$context->buildViolation("At least one reason must be choosen")
|
||||
$context
|
||||
->buildViolation('At least one reason must be chosen')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
public function getTitle()
|
||||
{
|
||||
return 'Filter by reason';
|
||||
}
|
||||
|
||||
|
||||
public function addRole()
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
}
|
||||
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
// collect all the reasons'name used in this filter in one array
|
||||
$reasonsNames = array_map(
|
||||
function(ActivityReason $r) {
|
||||
return "\"".$this->translatableStringHelper->localize($r->getName())."\"";
|
||||
},
|
||||
$this->reasonRepository->findBy(array('id' => $data['reasons']->toArray()))
|
||||
);
|
||||
|
||||
return array("Filtered by reasons: only %list%",
|
||||
["%list%" => implode(", ", $reasonsNames)]);
|
||||
fn(ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"',
|
||||
$this->activityReasonRepository->findBy(array('id' => $data['reasons']->toArray()))
|
||||
);
|
||||
|
||||
return [
|
||||
'Filtered by reasons: only %list%',
|
||||
[
|
||||
'%list%' => implode(", ", $reasonsNames),
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -1,67 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 Champs-Libres <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Filter;
|
||||
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
use Chill\ActivityBundle\Entity\ActivityType;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
class ActivityTypeFilter implements FilterInterface,
|
||||
ExportElementValidatedInterface
|
||||
class ActivityTypeFilter implements FilterInterface, ExportElementValidatedInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
protected $translatableStringHelper;
|
||||
|
||||
/**
|
||||
* The repository for activity reasons
|
||||
*
|
||||
* @var EntityRepository
|
||||
*/
|
||||
protected $typeRepository;
|
||||
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
protected ActivityTypeRepository $activityTypeRepository;
|
||||
|
||||
public function __construct(
|
||||
TranslatableStringHelper $helper,
|
||||
EntityRepository $typeRepository
|
||||
TranslatableStringHelperInterface $translatableStringHelper,
|
||||
ActivityTypeRepository $activityTypeRepository
|
||||
) {
|
||||
$this->translatableStringHelper = $helper;
|
||||
$this->typeRepository = $typeRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->activityTypeRepository = $activityTypeRepository;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
@ -72,14 +42,14 @@ class ActivityTypeFilter implements FilterInterface,
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('selected_activity_types', $data['types']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if a join between Activity and Reason is already defined
|
||||
*
|
||||
*
|
||||
* @param Join[] $joins
|
||||
* @return boolean
|
||||
*/
|
||||
@ -90,7 +60,7 @@ class ActivityTypeFilter implements FilterInterface,
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -101,48 +71,50 @@ class ActivityTypeFilter implements FilterInterface,
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
//create a local copy of translatableStringHelper
|
||||
$helper = $this->translatableStringHelper;
|
||||
|
||||
$builder->add('types', EntityType::class, array(
|
||||
'class' => ActivityType::class,
|
||||
'choice_label' => function (ActivityType $type) use ($helper) {
|
||||
return $helper->localize($type->getName());
|
||||
},
|
||||
'multiple' => true,
|
||||
'expanded' => false
|
||||
));
|
||||
$builder->add(
|
||||
'types',
|
||||
EntityType::class,
|
||||
[
|
||||
'class' => ActivityType::class,
|
||||
'choice_label' => fn(ActivityType $type) => $this->translatableStringHelper->localize($type->getName()),
|
||||
'multiple' => true,
|
||||
'expanded' => false
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function validateForm($data, ExecutionContextInterface $context)
|
||||
{
|
||||
if ($data['types'] === null || count($data['types']) === 0) {
|
||||
$context->buildViolation("At least one type must be choosen")
|
||||
$context
|
||||
->buildViolation('At least one type must be chosen')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
public function getTitle()
|
||||
{
|
||||
return 'Filter by activity type';
|
||||
}
|
||||
|
||||
|
||||
public function addRole()
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
}
|
||||
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
// collect all the reasons'name used in this filter in one array
|
||||
$reasonsNames = array_map(
|
||||
function(ActivityType $t) {
|
||||
return "\"".$this->translatableStringHelper->localize($t->getName())."\"";
|
||||
},
|
||||
$this->typeRepository->findBy(array('id' => $data['types']->toArray()))
|
||||
);
|
||||
|
||||
return array("Filtered by activity type: only %list%",
|
||||
["%list%" => implode(", ", $reasonsNames)]);
|
||||
fn(ActivityType $t): string => '"' . $this->translatableStringHelper->localize($t->getName()) . '"',
|
||||
$this->activityTypeRepository->findBy(['id' => $data['types']->toArray()])
|
||||
);
|
||||
|
||||
return [
|
||||
'Filtered by activity type: only %list%',
|
||||
[
|
||||
'%list%' => implode(", ", $reasonsNames),
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +1,14 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 Champs-Libres <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Filter;
|
||||
|
||||
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
|
||||
@ -29,78 +18,58 @@ use Doctrine\ORM\Query\Expr;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Chill\ActivityBundle\Entity\ActivityReason;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class PersonHavingActivityBetweenDateFilter implements FilterInterface,
|
||||
ExportElementValidatedInterface
|
||||
class PersonHavingActivityBetweenDateFilter implements FilterInterface, ExportElementValidatedInterface
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
protected $translatableStringHelper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var EntityRepository
|
||||
*/
|
||||
protected $activityReasonRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
protected ActivityReasonRepository $activityReasonRepository;
|
||||
|
||||
protected TranslatorInterface $translator;
|
||||
|
||||
public function __construct(
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
EntityRepository $activityReasonRepository,
|
||||
TranslatorInterface $translator
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
ActivityReasonRepository $activityReasonRepository,
|
||||
TranslatorInterface $translator
|
||||
) {
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->activityReasonRepository = $activityReasonRepository;
|
||||
$this->translator = $translator;
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
|
||||
public function addRole()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(\Doctrine\ORM\QueryBuilder $qb, $data)
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
// create a query for activity
|
||||
$sqb = $qb->getEntityManager()->createQueryBuilder();
|
||||
$sqb->select("person_person_having_activity.id")
|
||||
->from("ChillActivityBundle:Activity", "activity_person_having_activity")
|
||||
->join("activity_person_having_activity.person", "person_person_having_activity")
|
||||
;
|
||||
$sqb->select('person_person_having_activity.id')
|
||||
->from('ChillActivityBundle:Activity', 'activity_person_having_activity')
|
||||
->join('activity_person_having_activity.person', 'person_person_having_activity');
|
||||
|
||||
// add clause between date
|
||||
$sqb->where("activity_person_having_activity.date BETWEEN "
|
||||
. ":person_having_activity_between_date_from"
|
||||
. " AND "
|
||||
. ":person_having_activity_between_date_to");
|
||||
$sqb->where('activity_person_having_activity.date BETWEEN '
|
||||
. ':person_having_activity_between_date_from'
|
||||
. ' AND '
|
||||
. ':person_having_activity_between_date_to');
|
||||
|
||||
// add clause activity reason
|
||||
$sqb->join('activity_person_having_activity.reasons',
|
||||
'reasons_person_having_activity');
|
||||
$sqb->join('activity_person_having_activity.reasons', 'reasons_person_having_activity');
|
||||
|
||||
$sqb->andWhere(
|
||||
$sqb->expr()->in(
|
||||
'reasons_person_having_activity',
|
||||
":person_having_activity_reasons")
|
||||
);
|
||||
|
||||
$sqb->expr()->in(
|
||||
'reasons_person_having_activity', ':person_having_activity_reasons'
|
||||
)
|
||||
);
|
||||
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->in('person.id', $sqb->getDQL());
|
||||
|
||||
@ -109,11 +78,11 @@ class PersonHavingActivityBetweenDateFilter implements FilterInterface,
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('person_having_activity_between_date_from',
|
||||
$qb->setParameter('person_having_activity_between_date_from',
|
||||
$data['date_from']);
|
||||
$qb->setParameter('person_having_activity_between_date_to',
|
||||
$qb->setParameter('person_having_activity_between_date_to',
|
||||
$data['date_to']);
|
||||
$qb->setParameter('person_having_activity_reasons', $data['reasons']);
|
||||
}
|
||||
@ -123,51 +92,45 @@ class PersonHavingActivityBetweenDateFilter implements FilterInterface,
|
||||
return Declarations::PERSON_IMPLIED_IN;
|
||||
}
|
||||
|
||||
public function buildForm(\Symfony\Component\Form\FormBuilderInterface $builder)
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('date_from', DateType::class, array(
|
||||
'label' => "Implied in an activity after this date",
|
||||
$builder->add('date_from', DateType::class, [
|
||||
'label' => 'Implied in an activity after this date',
|
||||
'data' => new \DateTime(),
|
||||
'attr' => array('class' => 'datepicker'),
|
||||
'attr' => ['class' => 'datepicker'],
|
||||
'widget'=> 'single_text',
|
||||
'format' => 'dd-MM-yyyy',
|
||||
));
|
||||
|
||||
$builder->add('date_to', DateType::class, array(
|
||||
'label' => "Implied in an activity before this date",
|
||||
]);
|
||||
|
||||
$builder->add('date_to', DateType::class, [
|
||||
'label' => 'Implied in an activity before this date',
|
||||
'data' => new \DateTime(),
|
||||
'attr' => array('class' => 'datepicker'),
|
||||
'attr' => ['class' => 'datepicker'],
|
||||
'widget'=> 'single_text',
|
||||
'format' => 'dd-MM-yyyy',
|
||||
));
|
||||
|
||||
$builder->add('reasons', EntityType::class, array(
|
||||
'class' => 'ChillActivityBundle:ActivityReason',
|
||||
'choice_label' => function (ActivityReason $reason) {
|
||||
return $this->translatableStringHelper
|
||||
->localize($reason->getName());
|
||||
},
|
||||
'group_by' => function(ActivityReason $reason) {
|
||||
return $this->translatableStringHelper
|
||||
->localize($reason->getCategory()->getName());
|
||||
},
|
||||
]);
|
||||
|
||||
$builder->add('reasons', EntityType::class, [
|
||||
'class' => ActivityReason::class,
|
||||
'choice_label' => fn (ActivityReason $reason): ?string => $this->translatableStringHelper->localize($reason->getName()),
|
||||
'group_by' => fn(ActivityReason $reason): ?string => $this->translatableStringHelper->localize($reason->getCategory()->getName()),
|
||||
'data' => $this->activityReasonRepository->findAll(),
|
||||
'multiple' => true,
|
||||
'expanded' => false,
|
||||
'label' => "Activity reasons for those activities"
|
||||
));
|
||||
|
||||
'label' => 'Activity reasons for those activities'
|
||||
]);
|
||||
|
||||
$builder->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
|
||||
/* @var $filterForm \Symfony\Component\Form\FormInterface */
|
||||
/* @var FormInterface $filterForm */
|
||||
$filterForm = $event->getForm()->getParent();
|
||||
$enabled = $filterForm->get(FilterType::ENABLED_FIELD)->getData();
|
||||
|
||||
|
||||
if ($enabled === true) {
|
||||
// if the filter is enabled, add some validation
|
||||
$form = $event->getForm();
|
||||
$date_from = $form->get('date_from')->getData();
|
||||
$date_to = $form->get('date_to')->getData();
|
||||
|
||||
|
||||
// check that fields are not empty
|
||||
if ($date_from === null) {
|
||||
$form->get('date_from')->addError(new FormError(
|
||||
@ -178,8 +141,8 @@ class PersonHavingActivityBetweenDateFilter implements FilterInterface,
|
||||
$form->get('date_to')->addError(new FormError(
|
||||
$this->translator->trans('This field '
|
||||
. 'should not be empty')));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// check that date_from is before date_to
|
||||
if (
|
||||
($date_from !== null && $date_to !== null)
|
||||
@ -194,35 +157,37 @@ class PersonHavingActivityBetweenDateFilter implements FilterInterface,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public function validateForm($data, ExecutionContextInterface $context)
|
||||
{
|
||||
if ($data['reasons'] === null || count($data['reasons']) === 0) {
|
||||
$context->buildViolation("At least one reason must be choosen")
|
||||
$context->buildViolation('At least one reason must be chosen')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
return array(
|
||||
"Filtered by person having an activity between %date_from% and "
|
||||
. "%date_to% with reasons %reasons_name%",
|
||||
array(
|
||||
"%date_from%" => $data['date_from']->format('d-m-Y'),
|
||||
return [
|
||||
'Filtered by person having an activity between %date_from% and '
|
||||
. '%date_to% with reasons %reasons_name%',
|
||||
[
|
||||
'%date_from%' => $data['date_from']->format('d-m-Y'),
|
||||
'%date_to%' => $data['date_to']->format('d-m-Y'),
|
||||
"%reasons_name%" => implode(", ", array_map(
|
||||
function (ActivityReason $r) {
|
||||
return '"'.$this->translatableStringHelper->
|
||||
localize($r->getName()).'"';
|
||||
},
|
||||
$data['reasons']))
|
||||
));
|
||||
'%reasons_name%' => implode(
|
||||
", ",
|
||||
array_map(
|
||||
fn(ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"',
|
||||
$data['reasons']
|
||||
)
|
||||
)
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return "Filtered by person having an activity in a period";
|
||||
return 'Filtered by person having an activity in a period';
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,56 +1,29 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
||||
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Form\Type;
|
||||
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Chill\ActivityBundle\Entity\ActivityType;
|
||||
|
||||
/**
|
||||
* Description of TranslatableActivityType
|
||||
*
|
||||
* @author Champs-Libres Coop
|
||||
*/
|
||||
class TranslatableActivityType extends AbstractType
|
||||
{
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
protected $translatableStringHelper;
|
||||
|
||||
protected $activityTypeRepository;
|
||||
protected ActivityTypeRepository $activityTypeRepository;
|
||||
|
||||
public function __construct(
|
||||
TranslatableStringHelper $helper,
|
||||
EntityRepository $activityTypeRepository
|
||||
)
|
||||
{
|
||||
TranslatableStringHelperInterface $helper,
|
||||
ActivityTypeRepository $activityTypeRepository
|
||||
) {
|
||||
$this->translatableStringHelper = $helper;
|
||||
$this->activityTypeRepository = $activityTypeRepository;
|
||||
}
|
||||
@ -65,22 +38,21 @@ class TranslatableActivityType extends AbstractType
|
||||
return EntityType::class;
|
||||
}
|
||||
|
||||
public function buildForm(\Symfony\Component\Form\FormBuilderInterface $builder, array $options) {
|
||||
/* @var $qb \Doctrine\ORM\QueryBuilder */
|
||||
public function buildForm(FormBuilderInterface $builder, array $options) {
|
||||
/* @var QueryBuilder $qb */
|
||||
$qb = $options['query_builder'];
|
||||
|
||||
if ($options['active_only'] === true) {
|
||||
$qb->where($qb->expr()->eq('at.active', ':active'));
|
||||
$qb->setParameter('active', true, \Doctrine\DBAL\Types\Types::BOOLEAN);
|
||||
$qb->setParameter('active', true, Types::BOOLEAN);
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
|
||||
$resolver->setDefaults(
|
||||
array(
|
||||
'class' => 'ChillActivityBundle:ActivityType',
|
||||
'class' => ActivityType::class,
|
||||
'active_only' => true,
|
||||
'query_builder' => $this->activityTypeRepository
|
||||
->createQueryBuilder('at'),
|
||||
|
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\ActivityBundle\Entity\ActivityReasonCategory;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method ActivityReasonCategory|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method ActivityReasonCategory|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method ActivityReasonCategory[] findAll()
|
||||
* @method ActivityReasonCategory[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class ActivityReasonCategoryRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, ActivityReasonCategory::class);
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\ActivityBundle\Entity\ActivityReason;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method ActivityReason|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method ActivityReason|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method ActivityReason[] findAll()
|
||||
* @method ActivityReason[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class ActivityReasonRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, ActivityReason::class);
|
||||
}
|
||||
}
|
@ -1,24 +1,6 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2021, Champs Libres Cooperative SCRLFS,
|
||||
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
@ -29,10 +11,10 @@ use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method AccompanyingPeriodParticipation|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method AccompanyingPeriodParticipation|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method AccompanyingPeriodParticipation[] findAll()
|
||||
* @method AccompanyingPeriodParticipation[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
* @method Activity|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method Activity|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method Activity[] findAll()
|
||||
* @method Activity[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class ActivityRepository extends ServiceEntityRepository
|
||||
{
|
||||
@ -42,12 +24,7 @@ class ActivityRepository extends ServiceEntityRepository
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $person
|
||||
* @param array $scopes
|
||||
* @param string[] $orderBy
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return array|Activity[]
|
||||
* @return Activity[]
|
||||
*/
|
||||
public function findByPersonImplied(Person $person, array $scopes, ?array $orderBy = [ 'date' => 'DESC'], ?int $limit = 100, ?int $offset = 0): array
|
||||
{
|
||||
@ -63,8 +40,7 @@ class ActivityRepository extends ServiceEntityRepository
|
||||
':person MEMBER OF a.persons'
|
||||
)
|
||||
)
|
||||
->setParameter('person', $person)
|
||||
;
|
||||
->setParameter('person', $person);
|
||||
|
||||
foreach ($orderBy as $k => $dir) {
|
||||
$qb->addOrderBy('a.'.$k, $dir);
|
||||
@ -72,17 +48,11 @@ class ActivityRepository extends ServiceEntityRepository
|
||||
|
||||
$qb->setMaxResults($limit)->setFirstResult($offset);
|
||||
|
||||
return $qb->getQuery()
|
||||
->getResult();
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccompanyingPeriod $period
|
||||
* @param array $scopes
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @param array|string[] $orderBy
|
||||
* @return array|Activity[]
|
||||
* @return Activity[]
|
||||
*/
|
||||
public function findByAccompanyingPeriod(AccompanyingPeriod $period, array $scopes, ?bool $allowNullScope = false, ?int $limit = 100, ?int $offset = 0, array $orderBy = ['date' => 'desc']): array
|
||||
{
|
||||
@ -92,8 +62,7 @@ class ActivityRepository extends ServiceEntityRepository
|
||||
if (!$allowNullScope) {
|
||||
$qb
|
||||
->where($qb->expr()->in('a.scope', ':scopes'))
|
||||
->setParameter('scopes', $scopes)
|
||||
;
|
||||
->setParameter('scopes', $scopes);
|
||||
} else {
|
||||
$qb
|
||||
->where(
|
||||
@ -102,16 +71,14 @@ class ActivityRepository extends ServiceEntityRepository
|
||||
$qb->expr()->isNull('a.scope')
|
||||
)
|
||||
)
|
||||
->setParameter('scopes', $scopes)
|
||||
;
|
||||
->setParameter('scopes', $scopes);
|
||||
}
|
||||
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->eq('a.accompanyingPeriod', ':period')
|
||||
)
|
||||
->setParameter('period', $period)
|
||||
;
|
||||
->setParameter('period', $period);
|
||||
|
||||
foreach ($orderBy as $k => $dir) {
|
||||
$qb->addOrderBy('a.'.$k, $dir);
|
||||
@ -119,7 +86,6 @@ class ActivityRepository extends ServiceEntityRepository
|
||||
|
||||
$qb->setMaxResults($limit)->setFirstResult($offset);
|
||||
|
||||
return $qb->getQuery()
|
||||
->getResult();
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\ActivityBundle\Entity\ActivityTypeCategory;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method ActivityTypeCategory|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method ActivityTypeCategory|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method ActivityTypeCategory[] findAll()
|
||||
* @method ActivityTypeCategory[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class ActivityTypeCategoryRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, ActivityTypeCategory::class);
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\ActivityBundle\Entity\ActivityType;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method ActivityType|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method ActivityType|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method ActivityType[] findAll()
|
||||
* @method ActivityType[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class ActivityTypeRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, ActivityType::class);
|
||||
}
|
||||
}
|
@ -11,9 +11,12 @@
|
||||
</div>
|
||||
|
||||
<div v-if="getContext === 'accompanyingCourse' && filterSuggestedPersons.length > 0">
|
||||
<ul>
|
||||
<ul class="list-unstyled">
|
||||
<li v-for="p in filterSuggestedPersons" @click="addNewPerson(p)">
|
||||
{{ p.text }}
|
||||
<span class="badge bg-primary" style="cursor: pointer;">
|
||||
<i class="fa fa-plus fa-fw text-success"></i>
|
||||
{{ p.text }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<span class="chill_denomination">
|
||||
{{ textCutted }}
|
||||
</span>
|
||||
<a class="fa fa-fw fa-times"
|
||||
<a class="fa fa-fw fa-times text-danger text-decoration-none"
|
||||
@click.prevent="$emit('remove', person)">
|
||||
</a>
|
||||
</span>
|
||||
|
@ -27,14 +27,16 @@
|
||||
{{ activity.type.name | localize_translatable_string }}
|
||||
|
||||
<ul class="small_in_title">
|
||||
{% if activity.location and t.locationVisible %}
|
||||
<li>
|
||||
<abbr title="{{ 'location'|trans }}">{{ 'location'|trans ~ ': ' }}</abbr>
|
||||
{# TODO {% if activity.location %}{{ activity.location }}{% endif %} #}
|
||||
Domicile de l'usager
|
||||
<span class="item-key">{{ 'location'|trans ~ ': ' }}</span>
|
||||
<span>{{ activity.location.locationType.title|localize_translatable_string }}</span>
|
||||
{{ activity.location.name }}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if activity.user and t.userVisible %}
|
||||
<li>
|
||||
<abbr title="{{ 'Referrer'|trans }}">{{ 'Referrer'|trans ~ ': ' }}</abbr>
|
||||
<span class="item-key">{{ 'Referrer'|trans ~ ': ' }}</span>
|
||||
{{ activity.user.usernameCanonical }}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
@ -40,7 +40,6 @@
|
||||
},
|
||||
{ 'title': 'Users concerned'|trans,
|
||||
'items': entity.users,
|
||||
'path' : 'admin_user_show',
|
||||
'key' : 'id'
|
||||
},
|
||||
] %}
|
||||
@ -58,6 +57,7 @@
|
||||
<ul class="list-content">
|
||||
{% for item in bloc.items %}
|
||||
<li>
|
||||
{% if bloc.path is defined %}
|
||||
<a href="{{ _self.href(bloc.path, bloc.key, item.id) }}">
|
||||
<span class="{% if (badge_person is defined and badge_person == true) %}badge-person{% else %}badge bg-primary{% endif %}">
|
||||
{{ item|chill_entity_render_box({
|
||||
@ -66,6 +66,14 @@
|
||||
}) }}
|
||||
</span>
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="{% if (badge_person is defined and badge_person == true) %}badge-person{% else %}badge bg-primary{% endif %}">
|
||||
{{ item|chill_entity_render_box({
|
||||
'render': 'raw',
|
||||
'addAltNames': false
|
||||
}) }}
|
||||
</span>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
@ -85,6 +93,7 @@
|
||||
<ul class="list-content">
|
||||
{% for item in bloc.items %}
|
||||
<li>
|
||||
{% if bloc.path is defined %}
|
||||
<a href="{{ _self.href(bloc.path, bloc.key, item.id) }}">
|
||||
<span class="{% if (badge_person is defined and badge_person == true) %}badge-person{% else %}badge bg-primary{% endif %}">
|
||||
{{ item|chill_entity_render_box({
|
||||
@ -93,6 +102,12 @@
|
||||
}) }}
|
||||
</span>
|
||||
</a>
|
||||
{% else %}
|
||||
{{ item|chill_entity_render_box({
|
||||
'render': 'raw',
|
||||
'addAltNames': false
|
||||
}) }}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
@ -114,12 +129,19 @@
|
||||
{% for item in bloc.items %}
|
||||
|
||||
<span class="wl-item {% if (badge_person is defined and badge_person == true) %}badge-person{% else %}badge bg-primary{% endif %}">
|
||||
{% if bloc.path is defined %}
|
||||
<a href="{{ _self.href(bloc.path, bloc.key, item.id) }}">
|
||||
{{ item|chill_entity_render_box({
|
||||
'render': 'raw',
|
||||
'addAltNames': false
|
||||
}) }}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ item|chill_entity_render_box({
|
||||
'render': 'raw',
|
||||
'addAltNames': false
|
||||
}) }}
|
||||
{% endif %}
|
||||
</span>
|
||||
|
||||
{% endfor %}
|
||||
|
@ -10,7 +10,7 @@
|
||||
'title' : 'Remove activity'|trans,
|
||||
'confirm_question' : 'Are you sure you want to remove the activity about "%name%" ?'|trans({ '%name%' : accompanyingCourse.id } ),
|
||||
'cancel_route' : 'chill_activity_activity_list',
|
||||
'cancel_parameters' : { 'accompanying_course_id' : accompanyingCourse.id, 'id' : activity.id },
|
||||
'cancel_parameters' : { 'accompanying_period_id' : accompanyingCourse.id, 'id' : activity.id },
|
||||
'form' : delete_form
|
||||
} ) }}
|
||||
{% endblock %}
|
||||
|
@ -55,7 +55,7 @@
|
||||
{% endif %}
|
||||
|
||||
<h2 class="chill-red">{{ 'Concerned groups'|trans }}</h2>
|
||||
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {'context': context, 'with_display': 'bloc' } %}
|
||||
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {'context': context, 'with_display': 'bloc', 'badge_person': 'true' } %}
|
||||
|
||||
<h2 class="chill-red">{{ 'Activity data'|trans }}</h2>
|
||||
|
||||
|
@ -1,4 +1,2 @@
|
||||
|
||||
{{ dump(notification) }}
|
||||
|
||||
<a href="{{ path('chill_activity_activity_show', {'id': notification.relatedEntityId }) }}">Go to Activity</a>
|
||||
|
@ -1,94 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
* Copyright (C) 2015 Champs Libres <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Timeline;
|
||||
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface;
|
||||
use Chill\MainBundle\Timeline\TimelineProviderInterface;
|
||||
use Chill\ActivityBundle\Repository\ActivityACLAwareRepository;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\MainBundle\Timeline\TimelineSingleQuery;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
/**
|
||||
* Provide activity for inclusion in timeline
|
||||
*
|
||||
*/
|
||||
class TimelineActivityProvider implements TimelineProviderInterface
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* @var EntityManager
|
||||
*/
|
||||
protected $em;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var AuthorizationHelper
|
||||
*/
|
||||
protected $helper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \Chill\MainBundle\Entity\User
|
||||
*/
|
||||
protected $user;
|
||||
protected EntityManagerInterface $em;
|
||||
|
||||
protected AuthorizationHelperInterface $helper;
|
||||
|
||||
protected UserInterface $user;
|
||||
|
||||
protected ActivityACLAwareRepository $aclAwareRepository;
|
||||
|
||||
private const SUPPORTED_CONTEXTS = [ 'center', 'person'];
|
||||
|
||||
/**
|
||||
* TimelineActivityProvider constructor.
|
||||
*
|
||||
* @param EntityManager $em
|
||||
* @param AuthorizationHelper $helper
|
||||
* @param TokenStorageInterface $storage
|
||||
*/
|
||||
|
||||
public function __construct(
|
||||
EntityManager $em,
|
||||
AuthorizationHelper $helper,
|
||||
EntityManagerInterface $em,
|
||||
AuthorizationHelperInterface $helper,
|
||||
TokenStorageInterface $storage,
|
||||
ActivityACLAwareRepository $aclAwareRepository
|
||||
)
|
||||
{
|
||||
) {
|
||||
$this->em = $em;
|
||||
$this->helper = $helper;
|
||||
$this->aclAwareRepository = $aclAwareRepository;
|
||||
|
||||
if (!$storage->getToken()->getUser() instanceof \Chill\MainBundle\Entity\User)
|
||||
|
||||
if (!$storage->getToken()->getUser() instanceof User)
|
||||
{
|
||||
throw new \RuntimeException('A user should be authenticated !');
|
||||
}
|
||||
|
||||
|
||||
$this->user = $storage->getToken()->getUser();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function fetchQuery($context, array $args)
|
||||
@ -97,43 +56,42 @@ class TimelineActivityProvider implements TimelineProviderInterface
|
||||
return TimelineSingleQuery::fromArray($this->aclAwareRepository
|
||||
->queryTimelineIndexer($context, $args));
|
||||
}
|
||||
|
||||
|
||||
$metadataActivity = $this->em->getClassMetadata(Activity::class);
|
||||
|
||||
[$where, $parameters] = $this->getWhereClauseForPerson($args['person']);
|
||||
|
||||
|
||||
return TimelineSingleQuery::fromArray([
|
||||
'id' => $metadataActivity->getTableName()
|
||||
.'.'.$metadataActivity->getColumnName('id'),
|
||||
'type' => 'activity',
|
||||
'date' => $metadataActivity->getTableName()
|
||||
.'.'.$metadataActivity->getColumnName('date'),
|
||||
'FROM' => $this->getFromClausePerson($args['person']),
|
||||
'FROM' => $this->getFromClausePerson(),
|
||||
'WHERE' => $where,
|
||||
'parameters' => $parameters
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
private function getWhereClauseForPerson(Person $person)
|
||||
{
|
||||
$parameters = [];
|
||||
$metadataActivity = $this->em->getClassMetadata(Activity::class);
|
||||
$associationMapping = $metadataActivity->getAssociationMapping('person');
|
||||
$role = new Role('CHILL_ACTIVITY_SEE');
|
||||
$reachableScopes = $this->helper->getReachableScopes($this->user,
|
||||
$role, $person->getCenter());
|
||||
$reachableScopes = $this->helper->getReachableScopes($this->user, $role->getRole(), $person->getCenter());
|
||||
$whereClause = sprintf(' {activity.person_id} = ? AND {activity.scope_id} IN ({scopes_ids}) ');
|
||||
$scopes_ids = [];
|
||||
|
||||
// first parameter: activity.person_id
|
||||
// first parameter: activity.person_id
|
||||
$parameters[] = $person->getId();
|
||||
|
||||
// loop on reachable scopes
|
||||
// loop on reachable scopes
|
||||
foreach ($reachableScopes as $scope) {
|
||||
if (\in_array($scope->getId(), $scopes_ids)) {
|
||||
continue;
|
||||
}
|
||||
$scopes_ids[] = '?';
|
||||
$scopes_ids[] = '?';
|
||||
$parameters[] = $scope->getId();
|
||||
}
|
||||
|
||||
@ -151,47 +109,40 @@ class TimelineActivityProvider implements TimelineProviderInterface
|
||||
$parameters
|
||||
];
|
||||
}
|
||||
|
||||
private function getFromClausePerson()
|
||||
|
||||
private function getFromClausePerson(): string
|
||||
{
|
||||
$metadataActivity = $this->em->getClassMetadata(Activity::class);
|
||||
$metadataPerson = $this->em->getClassMetadata(Person::class);
|
||||
$associationMapping = $metadataActivity->getAssociationMapping('person');
|
||||
|
||||
return $metadataActivity->getTableName().' JOIN '
|
||||
.$metadataPerson->getTableName().' ON '
|
||||
.$metadataPerson->getTableName().'.'.
|
||||
$associationMapping['joinColumns'][0]['referencedColumnName']
|
||||
.' = '
|
||||
.$associationMapping['joinColumns'][0]['name']
|
||||
;
|
||||
|
||||
return sprintf(
|
||||
"%s JOIN %s ON %s.%s = %s",
|
||||
$metadataActivity->getTableName(),
|
||||
$metadataPerson->getTableName(),
|
||||
$metadataPerson->getTableName(),
|
||||
$associationMapping['joinColumns'][0]['referencedColumnName'],
|
||||
$associationMapping['joinColumns'][0]['name']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getEntities(array $ids)
|
||||
|
||||
public function getEntities(array $ids): array
|
||||
{
|
||||
$activities = $this->em->getRepository(Activity::class)
|
||||
->findBy(array('id' => $ids));
|
||||
|
||||
|
||||
$result = array();
|
||||
foreach($activities as $activity) {
|
||||
$result[$activity->getId()] = $activity;
|
||||
}
|
||||
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getEntityTemplate($entity, $context, array $args)
|
||||
public function getEntityTemplate($entity, $context, array $args): array
|
||||
{
|
||||
$this->checkContext($context);
|
||||
|
||||
|
||||
return [
|
||||
'template' => 'ChillActivityBundle:Timeline:activity_person_context.html.twig',
|
||||
'template_data' => [
|
||||
@ -201,26 +152,25 @@ class TimelineActivityProvider implements TimelineProviderInterface
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function supportsType($type)
|
||||
public function supportsType($type): bool
|
||||
{
|
||||
return $type === 'activity';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* check if the context is supported
|
||||
*
|
||||
* @param string $context
|
||||
* Check if the context is supported.
|
||||
*
|
||||
* @throws \LogicException if the context is not supported
|
||||
*/
|
||||
private function checkContext($context)
|
||||
private function checkContext(string $context)
|
||||
{
|
||||
if (FALSE === \in_array($context, self::SUPPORTED_CONTEXTS)) {
|
||||
throw new \LogicException("The context '$context' is not "
|
||||
. "supported. Currently only 'person' is supported");
|
||||
throw new \LogicException(
|
||||
sprintf(
|
||||
"The context '%s' is not supported. Currently only 'person' is supported",
|
||||
$context
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
services:
|
||||
_defaults:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
chill.activity.timeline:
|
||||
class: Chill\ActivityBundle\Timeline\TimelineActivityProvider
|
||||
@ -13,17 +16,14 @@ services:
|
||||
- { name: chill.timeline, context: 'center' }
|
||||
|
||||
Chill\ActivityBundle\Menu\:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
resource: '../Menu/'
|
||||
tags: ['chill.menu_builder']
|
||||
|
||||
Chill\ActivityBundle\Notification\:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
resource: '../Notification'
|
||||
|
||||
Chill\ActivityBundle\Security\Authorization\:
|
||||
resource: '../Security/Authorization/'
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Chill\ActivityBundle\Repository\:
|
||||
resource: '../Repository/'
|
||||
|
@ -1,82 +1,56 @@
|
||||
services:
|
||||
_defaults:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
chill.activity.export.count_activity:
|
||||
class: Chill\ActivityBundle\Export\Export\CountActivity
|
||||
arguments:
|
||||
- "@doctrine.orm.entity_manager"
|
||||
tags:
|
||||
- { name: chill.export, alias: 'count_activity' }
|
||||
|
||||
|
||||
chill.activity.export.sum_activity_duration:
|
||||
class: Chill\ActivityBundle\Export\Export\StatActivityDuration
|
||||
arguments:
|
||||
- "@doctrine.orm.entity_manager"
|
||||
- "sum"
|
||||
tags:
|
||||
- { name: chill.export, alias: 'sum_activity_duration' }
|
||||
|
||||
|
||||
chill.activity.export.list_activity:
|
||||
class: Chill\ActivityBundle\Export\Export\ListActivity
|
||||
arguments:
|
||||
- "@doctrine.orm.entity_manager"
|
||||
- "@translator"
|
||||
- "@chill.main.helper.translatable_string"
|
||||
tags:
|
||||
- { name: chill.export, alias: 'list_activity' }
|
||||
|
||||
|
||||
chill.activity.export.reason_filter:
|
||||
class: Chill\ActivityBundle\Export\Filter\ActivityReasonFilter
|
||||
arguments:
|
||||
- "@chill.main.helper.translatable_string"
|
||||
- "@chill_activity.repository.reason"
|
||||
tags:
|
||||
- { name: chill.export_filter, alias: 'activity_reason_filter' }
|
||||
|
||||
|
||||
chill.activity.export.type_filter:
|
||||
class: Chill\ActivityBundle\Export\Filter\ActivityTypeFilter
|
||||
arguments:
|
||||
- "@chill.main.helper.translatable_string"
|
||||
- "@chill_activity.repository.activity_type"
|
||||
tags:
|
||||
- { name: chill.export_filter, alias: 'activity_type_filter' }
|
||||
|
||||
|
||||
chill.activity.export.date_filter:
|
||||
class: Chill\ActivityBundle\Export\Filter\ActivityDateFilter
|
||||
arguments:
|
||||
- "@translator"
|
||||
tags:
|
||||
- { name: chill.export_filter, alias: 'activity_date_filter' }
|
||||
|
||||
chill.activity.export.person_having_an_activity_between_date_filter:
|
||||
class: Chill\ActivityBundle\Export\Filter\PersonHavingActivityBetweenDateFilter
|
||||
arguments:
|
||||
- "@chill.main.helper.translatable_string"
|
||||
- "@chill_activity.repository.reason"
|
||||
- "@translator"
|
||||
tags:
|
||||
- #0 register as a filter
|
||||
name: chill.export_filter
|
||||
alias: 'activity_person_having_ac_bw_date_filter'
|
||||
|
||||
|
||||
chill.activity.export.reason_aggregator:
|
||||
class: Chill\ActivityBundle\Export\Aggregator\ActivityReasonAggregator
|
||||
arguments:
|
||||
- "@chill_activity.repository.reason_category"
|
||||
- "@chill_activity.repository.reason"
|
||||
- "@chill.main.helper.translatable_string"
|
||||
tags:
|
||||
- { name: chill.export_aggregator, alias: activity_reason_aggregator }
|
||||
|
||||
|
||||
chill.activity.export.type_aggregator:
|
||||
class: Chill\ActivityBundle\Export\Aggregator\ActivityTypeAggregator
|
||||
arguments:
|
||||
- "@chill_activity.repository.activity_type"
|
||||
- "@chill.main.helper.translatable_string"
|
||||
tags:
|
||||
- { name: chill.export_aggregator, alias: activity_type_aggregator }
|
||||
|
||||
|
||||
chill.activity.export.user_aggregator:
|
||||
class: Chill\ActivityBundle\Export\Aggregator\ActivityUserAggregator
|
||||
arguments:
|
||||
$em: "@doctrine.orm.entity_manager"
|
||||
tags:
|
||||
- { name: chill.export_aggregator, alias: activity_user_aggregator }
|
||||
|
@ -1,4 +1,6 @@
|
||||
services:
|
||||
Chill\ActivityBundle\DataFixtures\ORM\:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
resource: ../../DataFixtures/ORM
|
||||
tags: [ 'doctrine.fixture.orm' ]
|
||||
|
@ -1,28 +1,12 @@
|
||||
---
|
||||
services:
|
||||
chill_activity.repository.activity_type:
|
||||
class: Doctrine\ORM\EntityRepository
|
||||
factory: ['@doctrine.orm.entity_manager', getRepository]
|
||||
arguments:
|
||||
- 'Chill\ActivityBundle\Entity\ActivityType'
|
||||
|
||||
chill_activity.repository.reason:
|
||||
class: Doctrine\ORM\EntityRepository
|
||||
factory: ['@doctrine.orm.entity_manager', getRepository]
|
||||
arguments:
|
||||
- 'Chill\ActivityBundle\Entity\ActivityReason'
|
||||
|
||||
chill_activity.repository.reason_category:
|
||||
class: Doctrine\ORM\EntityRepository
|
||||
factory: ['@doctrine.orm.entity_manager', getRepository]
|
||||
arguments:
|
||||
- 'Chill\ActivityBundle\Entity\ActivityReasonCategory'
|
||||
|
||||
Chill\ActivityBundle\Repository\ActivityRepository:
|
||||
tags: [doctrine.repository_service]
|
||||
arguments:
|
||||
- '@Doctrine\Persistence\ManagerRegistry'
|
||||
chill_activity.repository.activity_type: '@Chill\ActivityBundle\Repository\ActivityTypeRepository'
|
||||
chill_activity.repository.reason: '@Chill\ActivityBundle\Repository\ActivityReasonRepository'
|
||||
chill_activity.repository.reason_category: '@Chill\ActivityBundle\Repository\ActivityReasonCategoryRepository'
|
||||
|
||||
# This is not a repository but merely a service. It needs to be moved out for simplicity.
|
||||
# The autowire and autoconfigure should be enabled globally and removed from the definition of the service.
|
||||
# Once autoloaded, there is no need to alias it to the interface here, it will be done automatically by Symfony.
|
||||
Chill\ActivityBundle\Repository\ActivityACLAwareRepository:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Activity;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20211119173555 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'remove comment on deprecated json_array type';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$columns = [
|
||||
'activitytype.name',
|
||||
'activitytypecategory.name'
|
||||
];
|
||||
|
||||
foreach ($columns as $col) {
|
||||
$this->addSql("COMMENT ON COLUMN $col IS NULL");
|
||||
}
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->throwIrreversibleMigrationException();
|
||||
}
|
||||
}
|
@ -15,8 +15,7 @@ use Doctrine\Common\Collections\Criteria;
|
||||
|
||||
final class AsideActivityController extends CRUDController
|
||||
{
|
||||
|
||||
private $categoryRepository;
|
||||
private AsideActivityCategoryRepository $categoryRepository;
|
||||
|
||||
public function __construct(AsideActivityCategoryRepository $categoryRepository)
|
||||
{
|
||||
@ -25,7 +24,7 @@ final class AsideActivityController extends CRUDController
|
||||
|
||||
protected function buildQueryEntities(string $action, Request $request, ?FilterOrderHelper $filterOrder = null)
|
||||
{
|
||||
$qb = parent::buildQueryEntities($action, $request, $filterOrder);
|
||||
$qb = parent::buildQueryEntities($action, $request);
|
||||
|
||||
if ('index' === $action) {
|
||||
$qb->where($qb->expr()->eq('e.agent', ':user'));
|
||||
|
@ -19,8 +19,6 @@ final class ChillAsideActivityExtension extends Extension implements PrependExte
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
public function load(array $configs, ContainerBuilder $container): void
|
||||
{
|
||||
@ -111,4 +109,4 @@ final class ChillAsideActivityExtension extends Extension implements PrependExte
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,13 +44,15 @@ class AsideActivityCategory
|
||||
* @ORM\ManyToOne(targetEntity=AsideActivityCategory::class, inversedBy="children")
|
||||
* @ORM\JoinColumn(nullable=true)
|
||||
*/
|
||||
private $parent;
|
||||
private ?AsideActivityCategory $parent = null;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=AsideActivityCategory::class, mappedBy="parent")
|
||||
*/
|
||||
private $children;
|
||||
|
||||
private AsideActivityCategory $oldParent;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->children = new ArrayCollection();
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\AsideActivityBundle\Form;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
|
||||
@ -14,12 +16,11 @@ use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
final class AsideActivityCategoryType extends AbstractType
|
||||
{
|
||||
private CategoryRender $categoryRender;
|
||||
|
||||
protected $translatableStringHelper;
|
||||
|
||||
public function __construct(TranslatableStringHelper $translatableStringHelper, CategoryRender $categoryRender)
|
||||
{
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
public function __construct(
|
||||
CategoryRender $categoryRender
|
||||
) {
|
||||
$this->categoryRender = $categoryRender;
|
||||
}
|
||||
|
||||
|
@ -25,18 +25,16 @@ use Symfony\Component\Templating\EngineInterface;
|
||||
|
||||
final class AsideActivityFormType extends AbstractType
|
||||
{
|
||||
protected array $timeChoices;
|
||||
private array $timeChoices;
|
||||
private TokenStorageInterface $storage;
|
||||
private CategoryRender $categoryRender;
|
||||
|
||||
public function __construct (
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
ParameterBagInterface $parameterBag,
|
||||
TokenStorageInterface $storage,
|
||||
CategoryRender $categoryRender
|
||||
){
|
||||
$this->timeChoices = $parameterBag->get('chill_aside_activity.form.time_duration');
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->storage = $storage;
|
||||
$this->categoryRender = $categoryRender;
|
||||
}
|
||||
|
@ -30,7 +30,9 @@ final class CategoryRender implements ChillEntityRenderInterface
|
||||
{
|
||||
$options = array_merge(self::DEFAULT_ARGS, $options);
|
||||
|
||||
$titles[] = $this->translatableStringHelper->localize($asideActivityCategory->getTitle());
|
||||
$titles = [
|
||||
$this->translatableStringHelper->localize($asideActivityCategory->getTitle()),
|
||||
];
|
||||
|
||||
while ($asideActivityCategory->hasParent()) {
|
||||
$asideActivityCategory = $asideActivityCategory->getParent();
|
||||
|
@ -1,42 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\AMLI\BudgetBundle\Form;
|
||||
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Chill\AMLI\BudgetBundle\Config\ConfigRepository;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\AMLI\BudgetBundle\Entity\Charge;
|
||||
|
||||
class ChargeType extends AbstractType
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var ConfigRepository
|
||||
*/
|
||||
protected $configRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
protected $translatableStringHelper;
|
||||
|
||||
protected ConfigRepository $configRepository;
|
||||
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
ConfigRepository $configRepository,
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
ConfigRepository $configRepository,
|
||||
TranslatableStringHelperInterface $translatableStringHelper
|
||||
) {
|
||||
$this->configRepository = $configRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
@ -45,24 +37,23 @@ class ChargeType extends AbstractType
|
||||
'placeholder' => 'Choose a charge type'
|
||||
])
|
||||
->add('amount', MoneyType::class)
|
||||
->add('comment', TextAreaType::class, [
|
||||
->add('comment', TextareaType::class, [
|
||||
'required' => false
|
||||
])
|
||||
;
|
||||
|
||||
]);
|
||||
|
||||
if ($options['show_start_date']) {
|
||||
$builder->add('startDate', ChillDateType::class, [
|
||||
'label' => 'Start of validity period'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
if ($options['show_end_date']) {
|
||||
$builder->add('endDate', ChillDateType::class, [
|
||||
'required' => false,
|
||||
'label' => 'End of validity period'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
if ($options['show_help']) {
|
||||
$builder->add('help', ChoiceType::class, [
|
||||
'choices' => [
|
||||
@ -77,48 +68,39 @@ class ChargeType extends AbstractType
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function getTypes()
|
||||
{
|
||||
$charges = $this->configRepository
|
||||
->getChargesLabels();
|
||||
|
||||
|
||||
// rewrite labels to filter in language
|
||||
foreach ($charges as $key => $labels) {
|
||||
$charges[$key] = $this->translatableStringHelper->localize($labels);
|
||||
}
|
||||
|
||||
|
||||
\asort($charges);
|
||||
|
||||
|
||||
return \array_flip($charges);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults(array(
|
||||
'data_class' => 'Chill\AMLI\BudgetBundle\Entity\Charge',
|
||||
'data_class' => Charge::class,
|
||||
'show_start_date' => true,
|
||||
'show_end_date' => true,
|
||||
'show_help' => true
|
||||
));
|
||||
|
||||
|
||||
$resolver
|
||||
->setAllowedTypes('show_start_date', 'boolean')
|
||||
->setAllowedTypes('show_end_date', 'boolean')
|
||||
->setAllowedTypes('show_help', 'boolean')
|
||||
;
|
||||
->setAllowedTypes('show_help', 'boolean');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return 'chill_amli_budgetbundle_charge';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\AMLI\BudgetBundle\Form;
|
||||
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
@ -10,32 +13,22 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Chill\AMLI\BudgetBundle\Config\ConfigRepository;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
|
||||
class ResourceType extends AbstractType
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var ConfigRepository
|
||||
*/
|
||||
protected $configRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
protected $translatableStringHelper;
|
||||
|
||||
protected ConfigRepository $configRepository;
|
||||
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
ConfigRepository $configRepository,
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
ConfigRepository $configRepository,
|
||||
TranslatableStringHelperInterface $translatableStringHelper
|
||||
) {
|
||||
$this->configRepository = $configRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
@ -45,17 +38,16 @@ class ResourceType extends AbstractType
|
||||
'label' => 'Resource element type'
|
||||
])
|
||||
->add('amount', MoneyType::class)
|
||||
->add('comment', TextAreaType::class, [
|
||||
->add('comment', TextareaType::class, [
|
||||
'required' => false
|
||||
])
|
||||
;
|
||||
|
||||
]);
|
||||
|
||||
if ($options['show_start_date']) {
|
||||
$builder->add('startDate', ChillDateType::class, [
|
||||
'label' => 'Start of validity period'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
if ($options['show_end_date']) {
|
||||
$builder->add('endDate', ChillDateType::class, [
|
||||
'required' => false,
|
||||
@ -63,25 +55,7 @@ class ResourceType extends AbstractType
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function getTypes()
|
||||
{
|
||||
$resources = $this->configRepository
|
||||
->getResourcesLabels();
|
||||
|
||||
// rewrite labels to filter in language
|
||||
foreach ($resources as $key => $labels) {
|
||||
$resources[$key] = $this->translatableStringHelper->localize($labels);
|
||||
}
|
||||
|
||||
asort($resources);
|
||||
|
||||
return \array_flip($resources);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults(array(
|
||||
@ -89,20 +63,29 @@ class ResourceType extends AbstractType
|
||||
'show_start_date' => true,
|
||||
'show_end_date' => true
|
||||
));
|
||||
|
||||
|
||||
$resolver
|
||||
->setAllowedTypes('show_start_date', 'boolean')
|
||||
->setAllowedTypes('show_end_date', 'boolean')
|
||||
;
|
||||
->setAllowedTypes('show_end_date', 'boolean');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return 'chill_amli_budgetbundle_resource';
|
||||
}
|
||||
|
||||
private function getTypes()
|
||||
{
|
||||
$resources = $this->configRepository
|
||||
->getResourcesLabels();
|
||||
|
||||
// rewrite labels to filter in language
|
||||
foreach ($resources as $key => $labels) {
|
||||
$resources[$key] = $this->translatableStringHelper->localize($labels);
|
||||
}
|
||||
|
||||
asort($resources);
|
||||
|
||||
return \array_flip($resources);
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,6 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
||||
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\CalendarBundle\Controller;
|
||||
|
||||
@ -26,9 +8,11 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Privacy\PrivacyEvent;
|
||||
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\Form;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
@ -42,11 +26,6 @@ use Chill\MainBundle\Pagination\PaginatorFactory;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* Class CalendarController
|
||||
*
|
||||
* @package Chill\CalendarBundle\Controller
|
||||
*/
|
||||
class CalendarController extends AbstractController
|
||||
{
|
||||
protected EventDispatcherInterface $eventDispatcher;
|
||||
@ -97,9 +76,9 @@ class CalendarController extends AbstractController
|
||||
'calendarItems' => $calendarItems,
|
||||
'user' => $user
|
||||
]);
|
||||
}
|
||||
|
||||
} elseif ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
|
||||
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$total = $this->calendarRepository->countByAccompanyingPeriod($accompanyingPeriod);
|
||||
$paginator = $this->paginator->create($total);
|
||||
$calendarItems = $this->calendarRepository->findBy(
|
||||
@ -117,6 +96,8 @@ class CalendarController extends AbstractController
|
||||
'paginator' => $paginator
|
||||
]);
|
||||
}
|
||||
|
||||
throw new \Exception('Unable to list actions.');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,13 +106,14 @@ class CalendarController extends AbstractController
|
||||
*/
|
||||
public function newAction(Request $request): Response
|
||||
{
|
||||
$view = null;
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
[$user, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$view = '@ChillCalendar/Calendar/newByAccompanyingCourse.html.twig';
|
||||
}
|
||||
}
|
||||
// elseif ($user instanceof User) {
|
||||
// $view = '@ChillCalendar/Calendar/newUser.html.twig';
|
||||
// }
|
||||
@ -161,17 +143,18 @@ class CalendarController extends AbstractController
|
||||
$params = $this->buildParamsToUrl($user, $accompanyingPeriod);
|
||||
|
||||
return $this->redirectToRoute('chill_calendar_calendar_list', $params);
|
||||
} elseif ($form->isSubmitted() and !$form->isValid()) {
|
||||
$this->addFlash('error', $this->get('translator')->trans('This form contains errors'));
|
||||
}
|
||||
|
||||
if ($form->isSubmitted() and !$form->isValid()) {
|
||||
$this->addFlash('error', $this->get('translator')->trans('This form contains errors'));
|
||||
}
|
||||
|
||||
if ($view === null) {
|
||||
throw $this->createNotFoundException('Template not found');
|
||||
}
|
||||
|
||||
$entity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']);
|
||||
|
||||
|
||||
return $this->render($view, [
|
||||
'user' => $user,
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
@ -187,44 +170,49 @@ class CalendarController extends AbstractController
|
||||
*/
|
||||
public function showAction(Request $request, $id): Response
|
||||
{
|
||||
$view = null;
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
[$user, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$view = '@ChillCalendar/Calendar/showByAccompanyingCourse.html.twig';
|
||||
}
|
||||
}
|
||||
elseif ($user instanceof User) {
|
||||
$view = '@ChillCalendar/Calendar/showByUser.html.twig';
|
||||
}
|
||||
|
||||
$entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id);
|
||||
|
||||
if (!$entity) {
|
||||
throw $this->createNotFoundException('Unable to find Calendar entity.');
|
||||
}
|
||||
|
||||
if (null !== $accompanyingPeriod) {
|
||||
$entity->personsAssociated = $entity->getPersonsAssociated();
|
||||
$entity->personsNotAssociated = $entity->getPersonsNotAssociated();
|
||||
}
|
||||
|
||||
// $deleteForm = $this->createDeleteForm($id, $accompanyingPeriod);
|
||||
|
||||
if ($view === null) {
|
||||
throw $this->createNotFoundException('Template not found');
|
||||
}
|
||||
|
||||
$personsId = [];
|
||||
foreach ($entity->getPersons() as $p) {
|
||||
array_push($personsId, $p->getId());
|
||||
/** @var Calendar $entity */
|
||||
$entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id);
|
||||
|
||||
if (null === $entity) {
|
||||
throw $this->createNotFoundException('Unable to find Calendar entity.');
|
||||
}
|
||||
|
||||
$professionalsId = [];
|
||||
foreach ($entity->getProfessionals() as $p) {
|
||||
array_push($professionalsId, $p->getId());
|
||||
if (null !== $accompanyingPeriod) {
|
||||
// @TODO: These properties are declared dynamically.
|
||||
// It must be removed.
|
||||
// @See https://wiki.php.net/rfc/deprecate_dynamic_properties
|
||||
$entity->personsAssociated = $entity->getPersonsAssociated();
|
||||
$entity->personsNotAssociated = $entity->getPersonsNotAssociated();
|
||||
}
|
||||
|
||||
// $deleteForm = $this->createDeleteForm($id, $accompanyingPeriod);
|
||||
|
||||
$personsId = array_map(
|
||||
static fn (Person $p): int => $p->getId(),
|
||||
$entity->getPersons()
|
||||
);
|
||||
|
||||
$professionalsId = array_map(
|
||||
static fn (ThirdParty $thirdParty): ?int => $thirdParty->getId(),
|
||||
$entity->getProfessionals()
|
||||
);
|
||||
|
||||
$durationTime = $entity->getEndDate()->diff($entity->getStartDate());
|
||||
$durationTimeInMinutes = $durationTime->days*1440 + $durationTime->h*60 + $durationTime->i;
|
||||
|
||||
@ -240,7 +228,7 @@ class CalendarController extends AbstractController
|
||||
|
||||
return $this->render($view, [
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
'entity' => $entity,
|
||||
'entity' => $entity,
|
||||
'user' => $user,
|
||||
'activityData' => $activityData
|
||||
//'delete_form' => $deleteForm->createView(),
|
||||
@ -255,6 +243,7 @@ class CalendarController extends AbstractController
|
||||
*/
|
||||
public function editAction($id, Request $request): Response
|
||||
{
|
||||
$view = null;
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
[$user, $accompanyingPeriod] = $this->getEntity($request);
|
||||
@ -283,8 +272,11 @@ class CalendarController extends AbstractController
|
||||
$this->addFlash('success', $this->get('translator')->trans('Success : calendar item updated!'));
|
||||
|
||||
$params = $this->buildParamsToUrl($user, $accompanyingPeriod);
|
||||
|
||||
return $this->redirectToRoute('chill_calendar_calendar_list', $params);
|
||||
} elseif ($form->isSubmitted() and !$form->isValid()) {
|
||||
}
|
||||
|
||||
if ($form->isSubmitted() and !$form->isValid()) {
|
||||
$this->addFlash('error', $this->get('translator')->trans('This form contains errors'));
|
||||
}
|
||||
|
||||
@ -295,7 +287,7 @@ class CalendarController extends AbstractController
|
||||
}
|
||||
|
||||
$entity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']);
|
||||
|
||||
|
||||
return $this->render($view, [
|
||||
'entity' => $entity,
|
||||
'form' => $form->createView(),
|
||||
@ -312,13 +304,14 @@ class CalendarController extends AbstractController
|
||||
*/
|
||||
public function deleteAction(Request $request, $id)
|
||||
{
|
||||
$view = null;
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
[$user, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$view = '@ChillCalendar/Calendar/confirm_deleteByAccompanyingCourse.html.twig';
|
||||
}
|
||||
}
|
||||
elseif ($user instanceof User) {
|
||||
$view = '@ChillCalendar/Calendar/confirm_deleteByUser.html.twig';
|
||||
}
|
||||
@ -367,7 +360,7 @@ class CalendarController extends AbstractController
|
||||
/**
|
||||
* Creates a form to delete a Calendar entity by id.
|
||||
*/
|
||||
private function createDeleteForm(int $id, ?User $user, ?AccompanyingPeriod $accompanyingPeriod): Form
|
||||
private function createDeleteForm(int $id, ?User $user, ?AccompanyingPeriod $accompanyingPeriod): FormInterface
|
||||
{
|
||||
$params = $this->buildParamsToUrl($user, $accompanyingPeriod);
|
||||
$params['id'] = $id;
|
||||
@ -414,17 +407,14 @@ class CalendarController extends AbstractController
|
||||
];
|
||||
}
|
||||
|
||||
private function buildParamsToUrl(
|
||||
?User $user,
|
||||
?AccompanyingPeriod $accompanyingPeriod
|
||||
): array {
|
||||
private function buildParamsToUrl(?User $user, ?AccompanyingPeriod $accompanyingPeriod): array {
|
||||
$params = [];
|
||||
|
||||
if ($user) {
|
||||
if (null !== $user) {
|
||||
$params['user_id'] = $user->getId();
|
||||
}
|
||||
|
||||
if ($accompanyingPeriod) {
|
||||
if (null !== $accompanyingPeriod) {
|
||||
$params['accompanying_period_id'] = $accompanyingPeriod->getId();
|
||||
}
|
||||
|
||||
|
@ -1,25 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\CalendarBundle\DataFixtures\ORM;
|
||||
|
||||
use Chill\CalendarBundle\Entity\CalendarRange;
|
||||
use Chill\MainBundle\DataFixtures\ORM\LoadUsers;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Repository\UserRepository;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Bundle\FixturesBundle\FixtureGroupInterface;
|
||||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
|
||||
class LoadCalendarRange extends Fixture implements FixtureGroupInterface, OrderedFixtureInterface
|
||||
{
|
||||
private UserRepository $userRepository;
|
||||
|
||||
public static array $references = [];
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em
|
||||
UserRepository $userRepository
|
||||
) {
|
||||
$this->userRepository = $em->getRepository(User::class);
|
||||
$this->userRepository = $userRepository;
|
||||
}
|
||||
|
||||
public function getOrder(): int
|
||||
@ -32,12 +37,10 @@ class LoadCalendarRange extends Fixture implements FixtureGroupInterface, Ordere
|
||||
return ['calendar'];
|
||||
}
|
||||
|
||||
public static $references = [];
|
||||
|
||||
public function load(ObjectManager $manager): void
|
||||
{
|
||||
$arr = range(-50, 50);
|
||||
|
||||
|
||||
print "Creating calendar range ('plage de disponibilités')\n";
|
||||
|
||||
$users = $this->userRepository->findAll();
|
||||
@ -70,7 +73,7 @@ class LoadCalendarRange extends Fixture implements FixtureGroupInterface, Ordere
|
||||
->setUser($u)
|
||||
->setStartDate($startEvent)
|
||||
->setEndDate($endEvent);
|
||||
|
||||
|
||||
$manager->persist($calendarRange);
|
||||
}
|
||||
|
||||
@ -79,4 +82,4 @@ class LoadCalendarRange extends Fixture implements FixtureGroupInterface, Ordere
|
||||
}
|
||||
$manager->flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Calendar;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20211119173557 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'remove comment on deprecated json_array type';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$columns = [
|
||||
'chill_calendar.cancel_reason.name',
|
||||
'chill_calendar.invite.status',
|
||||
];
|
||||
|
||||
foreach ($columns as $col) {
|
||||
$this->addSql("COMMENT ON COLUMN $col IS NULL");
|
||||
}
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->throwIrreversibleMigrationException();
|
||||
}
|
||||
}
|
@ -45,25 +45,25 @@ class CreateFieldsOnGroupCommand extends Command
|
||||
{
|
||||
const ARG_PATH = 'path';
|
||||
const ARG_DELETE = 'delete';
|
||||
|
||||
|
||||
/**
|
||||
* @var CustomFieldProvider
|
||||
*/
|
||||
private $customFieldProvider;
|
||||
|
||||
|
||||
/**
|
||||
* @var EntityManager
|
||||
*/
|
||||
private $entityManager;
|
||||
|
||||
|
||||
/**
|
||||
* @var ValidatorInterface
|
||||
*/
|
||||
private $validator;
|
||||
|
||||
|
||||
private $availableLanguages;
|
||||
private $customizablesEntities;
|
||||
|
||||
|
||||
/**
|
||||
* CreateFieldsOnGroupCommand constructor.
|
||||
*
|
||||
@ -87,7 +87,7 @@ class CreateFieldsOnGroupCommand extends Command
|
||||
$this->customizablesEntities = $customizablesEntities;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('chill:custom_fields:populate_group')
|
||||
@ -111,7 +111,7 @@ class CreateFieldsOnGroupCommand extends Command
|
||||
$em->remove($field);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
@ -120,18 +120,18 @@ class CreateFieldsOnGroupCommand extends Command
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$helper = $this->getHelperSet()->get('question');
|
||||
|
||||
|
||||
$em = $this->entityManager;
|
||||
|
||||
|
||||
$customFieldsGroups = $em
|
||||
->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')
|
||||
->findAll();
|
||||
|
||||
|
||||
if (count($customFieldsGroups) === 0) {
|
||||
$output->writeln('<error>There aren\'t any CustomFieldsGroup recorded'
|
||||
. ' Please create at least one.</error>');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$table = new Table($output);
|
||||
$table
|
||||
->setHeaders(array_merge(
|
||||
@ -141,7 +141,7 @@ class CreateFieldsOnGroupCommand extends Command
|
||||
->setRows($this->_prepareRows($customFieldsGroups))
|
||||
->render()
|
||||
;
|
||||
|
||||
|
||||
$question = new Question(
|
||||
"Enter the customfieldGroup's id on which the custom fields should be added: ");
|
||||
$question->setNormalizer(
|
||||
@ -151,24 +151,23 @@ class CreateFieldsOnGroupCommand extends Command
|
||||
return $customFieldsGroup;
|
||||
}
|
||||
}
|
||||
throw new \RunTimeException('The id does not match an existing '
|
||||
. 'CustomFieldsGroup');
|
||||
throw new \RuntimeException('The id does not match an existing CustomFieldsGroup');
|
||||
}
|
||||
);
|
||||
$customFieldsGroup = $helper->ask($input, $output, $question);
|
||||
|
||||
|
||||
|
||||
if ($input->getOption(self::ARG_DELETE)) {
|
||||
$this->deleteFieldsForCFGroup($customFieldsGroup);
|
||||
}
|
||||
|
||||
$fieldsInput = $this->_parse($input->getArgument(self::ARG_PATH),
|
||||
|
||||
$fieldsInput = $this->_parse($input->getArgument(self::ARG_PATH),
|
||||
$output);
|
||||
|
||||
|
||||
$fields = $this->_addFields($customFieldsGroup, $fieldsInput, $output);
|
||||
}
|
||||
|
||||
private function _prepareRows ($customFieldsGroups)
|
||||
|
||||
private function _prepareRows ($customFieldsGroups)
|
||||
{
|
||||
$rows = array();
|
||||
$languages = $this->availableLanguages;
|
||||
@ -177,8 +176,8 @@ class CreateFieldsOnGroupCommand extends Command
|
||||
foreach ($this->customizablesEntities as $entry) {
|
||||
$customizableEntities[$entry['class']] = $entry['name'];
|
||||
}
|
||||
|
||||
array_walk($customFieldsGroups,
|
||||
|
||||
array_walk($customFieldsGroups,
|
||||
function(CustomFieldsGroup $customFieldGroup, $key)
|
||||
use ($languages, &$rows, $customizableEntities) {
|
||||
//set id and entity
|
||||
@ -186,7 +185,7 @@ class CreateFieldsOnGroupCommand extends Command
|
||||
$customFieldGroup->getId(),
|
||||
$customizableEntities[$customFieldGroup->getEntity()]
|
||||
);
|
||||
|
||||
|
||||
foreach ($languages as $lang) {
|
||||
//todo replace with service to find lang when available
|
||||
$row[] = (isset($customFieldGroup->getName()[$lang])) ?
|
||||
@ -196,42 +195,42 @@ class CreateFieldsOnGroupCommand extends Command
|
||||
$rows[] = $row;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
|
||||
private function _parse($path, OutputInterface $output)
|
||||
{
|
||||
$parser = new Parser();
|
||||
|
||||
|
||||
if (!file_exists($path)) {
|
||||
throw new \RunTimeException("file does not exist");
|
||||
throw new \RuntimeException("file does not exist");
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
$values = $parser->parse(file_get_contents($path));
|
||||
} catch (ParseException $ex) {
|
||||
throw new \RunTimeException("The yaml file is not valid", 0, $ex);
|
||||
throw new \RuntimeException("The yaml file is not valid", 0, $ex);
|
||||
}
|
||||
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
|
||||
private function _addFields(CustomFieldsGroup $group, $values, OutputInterface $output)
|
||||
{
|
||||
|
||||
|
||||
$em = $this->entityManager;
|
||||
|
||||
$languages = $this->availableLanguages;
|
||||
|
||||
|
||||
foreach($values['fields'] as $slug => $field) {
|
||||
//check the cf type exists
|
||||
$cfType = $this->customFieldProvider->getCustomFieldByType($field['type']);
|
||||
if ($cfType === NULL) {
|
||||
throw new \RunTimeException('the type '.$field['type'].' '
|
||||
throw new \RuntimeException('the type '.$field['type'].' '
|
||||
. 'does not exists');
|
||||
}
|
||||
|
||||
|
||||
$cf = new CustomField();
|
||||
$cf->setSlug($slug)
|
||||
->setName($field['name'])
|
||||
@ -239,7 +238,7 @@ class CreateFieldsOnGroupCommand extends Command
|
||||
->setOrdering($field['ordering'])
|
||||
->setType($field['type'])
|
||||
->setCustomFieldsGroup($group);
|
||||
|
||||
|
||||
//add to table
|
||||
$names = array();
|
||||
foreach ($languages as $lang) {
|
||||
@ -248,17 +247,17 @@ class CreateFieldsOnGroupCommand extends Command
|
||||
$cf->getName()[$lang] :
|
||||
'Not available in this language';
|
||||
}
|
||||
|
||||
|
||||
if ($this->validator->validate($cf)) {
|
||||
$em->persist($cf);
|
||||
$output->writeln("<info>Adding Custom Field of type "
|
||||
.$cf->getType()."\t with slug ".$cf->getSlug().
|
||||
"\t and names : ".implode($names, ', ')."</info>");
|
||||
} else {
|
||||
throw new \RunTimeException("Error in field ".$slug);
|
||||
throw new \RuntimeException("Error in field ".$slug);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$em->flush();
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,6 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\CustomFieldsBundle\CustomFields;
|
||||
|
||||
@ -29,36 +14,21 @@ use Symfony\Bridge\Twig\TwigEngine;
|
||||
use Chill\MainBundle\Form\Type\Select2ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class CustomFieldLongChoice extends AbstractCustomField
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var OptionRepository
|
||||
*/
|
||||
private $optionRepository;
|
||||
private OptionRepository $optionRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
private $translatableStringHelper;
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
/**
|
||||
* @var TwigEngine
|
||||
*/
|
||||
private $templating;
|
||||
private TwigEngine $templating;
|
||||
|
||||
const KEY = 'key';
|
||||
public const KEY = 'key';
|
||||
|
||||
public function __construct(OptionRepository $optionRepository,
|
||||
public function __construct(
|
||||
OptionRepository $optionRepository,
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
TwigEngine $twigEngine)
|
||||
{
|
||||
TwigEngine $twigEngine
|
||||
) {
|
||||
$this->optionRepository = $optionRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->templating = $twigEngine;
|
||||
@ -76,12 +46,7 @@ class CustomFieldLongChoice extends AbstractCustomField
|
||||
'choice_label' => function(Option $option) use ($translatableStringHelper) {
|
||||
return $translatableStringHelper->localize($option->getText());
|
||||
},
|
||||
'choice_value' => function ($key) use ($entries) {
|
||||
if ($key === NULL) {
|
||||
return null;
|
||||
}
|
||||
return $key->getId();
|
||||
},
|
||||
'choice_value' => static fn (Option $key): ?int => $key === null ? null : $key->getId(),
|
||||
'multiple' => false,
|
||||
'expanded' => false,
|
||||
'required' => $customField->isRequired(),
|
||||
@ -89,15 +54,16 @@ class CustomFieldLongChoice extends AbstractCustomField
|
||||
'group_by' => function(Option $option) use ($translatableStringHelper) {
|
||||
if ($option->hasParent()) {
|
||||
return $translatableStringHelper->localize($option->getParent()->getText());
|
||||
} else {
|
||||
return $translatableStringHelper->localize($option->getText());
|
||||
}
|
||||
|
||||
return $translatableStringHelper->localize($option->getText());
|
||||
},
|
||||
'label' => $translatableStringHelper->localize($customField->getName())
|
||||
));
|
||||
$builder->get($customField->getSlug())
|
||||
->addModelTransformer(new CustomFieldDataTransformer($this, $customField));
|
||||
|
||||
$builder
|
||||
->get($customField->getSlug())
|
||||
->addModelTransformer(new CustomFieldDataTransformer($this, $customField));
|
||||
}
|
||||
|
||||
public function buildOptionsForm(FormBuilderInterface $builder)
|
||||
|
@ -28,27 +28,31 @@ class ChillCustomFieldsExtension extends Extension implements PrependExtensionIn
|
||||
$loader->load('services/fixtures.yaml');
|
||||
$loader->load('services/controller.yaml');
|
||||
$loader->load('services/command.yaml');
|
||||
|
||||
|
||||
//add at least a blank array at 'customizable_entities' options
|
||||
//$customizable_entities = (isset($config['customizables_entities'])
|
||||
// && $config['customizables_entities'] !== FALSE)
|
||||
//$customizable_entities = (isset($config['customizables_entities'])
|
||||
// && $config['customizables_entities'] !== FALSE)
|
||||
// ? $config['customizables_entities'] : array();
|
||||
|
||||
$container->setParameter('chill_custom_fields.customizables_entities',
|
||||
|
||||
$container->setParameter('chill_custom_fields.customizables_entities',
|
||||
$config['customizables_entities']);
|
||||
$container->setParameter('chill_custom_fields.show_empty_values',
|
||||
$container->setParameter('chill_custom_fields.show_empty_values',
|
||||
$config['show_empty_values_in_views']);
|
||||
}
|
||||
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see \Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface::prepend()
|
||||
*/
|
||||
public function prepend(ContainerBuilder $container)
|
||||
public function prepend(ContainerBuilder $container)
|
||||
{
|
||||
// add form layout to twig resources
|
||||
$twigConfig['form_themes'][] = 'ChillCustomFieldsBundle:Form:fields.html.twig';
|
||||
$twigConfig = [
|
||||
'form_themes' => [
|
||||
'ChillCustomFieldsBundle:Form:fields.html.twig',
|
||||
],
|
||||
];
|
||||
$container->prependExtensionConfig('twig', $twigConfig);
|
||||
|
||||
|
||||
//add routes for custom bundle
|
||||
$container->prependExtensionConfig('chill_main', array(
|
||||
'routing' => array(
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace Chill\CustomFieldsBundle\Form;
|
||||
|
||||
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
@ -15,7 +16,7 @@ use Chill\MainBundle\Form\Type\TranslatableStringFormType;
|
||||
class CustomFieldsGroupType extends AbstractType
|
||||
{
|
||||
|
||||
|
||||
|
||||
private $customizableEntities; //TODO : add comment about this variable
|
||||
|
||||
/**
|
||||
@ -52,50 +53,48 @@ class CustomFieldsGroupType extends AbstractType
|
||||
))
|
||||
;
|
||||
|
||||
$builder->addEventListener(FormEvents::POST_SET_DATA,
|
||||
function(FormEvent $event) use ($customizableEntities, $builder){
|
||||
$form = $event->getForm();
|
||||
$group = $event->getData();
|
||||
$builder->addEventListener(
|
||||
FormEvents::POST_SET_DATA,
|
||||
function(FormEvent $event) use ($customizableEntities, $builder) {
|
||||
$form = $event->getForm();
|
||||
$group = $event->getData();
|
||||
|
||||
//stop the function if entity is not set
|
||||
if ($group->getEntity() === NULL) {
|
||||
return;
|
||||
}
|
||||
//stop the function if entity is not set
|
||||
if ($group->getEntity() === NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (count($customizableEntities[$group->getEntity()]['options']) > 0) {
|
||||
$optionBuilder = $builder
|
||||
->getFormFactory()
|
||||
->createBuilderForProperty(
|
||||
'Chill\CustomFieldsBundle\Entity\CustomFieldsGroup',
|
||||
'options'
|
||||
)
|
||||
->create('options', null, array(
|
||||
'compound' => true,
|
||||
'auto_initialize' => false,
|
||||
'required' => false)
|
||||
);
|
||||
}
|
||||
$optionBuilder = null;
|
||||
if (count($customizableEntities[$group->getEntity()]['options']) > 0) {
|
||||
$optionBuilder = $builder
|
||||
->getFormFactory()
|
||||
->createBuilderForProperty(CustomFieldsGroup::class, 'options')
|
||||
->create(
|
||||
'options',
|
||||
null,
|
||||
[
|
||||
'compound' => true,
|
||||
'auto_initialize' => false,
|
||||
'required' => false
|
||||
]
|
||||
);
|
||||
|
||||
foreach($customizableEntities[$group->getEntity()]['options'] as $key => $option) {
|
||||
$optionBuilder
|
||||
->add($key, $option['form_type'], $option['form_options'])
|
||||
;
|
||||
}
|
||||
if (isset($optionBuilder) && $optionBuilder->count() > 0) {
|
||||
$form->add($optionBuilder->getForm());
|
||||
$optionBuilder->add($key, $option['form_type'], $option['form_options']);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
if ((null !== $optionBuilder) && $optionBuilder->count() > 0) {
|
||||
$form->add($optionBuilder->getForm());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OptionsResolverInterface $resolver
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults(array(
|
||||
'data_class' => 'Chill\CustomFieldsBundle\Entity\CustomFieldsGroup'
|
||||
));
|
||||
$resolver->setDefaults([
|
||||
'data_class' => CustomFieldsGroup::class,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,12 +33,12 @@ class CustomFieldsGroupToIdTransformer implements DataTransformerInterface
|
||||
if (null === $customFieldsGroup) {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
if (!$customFieldsGroup instanceof CustomFieldsGroup) {
|
||||
throw new TransformationFailedException(sprintf('Transformation failed: '
|
||||
. 'the expected type of the transforme function is an '
|
||||
. 'object of type Chill\CustomFieldsBundle\Entity\CustomFieldsGroup, '
|
||||
. '%s given (value : %s)', gettype($customFieldsGroup),
|
||||
. '%s given (value : %s)', gettype($customFieldsGroup),
|
||||
$customFieldsGroup));
|
||||
}
|
||||
|
||||
@ -57,26 +57,31 @@ class CustomFieldsGroupToIdTransformer implements DataTransformerInterface
|
||||
if (!$id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
if ($id instanceof CustomFieldsGroup) {
|
||||
throw new TransformationFailedException(sprintf(
|
||||
throw new TransformationFailedException(
|
||||
sprintf(
|
||||
'The transformation failed: the expected argument on '
|
||||
. 'reverseTransform is an object of type int,'
|
||||
. 'Chill\CustomFieldsBundle\Entity\CustomFieldsGroup, '
|
||||
. 'given', gettype($id)));
|
||||
. 'given'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$customFieldsGroup = $this->om
|
||||
->getRepository('ChillCustomFieldsBundle:customFieldsGroup')->find($id)
|
||||
->getRepository(CustomFieldsGroup::class)->find($id)
|
||||
;
|
||||
|
||||
if (null === $customFieldsGroup) {
|
||||
throw new TransformationFailedException(sprintf(
|
||||
'Le group avec le numéro "%s" ne peut pas être trouvé!',
|
||||
$id
|
||||
));
|
||||
throw new TransformationFailedException(
|
||||
sprintf(
|
||||
'Le group avec le numéro "%s" ne peut pas être trouvé!',
|
||||
$id
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $customFieldsGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\CustomFieldsBundle\Form\DataTransformer;
|
||||
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
|
||||
class JsonCustomFieldToArrayTransformer implements DataTransformerInterface {
|
||||
/**
|
||||
* @var ObjectManager
|
||||
*/
|
||||
private $om;
|
||||
private ObjectManager $om;
|
||||
|
||||
private array $customField;
|
||||
|
||||
/**
|
||||
* @param ObjectManager $om
|
||||
*/
|
||||
public function __construct(ObjectManager $om)
|
||||
{
|
||||
$this->om = $om;
|
||||
|
||||
$customFields = $this->om
|
||||
->getRepository('ChillCustomFieldsBundle:CustomField')
|
||||
->getRepository(CustomField::class)
|
||||
->findAll();
|
||||
|
||||
|
||||
// @TODO: in the array_map callback, CustomField::getLabel() does not exist. What do we do here?
|
||||
$customFieldsLablels = array_map(
|
||||
function($e) { return $e->getLabel(); },
|
||||
$customFields);
|
||||
@ -36,20 +35,12 @@ class JsonCustomFieldToArrayTransformer implements DataTransformerInterface {
|
||||
{
|
||||
echo $customFieldsJSON;
|
||||
|
||||
if($customFieldsJSON === null) { // lors de la creation
|
||||
$customFieldsArray = array();
|
||||
if($customFieldsJSON === null) {
|
||||
$customFieldsArray = [];
|
||||
} else {
|
||||
$customFieldsArray = json_decode($customFieldsJSON,true);
|
||||
$customFieldsArray = json_decode($customFieldsJSON, true, 512, JSON_THROW_ON_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
echo "<br> - 4 - <br>";
|
||||
|
||||
var_dump($customFieldsArray);
|
||||
|
||||
echo "<br> - 5 - <br>";
|
||||
*/
|
||||
|
||||
$customFieldsArrayRet = array();
|
||||
|
||||
foreach ($customFieldsArray as $key => $value) {
|
||||
@ -62,7 +53,7 @@ class JsonCustomFieldToArrayTransformer implements DataTransformerInterface {
|
||||
} else {
|
||||
$entityClass = substr($type, 10, -1);
|
||||
}
|
||||
|
||||
|
||||
$customFieldsArrayRet[$key] = $this->om
|
||||
->getRepository('ChillCustomFieldsBundle:' . $entityClass)
|
||||
->findOneById($value);
|
||||
@ -86,10 +77,10 @@ class JsonCustomFieldToArrayTransformer implements DataTransformerInterface {
|
||||
{
|
||||
/*
|
||||
echo "<br> - - 7 - <br>";
|
||||
|
||||
|
||||
|
||||
var_dump(array_keys($customFieldsArray));
|
||||
|
||||
|
||||
echo "<br> - - 8 - <br>";
|
||||
|
||||
var_dump(array_keys($this->customField));
|
||||
@ -112,7 +103,7 @@ class JsonCustomFieldToArrayTransformer implements DataTransformerInterface {
|
||||
//$entityClass = substr($type, 10, -1);
|
||||
//echo $entityClasss;
|
||||
if(strpos($type, 'ManyToOnePersist') === 0) {
|
||||
// PEUT ETRE A FAIRE SI SEULEMENT $value->getId() ne renvoie rien...
|
||||
// PEUT ETRE A FAIRE SI SEULEMENT $value->getId() ne renvoie rien...
|
||||
//
|
||||
//
|
||||
$this->om->persist($value); // pas bon ici
|
||||
@ -121,7 +112,7 @@ class JsonCustomFieldToArrayTransformer implements DataTransformerInterface {
|
||||
// et faire le persist qd fait sur l'obj parent
|
||||
// regarder : http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html
|
||||
// ou : http://symfony.com/doc/current/cookbook/doctrine/event_listeners_subscribers.html
|
||||
// dans yml :
|
||||
// dans yml :
|
||||
// lifecycleCallbacks:
|
||||
// prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersist ]
|
||||
$this->om->flush(); // sinon l'id pose pbm
|
||||
@ -142,4 +133,4 @@ class JsonCustomFieldToArrayTransformer implements DataTransformerInterface {
|
||||
|
||||
return json_encode($customFieldsArrayRet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -145,5 +145,7 @@ class DocGeneratorTemplateController extends AbstractController
|
||||
} catch (TransferException $e) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
throw new \Exception('Unable to generate document.');
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\DocGeneratorBundle\Serializer\Encoder;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
||||
|
||||
class DocGenEncoder implements \Symfony\Component\Serializer\Encoder\EncoderInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function encode($data, string $format, array $context = [])
|
||||
{
|
||||
if (!$this->isAssociative($data)) {
|
||||
throw new UnexpectedValueException("Only associative arrays are allowed; lists are not allowed");
|
||||
}
|
||||
|
||||
$result = [];
|
||||
$this->recusiveEncoding($data, $result, '');
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function recusiveEncoding(array $data, array &$result, $path)
|
||||
{
|
||||
if ($this->isAssociative($data)) {
|
||||
foreach ($data as $key => $value) {
|
||||
if (\is_array($value)) {
|
||||
$this->recusiveEncoding($value, $result, $this->canonicalizeKey($path, $key));
|
||||
} else {
|
||||
$result[$this->canonicalizeKey($path, $key)] = $value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($data as $elem) {
|
||||
|
||||
if (!$this->isAssociative($elem)) {
|
||||
throw new UnexpectedValueException(sprintf("Embedded loops are not allowed. See data under %s path", $path));
|
||||
}
|
||||
|
||||
$sub = [];
|
||||
$this->recusiveEncoding($elem, $sub, '');
|
||||
$result[$path][] = $sub;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function canonicalizeKey(string $path, string $key): string
|
||||
{
|
||||
return $path === '' ? $key : $path.'_'.$key;
|
||||
}
|
||||
|
||||
private function isAssociative(array $data)
|
||||
{
|
||||
$keys = \array_keys($data);
|
||||
|
||||
return $keys !== \array_keys($keys);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function supportsEncoding(string $format)
|
||||
{
|
||||
return $format === 'docgen';
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\DocGeneratorBundle\Serializer\Helper;
|
||||
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
class NormalizeNullValueHelper
|
||||
{
|
||||
private NormalizerInterface $normalizer;
|
||||
|
||||
public function __construct(NormalizerInterface $normalizer)
|
||||
{
|
||||
$this->normalizer = $normalizer;
|
||||
}
|
||||
|
||||
public function normalize(array $attributes, string $format = 'docgen', ?array $context = [])
|
||||
{
|
||||
$data = [];
|
||||
|
||||
foreach ($attributes as $key => $class) {
|
||||
if (is_numeric($key)) {
|
||||
$data[$class] = '';
|
||||
} else {
|
||||
switch ($class) {
|
||||
case 'array':
|
||||
case 'bool':
|
||||
case 'double':
|
||||
case 'float':
|
||||
case 'int':
|
||||
case 'resource':
|
||||
case 'string':
|
||||
case 'null':
|
||||
$data[$key] = '';
|
||||
break;
|
||||
default:
|
||||
$data[$key] = $this->normalizer->normalize(null, $format, \array_merge(
|
||||
$context,
|
||||
['docgen:expects' => $class]
|
||||
));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -0,0 +1,177 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\DocGeneratorBundle\Serializer\Normalizer;
|
||||
|
||||
use Chill\DocGeneratorBundle\Serializer\Helper\NormalizeNullValueHelper;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessor;
|
||||
use Symfony\Component\Serializer\Exception\ExceptionInterface;
|
||||
use Symfony\Component\Serializer\Exception\LogicException;
|
||||
use Symfony\Component\Serializer\Mapping\AttributeMetadata;
|
||||
use Symfony\Component\Serializer\Mapping\ClassMetadata;
|
||||
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
class DocGenObjectNormalizer implements NormalizerInterface, NormalizerAwareInterface
|
||||
{
|
||||
use NormalizerAwareTrait;
|
||||
|
||||
private ClassMetadataFactoryInterface $classMetadataFactory;
|
||||
private PropertyAccessor $propertyAccess;
|
||||
|
||||
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory)
|
||||
{
|
||||
$this->classMetadataFactory = $classMetadataFactory;
|
||||
$this->propertyAccess = PropertyAccess::createPropertyAccessor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function normalize($object, string $format = null, array $context = [])
|
||||
{
|
||||
$classMetadataKey = $object ?? $context['docgen:expects'];
|
||||
|
||||
if (!$this->classMetadataFactory->hasMetadataFor($classMetadataKey)) {
|
||||
throw new LogicException(sprintf("This object does not have metadata: %s. Add groups on this entity to allow to serialize with the format %s and groups %s", is_object($object) ? get_class($object) : $context['docgen:expects'], $format, \implode(', ', $context['groups'])));
|
||||
}
|
||||
|
||||
$metadata = $this->classMetadataFactory->getMetadataFor($classMetadataKey);
|
||||
$expectedGroups = \array_key_exists(AbstractNormalizer::GROUPS, $context) ?
|
||||
\is_array($context[AbstractNormalizer::GROUPS]) ? $context[AbstractNormalizer::GROUPS] : [$context[AbstractNormalizer::GROUPS]]
|
||||
: [];
|
||||
$attributes = \array_filter(
|
||||
$metadata->getAttributesMetadata(),
|
||||
function (AttributeMetadata $a) use ($expectedGroups) {
|
||||
foreach ($a->getGroups() as $g) {
|
||||
if (\in_array($g, $expectedGroups, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (null === $object) {
|
||||
return $this->normalizeNullData($format, $context, $metadata, $attributes);
|
||||
}
|
||||
|
||||
return $this->normalizeObject($object, $format, $context, $expectedGroups, $metadata, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $format
|
||||
* @param array $context
|
||||
* @param array $expectedGroups
|
||||
* @param ClassMetadata $metadata
|
||||
* @param array|AttributeMetadata[] $attributes
|
||||
*/
|
||||
private function normalizeNullData(string $format, array $context, ClassMetadata $metadata, array $attributes): array
|
||||
{
|
||||
$keys = [];
|
||||
|
||||
foreach ($attributes as $attribute) {
|
||||
$key = $attribute->getSerializedName() ?? $attribute->getName();
|
||||
$keys[$key] = $this->getExpectedType($attribute, $metadata->getReflectionClass());
|
||||
}
|
||||
|
||||
$normalizer = new NormalizeNullValueHelper($this->normalizer);
|
||||
|
||||
return $normalizer->normalize($keys, $format, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $object
|
||||
* @param $format
|
||||
* @param array $context
|
||||
* @param array $expectedGroups
|
||||
* @param ClassMetadata $metadata
|
||||
* @param array|AttributeMetadata[] $attributes
|
||||
* @return array
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
private function normalizeObject($object, $format, array $context, array $expectedGroups, ClassMetadata $metadata, array $attributes)
|
||||
{
|
||||
$data = [];
|
||||
$reflection = $metadata->getReflectionClass();
|
||||
|
||||
foreach ($attributes as $attribute) {
|
||||
/** @var AttributeMetadata $attribute */
|
||||
$value = $this->propertyAccess->getValue($object, $attribute->getName());
|
||||
$key = $attribute->getSerializedName() ?? $attribute->getName();
|
||||
|
||||
if (is_object($value)) {
|
||||
$data[$key] =
|
||||
$this->normalizer->normalize($value, $format, \array_merge(
|
||||
$context, $attribute->getNormalizationContextForGroups($expectedGroups)
|
||||
));
|
||||
} elseif (null === $value) {
|
||||
$data[$key] = $this->normalizeNullOutputValue($format, $context, $attribute, $reflection);
|
||||
} else {
|
||||
$data[$key] = (string) $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function getExpectedType(AttributeMetadata $attribute, \ReflectionClass $reflection): string
|
||||
{
|
||||
// we have to get the expected content
|
||||
if ($reflection->hasProperty($attribute->getName())) {
|
||||
$type = $reflection->getProperty($attribute->getName())->getType();
|
||||
} elseif ($reflection->hasMethod($attribute->getName())) {
|
||||
$type = $reflection->getMethod($attribute->getName())->getReturnType();
|
||||
} else {
|
||||
throw new \LogicException(sprintf(
|
||||
"Could not determine how the content is determined for the attribute %s. Add attribute property only on property or method", $attribute->getName()
|
||||
));
|
||||
}
|
||||
|
||||
if (null === $type) {
|
||||
throw new \LogicException(sprintf(
|
||||
"Could not determine the type for this attribute: %s. Add a return type to the method or property declaration", $attribute->getName()
|
||||
));
|
||||
}
|
||||
|
||||
return $type->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
private function normalizeNullOutputValue($format, array $context, AttributeMetadata $attribute, \ReflectionClass $reflection)
|
||||
{
|
||||
$type = $this->getExpectedType($attribute, $reflection);
|
||||
|
||||
switch ($type) {
|
||||
case 'array':
|
||||
case 'bool':
|
||||
case 'double':
|
||||
case 'float':
|
||||
case 'int':
|
||||
case 'resource':
|
||||
case 'string':
|
||||
return '';
|
||||
default:
|
||||
return $this->normalizer->normalize(
|
||||
null,
|
||||
$format,
|
||||
\array_merge(
|
||||
$context,
|
||||
['docgen:expects' => $type]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function supportsNormalization($data, string $format = null): bool
|
||||
{
|
||||
return $format === 'docgen' && (is_object($data) || null === $data);
|
||||
}
|
||||
}
|
@ -8,3 +8,10 @@ services:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
resource: '../Repository/'
|
||||
|
||||
Chill\DocGeneratorBundle\Serializer\Normalizer\:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
resource: '../Serializer/Normalizer/'
|
||||
tags:
|
||||
- { name: 'serializer.normalizer', priority: -152 }
|
||||
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\DocGenerator;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20211119173556 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'remove comment on deprecated json_array type';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$columns = [
|
||||
'chill_docgen_template.name'
|
||||
];
|
||||
|
||||
foreach ($columns as $col) {
|
||||
$this->addSql("COMMENT ON COLUMN $col IS NULL");
|
||||
}
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->throwIrreversibleMigrationException();
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\DocGeneratorBundle\Tests\Serializer\Encoder;
|
||||
|
||||
use Chill\DocGeneratorBundle\Serializer\Encoder\DocGenEncoder;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
||||
|
||||
class DocGenEncoderTest extends TestCase
|
||||
{
|
||||
private DocGenEncoder $encoder;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->encoder = new DocGenEncoder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider generateEncodeData
|
||||
*/
|
||||
public function testEncode($expected, $data, string $msg)
|
||||
{
|
||||
$generated = $this->encoder->encode($data, 'docgen');
|
||||
$this->assertEquals($expected, $generated, $msg);
|
||||
}
|
||||
|
||||
public function testEmbeddedLoopsThrowsException()
|
||||
{
|
||||
$this->expectException(UnexpectedValueException::class);
|
||||
|
||||
$data = [
|
||||
'data' => [
|
||||
['item' => 'one'],
|
||||
[
|
||||
'embedded' => [
|
||||
[
|
||||
['subitem' => 'two'],
|
||||
['subitem' => 'three']
|
||||
]
|
||||
]
|
||||
],
|
||||
]
|
||||
];
|
||||
|
||||
$this->encoder->encode($data, 'docgen');
|
||||
}
|
||||
|
||||
public function generateEncodeData()
|
||||
{
|
||||
yield [ ['tests' => 'ok'], ['tests' => 'ok'], "A simple test with a simple array"];
|
||||
|
||||
yield [
|
||||
// expected:
|
||||
['item_subitem' => 'value'],
|
||||
// data:
|
||||
['item' => ['subitem' => 'value']],
|
||||
"A test with multidimensional array"
|
||||
];
|
||||
|
||||
yield [
|
||||
// expected:
|
||||
[ 'data' => [['item' => 'one'], ['item' => 'two']] ],
|
||||
// data:
|
||||
[ 'data' => [['item' => 'one'], ['item' => 'two']] ],
|
||||
"a list of items"
|
||||
];
|
||||
|
||||
yield [
|
||||
// expected:
|
||||
[ 'data' => [['item_subitem' => 'alpha'], ['item' => 'two']] ],
|
||||
// data:
|
||||
[ 'data' => [['item' => ['subitem' => 'alpha']], ['item' => 'two'] ] ],
|
||||
"a list of items with multidimensional array inside item"
|
||||
];
|
||||
|
||||
yield [
|
||||
// expected:
|
||||
[
|
||||
'persons' => [
|
||||
[
|
||||
'firstname' => 'Jonathan',
|
||||
'lastname' => 'Dupont',
|
||||
'dateOfBirth_long' => '16 juin 1981',
|
||||
'dateOfBirth_short' => '16/06/1981',
|
||||
'father_firstname' => 'Marcel',
|
||||
'father_lastname' => 'Dupont',
|
||||
'father_dateOfBirth_long' => '10 novembre 1953',
|
||||
'father_dateOfBirth_short' => '10/11/1953'
|
||||
],
|
||||
]
|
||||
],
|
||||
// data:
|
||||
[
|
||||
'persons' => [
|
||||
[
|
||||
'firstname' => 'Jonathan',
|
||||
'lastname' => 'Dupont',
|
||||
'dateOfBirth' => [ 'long' => '16 juin 1981', 'short' => '16/06/1981'],
|
||||
'father' => [
|
||||
'firstname' => 'Marcel',
|
||||
'lastname' => 'Dupont',
|
||||
'dateOfBirth' => ['long' => '10 novembre 1953', 'short' => '10/11/1953']
|
||||
]
|
||||
],
|
||||
]
|
||||
],
|
||||
"a longer list, with near real data inside and embedded associative arrays"
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\DocGeneratorBundle\tests\Serializer\Normalizer;
|
||||
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
class DocGenObjectNormalizerTest extends KernelTestCase
|
||||
{
|
||||
private NormalizerInterface $normalizer;
|
||||
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
self::bootKernel();
|
||||
|
||||
$this->normalizer = self::$container->get(NormalizerInterface::class);
|
||||
}
|
||||
|
||||
public function testNormalizationBasic()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setUsername('User Test');
|
||||
$user->setMainCenter($center = new Center());
|
||||
$center->setName('test');
|
||||
|
||||
$normalized = $this->normalizer->normalize($user, 'docgen', [ AbstractNormalizer::GROUPS => ['docgen:read']]);
|
||||
$expected = [
|
||||
'label' => 'User Test',
|
||||
'email' => '',
|
||||
'mainCenter' => [
|
||||
'name' => 'test'
|
||||
]
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $normalized, "test normalization fo an user");
|
||||
}
|
||||
|
||||
public function testNormalizeWithNullValueEmbedded()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setUsername('User Test');
|
||||
|
||||
$normalized = $this->normalizer->normalize($user, 'docgen', [ AbstractNormalizer::GROUPS => ['docgen:read']]);
|
||||
$expected = [
|
||||
'label' => 'User Test',
|
||||
'email' => '',
|
||||
'mainCenter' => [
|
||||
'name' => ''
|
||||
]
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $normalized, "test normalization fo an user with null center");
|
||||
}
|
||||
|
||||
public function testNormalizeNullObjectWithObjectEmbedded()
|
||||
{
|
||||
$normalized = $this->normalizer->normalize(null, 'docgen', [
|
||||
AbstractNormalizer::GROUPS => ['docgen:read'],
|
||||
'docgen:expects' => User::class,
|
||||
]);
|
||||
|
||||
$expected = [
|
||||
'label' => '',
|
||||
'email' => '',
|
||||
'mainCenter' => [
|
||||
'name' => ''
|
||||
]
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $normalized, "test normalization for a null user");
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\DocStoreBundle\Controller;
|
||||
|
||||
use Chill\DocStoreBundle\Entity\DocumentCategory;
|
||||
@ -9,11 +11,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Chill\DocStoreBundle\ChillDocStoreBundle;
|
||||
|
||||
/**
|
||||
* Class DocumentCategoryController
|
||||
*
|
||||
* @package Chill\DocStoreBundle\Controller
|
||||
* @Route("/{_locale}/admin/document/category")
|
||||
*/
|
||||
class DocumentCategoryController extends AbstractController
|
||||
@ -24,11 +24,14 @@ class DocumentCategoryController extends AbstractController
|
||||
public function index(): Response
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$categories = $em->getRepository("ChillDocStoreBundle:DocumentCategory")->findAll();
|
||||
$categories = $em->getRepository(DocumentCategory::class)->findAll();
|
||||
|
||||
return $this->render(
|
||||
'ChillDocStoreBundle:DocumentCategory:index.html.twig',
|
||||
['document_categories' => $categories]);
|
||||
[
|
||||
'document_categories' => $categories,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -37,13 +40,10 @@ class DocumentCategoryController extends AbstractController
|
||||
public function new(Request $request): Response
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$documentCategory = new DocumentCategory();
|
||||
$documentCategory
|
||||
->setBundleId('Chill\DocStoreBundle\ChillDocStoreBundle');
|
||||
$documentCategory
|
||||
->setIdInsideBundle(
|
||||
$em->getRepository("ChillDocStoreBundle:DocumentCategory")
|
||||
->nextIdInsideBundle());
|
||||
$documentCategory = new DocumentCategory(
|
||||
ChillDocStoreBundle::class,
|
||||
$em->getRepository(DocumentCategory::class)->nextIdInsideBundle()
|
||||
);
|
||||
$documentCategory
|
||||
->setDocumentClass(PersonDocument::class);
|
||||
|
||||
@ -56,11 +56,10 @@ class DocumentCategoryController extends AbstractController
|
||||
$em->flush();
|
||||
|
||||
return $this->redirectToRoute('document_category_index');
|
||||
} else {
|
||||
$documentCategory->setBundleId(
|
||||
'Chill\DocStoreBundle\ChillDocStoreBundle');
|
||||
}
|
||||
|
||||
$documentCategory->setBundleId(ChillDocStoreBundle::class);
|
||||
|
||||
return $this->render('ChillDocStoreBundle:DocumentCategory:new.html.twig', [
|
||||
'document_category' => $documentCategory,
|
||||
'form' => $form->createView(),
|
||||
|
@ -38,7 +38,7 @@ class LoadDocumentACL extends AbstractFixture implements OrderedFixtureInterface
|
||||
return 35000;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
foreach (LoadPermissionsGroup::$refs as $permissionsGroupRef) {
|
||||
@ -57,15 +57,15 @@ class LoadDocumentACL extends AbstractFixture implements OrderedFixtureInterface
|
||||
break;
|
||||
case 'administrative':
|
||||
case 'direction':
|
||||
if (in_array($scope->getName()['en'], array('administrative', 'social'))) {
|
||||
if (in_array($scope->getName()['en'], array('administrative', 'social'), true)) {
|
||||
printf("denying power on %s\n", $scope->getName()['en']);
|
||||
break 2; // we do not want any power on social or administrative
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
printf("Adding Person report acl to %s "
|
||||
. "permission group, scope '%s' \n",
|
||||
. "permission group, scope '%s' \n",
|
||||
$permissionsGroup->getName(), $scope->getName()['en']);
|
||||
$roleScopeUpdate = (new RoleScope())
|
||||
->setRole(PersonDocumentVoter::CREATE)
|
||||
@ -83,9 +83,9 @@ class LoadDocumentACL extends AbstractFixture implements OrderedFixtureInterface
|
||||
$manager->persist($roleScopeCreate);
|
||||
$manager->persist($roleScopeDelete);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\DocStoreBundle\Repository;
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Entity\AccompanyingCourseDocument;
|
||||
namespace Chill\DocStoreBundle\EntityRepository;
|
||||
|
||||
use Chill\DocStoreBundle\Entity\AccompanyingCourseDocument;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
|
@ -34,6 +34,6 @@ class DocumentCategoryRepository extends EntityRepository
|
||||
'SELECT MAX(c.idInsideBundle) + 1 FROM ChillDocStoreBundle:DocumentCategory c')
|
||||
->getSingleResult();
|
||||
|
||||
return $array_res[1] ?: 0;
|
||||
return reset($array_res);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\DocStore;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20211119173558 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'remove comment on deprecated json_array type';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$columns = [
|
||||
'chill_doc.document_category.name',
|
||||
'chill_doc.stored_object.key',
|
||||
'chill_doc.stored_object.iv',
|
||||
'chill_doc.stored_object.datas',
|
||||
];
|
||||
|
||||
foreach ($columns as $col) {
|
||||
$this->addSql("COMMENT ON COLUMN $col IS NULL");
|
||||
}
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->throwIrreversibleMigrationException();
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ use ArrayIterator;
|
||||
use Chill\EventBundle\Entity\Event;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Chill\EventBundle\Entity\Participation;
|
||||
@ -39,12 +40,12 @@ use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
||||
*/
|
||||
class ParticipationController extends AbstractController
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @var \Psr\Log\LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
|
||||
/**
|
||||
* ParticipationController constructor.
|
||||
*
|
||||
@ -54,10 +55,10 @@ class ParticipationController extends AbstractController
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show a form to add a participation
|
||||
*
|
||||
*
|
||||
* This function parse the person_id / persons_ids query argument
|
||||
* and decide if it should process a single or multiple participation. Depending
|
||||
* on this, the appropriate layout and form.
|
||||
@ -67,46 +68,46 @@ class ParticipationController extends AbstractController
|
||||
*/
|
||||
public function newAction(Request $request)
|
||||
{
|
||||
|
||||
|
||||
// test the request is correct
|
||||
try {
|
||||
$this->testRequest($request);
|
||||
} catch (\RuntimeException $ex) {
|
||||
$this->logger->warning($ex->getMessage());
|
||||
|
||||
|
||||
return (new Response())
|
||||
->setStatusCode(Response::HTTP_BAD_REQUEST)
|
||||
->setContent($ex->getMessage());
|
||||
}
|
||||
|
||||
|
||||
// forward to other action
|
||||
$single = $request->query->has('person_id');
|
||||
$multiple = $request->query->has('persons_ids');
|
||||
|
||||
|
||||
if ($single === true) {
|
||||
return $this->newSingle($request);
|
||||
}
|
||||
|
||||
|
||||
if ($multiple === true) {
|
||||
|
||||
|
||||
return $this->newMultiple($request);
|
||||
}
|
||||
|
||||
|
||||
// at this point, we miss the required fields. Throw an error
|
||||
return (new Response())
|
||||
->setStatusCode(Response::HTTP_BAD_REQUEST)
|
||||
->setContent("You must provide either 'person_id' or "
|
||||
. "'persons_ids' argument in query");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Test that the query parameters are valid :
|
||||
*
|
||||
*
|
||||
* - an `event_id` is existing ;
|
||||
* - `person_id` and `persons_ids` are **not** both present ;
|
||||
* - `persons_id` is correct (contains only numbers and a ','.
|
||||
*
|
||||
*
|
||||
* @param Request $request
|
||||
* @throws \RuntimeException if an error is detected
|
||||
*/
|
||||
@ -114,64 +115,64 @@ class ParticipationController extends AbstractController
|
||||
{
|
||||
$single = $request->query->has('person_id');
|
||||
$multiple = $request->query->has('persons_ids');
|
||||
|
||||
|
||||
if ($single === true AND $multiple === true) {
|
||||
// we are not allowed to have both person_id and persons_ids
|
||||
throw new \RuntimeException("You are not allow to provide both 'person_id' and "
|
||||
. "'persons_ids' simulaneously");
|
||||
}
|
||||
|
||||
|
||||
if ($multiple === true) {
|
||||
$persons_ids = $request->query->get('persons_ids');
|
||||
|
||||
|
||||
if (!preg_match('/^([0-9]{1,},{0,1}){1,}[0-9]{0,}$/', $persons_ids)) {
|
||||
throw new \RuntimeException("The persons_ids value should "
|
||||
. "contains int separated by ','");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check for event_id - this could be removed later
|
||||
if ($request->query->has('event_id') === FALSE) {
|
||||
throw new \RuntimeException("You must provide an event_id");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show a form with single participation.
|
||||
*
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
protected function newSingle(Request $request)
|
||||
{
|
||||
|
||||
|
||||
$returnPath = $request->query->get('return_path') ?
|
||||
$request->query->get('return_path') : null;
|
||||
|
||||
|
||||
$participation = $this->handleRequest($request, new Participation(), false);
|
||||
|
||||
$this->denyAccessUnlessGranted(ParticipationVoter::CREATE,
|
||||
|
||||
$this->denyAccessUnlessGranted(ParticipationVoter::CREATE,
|
||||
$participation, 'The user is not allowed to create this participation');
|
||||
|
||||
|
||||
$form = $this->createCreateForm($participation, $returnPath);
|
||||
|
||||
|
||||
return $this->render('ChillEventBundle:Participation:new.html.twig', array(
|
||||
'form' => $form->createView(),
|
||||
'participation' => $participation,
|
||||
'ignored_participations' => array() // this is required, see self::newMultiple
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show a form with multiple participation.
|
||||
*
|
||||
*
|
||||
* If a person is already participating on the event (if a participation with
|
||||
* the same person is associated with the event), the participation is ignored.
|
||||
*
|
||||
*
|
||||
* If all but one participation is ignored, the page show the same response
|
||||
* than the newSingle function.
|
||||
*
|
||||
* than the newSingle function.
|
||||
*
|
||||
* If all participations must be ignored, an error is shown and the method redirects
|
||||
* to the event 'show' view with an appropriate flash message.
|
||||
*
|
||||
@ -181,24 +182,24 @@ class ParticipationController extends AbstractController
|
||||
protected function newMultiple(Request $request)
|
||||
{
|
||||
$participations = $this->handleRequest($request, new Participation(), true);
|
||||
|
||||
|
||||
foreach ($participations as $i => $participation) {
|
||||
$ignoredParticipations = $newParticipations = [];
|
||||
|
||||
foreach ($participations as $participation) {
|
||||
// check for authorization
|
||||
$this->denyAccessUnlessGranted(ParticipationVoter::CREATE,
|
||||
$this->denyAccessUnlessGranted(ParticipationVoter::CREATE,
|
||||
$participation, 'The user is not allowed to create this participation');
|
||||
|
||||
|
||||
// create a collection of person's id participating to the event
|
||||
/* @var $peopleParticipating \Doctrine\Common\Collections\ArrayCollection */
|
||||
$peopleParticipating = isset($peopleParticipating) ? $peopleParticipating :
|
||||
$participation->getEvent()->getParticipations()->map(
|
||||
function(Participation $p) { return $p->getPerson()->getId(); }
|
||||
);
|
||||
// check that the user is not already in the event
|
||||
// check that the user is not already in the event
|
||||
if ($peopleParticipating->contains($participation->getPerson()->getId())) {
|
||||
$ignoredParticipations[] = $participation
|
||||
->getEvent()->getParticipations()->filter(
|
||||
function (Participation $p) use ($participation) {
|
||||
function (Participation $p) use ($participation) {
|
||||
return $p->getPerson()->getId() === $participation->getPerson()->getId();
|
||||
}
|
||||
)->first();
|
||||
@ -206,40 +207,47 @@ class ParticipationController extends AbstractController
|
||||
$newParticipations[] = $participation;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// this is where the function redirect depending on valid participation
|
||||
|
||||
if (!isset($newParticipations)) {
|
||||
|
||||
if ([] === $newParticipations) {
|
||||
// if we do not have nay participants, redirect to event view
|
||||
$this->addFlash('error', $this->get('translator')->trans(
|
||||
'None of the requested people may participate '
|
||||
. 'the event: they are maybe already participating.'));
|
||||
|
||||
|
||||
return $this->redirectToRoute('chill_event__event_show', array(
|
||||
'event_id' => $request->query->getInt('event_id', 0)
|
||||
));
|
||||
} elseif (count($newParticipations) > 1) {
|
||||
}
|
||||
|
||||
if (count($newParticipations) > 1) {
|
||||
// if we have multiple participations, show a form with multiple participations
|
||||
$form = $this->createCreateFormMultiple($newParticipations);
|
||||
|
||||
return $this->render('ChillEventBundle:Participation:new-multiple.html.twig', array(
|
||||
return $this->render(
|
||||
'ChillEventBundle:Participation:new-multiple.html.twig',
|
||||
[
|
||||
'form' => $form->createView(),
|
||||
'participations' => $newParticipations,
|
||||
'ignored_participations' => isset($ignoredParticipations) ? $ignoredParticipations : array()
|
||||
));
|
||||
} else {
|
||||
// if we have only one participation, show the same form than for single participation
|
||||
$form = $this->createCreateForm($participation);
|
||||
|
||||
return $this->render('ChillEventBundle:Participation:new.html.twig', array(
|
||||
'ignored_participations' => $ignoredParticipations
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// if we have only one participation, show the same form than for single participation
|
||||
$form = $this->createCreateForm($participation);
|
||||
|
||||
return $this->render(
|
||||
'ChillEventBundle:Participation:new.html.twig',
|
||||
[
|
||||
'form' => $form->createView(),
|
||||
'participation' => $participation,
|
||||
'ignored_participations' => isset($ignoredParticipations) ? $ignoredParticipations : array()
|
||||
));
|
||||
|
||||
}
|
||||
'ignored_participations' => $ignoredParticipations,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
|
||||
@ -251,32 +259,32 @@ class ParticipationController extends AbstractController
|
||||
$this->testRequest($request);
|
||||
} catch (\RuntimeException $ex) {
|
||||
$this->logger->warning($ex->getMessage());
|
||||
|
||||
|
||||
return (new Response())
|
||||
->setStatusCode(Response::HTTP_BAD_REQUEST)
|
||||
->setContent($ex->getMessage());
|
||||
}
|
||||
|
||||
|
||||
// forward to other action
|
||||
$single = $request->query->has('person_id');
|
||||
$multiple = $request->query->has('persons_ids');
|
||||
|
||||
|
||||
if ($single === true) {
|
||||
return $this->createSingle($request);
|
||||
}
|
||||
|
||||
|
||||
if ($multiple === true) {
|
||||
|
||||
|
||||
return $this->createMultiple($request);
|
||||
}
|
||||
|
||||
|
||||
// at this point, we miss the required fields. Throw an error
|
||||
return (new Response())
|
||||
->setStatusCode(Response::HTTP_BAD_REQUEST)
|
||||
->setContent("You must provide either 'person_id' or "
|
||||
. "'persons_ids' argument in query");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
|
||||
@ -284,41 +292,41 @@ class ParticipationController extends AbstractController
|
||||
public function createSingle(Request $request)
|
||||
{
|
||||
$participation = $this->handleRequest($request, new Participation(), false);
|
||||
|
||||
$this->denyAccessUnlessGranted(ParticipationVoter::CREATE,
|
||||
|
||||
$this->denyAccessUnlessGranted(ParticipationVoter::CREATE,
|
||||
$participation, 'The user is not allowed to create this participation');
|
||||
|
||||
|
||||
$form = $this->createCreateForm($participation);
|
||||
$form->handleRequest($request);
|
||||
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
|
||||
$em->persist($participation);
|
||||
$em->flush();
|
||||
|
||||
|
||||
$this->addFlash('success', $this->get('translator')->trans(
|
||||
'The participation was created'
|
||||
));
|
||||
|
||||
|
||||
if ($request->query->get('return_path'))
|
||||
{
|
||||
return $this->redirect($request->query->get('return_path'));
|
||||
|
||||
|
||||
} else {
|
||||
return $this->redirectToRoute('chill_event__event_show', array(
|
||||
'event_id' => $participation->getEvent()->getId()
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return $this->render('ChillEventBundle:Participation:new.html.twig', array(
|
||||
'form' => $form->createView(),
|
||||
'participation' => $participation
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
|
||||
@ -326,95 +334,92 @@ class ParticipationController extends AbstractController
|
||||
public function createMultiple(Request $request)
|
||||
{
|
||||
$participations = $this->handleRequest($request, new Participation(), true);
|
||||
|
||||
|
||||
foreach($participations as $participation) {
|
||||
$this->denyAccessUnlessGranted(ParticipationVoter::CREATE,
|
||||
$this->denyAccessUnlessGranted(ParticipationVoter::CREATE,
|
||||
$participation, 'The user is not allowed to create this participation');
|
||||
}
|
||||
|
||||
|
||||
$form = $this->createCreateFormMultiple($participations);
|
||||
$form->handleRequest($request);
|
||||
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$data = $form->getData();
|
||||
|
||||
|
||||
foreach($data['participations'] as $participation) {
|
||||
$em->persist($participation);
|
||||
}
|
||||
|
||||
|
||||
$em->flush();
|
||||
|
||||
|
||||
$this->addFlash('success', $this->get('translator')->trans(
|
||||
'The participations were created'
|
||||
));
|
||||
|
||||
|
||||
return $this->redirectToRoute('chill_event__event_show', array(
|
||||
'event_id' => $participations[0]->getEvent()->getId()
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
return $this->render('ChillEventBundle:Participation:new.html.twig', array(
|
||||
'form' => $form->createView(),
|
||||
'participation' => $participation
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Handle the request to adapt $participation.
|
||||
*
|
||||
* If the request is multiple, the $participation object is cloned.
|
||||
*
|
||||
* If the request is multiple, the $participation object is cloned.
|
||||
* Limitations: the $participation should not be persisted.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Participation $participation
|
||||
* @param boolean $multiple (default false)
|
||||
*
|
||||
* @return Participation|Participations[] return one single participation if $multiple == false
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException if the event/person is not found
|
||||
* @throws \Symfony\Component\Security\Core\Exception\AccessDeniedException if the user does not have access to event/person
|
||||
*/
|
||||
protected function handleRequest(
|
||||
Request $request,
|
||||
Request $request,
|
||||
Participation $participation,
|
||||
$multiple = false)
|
||||
bool $multiple = false)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
if ($em->contains($participation)) {
|
||||
throw new \LogicException("The participation object should not be managed by "
|
||||
. "the object manager using the method ".__METHOD__);
|
||||
}
|
||||
|
||||
|
||||
$event_id = $request->query->getInt('event_id', 0); // sf4 check:
|
||||
// prevent error: `Argument 2 passed to ::getInt() must be of the type int, null given`
|
||||
|
||||
|
||||
if ($event_id !== NULL) {
|
||||
$event = $em->getRepository('ChillEventBundle:Event')
|
||||
->find($event_id);
|
||||
|
||||
|
||||
if ($event === NULL) {
|
||||
throw $this->createNotFoundException('The event with id '.$event_id.' is not found');
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted('CHILL_EVENT_SEE', $event,
|
||||
|
||||
$this->denyAccessUnlessGranted('CHILL_EVENT_SEE', $event,
|
||||
'The user is not allowed to see the event');
|
||||
|
||||
|
||||
$participation->setEvent($event);
|
||||
}
|
||||
|
||||
// this script should be able to handle multiple, so we translate
|
||||
|
||||
// this script should be able to handle multiple, so we translate
|
||||
// single person_id in an array
|
||||
$persons_ids = $request->query->has('person_id') ?
|
||||
[$request->query->getInt('person_id', 0)] // sf4 check:
|
||||
// prevent error: `Argument 2 passed to ::getInt() must be of the type int, null given`
|
||||
: explode(',', $request->query->get('persons_ids'));
|
||||
$participations = array();
|
||||
|
||||
|
||||
foreach($persons_ids as $person_id) {
|
||||
|
||||
|
||||
// clone if we have to reuse the $participation
|
||||
$participation = count($persons_ids) > 1 ? clone $participation : $participation;
|
||||
|
||||
|
||||
if ($person_id !== NULL) {
|
||||
$person = $em->getRepository('ChillPersonBundle:Person')
|
||||
->find($person_id);
|
||||
@ -428,21 +433,19 @@ class ParticipationController extends AbstractController
|
||||
|
||||
$participation->setPerson($person);
|
||||
}
|
||||
|
||||
|
||||
$participations[] = $participation;
|
||||
}
|
||||
|
||||
|
||||
return $multiple ? $participations : $participations[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Participation $participation
|
||||
* @param null $return_path
|
||||
* @return \Symfony\Component\Form\FormInterface
|
||||
*/
|
||||
public function createCreateForm(Participation $participation, $return_path = null)
|
||||
public function createCreateForm(Participation $participation, $return_path = null): FormInterface
|
||||
{
|
||||
|
||||
|
||||
$form = $this->createForm(ParticipationType::class, $participation, array(
|
||||
'event_type' => $participation->getEvent()->getType(),
|
||||
'action' => $this->generateUrl('chill_event_participation_create', array(
|
||||
@ -451,26 +454,22 @@ class ParticipationController extends AbstractController
|
||||
'person_id' => $participation->getPerson()->getId()
|
||||
))
|
||||
));
|
||||
|
||||
|
||||
$form->add('submit', SubmitType::class, array(
|
||||
'label' => 'Create'
|
||||
));
|
||||
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $participations
|
||||
* @return \Symfony\Component\Form\FormInterface
|
||||
*/
|
||||
public function createCreateFormMultiple(array $participations)
|
||||
|
||||
public function createCreateFormMultiple(array $participations): FormInterface
|
||||
{
|
||||
$form = $this->createForm(\Symfony\Component\Form\Extension\Core\Type\FormType::class,
|
||||
array('participations' => $participations), array(
|
||||
'action' => $this->generateUrl('chill_event_participation_create', array(
|
||||
'event_id' => current($participations)->getEvent()->getId(),
|
||||
'persons_ids' => implode(',', array_map(
|
||||
function(Participation $p) { return $p->getPerson()->getId(); },
|
||||
function(Participation $p) { return $p->getPerson()->getId(); },
|
||||
$participations))
|
||||
)
|
||||
)));
|
||||
@ -481,109 +480,107 @@ class ParticipationController extends AbstractController
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
$form->add('submit', SubmitType::class, array(
|
||||
'label' => 'Create'
|
||||
));
|
||||
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* show an edit form for the participation with the given id.
|
||||
*
|
||||
* @param int $participation_id
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* Show an edit form for the participation with the given id.
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException if the participation is not found
|
||||
* @throws \Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException if the user is not allowed to edit the participation
|
||||
*/
|
||||
public function editAction($participation_id)
|
||||
public function editAction(int $participation_id): Response
|
||||
{
|
||||
/* @var $participation Participation */
|
||||
$participation = $this->getDoctrine()->getManager()
|
||||
->getRepository('ChillEventBundle:Participation')
|
||||
->getRepository(Participation::class)
|
||||
->find($participation_id);
|
||||
|
||||
|
||||
if ($participation === NULL) {
|
||||
throw $this->createNotFoundException('The participation is not found');
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted(ParticipationVoter::UPDATE, $participation,
|
||||
|
||||
$this->denyAccessUnlessGranted(ParticipationVoter::UPDATE, $participation,
|
||||
'You are not allowed to edit this participation');
|
||||
|
||||
|
||||
$form = $this->createEditForm($participation);
|
||||
|
||||
return $this->render('ChillEventBundle:Participation:edit.html.twig', array(
|
||||
|
||||
return $this->render('ChillEventBundle:Participation:edit.html.twig', [
|
||||
'form' => $form->createView(),
|
||||
'participation' => $participation
|
||||
));
|
||||
'participation' => $participation,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $participation_id
|
||||
* @param Request $request
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
|
||||
*/
|
||||
public function updateAction($participation_id, Request $request)
|
||||
|
||||
public function updateAction(int $participation_id, Request $request): Response
|
||||
{
|
||||
/* @var $participation Participation */
|
||||
$participation = $this->getDoctrine()->getManager()
|
||||
->getRepository('ChillEventBundle:Participation')
|
||||
->getRepository(Participation::class)
|
||||
->find($participation_id);
|
||||
|
||||
|
||||
if ($participation === NULL) {
|
||||
throw $this->createNotFoundException('The participation is not found');
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted(ParticipationVoter::UPDATE, $participation,
|
||||
|
||||
$this->denyAccessUnlessGranted(ParticipationVoter::UPDATE, $participation,
|
||||
'You are not allowed to edit this participation');
|
||||
|
||||
|
||||
$form = $this->createEditForm($participation);
|
||||
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
|
||||
$em->flush();
|
||||
|
||||
|
||||
$this->addFlash('success', $this->get('translator')->trans(
|
||||
'The participation was updated'
|
||||
));
|
||||
|
||||
return $this->redirectToRoute('chill_event__event_show', array(
|
||||
'event_id' => $participation->getEvent()->getId()
|
||||
));
|
||||
|
||||
|
||||
return $this->redirectToRoute('chill_event__event_show', [
|
||||
'event_id' => $participation->getEvent()->getId(),
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
return $this->render('ChillEventBundle:Participation:edit.html.twig', array(
|
||||
|
||||
return $this->render('ChillEventBundle:Participation:edit.html.twig', [
|
||||
'form' => $form->createView(),
|
||||
'participation' => $participation
|
||||
));
|
||||
'participation' => $participation,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Participation $participation
|
||||
* @return \Symfony\Component\Form\FormInterface
|
||||
*/
|
||||
public function createEditForm(Participation $participation)
|
||||
|
||||
public function createEditForm(Participation $participation): FormInterface
|
||||
{
|
||||
$form = $this->createForm(ParticipationType::class, $participation, array(
|
||||
'event_type' => $participation->getEvent()->getType(),
|
||||
'action' => $this->generateUrl('chill_event_participation_update', array(
|
||||
'participation_id' => $participation->getId()
|
||||
))
|
||||
));
|
||||
|
||||
$form->add('submit', SubmitType::class, array(
|
||||
'label' => 'Edit'
|
||||
));
|
||||
|
||||
$form = $this->createForm(
|
||||
ParticipationType::class,
|
||||
$participation,
|
||||
[
|
||||
'event_type' => $participation->getEvent()->getType(),
|
||||
'action' => $this->generateUrl(
|
||||
'chill_event_participation_update',
|
||||
[
|
||||
'participation_id' => $participation->getId(),
|
||||
]
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
$form->add(
|
||||
'submit',
|
||||
SubmitType::class, [
|
||||
'label' => 'Edit',
|
||||
]
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* show a form to edit multiple participation for the same event.
|
||||
*
|
||||
@ -594,84 +591,84 @@ class ParticipationController extends AbstractController
|
||||
{
|
||||
$event = $this->getDoctrine()->getRepository('ChillEventBundle:Event')
|
||||
->find($event_id);
|
||||
|
||||
|
||||
if ($event === null) {
|
||||
throw $this->createNotFoundException("The event with id $event_id is not found");
|
||||
}
|
||||
|
||||
|
||||
// check for ACL, on Event level and on Participation Level
|
||||
$this->denyAccessUnlessGranted('CHILL_EVENT_SEE', $event, "You are not allowed "
|
||||
. "to see this event");
|
||||
foreach ($event->getParticipations() as $participation) {
|
||||
$this->denyAccessUnlessGranted(ParticipationVoter::UPDATE, $participation,
|
||||
$this->denyAccessUnlessGranted(ParticipationVoter::UPDATE, $participation,
|
||||
"You are not allowed to update participation with id ".$participation->getId());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
switch ($event->getParticipations()->count()) {
|
||||
|
||||
|
||||
case 0:
|
||||
// if there aren't any participation, redirect to the 'show' view with an add flash
|
||||
$this->addFlash('warning', $this->get('translator')
|
||||
->trans( "There are no participation to edit for this event"));
|
||||
|
||||
return $this->redirectToRoute('chill_event__event_show',
|
||||
return $this->redirectToRoute('chill_event__event_show',
|
||||
array('event_id' => $event->getId()));
|
||||
|
||||
|
||||
case 1:
|
||||
// redirect to the form for a single participation
|
||||
return $this->redirectToRoute('chill_event_participation_edit', array(
|
||||
'participation_id' => $event->getParticipations()->current()->getId()
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$form = $this->createEditFormMultiple($event->getParticipations(), $event);
|
||||
|
||||
|
||||
return $this->render('ChillEventBundle:Participation:edit-multiple.html.twig', array(
|
||||
'event' => $event,
|
||||
'participations' => $event->getParticipations(),
|
||||
'form' => $form->createView()
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
public function updateMultipleAction($event_id, Request $request)
|
||||
{
|
||||
/* @var $event \Chill\EventBundle\Entity\Event */
|
||||
$event = $this->getDoctrine()->getRepository('ChillEventBundle:Event')
|
||||
->find($event_id);
|
||||
|
||||
|
||||
if ($event === null) {
|
||||
throw $this->createNotFoundException("The event with id $event_id is not found");
|
||||
}
|
||||
|
||||
|
||||
$this->denyAccessUnlessGranted('CHILL_EVENT_SEE', $event, "You are not allowed "
|
||||
. "to see this event");
|
||||
foreach ($event->getParticipations() as $participation) {
|
||||
$this->denyAccessUnlessGranted(ParticipationVoter::UPDATE, $participation,
|
||||
$this->denyAccessUnlessGranted(ParticipationVoter::UPDATE, $participation,
|
||||
"You are not allowed to update participation with id ".$participation->getId());
|
||||
}
|
||||
|
||||
|
||||
$form = $this->createEditFormMultiple($event->getParticipations(), $event);
|
||||
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->getDoctrine()->getManager()->flush();
|
||||
|
||||
|
||||
$this->addFlash('success', $this->get('translator')->trans("The participations "
|
||||
. "have been successfully updated."));
|
||||
|
||||
return $this->redirectToRoute('chill_event__event_show',
|
||||
|
||||
return $this->redirectToRoute('chill_event__event_show',
|
||||
array('event_id' => $event->getId()));
|
||||
}
|
||||
|
||||
|
||||
return $this->render('ChillEventBundle:Participation:edit-multiple.html.twig', array(
|
||||
'event' => $event,
|
||||
'participations' => $event->getParticipations(),
|
||||
'form' => $form->createView()
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ArrayIterator $participations
|
||||
* @param Event $event
|
||||
@ -679,14 +676,14 @@ class ParticipationController extends AbstractController
|
||||
*/
|
||||
protected function createEditFormMultiple(ArrayIterator $participations, Event $event)
|
||||
{
|
||||
$form = $this->createForm(\Symfony\Component\Form\Extension\Core\Type\FormType::class,
|
||||
$form = $this->createForm(\Symfony\Component\Form\Extension\Core\Type\FormType::class,
|
||||
array('participations' => $participations), array(
|
||||
'method' => 'POST',
|
||||
'action' => $this->generateUrl('chill_event_participation_update_multiple', array(
|
||||
'event_id' => $event->getId()
|
||||
))
|
||||
));
|
||||
|
||||
|
||||
$form->add('participations', CollectionType::class, array(
|
||||
'entry_type' => ParticipationType::class,
|
||||
'entry_options' => array(
|
||||
@ -694,14 +691,14 @@ class ParticipationController extends AbstractController
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
$form->add('submit', SubmitType::class, array(
|
||||
'label' => 'Update'
|
||||
));
|
||||
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param integer $participation_id
|
||||
* @param Request $request
|
||||
@ -713,28 +710,28 @@ class ParticipationController extends AbstractController
|
||||
$participation = $em->getRepository('ChillEventBundle:Participation')->findOneBy([
|
||||
'id' => $participation_id
|
||||
]);
|
||||
|
||||
|
||||
if (! $participation) {
|
||||
throw $this->createNotFoundException('Unable to find participation.');
|
||||
}
|
||||
|
||||
|
||||
/** @var Event $event */
|
||||
$event = $participation->getEvent();
|
||||
|
||||
|
||||
$form = $this->createDeleteForm($participation_id);
|
||||
|
||||
|
||||
if ($request->getMethod() === Request::METHOD_DELETE) {
|
||||
$form->handleRequest($request);
|
||||
|
||||
|
||||
if ($form->isValid()) {
|
||||
|
||||
|
||||
$em->remove($participation);
|
||||
$em->flush();
|
||||
|
||||
|
||||
$this->addFlash('success', $this->get('translator')
|
||||
->trans("The participation has been sucessfully removed")
|
||||
);
|
||||
|
||||
|
||||
return $this->redirectToRoute('chill_event__event_show', [
|
||||
'event_id' => $event->getId()
|
||||
]);
|
||||
@ -744,9 +741,9 @@ class ParticipationController extends AbstractController
|
||||
'event_id' => $event->getId(),
|
||||
'delete_form' => $form->createView()
|
||||
]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $participation_id
|
||||
* @return \Symfony\Component\Form\FormInterface
|
||||
@ -762,5 +759,5 @@ class ParticipationController extends AbstractController
|
||||
->getForm()
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -50,19 +50,19 @@ class LoadRolesACL extends AbstractFixture implements OrderedFixtureInterface
|
||||
break;
|
||||
case 'administrative':
|
||||
case 'direction':
|
||||
if (in_array($scope->getName()['en'], array('administrative', 'social'))) {
|
||||
if (in_array($scope->getName()['en'], array('administrative', 'social'), true)) {
|
||||
break 2; // we do not want any power on social or administrative
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
printf("Adding CHILL_EVENT_UPDATE & CHILL_EVENT_CREATE "
|
||||
. "& CHILL_EVENT_PARTICIPATION_UPDATE & CHILL_EVENT_PARTICIPATION_CREATE "
|
||||
. "& CHILL_EVENT_SEE & CHILL_EVENT_SEE_DETAILS "
|
||||
. "to %s "
|
||||
. "permission group, scope '%s' \n",
|
||||
. "permission group, scope '%s' \n",
|
||||
$permissionsGroup->getName(), $scope->getName()['en']);
|
||||
|
||||
|
||||
$roleScopeUpdate = (new RoleScope())
|
||||
->setRole('CHILL_EVENT_UPDATE')
|
||||
->setScope($scope);
|
||||
@ -71,7 +71,7 @@ class LoadRolesACL extends AbstractFixture implements OrderedFixtureInterface
|
||||
->setScope($scope);
|
||||
$permissionsGroup->addRoleScope($roleScopeUpdate);
|
||||
$permissionsGroup->addRoleScope($roleScopeUpdate2);
|
||||
|
||||
|
||||
$roleScopeCreate = (new RoleScope())
|
||||
->setRole('CHILL_EVENT_CREATE')
|
||||
->setScope($scope);
|
||||
@ -80,7 +80,7 @@ class LoadRolesACL extends AbstractFixture implements OrderedFixtureInterface
|
||||
->setScope($scope);
|
||||
$permissionsGroup->addRoleScope($roleScopeCreate);
|
||||
$permissionsGroup->addRoleScope($roleScopeCreate2);
|
||||
|
||||
|
||||
$roleScopeSee = (new RoleScope())
|
||||
->setRole('CHILL_EVENT_SEE')
|
||||
->setScope($scope);
|
||||
@ -89,7 +89,7 @@ class LoadRolesACL extends AbstractFixture implements OrderedFixtureInterface
|
||||
->setScope($scope);
|
||||
$permissionsGroup->addRoleScope($roleScopeSee);
|
||||
$permissionsGroup->addRoleScope($roleScopeSee2);
|
||||
|
||||
|
||||
$manager->persist($roleScopeUpdate);
|
||||
$manager->persist($roleScopeUpdate2);
|
||||
$manager->persist($roleScopeCreate);
|
||||
@ -97,9 +97,9 @@ class LoadRolesACL extends AbstractFixture implements OrderedFixtureInterface
|
||||
$manager->persist($roleScopeSee);
|
||||
$manager->persist($roleScopeSee2);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
|
@ -1,50 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\AMLI\FamilyMembersBundle\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Chill\AMLI\FamilyMembersBundle\Repository\FamilyMemberRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Chill\AMLI\FamilyMembersBundle\Entity\FamilyMember;
|
||||
use Chill\AMLI\FamilyMembersBundle\Security\Voter\FamilyMemberVoter;
|
||||
use Chill\AMLI\FamilyMembersBundle\Form\FamilyMemberType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class FamilyMemberController extends Controller
|
||||
class FamilyMemberController extends AbstractController
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
protected $em;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $chillMainLogger;
|
||||
|
||||
private EntityManagerInterface $em;
|
||||
|
||||
protected TranslatorInterface $translator;
|
||||
|
||||
protected LoggerInterface $chillMainLogger;
|
||||
|
||||
private FamilyMemberRepository $familyMemberRepository;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
EntityManagerInterface $entityManager,
|
||||
TranslatorInterface $translator,
|
||||
LoggerInterface $chillMainLogger
|
||||
LoggerInterface $chillMainLogger,
|
||||
FamilyMemberRepository $familyMemberRepository
|
||||
) {
|
||||
$this->em = $em;
|
||||
$this->em = $entityManager;
|
||||
$this->translator = $translator;
|
||||
$this->chillMainLogger = $chillMainLogger;
|
||||
$this->familyMemberRepository = $familyMemberRepository;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Route(
|
||||
* "{_locale}/family-members/family-members/by-person/{id}",
|
||||
@ -54,15 +50,13 @@ class FamilyMemberController extends Controller
|
||||
public function indexAction(Person $person)
|
||||
{
|
||||
$this->denyAccessUnlessGranted(FamilyMemberVoter::SHOW, $person);
|
||||
|
||||
$familyMembers = $this->em
|
||||
->getRepository(FamilyMember::class)
|
||||
->findByPerson($person);
|
||||
|
||||
return $this->render('ChillAMLIFamilyMembersBundle:FamilyMember:index.html.twig', array(
|
||||
|
||||
$familyMembers = $this->familyMemberRepository->findByPerson($person);
|
||||
|
||||
return $this->render('ChillAMLIFamilyMembersBundle:FamilyMember:index.html.twig', [
|
||||
'person' => $person,
|
||||
'familyMembers' => $familyMembers
|
||||
));
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -73,33 +67,30 @@ class FamilyMemberController extends Controller
|
||||
*/
|
||||
public function newAction(Person $person, Request $request)
|
||||
{
|
||||
$familyMember = (new FamilyMember())
|
||||
->setPerson($person)
|
||||
;
|
||||
|
||||
$familyMember = (new FamilyMember())->setPerson($person);
|
||||
|
||||
$this->denyAccessUnlessGranted(FamilyMemberVoter::CREATE, $familyMember);
|
||||
|
||||
|
||||
$form = $this->createForm(FamilyMemberType::class, $familyMember);
|
||||
$form->add('submit', SubmitType::class);
|
||||
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() and $form->isValid()) {
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->persist($familyMember);
|
||||
$em->flush();
|
||||
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->em->persist($familyMember);
|
||||
$this->em->flush();
|
||||
|
||||
$this->addFlash('success', $this->translator->trans('Family member created'));
|
||||
|
||||
|
||||
return $this->redirectToRoute('chill_family_members_family_members_index', [
|
||||
'id' => $person->getId()
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->render('ChillAMLIFamilyMembersBundle:FamilyMember:new.html.twig', array(
|
||||
|
||||
return $this->render('ChillAMLIFamilyMembersBundle:FamilyMember:new.html.twig', [
|
||||
'form' => $form->createView(),
|
||||
'person' => $person
|
||||
));
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,79 +102,73 @@ class FamilyMemberController extends Controller
|
||||
public function editAction(FamilyMember $familyMember, Request $request)
|
||||
{
|
||||
$this->denyAccessUnlessGranted(FamilyMemberVoter::UPDATE, $familyMember);
|
||||
|
||||
|
||||
$form = $this->createForm(FamilyMemberType::class, $familyMember);
|
||||
$form->add('submit', SubmitType::class);
|
||||
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() and $form->isValid()) {
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->flush();
|
||||
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->em->flush();
|
||||
|
||||
$this->addFlash('success', $this->translator->trans('Family member updated'));
|
||||
|
||||
|
||||
return $this->redirectToRoute('chill_family_members_family_members_index', [
|
||||
'id' => $familyMember->getPerson()->getId()
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->render('ChillAMLIFamilyMembersBundle:FamilyMember:edit.html.twig', array(
|
||||
|
||||
return $this->render('ChillAMLIFamilyMembersBundle:FamilyMember:edit.html.twig', [
|
||||
'familyMember' => $familyMember,
|
||||
'form' => $form->createView(),
|
||||
'person' => $familyMember->getPerson()
|
||||
));
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @Route(
|
||||
* "{_locale}/family-members/family-members/{id}/delete",
|
||||
* name="chill_family_members_family_members_delete"
|
||||
* )
|
||||
*
|
||||
* @param FamilyMember $familyMember
|
||||
* @param Request $request
|
||||
* @return \Symfony\Component\BrowserKit\Response
|
||||
*/
|
||||
public function deleteAction(FamilyMember $familyMember, Request $request)
|
||||
public function deleteAction(FamilyMember $familyMember, Request $request): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted(FamilyMemberVoter::DELETE, $familyMember, 'You are not '
|
||||
. 'allowed to delete this family membership');
|
||||
|
||||
$form = $this->createDeleteForm($id);
|
||||
$form = $this->createDeleteForm();
|
||||
|
||||
if ($request->getMethod() === Request::METHOD_DELETE) {
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isValid()) {
|
||||
$this->chillMainLogger->notice("A family member has been removed", array(
|
||||
$this->chillMainLogger->notice("A family member has been removed", [
|
||||
'by_user' => $this->getUser()->getUsername(),
|
||||
'family_member_id' => $familyMember->getId(),
|
||||
'name' => $familyMember->getFirstname()." ".$familyMember->getLastname(),
|
||||
'link' => $familyMember->getLink()
|
||||
));
|
||||
]);
|
||||
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->remove($familyMember);
|
||||
$em->flush();
|
||||
$this->em->remove($familyMember);
|
||||
$this->em->flush();
|
||||
|
||||
$this->addFlash('success', $this->translator
|
||||
->trans("The family member has been successfully removed."));
|
||||
|
||||
return $this->redirectToRoute('chill_family_members_family_members_index', array(
|
||||
return $this->redirectToRoute('chill_family_members_family_members_index', [
|
||||
'id' => $familyMember->getPerson()->getId()
|
||||
));
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $this->render('ChillAMLIFamilyMembersBundle:FamilyMember:confirm_delete.html.twig', array(
|
||||
return $this->render('ChillAMLIFamilyMembersBundle:FamilyMember:confirm_delete.html.twig', [
|
||||
'familyMember' => $familyMember,
|
||||
'delete_form' => $form->createView()
|
||||
));
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Route(
|
||||
* "{_locale}/family-members/family-members/{id}/view",
|
||||
@ -193,24 +178,21 @@ class FamilyMemberController extends Controller
|
||||
public function viewAction(FamilyMember $familyMember)
|
||||
{
|
||||
$this->denyAccessUnlessGranted(FamilyMemberVoter::SHOW, $familyMember);
|
||||
|
||||
return $this->render('ChillAMLIFamilyMembersBundle:FamilyMember:view.html.twig', array(
|
||||
|
||||
return $this->render('ChillAMLIFamilyMembersBundle:FamilyMember:view.html.twig', [
|
||||
'familyMember' => $familyMember
|
||||
));
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a form to delete a help request entity by id.
|
||||
*
|
||||
* @param mixed $id The entity id
|
||||
*
|
||||
* @return \Symfony\Component\Form\Form The form
|
||||
*/
|
||||
private function createDeleteForm($id)
|
||||
private function createDeleteForm(): FormInterface
|
||||
{
|
||||
return $this->createFormBuilder()
|
||||
return $this
|
||||
->createFormBuilder()
|
||||
->setMethod(Request::METHOD_DELETE)
|
||||
->add('submit', SubmitType::class, array('label' => 'Delete'))
|
||||
->add('submit', SubmitType::class, ['label' => 'Delete'])
|
||||
->getForm()
|
||||
;
|
||||
}
|
||||
|
@ -1,17 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\AMLI\FamilyMembersBundle\Repository;
|
||||
|
||||
use Chill\AMLI\FamilyMembersBundle\Entity\FamilyMember;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* FamilyMemberRepository
|
||||
*
|
||||
* @method FamilyMember|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method FamilyMember|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method FamilyMember[] findAll()
|
||||
* @method FamilyMember[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class FamilyMemberRepository extends \Doctrine\ORM\EntityRepository
|
||||
class FamilyMemberRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function findActiveByPerson(Person $person)
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
return $this->findBy([ 'person' => $person ]);
|
||||
parent::__construct($registry, FamilyMember::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FamilyMember[]
|
||||
*/
|
||||
public function findByPerson(Person $person): array
|
||||
{
|
||||
return $this->findBy(['person' => $person]);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\CRUD\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
@ -14,94 +16,77 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
class AbstractCRUDController extends AbstractController
|
||||
abstract class AbstractCRUDController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* The crud configuration
|
||||
* The crud configuration
|
||||
*
|
||||
* This configuration si defined by `chill_main['crud']` or `chill_main['apis']`
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected array $crudConfig = [];
|
||||
|
||||
/**
|
||||
* get the instance of the entity with the given id
|
||||
*
|
||||
* @param string $id
|
||||
* @return object
|
||||
*
|
||||
* @throw Symfony\Component\HttpKernel\Exception\NotFoundHttpException if the object is not found
|
||||
*/
|
||||
protected function getEntity($action, $id, Request $request): object
|
||||
protected function getEntity($action, string $id, Request $request): object
|
||||
{
|
||||
$e = $this->getDoctrine()
|
||||
$e = $this
|
||||
->getDoctrine()
|
||||
->getRepository($this->getEntityClass())
|
||||
->find($id);
|
||||
|
||||
if (NULL === $e) {
|
||||
if (null === $e) {
|
||||
throw $this->createNotFoundException(sprintf("The object %s for id %s is not found", $this->getEntityClass(), $id));
|
||||
}
|
||||
|
||||
return $e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an entity.
|
||||
*
|
||||
* @param string $action
|
||||
* @param Request $request
|
||||
* @return object
|
||||
*/
|
||||
protected function createEntity(string $action, Request $request): object
|
||||
{
|
||||
$type = $this->getEntityClass();
|
||||
|
||||
return new $type;
|
||||
$class = $this->getEntityClass();
|
||||
|
||||
return new $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of entities
|
||||
*
|
||||
* By default, count all entities. You can customize the query by
|
||||
* By default, count all entities. You can customize the query by
|
||||
* using the method `customizeQuery`.
|
||||
*
|
||||
* @param string $action
|
||||
* @param Request $request
|
||||
* @return int
|
||||
*/
|
||||
protected function countEntities(string $action, Request $request, $_format): int
|
||||
{
|
||||
return $this->buildQueryEntities($action, $request)
|
||||
->select('COUNT(e)')
|
||||
->getQuery()
|
||||
->getSingleScalarResult()
|
||||
;
|
||||
->getSingleScalarResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the entity.
|
||||
*
|
||||
*
|
||||
* By default, get all entities. You can customize the query by using the
|
||||
* method `customizeQuery`.
|
||||
*
|
||||
*
|
||||
* The method `orderEntity` is called internally to order entities.
|
||||
*
|
||||
*
|
||||
* It returns, by default, a query builder.
|
||||
*
|
||||
*/
|
||||
protected function queryEntities(string $action, Request $request, string $_format, PaginatorInterface $paginator)
|
||||
{
|
||||
$query = $this->buildQueryEntities($action, $request)
|
||||
->setFirstResult($paginator->getCurrentPage()->getFirstItemNumber())
|
||||
->setMaxResults($paginator->getItemsPerPage());
|
||||
|
||||
|
||||
// allow to order queries and return the new query
|
||||
return $this->orderQuery($action, $query, $request, $paginator, $_format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add ordering fields in the query build by self::queryEntities
|
||||
*
|
||||
*/
|
||||
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator, $_format)
|
||||
{
|
||||
@ -112,14 +97,12 @@ class AbstractCRUDController extends AbstractController
|
||||
* Build the base query for listing all entities.
|
||||
*
|
||||
* This method is used internally by `countEntities` `queryEntities`
|
||||
*
|
||||
*
|
||||
* This base query does not contains any `WHERE` or `SELECT` clauses. You
|
||||
* can add some by using the method `customizeQuery`.
|
||||
*
|
||||
* The alias for the entity is "e".
|
||||
*
|
||||
* @param string $action
|
||||
* @param Request $request
|
||||
*
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
protected function buildQueryEntities(string $action, Request $request)
|
||||
@ -127,8 +110,7 @@ class AbstractCRUDController extends AbstractController
|
||||
$qb = $this->getDoctrine()->getManager()
|
||||
->createQueryBuilder()
|
||||
->select('e')
|
||||
->from($this->getEntityClass(), 'e')
|
||||
;
|
||||
->from($this->getEntityClass(), 'e');
|
||||
|
||||
$this->customizeQuery($action, $request, $qb);
|
||||
|
||||
@ -138,55 +120,54 @@ class AbstractCRUDController extends AbstractController
|
||||
protected function customizeQuery(string $action, Request $request, $query): void {}
|
||||
|
||||
/**
|
||||
* Get the result of the query
|
||||
* Get the result of the query.
|
||||
*/
|
||||
protected function getQueryResult(string $action, Request $request, string $_format, int $totalItems, PaginatorInterface $paginator, $query)
|
||||
protected function getQueryResult(string $action, Request $request, string $_format, int $totalItems, PaginatorInterface $paginator, $query)
|
||||
{
|
||||
return $query->getQuery()->getResult();
|
||||
}
|
||||
|
||||
protected function onPreIndex(string $action, Request $request, string $_format): ?Response
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* method used by indexAction
|
||||
*/
|
||||
protected function onPreIndexBuildQuery(string $action, Request $request, string $_format, int $totalItems, PaginatorInterface $paginator): ?Response
|
||||
{
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* method used by indexAction
|
||||
* Method used by indexAction.
|
||||
*/
|
||||
protected function onPreIndexBuildQuery(string $action, Request $request, string $_format, int $totalItems, PaginatorInterface $paginator): ?Response
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used by indexAction.
|
||||
*/
|
||||
protected function onPostIndexBuildQuery(string $action, Request $request, string $_format, int $totalItems, PaginatorInterface $paginator, $query): ?Response
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* method used by indexAction
|
||||
* Method used by indexAction.
|
||||
*/
|
||||
protected function onPostIndexFetchQuery(string $action, Request $request, string $_format, int $totalItems, PaginatorInterface $paginator, $entities): ?Response
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the complete FQDN of the class
|
||||
*
|
||||
* @return string the complete fqdn of the class
|
||||
* Get the FQDN of the class.
|
||||
*
|
||||
* @return class-string The FQDN of the class
|
||||
*/
|
||||
protected function getEntityClass(): string
|
||||
{
|
||||
return $this->crudConfig['class'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* called on post fetch entity
|
||||
* Called on post fetch entity.
|
||||
*/
|
||||
protected function onPostFetchEntity(string $action, Request $request, $entity, $_format): ?Response
|
||||
{
|
||||
@ -194,7 +175,7 @@ class AbstractCRUDController extends AbstractController
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on post check ACL
|
||||
* Called on post check ACL.
|
||||
*/
|
||||
protected function onPostCheckACL(string $action, Request $request, string $_format, $entity): ?Response
|
||||
{
|
||||
@ -203,23 +184,23 @@ class AbstractCRUDController extends AbstractController
|
||||
|
||||
/**
|
||||
* check the acl. Called by every action.
|
||||
*
|
||||
* By default, check the role given by `getRoleFor` for the value given in
|
||||
*
|
||||
* By default, check the role given by `getRoleFor` for the value given in
|
||||
* $entity.
|
||||
*
|
||||
*
|
||||
* Throw an \Symfony\Component\Security\Core\Exception\AccessDeniedHttpException
|
||||
* if not accessible.
|
||||
*
|
||||
*
|
||||
* @throws \Symfony\Component\Security\Core\Exception\AccessDeniedHttpException
|
||||
*/
|
||||
protected function checkACL(string $action, Request $request, string $_format, $entity = null)
|
||||
{
|
||||
// @TODO: Implements abstract getRoleFor method or do it in the interface.
|
||||
$this->denyAccessUnlessGranted($this->getRoleFor($action, $request, $entity, $_format), $entity);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string the crud name
|
||||
* @return string The crud name.
|
||||
*/
|
||||
protected function getCrudName(): string
|
||||
{
|
||||
@ -230,7 +211,7 @@ class AbstractCRUDController extends AbstractController
|
||||
{
|
||||
return $this->crudConfig['actions'][$action];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the crud configuration
|
||||
*
|
||||
@ -241,9 +222,6 @@ class AbstractCRUDController extends AbstractController
|
||||
$this->crudConfig = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PaginatorFactory
|
||||
*/
|
||||
protected function getPaginatorFactory(): PaginatorFactory
|
||||
{
|
||||
return $this->container->get('chill_main.paginator_factory');
|
||||
@ -254,9 +232,6 @@ class AbstractCRUDController extends AbstractController
|
||||
return $this->get('validator');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getSubscribedServices(): array
|
||||
{
|
||||
return \array_merge(
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\CRUD\Controller;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@ -17,36 +19,36 @@ class ApiController extends AbstractCRUDController
|
||||
{
|
||||
/**
|
||||
* The view action.
|
||||
*
|
||||
*
|
||||
* Some steps may be overriden during this process of rendering:
|
||||
*
|
||||
*
|
||||
* This method:
|
||||
*
|
||||
*
|
||||
* 1. fetch the entity, using `getEntity`
|
||||
* 2. launch `onPostFetchEntity`. If postfetch is an instance of Response,
|
||||
* this response is returned.
|
||||
* 2. throw an HttpNotFoundException if entity is null
|
||||
* 3. check ACL using `checkACL` ;
|
||||
* 4. launch `onPostCheckACL`. If the result is an instance of Response,
|
||||
* 4. launch `onPostCheckACL`. If the result is an instance of Response,
|
||||
* this response is returned ;
|
||||
* 5. Serialize the entity and return the result. The serialization context is given by `getSerializationContext`
|
||||
*
|
||||
*
|
||||
*/
|
||||
protected function entityGet(string $action, Request $request, $id, $_format = 'html'): Response
|
||||
{
|
||||
$entity = $this->getEntity($action, $id, $request, $_format);
|
||||
|
||||
$entity = $this->getEntity($action, $id, $request);
|
||||
|
||||
$postFetch = $this->onPostFetchEntity($action, $request, $entity, $_format);
|
||||
|
||||
|
||||
if ($postFetch instanceof Response) {
|
||||
return $postFetch;
|
||||
}
|
||||
|
||||
|
||||
$response = $this->checkACL($action, $request, $_format, $entity);
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
$response = $this->onPostCheckACL($action, $request, $_format, $entity);
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
@ -86,7 +88,7 @@ class ApiController extends AbstractCRUDController
|
||||
case Request::METHOD_PATCH:
|
||||
return $this->entityPut('_entity', $request, $id, $_format);
|
||||
case Request::METHOD_POST:
|
||||
return $this->entityPostAction('_entity', $request, $id, $_format);
|
||||
return $this->entityPostAction('_entity', $request, $id);
|
||||
case Request::METHOD_DELETE:
|
||||
return $this->entityDelete('_entity', $request, $id, $_format);
|
||||
default:
|
||||
@ -112,9 +114,9 @@ class ApiController extends AbstractCRUDController
|
||||
} catch (NotEncodableValueException $e) {
|
||||
throw new BadRequestException("invalid json", 400, $e);
|
||||
}
|
||||
|
||||
|
||||
$errors = $this->validate($action, $request, $_format, $entity);
|
||||
|
||||
|
||||
$response = $this->onAfterValidation($action, $request, $_format, $entity, $errors);
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
@ -126,12 +128,12 @@ class ApiController extends AbstractCRUDController
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
$response = $this->checkACL($action, $request, $_format, $entity);
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
$response = $this->onPostCheckACL($action, $request, $_format, $entity);
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
@ -148,33 +150,33 @@ class ApiController extends AbstractCRUDController
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
return $this->json(
|
||||
$entity,
|
||||
Response::HTTP_OK,
|
||||
[],
|
||||
[],
|
||||
$this->getContextForSerializationPostAlter($action, $request, $_format, $entity)
|
||||
);
|
||||
}
|
||||
public function entityPut($action, Request $request, $id, string $_format): Response
|
||||
{
|
||||
$entity = $this->getEntity($action, $id, $request, $_format);
|
||||
|
||||
$entity = $this->getEntity($action, $id, $request);
|
||||
|
||||
$postFetch = $this->onPostFetchEntity($action, $request, $entity, $_format);
|
||||
if ($postFetch instanceof Response) {
|
||||
return $postFetch;
|
||||
}
|
||||
|
||||
|
||||
if (NULL === $entity) {
|
||||
throw $this->createNotFoundException(sprintf("The %s with id %s "
|
||||
. "is not found", $this->getCrudName(), $id));
|
||||
}
|
||||
|
||||
|
||||
$response = $this->checkACL($action, $request, $_format, $entity);
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
$response = $this->onPostCheckACL($action, $request, $_format, $entity);
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
@ -184,7 +186,7 @@ class ApiController extends AbstractCRUDController
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
$entity = $this->deserialize($action, $request, $_format, $entity);
|
||||
} catch (NotEncodableValueException $e) {
|
||||
@ -215,13 +217,13 @@ class ApiController extends AbstractCRUDController
|
||||
return $this->json(
|
||||
$entity,
|
||||
Response::HTTP_OK,
|
||||
[],
|
||||
[],
|
||||
$this->getContextForSerializationPostAlter($action, $request, $_format, $entity)
|
||||
);
|
||||
}
|
||||
public function entityDelete($action, Request $request, $id, string $_format): Response
|
||||
{
|
||||
$entity = $this->getEntity($action, $id, $request, $_format);
|
||||
$entity = $this->getEntity($action, $id, $request);
|
||||
|
||||
if (NULL === $entity) {
|
||||
throw $this->createNotFoundException(sprintf("The %s with id %s "
|
||||
@ -287,7 +289,7 @@ class ApiController extends AbstractCRUDController
|
||||
protected function validate(string $action, Request $request, string $_format, $entity, array $more = []): ConstraintViolationListInterface
|
||||
{
|
||||
$validationGroups = $this->getValidationGroups($action, $request, $_format, $entity);
|
||||
|
||||
|
||||
return $this->getValidator()->validate($entity, null, $validationGroups);
|
||||
}
|
||||
|
||||
@ -309,7 +311,7 @@ class ApiController extends AbstractCRUDController
|
||||
|
||||
return $this->getSerializer()->deserialize($request->getContent(), $this->getEntityClass(), $_format, $context);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Base action for indexing entities
|
||||
@ -327,11 +329,11 @@ class ApiController extends AbstractCRUDController
|
||||
|
||||
/**
|
||||
* Build an index page.
|
||||
*
|
||||
*
|
||||
* Some steps may be overriden during this process of rendering.
|
||||
*
|
||||
*
|
||||
* This method:
|
||||
*
|
||||
*
|
||||
* 1. Launch `onPreIndex`
|
||||
* x. check acl. If it does return a response instance, return it
|
||||
* x. launch `onPostCheckACL`. If it does return a response instance, return it
|
||||
@ -342,58 +344,60 @@ class ApiController extends AbstractCRUDController
|
||||
* x. fetch the results, using `getQueryResult`
|
||||
* x. Launch `onPostIndexFetchQuery`. If it does return a response instance, return it
|
||||
* 4. Serialize the entities in a Collection, using `SerializeCollection`
|
||||
*
|
||||
*
|
||||
* @param string $action
|
||||
* @param Request $request
|
||||
* @return type
|
||||
*/
|
||||
protected function indexApiAction($action, Request $request, $_format)
|
||||
{
|
||||
$this->onPreIndex($action, $request, $_format);
|
||||
|
||||
|
||||
$response = $this->checkACL($action, $request, $_format);
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
if (!isset($entity)) {
|
||||
$entity = '';
|
||||
}
|
||||
|
||||
|
||||
$entity = '';
|
||||
|
||||
$response = $this->onPostCheckACL($action, $request, $_format, $entity);
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
$totalItems = $this->countEntities($action, $request, $_format);
|
||||
$paginator = $this->getPaginatorFactory()->create($totalItems);
|
||||
|
||||
$response = $this->onPreIndexBuildQuery($action, $request, $_format, $totalItems,
|
||||
$paginator);
|
||||
|
||||
|
||||
$response = $this->onPreIndexBuildQuery(
|
||||
$action,
|
||||
$request,
|
||||
$_format,
|
||||
$totalItems,
|
||||
$paginator
|
||||
);
|
||||
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
$query = $this->queryEntities($action, $request, $_format, $paginator);
|
||||
|
||||
$response = $this->onPostIndexBuildQuery($action, $request, $_format, $totalItems,
|
||||
|
||||
$response = $this->onPostIndexBuildQuery($action, $request, $_format, $totalItems,
|
||||
$paginator, $query);
|
||||
|
||||
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
$entities = $this->getQueryResult($action, $request, $_format, $totalItems, $paginator, $query);
|
||||
|
||||
$response = $this->onPostIndexFetchQuery($action, $request, $_format, $totalItems,
|
||||
|
||||
$response = $this->onPostIndexFetchQuery($action, $request, $_format, $totalItems,
|
||||
$paginator, $entities);
|
||||
|
||||
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
return $this->serializeCollection($action, $request, $_format, $paginator, $entities);
|
||||
|
||||
return $this->serializeCollection($action, $request, $_format, $paginator, $entities);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -402,7 +406,7 @@ class ApiController extends AbstractCRUDController
|
||||
* This method:
|
||||
*
|
||||
* 1. Fetch the base entity (throw 404 if not found)
|
||||
* 2. checkACL,
|
||||
* 2. checkACL,
|
||||
* 3. run onPostCheckACL, return response if any,
|
||||
* 4. deserialize posted data into the entity given by $postedDataType, with the context in $postedDataContext
|
||||
* 5. run 'add+$property' for POST method, or 'remove+$property' for DELETE method
|
||||
@ -410,7 +414,7 @@ class ApiController extends AbstractCRUDController
|
||||
* 7. run onAfterValidation
|
||||
* 8. if errors, return a 422 response with errors
|
||||
* 9. if $forcePersist === true, persist the entity
|
||||
* 10. flush the data
|
||||
* 10. flush the data
|
||||
* 11. run onAfterFlush
|
||||
* 12. return a 202 response for DELETE with empty body, or HTTP 200 for post with serialized posted entity
|
||||
*
|
||||
@ -425,7 +429,7 @@ class ApiController extends AbstractCRUDController
|
||||
* @throw BadRequestException if unable to deserialize the posted data
|
||||
* @throw BadRequestException if the method is not POST or DELETE
|
||||
*
|
||||
*/
|
||||
*/
|
||||
protected function addRemoveSomething(string $action, $id, Request $request, string $_format, string $property, string $postedDataType, array $postedDataContext = [], bool $forcePersist = false): Response
|
||||
{
|
||||
$entity = $this->getEntity($action, $id, $request);
|
||||
@ -500,12 +504,14 @@ class ApiController extends AbstractCRUDController
|
||||
return $this->json(
|
||||
$postedData,
|
||||
Response::HTTP_OK,
|
||||
[],
|
||||
[],
|
||||
$this->getContextForSerializationPostAlter($action, $request, $_format, $entity, [$postedData])
|
||||
);
|
||||
}
|
||||
|
||||
throw new \Exception('Unable to handle such request method.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serialize collections
|
||||
*
|
||||
@ -518,7 +524,7 @@ class ApiController extends AbstractCRUDController
|
||||
|
||||
return $this->json($model, Response::HTTP_OK, [], $context);
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected function getContextForSerialization(string $action, Request $request, string $_format, $entity): array
|
||||
{
|
||||
@ -535,7 +541,7 @@ class ApiController extends AbstractCRUDController
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the context for serialization post alter query (in case of
|
||||
* Get the context for serialization post alter query (in case of
|
||||
* PATCH, PUT, or POST method)
|
||||
*
|
||||
* This is called **after** the entity was altered.
|
||||
@ -563,7 +569,7 @@ class ApiController extends AbstractCRUDController
|
||||
throw new \RuntimeException(sprintf("the config does not have any role for the ".
|
||||
"method %s nor a global role for the whole action. Add those to your ".
|
||||
"configuration or override the required method", $request->getMethod()));
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected function getSerializer(): SerializerInterface
|
||||
|
@ -1,22 +1,4 @@
|
||||
<?php
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2019, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Chill\MainBundle\CRUD\Controller;
|
||||
|
||||
@ -37,60 +19,40 @@ use Chill\MainBundle\Pagination\PaginatorInterface;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
|
||||
/**
|
||||
* Class CRUDController
|
||||
*
|
||||
* @package Chill\MainBundle\CRUD\Controller
|
||||
*/
|
||||
class CRUDController extends AbstractController
|
||||
{
|
||||
|
||||
/**
|
||||
* The crud configuration
|
||||
*
|
||||
* This configuration si defined by `chill_main['crud']`.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $crudConfig;
|
||||
protected array $crudConfig;
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
*/
|
||||
public function setCrudConfig(array $config)
|
||||
public function setCrudConfig(array $config): void
|
||||
{
|
||||
$this->crudConfig = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $parameter
|
||||
* @return Response
|
||||
*/
|
||||
public function CRUD($parameter)
|
||||
public function CRUD(?string $parameter): Response
|
||||
{
|
||||
return new Response($parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param $id
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
|
||||
*/
|
||||
public function delete(Request $request, $id)
|
||||
public function delete(Request $request, $id): Response
|
||||
{
|
||||
return $this->deleteAction('delete', $request, $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $action
|
||||
* @param Request $request
|
||||
* @param $id
|
||||
* @param null $formClass
|
||||
* @return null|\Symfony\Component\HttpFoundation\RedirectResponse|Response|void
|
||||
*/
|
||||
protected function deleteAction(string $action, Request $request, $id, $formClass = null)
|
||||
protected function deleteAction(string $action, Request $request, $id, $formClass = null): Response
|
||||
{
|
||||
$this->onPreDelete($action, $request, $id);
|
||||
$this->onPreDelete($action, $request);
|
||||
|
||||
$entity = $this->getEntity($action, $id, $request);
|
||||
|
||||
@ -101,8 +63,13 @@ class CRUDController extends AbstractController
|
||||
}
|
||||
|
||||
if (NULL === $entity) {
|
||||
throw $this->createNotFoundException(sprintf("The %s with id %s "
|
||||
. "is not found"), $this->getCrudName(), $id);
|
||||
throw $this->createNotFoundException(
|
||||
sprintf(
|
||||
'The %s with id %s is not found',
|
||||
$this->getCrudName(),
|
||||
$id
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$response = $this->checkACL($action, $entity);
|
||||
@ -141,7 +108,9 @@ class CRUDController extends AbstractController
|
||||
|
||||
return $this->redirectToRoute('chill_crud_'.$this->getCrudName().'_view', ['id' => $entity->getId()]);
|
||||
|
||||
} elseif ($form->isSubmitted()) {
|
||||
}
|
||||
|
||||
if ($form->isSubmitted()) {
|
||||
$this->addFlash('error', $this->generateFormErrorMessage($action, $form));
|
||||
}
|
||||
|
||||
@ -233,7 +202,6 @@ class CRUDController extends AbstractController
|
||||
*
|
||||
* @param string $action
|
||||
* @param Request $request
|
||||
* @return type
|
||||
*/
|
||||
protected function indexEntityAction($action, Request $request)
|
||||
{
|
||||
@ -244,9 +212,7 @@ class CRUDController extends AbstractController
|
||||
return $response;
|
||||
}
|
||||
|
||||
if (!isset($entity)) {
|
||||
$entity = '';
|
||||
}
|
||||
$entity = '';
|
||||
|
||||
$response = $this->onPostCheckACL($action, $request, $entity);
|
||||
if ($response instanceof Response) {
|
||||
@ -342,11 +308,12 @@ class CRUDController extends AbstractController
|
||||
*/
|
||||
protected function buildQueryEntities(string $action, Request $request)
|
||||
{
|
||||
$query = $this->getDoctrine()->getManager()
|
||||
$query = $this
|
||||
->getDoctrine()
|
||||
->getManager()
|
||||
->createQueryBuilder()
|
||||
->select('e')
|
||||
->from($this->getEntityClass(), 'e')
|
||||
;
|
||||
->from($this->getEntityClass(), 'e');
|
||||
|
||||
$this->customizeQuery($action, $request, $query);
|
||||
|
||||
@ -371,7 +338,7 @@ class CRUDController extends AbstractController
|
||||
*/
|
||||
protected function queryEntities(string $action, Request $request, PaginatorInterface $paginator, ?FilterOrderHelper $filterOrder = null)
|
||||
{
|
||||
$query = $this->buildQueryEntities($action, $request, $filterOrder)
|
||||
$query = $this->buildQueryEntities($action, $request)
|
||||
->setFirstResult($paginator->getCurrentPage()->getFirstItemNumber())
|
||||
->setMaxResults($paginator->getItemsPerPage());
|
||||
|
||||
@ -420,7 +387,7 @@ class CRUDController extends AbstractController
|
||||
*/
|
||||
protected function countEntities(string $action, Request $request, ?FilterOrderHelper $filterOrder = null): int
|
||||
{
|
||||
return $this->buildQueryEntities($action, $request, $filterOrder)
|
||||
return $this->buildQueryEntities($action, $request)
|
||||
->select('COUNT(e)')
|
||||
->getQuery()
|
||||
->getSingleScalarResult()
|
||||
@ -505,8 +472,13 @@ class CRUDController extends AbstractController
|
||||
}
|
||||
|
||||
if (NULL === $entity) {
|
||||
throw $this->createNotFoundException(sprintf("The %s with id %s "
|
||||
. "is not found", $this->getCrudName(), $id));
|
||||
throw $this->createNotFoundException(
|
||||
sprintf(
|
||||
'The %s with id %s is not found',
|
||||
$this->getCrudName(),
|
||||
$id
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$response = $this->checkACL($action, $entity);
|
||||
@ -598,8 +570,13 @@ class CRUDController extends AbstractController
|
||||
$entity = $this->getEntity($action, $id, $request);
|
||||
|
||||
if (NULL === $entity) {
|
||||
throw $this->createNotFoundException(sprintf("The %s with id %s "
|
||||
. "is not found", $this->getCrudName(), $id));
|
||||
throw $this->createNotFoundException(
|
||||
sprintf(
|
||||
'The %s with id %s is not found',
|
||||
$this->getCrudName(),
|
||||
$id
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$response = $this->checkACL($action, $entity);
|
||||
|
@ -1,22 +1,6 @@
|
||||
<?php
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2019, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\CRUD\Routing;
|
||||
|
||||
@ -27,22 +11,13 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
use Chill\MainBundle\CRUD\Controller\ApiController;
|
||||
use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||
|
||||
/**
|
||||
* Class CRUDRoutesLoader
|
||||
* Load the route for CRUD
|
||||
*
|
||||
* @package Chill\MainBundle\CRUD\Routing
|
||||
*/
|
||||
class CRUDRoutesLoader extends Loader
|
||||
{
|
||||
protected array $crudConfig = [];
|
||||
|
||||
protected array $apiCrudConfig = [];
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $isLoaded = false;
|
||||
|
||||
private bool $isLoaded = false;
|
||||
|
||||
private const ALL_SINGLE_METHODS = [
|
||||
Request::METHOD_GET,
|
||||
@ -52,19 +27,15 @@ class CRUDRoutesLoader extends Loader
|
||||
];
|
||||
|
||||
private const ALL_INDEX_METHODS = [ Request::METHOD_GET, Request::METHOD_HEAD ];
|
||||
|
||||
/**
|
||||
* CRUDRoutesLoader constructor.
|
||||
*
|
||||
* @param $crudConfig the config from cruds
|
||||
* @param $apicrudConfig the config from api_crud
|
||||
*/
|
||||
public function __construct(array $crudConfig, array $apiConfig)
|
||||
|
||||
public function __construct(array $crudConfig, array $apiCrudConfig)
|
||||
{
|
||||
$this->crudConfig = $crudConfig;
|
||||
$this->apiConfig = $apiConfig;
|
||||
$this->apiCrudConfig = $apiCrudConfig;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param mixed $resource
|
||||
* @param null $type
|
||||
@ -74,7 +45,7 @@ class CRUDRoutesLoader extends Loader
|
||||
{
|
||||
return 'CRUD' === $type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load routes for CRUD and CRUD Api
|
||||
*/
|
||||
@ -85,17 +56,17 @@ class CRUDRoutesLoader extends Loader
|
||||
}
|
||||
|
||||
$collection = new RouteCollection();
|
||||
|
||||
|
||||
foreach ($this->crudConfig as $crudConfig) {
|
||||
$collection->addCollection($this->loadCrudConfig($crudConfig));
|
||||
}
|
||||
foreach ($this->apiConfig as $crudConfig) {
|
||||
foreach ($this->apiCrudConfig as $crudConfig) {
|
||||
$collection->addCollection($this->loadApi($crudConfig));
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load routes for CRUD (without api)
|
||||
*
|
||||
@ -112,7 +83,7 @@ class CRUDRoutesLoader extends Loader
|
||||
$defaults = [
|
||||
'_controller' => $controller.':'.($action['controller_action'] ?? $name)
|
||||
];
|
||||
|
||||
|
||||
if ($name === 'index') {
|
||||
$path = "{_locale}".$crudConfig['base_path'];
|
||||
$route = new Route($path, $defaults);
|
||||
@ -126,10 +97,10 @@ class CRUDRoutesLoader extends Loader
|
||||
];
|
||||
$route = new Route($path, $defaults, $requirements);
|
||||
}
|
||||
|
||||
|
||||
$collection->add('chill_crud_'.$crudConfig['name'].'_'.$name, $route);
|
||||
}
|
||||
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
@ -186,14 +157,14 @@ class CRUDRoutesLoader extends Loader
|
||||
if (count($methods) === 0) {
|
||||
throw new \RuntimeException("The api configuration named \"{$crudConfig['name']}\", action \"{$name}\", ".
|
||||
"does not have any allowed methods. You should remove this action from the config ".
|
||||
"or allow, at least, one method");
|
||||
"or allow, at least, one method");
|
||||
}
|
||||
|
||||
if ('_entity' === $name && \in_array(Request::METHOD_POST, $methods)) {
|
||||
unset($methods[\array_search(Request::METHOD_POST, $methods)]);
|
||||
$entityPostRoute = $this->createEntityPostRoute($name, $crudConfig, $action,
|
||||
$entityPostRoute = $this->createEntityPostRoute($name, $crudConfig, $action,
|
||||
$controller);
|
||||
$collection->add("chill_api_single_{$crudConfig['name']}_{$name}_create",
|
||||
$collection->add("chill_api_single_{$crudConfig['name']}_{$name}_create",
|
||||
$entityPostRoute);
|
||||
}
|
||||
|
||||
@ -205,7 +176,7 @@ class CRUDRoutesLoader extends Loader
|
||||
|
||||
$route = new Route($path, $defaults, $requirements);
|
||||
$route->setMethods($methods);
|
||||
|
||||
|
||||
$collection->add('chill_api_single_'.$crudConfig['name'].'_'.$name, $route);
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace Chill\MainBundle;
|
||||
|
||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||
use Chill\MainBundle\Search\SearchApiInterface;
|
||||
use Chill\MainBundle\Search\SearchInterface;
|
||||
use Chill\MainBundle\Security\Authorization\ChillVoterInterface;
|
||||
use Chill\MainBundle\Security\ProvideRoleInterface;
|
||||
@ -41,6 +42,8 @@ class ChillMainBundle extends Bundle
|
||||
->addTag('chill_main.scope_resolver');
|
||||
$container->registerForAutoconfiguration(ChillEntityRenderInterface::class)
|
||||
->addTag('chill.render_entity');
|
||||
$container->registerForAutoconfiguration(SearchApiInterface::class)
|
||||
->addTag('chill.search_api_provider');
|
||||
|
||||
$container->addCompilerPass(new SearchableServicesCompilerPass());
|
||||
$container->addCompilerPass(new ConfigConsistencyCompilerPass());
|
||||
|
@ -1,7 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Command;
|
||||
|
||||
use Chill\MainBundle\Repository\UserRepository;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
@ -23,101 +26,51 @@ use League\Csv\Writer;
|
||||
|
||||
class ChillImportUsersCommand extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
protected $em;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var ValidatorInterface
|
||||
*/
|
||||
protected $validator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var UserPasswordEncoderInterface
|
||||
*/
|
||||
protected $passwordEncoder;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \Chill\MainBundle\Repository\UserRepository
|
||||
*/
|
||||
protected $userRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $doChanges = true;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var OutputInterface
|
||||
*/
|
||||
protected $tempOutput;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var InputInterface
|
||||
*/
|
||||
protected $tempInput;
|
||||
|
||||
protected EntityManagerInterface $em;
|
||||
|
||||
protected ValidatorInterface $validator;
|
||||
|
||||
protected LoggerInterface $logger;
|
||||
|
||||
protected UserPasswordEncoderInterface $passwordEncoder;
|
||||
|
||||
protected UserRepository $userRepository;
|
||||
|
||||
protected bool $doChanges = true;
|
||||
|
||||
protected OutputInterface $tempOutput;
|
||||
|
||||
protected InputInterface $tempInput;
|
||||
|
||||
/**
|
||||
* Centers and aliases.
|
||||
*
|
||||
*
|
||||
* key are aliases, values are an array of centers
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $centers = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $permissionGroups = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $groupCenters = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* @var Writer
|
||||
*/
|
||||
protected $output = null;
|
||||
|
||||
protected array $centers;
|
||||
|
||||
protected array $permissionGroups;
|
||||
|
||||
protected array $groupCenters;
|
||||
|
||||
protected Writer $output;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
LoggerInterface $logger,
|
||||
UserPasswordEncoderInterface $passwordEncoder,
|
||||
ValidatorInterface $validator
|
||||
ValidatorInterface $validator,
|
||||
UserRepository $userRepository
|
||||
) {
|
||||
$this->em = $em;
|
||||
$this->passwordEncoder = $passwordEncoder;
|
||||
$this->validator = $validator;
|
||||
$this->logger = $logger;
|
||||
|
||||
|
||||
$this->userRepository = $em->getRepository(User::class);
|
||||
|
||||
$this->userRepository = $userRepository;
|
||||
|
||||
parent::__construct('chill:main:import-users');
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
@ -126,25 +79,24 @@ class ChillImportUsersCommand extends Command
|
||||
->addArgument('csvfile', InputArgument::REQUIRED, 'Path to the csv file. Columns are: `username`, `email`, `center` (can contain alias), `permission group`')
|
||||
->addOption('grouping-centers', null, InputOption::VALUE_OPTIONAL, 'Path to a csv file to aggregate multiple centers into a single alias')
|
||||
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Do not commit the changes')
|
||||
->addOption('csv-dump', null, InputOption::VALUE_REQUIRED, 'A path to dump a summary of the created file')
|
||||
;
|
||||
->addOption('csv-dump', null, InputOption::VALUE_REQUIRED, 'A path to dump a summary of the created file');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->tempOutput = $output;
|
||||
$this->tempInput = $input;
|
||||
|
||||
|
||||
if ($input->getOption('dry-run')) {
|
||||
$this->doChanges = false;
|
||||
}
|
||||
|
||||
|
||||
$this->prepareWriter();
|
||||
|
||||
|
||||
if ($input->hasOption('grouping-centers')) {
|
||||
$this->prepareGroupingCenters();
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
$this->loadUsers();
|
||||
}
|
||||
@ -152,19 +104,19 @@ class ChillImportUsersCommand extends Command
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function prepareWriter()
|
||||
{
|
||||
$this->output = $output = Writer::createFromPath($this->tempInput
|
||||
->getOption('csv-dump'), 'a+');
|
||||
|
||||
|
||||
$output->insertOne([
|
||||
'email',
|
||||
'username',
|
||||
'id'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
protected function appendUserToFile(User $user)
|
||||
{
|
||||
$this->output->insertOne( [
|
||||
@ -173,35 +125,35 @@ class ChillImportUsersCommand extends Command
|
||||
$user->getId()
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
protected function loadUsers()
|
||||
{
|
||||
$reader = Reader::createFromPath($this->tempInput->getArgument('csvfile'));
|
||||
$reader->setHeaderOffset(0);
|
||||
|
||||
|
||||
foreach ($reader->getRecords() as $line => $r) {
|
||||
$this->logger->debug("starting handling new line", [
|
||||
'line' => $line
|
||||
]);
|
||||
|
||||
|
||||
if ($this->doesUserExists($r)) {
|
||||
$this->tempOutput->writeln(sprintf("User with username '%s' already "
|
||||
. "exists, skipping", $r["username"]));
|
||||
|
||||
|
||||
$this->logger->info("One user already exists, skipping creation", [
|
||||
'username_in_file' => $r['username'],
|
||||
'email_in_file' => $r['email'],
|
||||
'line' => $line
|
||||
]);
|
||||
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
$user = $this->createUser($line, $r);
|
||||
$this->appendUserToFile($user);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function doesUserExists($data)
|
||||
{
|
||||
if ($this->userRepository->countByUsernameOrEmail($data['username']) > 0) {
|
||||
@ -211,10 +163,10 @@ class ChillImportUsersCommand extends Command
|
||||
if ($this->userRepository->countByUsernameOrEmail($data['email']) > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected function createUser($offset, $data)
|
||||
{
|
||||
$user = new User();
|
||||
@ -222,41 +174,41 @@ class ChillImportUsersCommand extends Command
|
||||
->setEmail(\trim($data['email']))
|
||||
->setUsername(\trim($data['username']))
|
||||
->setEnabled(true)
|
||||
->setPassword($this->passwordEncoder->encodePassword($user,
|
||||
->setPassword($this->passwordEncoder->encodePassword($user,
|
||||
\bin2hex(\random_bytes(32))))
|
||||
;
|
||||
|
||||
|
||||
$errors = $this->validator->validate($user);
|
||||
|
||||
|
||||
if ($errors->count() > 0) {
|
||||
$errorMessages = $this->concatenateViolations($errors);
|
||||
|
||||
|
||||
$this->tempOutput->writeln(sprintf("%d errors found with user with username \"%s\" at line %d", $errors->count(), $data['username'], $offset));
|
||||
$this->tempOutput->writeln($errorMessages);
|
||||
|
||||
throw new \RuntimeException("Found errors while creating an user. "
|
||||
. "Watch messages in command output");
|
||||
}
|
||||
|
||||
|
||||
$pgs = $this->getPermissionGroup($data['permission group']);
|
||||
$centers = $this->getCenters($data['center']);
|
||||
|
||||
|
||||
foreach($pgs as $pg) {
|
||||
foreach ($centers as $center) {
|
||||
$groupcenter = $this->createOrGetGroupCenter($center, $pg);
|
||||
|
||||
|
||||
if (FALSE === $user->getGroupCenters()->contains($groupcenter)) {
|
||||
$user->addGroupCenter($groupcenter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($this->doChanges) {
|
||||
$this->em->persist($user);
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
|
||||
$this->logger->notice("Create user", [
|
||||
'username' => $user->getUsername(),
|
||||
'id' => $user->getId(),
|
||||
@ -265,65 +217,58 @@ class ChillImportUsersCommand extends Command
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
|
||||
protected function getPermissionGroup($alias)
|
||||
{
|
||||
if (\array_key_exists($alias, $this->permissionGroups)) {
|
||||
return $this->permissionGroups[$alias];
|
||||
}
|
||||
|
||||
|
||||
$permissionGroupsByName = [];
|
||||
|
||||
|
||||
foreach($this->em->getRepository(PermissionsGroup::class)
|
||||
->findAll() as $permissionGroup) {
|
||||
$permissionGroupsByName[$permissionGroup->getName()] = $permissionGroup;
|
||||
}
|
||||
|
||||
|
||||
if (count($permissionGroupsByName) === 0) {
|
||||
throw new \RuntimeException("no permission groups found. Create them "
|
||||
. "before importing users");
|
||||
}
|
||||
|
||||
$question = new ChoiceQuestion("To which permission groups associate with \"$alias\" ?",
|
||||
|
||||
$question = new ChoiceQuestion("To which permission groups associate with \"$alias\" ?",
|
||||
\array_keys($permissionGroupsByName));
|
||||
$question
|
||||
->setMultiselect(true)
|
||||
->setAutocompleterValues(\array_keys($permissionGroupsByName))
|
||||
->setNormalizer(function($value) {
|
||||
if (NULL === $value) { return ''; }
|
||||
|
||||
|
||||
return \trim($value);
|
||||
})
|
||||
;
|
||||
$helper = $this->getHelper('question');
|
||||
|
||||
|
||||
$keys = $helper->ask($this->tempInput, $this->tempOutput, $question);
|
||||
|
||||
|
||||
$this->tempOutput->writeln("You have chosen ".\implode(", ", $keys));
|
||||
|
||||
if ($helper->ask($this->tempInput, $this->tempOutput,
|
||||
|
||||
if ($helper->ask($this->tempInput, $this->tempOutput,
|
||||
new ConfirmationQuestion("Are you sure ?", true))) {
|
||||
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$this->permissionGroups[$alias][] = $permissionGroupsByName[$key];
|
||||
}
|
||||
|
||||
|
||||
return $this->permissionGroups[$alias];
|
||||
} else {
|
||||
$this->logger->error("Error while responding to a a question");
|
||||
|
||||
$this->tempOutput("Ok, I accept, but I do not know what to do. Please try again.");
|
||||
|
||||
throw new \RuntimeException("Error while responding to a question");
|
||||
}
|
||||
|
||||
$this->logger->error('Error while responding to a a question');
|
||||
$this->tempOutput->writeln('Ok, I accept, but I do not know what to do. Please try again.');
|
||||
|
||||
throw new \RuntimeException('Error while responding to a question');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Center $center
|
||||
* @param \Chill\MainBundle\Command\PermissionGroup $pg
|
||||
* @return GroupCenter
|
||||
*/
|
||||
|
||||
protected function createOrGetGroupCenter(Center $center, PermissionsGroup $pg): GroupCenter
|
||||
{
|
||||
if (\array_key_exists($center->getId(), $this->groupCenters)) {
|
||||
@ -331,36 +276,36 @@ class ChillImportUsersCommand extends Command
|
||||
return $this->groupCenters[$center->getId()][$pg->getId()];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$repository = $this->em->getRepository(GroupCenter::class);
|
||||
|
||||
|
||||
$groupCenter = $repository->findOneBy(array(
|
||||
'center' => $center,
|
||||
'permissionsGroup' => $pg
|
||||
));
|
||||
|
||||
|
||||
if ($groupCenter === NULL) {
|
||||
$groupCenter = new GroupCenter();
|
||||
$groupCenter
|
||||
->setCenter($center)
|
||||
->setPermissionsGroup($pg)
|
||||
;
|
||||
|
||||
|
||||
$this->em->persist($groupCenter);
|
||||
}
|
||||
|
||||
|
||||
$this->groupCenters[$center->getId()][$pg->getId()] = $groupCenter;
|
||||
|
||||
|
||||
return $groupCenter;
|
||||
}
|
||||
|
||||
|
||||
protected function prepareGroupingCenters()
|
||||
{
|
||||
$reader = Reader::createFromPath($this->tempInput->getOption('grouping-centers'));
|
||||
$reader->setHeaderOffset(0);
|
||||
|
||||
|
||||
foreach ($reader->getRecords() as $r) {
|
||||
$this->centers[$r['alias']] =
|
||||
$this->centers[$r['alias']] =
|
||||
\array_merge(
|
||||
$this->centers[$r['alias']] ?? [],
|
||||
$this->getCenters($r['center']
|
||||
@ -368,18 +313,18 @@ class ChillImportUsersCommand extends Command
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* return a list of centers matching the name of alias.
|
||||
*
|
||||
*
|
||||
* If the name match one center, this center is returned in an array.
|
||||
*
|
||||
* If the name match an alias, the centers corresponding to the alias are
|
||||
*
|
||||
* If the name match an alias, the centers corresponding to the alias are
|
||||
* returned in an array.
|
||||
*
|
||||
*
|
||||
* If the center is not found or alias is not created, a new center is created
|
||||
* and suggested to user
|
||||
*
|
||||
*
|
||||
* @param string $name the name of the center or the alias regrouping center
|
||||
* @return Center[]
|
||||
*/
|
||||
@ -387,62 +332,62 @@ class ChillImportUsersCommand extends Command
|
||||
{
|
||||
// sanitize
|
||||
$name = \trim($name);
|
||||
|
||||
|
||||
if (\array_key_exists($name, $this->centers)) {
|
||||
return $this->centers[$name];
|
||||
}
|
||||
|
||||
|
||||
// search for a center with given name
|
||||
$center = $this->em->getRepository(Center::class)
|
||||
->findOneByName($name);
|
||||
|
||||
|
||||
if ($center instanceof Center) {
|
||||
$this->centers[$name] = [$center];
|
||||
|
||||
|
||||
return $this->centers[$name];
|
||||
}
|
||||
|
||||
|
||||
// suggest and create
|
||||
$center = (new Center())
|
||||
->setName($name);
|
||||
|
||||
|
||||
$this->tempOutput->writeln("Center with name \"$name\" not found.");
|
||||
$qFormatter = $this->getHelper('question');
|
||||
$question = new ConfirmationQuestion("Create a center with name \"$name\" ?", true);
|
||||
|
||||
|
||||
if ($qFormatter->ask($this->tempInput, $this->tempOutput, $question)) {
|
||||
$this->centers[$name] = [ $center ];
|
||||
|
||||
|
||||
$errors = $this->validator->validate($center);
|
||||
|
||||
|
||||
if ($errors->count() > 0) {
|
||||
$errorMessages = $this->concatenateViolations($errors);
|
||||
|
||||
|
||||
$this->tempOutput->writeln(sprintf("%d errors found with center with name \"%s\"", $errors->count(), $name));
|
||||
$this->tempOutput->writeln($errorMessages);
|
||||
|
||||
|
||||
throw new \RuntimeException("Found errors while creating one center. "
|
||||
. "Watch messages in command output");
|
||||
}
|
||||
|
||||
|
||||
$this->em->persist($center);
|
||||
|
||||
|
||||
return $this->centers[$name];
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected function concatenateViolations(ConstraintViolationListInterface $list)
|
||||
{
|
||||
$str = [];
|
||||
|
||||
|
||||
foreach ($list as $e) {
|
||||
/* @var $e \Symfony\Component\Validator\ConstraintViolationInterface */
|
||||
$str[] = $e->getMessage();
|
||||
}
|
||||
|
||||
|
||||
return \implode(";", $str);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -10,18 +10,18 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||
/**
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop
|
||||
*
|
||||
*
|
||||
*/
|
||||
class LoadCountriesCommand extends Command
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @var EntityManager
|
||||
*/
|
||||
private $entityManager;
|
||||
|
||||
|
||||
private $availableLanguages;
|
||||
|
||||
|
||||
/**
|
||||
* LoadCountriesCommand constructor.
|
||||
*
|
||||
@ -34,7 +34,7 @@ class LoadCountriesCommand extends Command
|
||||
$this->availableLanguages=$availableLanguages;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-PHPdoc)
|
||||
* @see \Symfony\Component\Console\Command\Command::configure()
|
||||
@ -45,7 +45,7 @@ class LoadCountriesCommand extends Command
|
||||
->setDescription('Load or update countries in db. This command does not delete existing countries, '.
|
||||
'but will update names according to available languages');
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-PHPdoc)
|
||||
* @see \Symfony\Component\Console\Command\Command::execute()
|
||||
@ -54,43 +54,44 @@ class LoadCountriesCommand extends Command
|
||||
{
|
||||
$countries = static::prepareCountryList($this->availableLanguages);
|
||||
$em = $this->entityManager;
|
||||
|
||||
|
||||
foreach($countries as $country) {
|
||||
$countryStored = $em->getRepository('ChillMainBundle:Country')
|
||||
->findOneBy(array('countryCode' => $country->getCountryCode()));
|
||||
|
||||
|
||||
if (NULL === $countryStored) {
|
||||
$em->persist($country);
|
||||
} else {
|
||||
$countryStored->setName($country->getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
public static function prepareCountryList($languages)
|
||||
{
|
||||
$regionBundle = Intl::getRegionBundle();
|
||||
|
||||
$countries = [];
|
||||
|
||||
foreach ($languages as $language) {
|
||||
$countries[$language] = $regionBundle->getCountryNames($language);
|
||||
}
|
||||
|
||||
|
||||
$countryEntities = array();
|
||||
|
||||
|
||||
foreach ($countries[$languages[0]] as $countryCode => $name) {
|
||||
$names = array();
|
||||
|
||||
|
||||
foreach ($languages as $language) {
|
||||
$names[$language] = $countries[$language][$countryCode];
|
||||
}
|
||||
|
||||
|
||||
$country = new \Chill\MainBundle\Entity\Country();
|
||||
$country->setName($names)->setCountryCode($countryCode);
|
||||
$countryEntities[] = $country;
|
||||
}
|
||||
|
||||
|
||||
return $countryEntities;
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,13 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Champs-Libres <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Command;
|
||||
|
||||
use Chill\MainBundle\Doctrine\Model\Point;
|
||||
use Chill\MainBundle\Entity\Country;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
@ -31,38 +17,19 @@ use Symfony\Component\Filesystem\Filesystem;
|
||||
use Chill\MainBundle\Entity\PostalCode;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* Class LoadPostalCodesCommand
|
||||
*
|
||||
* @package Chill\MainBundle\Command
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class LoadPostalCodesCommand extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* @var EntityManager
|
||||
*/
|
||||
private $entityManager;
|
||||
|
||||
/**
|
||||
* @var ValidatorInterface
|
||||
*/
|
||||
private $validator;
|
||||
|
||||
/**
|
||||
* LoadPostalCodesCommand constructor.
|
||||
*
|
||||
* @param EntityManager $entityManager
|
||||
* @param ValidatorInterface $validator
|
||||
*/
|
||||
public function __construct(EntityManager $entityManager, ValidatorInterface $validator)
|
||||
private EntityManagerInterface $entityManager;
|
||||
|
||||
private ValidatorInterface $validator;
|
||||
|
||||
public function __construct(EntityManagerInterface $entityManager, ValidatorInterface $validator)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
$this->validator = $validator;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('chill:main:postal-code:populate')
|
||||
@ -78,10 +45,10 @@ class LoadPostalCodesCommand extends Command
|
||||
->addArgument('csv_file', InputArgument::REQUIRED, "the path to "
|
||||
. "the csv file. See the help for specifications.")
|
||||
->addOption(
|
||||
'delimiter',
|
||||
'd',
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
"The delimiter character of the csv file",
|
||||
'delimiter',
|
||||
'd',
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
"The delimiter character of the csv file",
|
||||
",")
|
||||
->addOption(
|
||||
'enclosure',
|
||||
@ -99,31 +66,26 @@ class LoadPostalCodesCommand extends Command
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
try {
|
||||
$csv = $this->getCSVResource($input);
|
||||
} catch (\RuntimeException $e) {
|
||||
$output->writeln('<error>Error during opening the csv file : '.
|
||||
$e->getMessage().'</error>');
|
||||
}
|
||||
|
||||
$csv = $this->getCSVResource($input);
|
||||
|
||||
if ($output->getVerbosity() === OutputInterface::VERBOSITY_VERY_VERBOSE) {
|
||||
$output->writeln('The content of the file is ...');
|
||||
$output->write(file_get_contents($input->getArgument('csv_file')));
|
||||
}
|
||||
|
||||
|
||||
$num = 0;
|
||||
$line = 0;
|
||||
|
||||
|
||||
while (($row = fgetcsv(
|
||||
$csv,
|
||||
0,
|
||||
$input->getOption('delimiter'),
|
||||
$input->getOption('enclosure'),
|
||||
$csv,
|
||||
0,
|
||||
$input->getOption('delimiter'),
|
||||
$input->getOption('enclosure'),
|
||||
$input->getOption('escape'))) !== false) {
|
||||
|
||||
|
||||
try{
|
||||
$this->addPostalCode($row, $output);
|
||||
$num++;
|
||||
@ -136,31 +98,31 @@ class LoadPostalCodesCommand extends Command
|
||||
}
|
||||
$line ++;
|
||||
}
|
||||
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
|
||||
$output->writeln('<info>'.$num.' were added !</info>');
|
||||
}
|
||||
|
||||
|
||||
private function getCSVResource(InputInterface $input)
|
||||
{
|
||||
$fs = new Filesystem();
|
||||
$filename = $input->getArgument('csv_file');
|
||||
|
||||
|
||||
if (!$fs->exists($filename)) {
|
||||
throw new \RuntimeException("The file does not exists or you do not "
|
||||
. "have the right to read it.");
|
||||
}
|
||||
|
||||
|
||||
$resource = fopen($filename, 'r');
|
||||
|
||||
|
||||
if ($resource == FALSE) {
|
||||
throw new \RuntimeException("The file '$filename' could not be opened.");
|
||||
}
|
||||
|
||||
|
||||
return $resource;
|
||||
}
|
||||
|
||||
|
||||
private function addPostalCode($row, OutputInterface $output)
|
||||
{
|
||||
if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
|
||||
@ -170,28 +132,28 @@ class LoadPostalCodesCommand extends Command
|
||||
$country = $em
|
||||
->getRepository(Country::class)
|
||||
->findOneBy(array('countryCode' => $row[2]));
|
||||
|
||||
|
||||
if ($country === NULL) {
|
||||
throw new CountryCodeNotFoundException(sprintf("The country with code %s is not found. Aborting to insert postal code with %s - %s",
|
||||
$row[2], $row[0], $row[1]));
|
||||
}
|
||||
|
||||
|
||||
// try to find an existing postal code
|
||||
$existingPC = $em
|
||||
->getRepository(PostalCode::class)
|
||||
->findBy(array('code' => $row[0], 'name' => $row[1]));
|
||||
|
||||
|
||||
if (count($existingPC) > 0) {
|
||||
throw new ExistingPostalCodeException(sprintf("A postal code with code : %s and name : %s already exists, skipping",
|
||||
throw new ExistingPostalCodeException(sprintf("A postal code with code : %s and name : %s already exists, skipping",
|
||||
$row[0], $row[1]));
|
||||
}
|
||||
|
||||
|
||||
$postalCode = (new PostalCode())
|
||||
->setCode($row[0])
|
||||
->setName($row[1])
|
||||
->setCountry($country)
|
||||
;
|
||||
|
||||
|
||||
if (NULL != $row[3]){
|
||||
$postalCode->setRefPostalCodeId($row[3]);
|
||||
}
|
||||
@ -205,7 +167,7 @@ class LoadPostalCodesCommand extends Command
|
||||
}
|
||||
|
||||
$errors = $this->validator->validate($postalCode);
|
||||
|
||||
|
||||
if ($errors->count() == 0) {
|
||||
$em->persist($postalCode);
|
||||
} else {
|
||||
@ -213,12 +175,12 @@ class LoadPostalCodesCommand extends Command
|
||||
foreach ($errors as $error) {
|
||||
$msg .= " ".$error->getMessage();
|
||||
}
|
||||
|
||||
|
||||
throw new PostalCodeNotValidException($msg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
|
||||
$output->writeln(sprintf('Creating postal code with code: %s, name: %s, countryCode: %s',
|
||||
$postalCode->getCode(), $postalCode->getName(), $postalCode->getCountry()->getCountryCode()));
|
||||
@ -229,15 +191,15 @@ class LoadPostalCodesCommand extends Command
|
||||
|
||||
class ExistingPostalCodeException extends \Exception
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
class CountryCodeNotFoundException extends \Exception
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
class PostalCodeNotValidException extends \Exception
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,20 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Controller;
|
||||
|
||||
use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||
use Chill\MainBundle\Entity\Country;
|
||||
use Chill\MainBundle\Pagination\PaginatorFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
class AdminCountryCRUDController extends CRUDController
|
||||
{
|
||||
|
||||
function __construct(PaginatorFactory $paginator)
|
||||
{
|
||||
$this->paginatorFactory = $paginator;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Controller;
|
||||
|
||||
use Chill\MainBundle\CRUD\Controller\AbstractCRUDController;
|
||||
@ -7,6 +9,7 @@ use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||
use Chill\MainBundle\Pagination\PaginatorInterface;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Form\Form;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@ -16,40 +19,23 @@ use Chill\MainBundle\Form\UserType;
|
||||
use Chill\MainBundle\Entity\GroupCenter;
|
||||
use Chill\MainBundle\Form\Type\ComposedGroupCenterType;
|
||||
use Chill\MainBundle\Form\UserPasswordType;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter;
|
||||
|
||||
|
||||
/**
|
||||
* Class UserController
|
||||
*
|
||||
* @package Chill\MainBundle\Controller
|
||||
*/
|
||||
class UserController extends CRUDController
|
||||
{
|
||||
|
||||
const FORM_GROUP_CENTER_COMPOSED = 'composed_groupcenter';
|
||||
|
||||
/**
|
||||
* @var \Psr\Log\LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
private LoggerInterface $logger;
|
||||
|
||||
/**
|
||||
* @var ValidatorInterface
|
||||
*/
|
||||
private $validator;
|
||||
private ValidatorInterface $validator;
|
||||
|
||||
private UserPasswordEncoderInterface $passwordEncoder;
|
||||
|
||||
/**
|
||||
* UserController constructor.
|
||||
*
|
||||
* @param LoggerInterface $logger
|
||||
* @param ValidatorInterface $validator
|
||||
*/
|
||||
public function __construct(
|
||||
LoggerInterface $chillLogger,
|
||||
ValidatorInterface $validator,
|
||||
@ -121,7 +107,7 @@ class UserController extends CRUDController
|
||||
*/
|
||||
public function editPasswordAction(User $user, Request $request)
|
||||
{
|
||||
$editForm = $this->createEditPasswordForm($user, $request);
|
||||
$editForm = $this->createEditPasswordForm($user);
|
||||
$editForm->handleRequest($request);
|
||||
|
||||
if ($editForm->isSubmitted() && $editForm->isValid()) {
|
||||
@ -150,20 +136,17 @@ class UserController extends CRUDController
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param User $user
|
||||
* @return \Symfony\Component\Form\Form
|
||||
*/
|
||||
private function createEditPasswordForm(User $user)
|
||||
private function createEditPasswordForm(User $user): FormInterface
|
||||
{
|
||||
return $this->createForm(UserPasswordType::class, null, array(
|
||||
'user' => $user
|
||||
))
|
||||
return $this->createForm(
|
||||
UserPasswordType::class,
|
||||
null,
|
||||
[
|
||||
'user' => $user
|
||||
]
|
||||
)
|
||||
->add('submit', SubmitType::class, array('label' => 'Change password'))
|
||||
->remove('actual_password')
|
||||
;
|
||||
->remove('actual_password');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -208,7 +191,7 @@ class UserController extends CRUDController
|
||||
* @Route("/{_locale}/admin/main/user/{uid}/add_link_groupcenter",
|
||||
* name="admin_user_add_groupcenter")
|
||||
*/
|
||||
public function addLinkGroupCenterAction(Request $request, $uid): RedirectResponse
|
||||
public function addLinkGroupCenterAction(Request $request, $uid): Response
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
@ -238,23 +221,22 @@ class UserController extends CRUDController
|
||||
return $this->redirect($this->generateUrl('chill_crud_admin_user_edit',
|
||||
\array_merge(['id' => $uid], $returnPathParams)));
|
||||
|
||||
} else {
|
||||
foreach($this->validator->validate($user) as $error)
|
||||
}
|
||||
|
||||
foreach($this->validator->validate($user) as $error) {
|
||||
$this->addFlash('error', $error->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('@ChillMain/User/edit.html.twig', array(
|
||||
return $this->render('@ChillMain/User/edit.html.twig', [
|
||||
'entity' => $user,
|
||||
'edit_form' => $this->createEditForm($user)->createView(),
|
||||
'add_groupcenter_form' => $this->createAddLinkGroupCenterForm($user)->createView(),
|
||||
'add_groupcenter_form' => $this->createAddLinkGroupCenterForm($user, $request)->createView(),
|
||||
'delete_groupcenter_form' => array_map(
|
||||
function(\Symfony\Component\Form\Form $form) {
|
||||
return $form->createView();
|
||||
|
||||
},
|
||||
iterator_to_array($this->getDeleteLinkGroupCenterByUser($user), true))
|
||||
));
|
||||
static fn(Form $form) => $form->createView(),
|
||||
iterator_to_array($this->getDeleteLinkGroupCenterByUser($user, $request), true)
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
private function getPersistedGroupCenter(GroupCenter $groupCenter)
|
||||
@ -279,10 +261,8 @@ class UserController extends CRUDController
|
||||
* Creates a form to delete a link to a GroupCenter
|
||||
*
|
||||
* @param mixed $permissionsGroup The entity id
|
||||
*
|
||||
* @return \Symfony\Component\Form\Form The form
|
||||
*/
|
||||
private function createDeleteLinkGroupCenterForm(User $user, GroupCenter $groupCenter, $request)
|
||||
private function createDeleteLinkGroupCenterForm(User $user, GroupCenter $groupCenter, $request): FormInterface
|
||||
{
|
||||
$returnPathParams = $request->query->has('returnPath') ? ['returnPath' => $request->query->get('returnPath')] : [];
|
||||
|
||||
@ -291,39 +271,29 @@ class UserController extends CRUDController
|
||||
array_merge($returnPathParams, ['uid' => $user->getId(), 'gcid' => $groupCenter->getId()])))
|
||||
->setMethod('DELETE')
|
||||
->add('submit', SubmitType::class, array('label' => 'Delete'))
|
||||
->getForm()
|
||||
;
|
||||
->getForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* create a form to add a link to a groupcenter
|
||||
*
|
||||
* @param User $user
|
||||
* @return \Symfony\Component\Form\Form
|
||||
* Create a form to add a link to a groupcenter.
|
||||
*/
|
||||
private function createAddLinkGroupCenterForm(User $user, Request $request)
|
||||
private function createAddLinkGroupCenterForm(User $user, Request $request): FormInterface
|
||||
{
|
||||
$returnPathParams = $request->query->has('returnPath') ? ['returnPath' => $request->query->get('returnPath')] : [];
|
||||
|
||||
return $this->createFormBuilder()
|
||||
->setAction($this->generateUrl('admin_user_add_groupcenter',
|
||||
array_merge($returnPathParams, ['uid' => $user->getId()])))
|
||||
->setMethod('POST')
|
||||
->add(self::FORM_GROUP_CENTER_COMPOSED, ComposedGroupCenterType::class)
|
||||
->add('submit', SubmitType::class, array('label' => 'Add a new groupCenter'))
|
||||
->getForm()
|
||||
;
|
||||
->setAction($this->generateUrl('admin_user_add_groupcenter',
|
||||
array_merge($returnPathParams, ['uid' => $user->getId()])))
|
||||
->setMethod('POST')
|
||||
->add(self::FORM_GROUP_CENTER_COMPOSED, ComposedGroupCenterType::class)
|
||||
->add('submit', SubmitType::class, array('label' => 'Add a new groupCenter'))
|
||||
->getForm();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param User $user
|
||||
*/
|
||||
private function getDeleteLinkGroupCenterByUser(User $user, Request $request)
|
||||
{
|
||||
foreach ($user->getGroupCenters() as $groupCenter) {
|
||||
yield $groupCenter->getId() => $this
|
||||
->createDeleteLinkGroupCenterForm($user, $groupCenter, $request);
|
||||
yield $groupCenter->getId() => $this->createDeleteLinkGroupCenterForm($user, $groupCenter, $request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,26 +24,26 @@ class LoadLanguages extends AbstractFixture implements ContainerAwareInterface,
|
||||
// Array of ancien languages (to exclude)
|
||||
private $ancientToExclude = ["ang", "egy", "fro", "goh", "grc", "la", "non", "peo", "pro", "sga",
|
||||
"dum", "enm", "frm", "gmh", "mga", "akk", "phn", "zxx", "got", "und"];
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
|
||||
public function setContainer(ContainerInterface $container = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
|
||||
public function getOrder() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
|
||||
public function load(ObjectManager $manager) {
|
||||
|
||||
|
||||
echo "loading languages... \n";
|
||||
|
||||
|
||||
foreach (Intl::getLanguageBundle()->getLanguageNames() as $code => $language) {
|
||||
if (
|
||||
!in_array($code, $this->regionalVersionToInclude)
|
||||
@ -58,23 +58,24 @@ class LoadLanguages extends AbstractFixture implements ContainerAwareInterface,
|
||||
$manager->persist($lang);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* prepare names for languages
|
||||
*
|
||||
* @param string $languageCode
|
||||
* Prepare names for languages.
|
||||
*
|
||||
* @return string[] languages name indexed by available language code
|
||||
*/
|
||||
private function prepareName($languageCode) {
|
||||
private function prepareName(string $languageCode): array {
|
||||
$names = [];
|
||||
|
||||
foreach ($this->container->getParameter('chill_main.available_languages') as $lang) {
|
||||
$names[$lang] = Intl::getLanguageBundle()->getLanguageName($languageCode);
|
||||
}
|
||||
|
||||
|
||||
return $names;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,35 +1,32 @@
|
||||
<?php
|
||||
/*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\DependencyInjection\CompilerPass;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Chill\MainBundle\Form\PermissionsGroupType;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use LogicException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class ACLFlagsCompilerPass implements CompilerPassInterface
|
||||
{
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$permissionGroupType = $container->getDefinition(PermissionsGroupType::class);
|
||||
|
||||
|
||||
foreach($container->findTaggedServiceIds('chill_main.flags') as $id => $tags) {
|
||||
$reference = new Reference($id);
|
||||
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
switch($tag['scope']) {
|
||||
case PermissionsGroupType::FLAG_SCOPE:
|
||||
|
||||
|
||||
$permissionGroupType->addMethodCall('addFlagProvider', [ $reference ]);
|
||||
break;
|
||||
default:
|
||||
throw new \LogicalException(sprintf(
|
||||
throw new LogicException(sprintf(
|
||||
"This tag 'scope' is not implemented: %s, on service with id %s", $tag['scope'], $id)
|
||||
);
|
||||
}
|
||||
|
@ -19,14 +19,11 @@ class Configuration implements ConfigurationInterface
|
||||
|
||||
use AddWidgetConfigurationTrait;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var ContainerBuilder
|
||||
*/
|
||||
private $containerBuilder;
|
||||
private ContainerBuilder $containerBuilder;
|
||||
|
||||
|
||||
public function __construct(array $widgetFactories = array(),
|
||||
public function __construct(
|
||||
array $widgetFactories,
|
||||
ContainerBuilder $containerBuilder)
|
||||
{
|
||||
$this->setWidgetFactories($widgetFactories);
|
||||
@ -107,6 +104,9 @@ class Configuration implements ConfigurationInterface
|
||||
->booleanNode('form_show_scopes')
|
||||
->defaultTrue()
|
||||
->end()
|
||||
->booleanNode('form_show_centers')
|
||||
->defaultTrue()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->arrayNode('redis')
|
||||
|
@ -30,27 +30,27 @@ use Chill\MainBundle\DependencyInjection\Widget\HasWidgetFactoriesExtensionInter
|
||||
|
||||
/**
|
||||
* Compile the configurations and inject required service into container.
|
||||
*
|
||||
*
|
||||
* The widgets are services tagged with :
|
||||
*
|
||||
*
|
||||
* ```
|
||||
* { name: chill_widget, alias: my_alias, place: my_place }
|
||||
* ```
|
||||
*
|
||||
* Or, if the tag does not exist or if you need to add some config to your
|
||||
*
|
||||
* Or, if the tag does not exist or if you need to add some config to your
|
||||
* service depending on the config, you should use a `WidgetFactory` (see
|
||||
* `WidgetFactoryInterface`.
|
||||
*
|
||||
* To reuse this compiler pass, simple execute the doProcess metho in your
|
||||
*
|
||||
* To reuse this compiler pass, simple execute the doProcess metho in your
|
||||
* compiler. Example :
|
||||
*
|
||||
*
|
||||
* ```
|
||||
* namespace Chill\MainBundle\DependencyInjection\CompilerPass;
|
||||
*
|
||||
*
|
||||
* use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
* use Chill\MainBundle\DependencyInjection\Widget\AbstractWidgetsCompilerPass;
|
||||
* class WidgetsCompilerPass extends AbstractWidgetsCompilerPass {
|
||||
*
|
||||
*
|
||||
* public function process(ContainerBuilder $container)
|
||||
* {
|
||||
* $this->doProcess($container, 'chill_main', 'chill_main.widgets');
|
||||
@ -58,58 +58,58 @@ use Chill\MainBundle\DependencyInjection\Widget\HasWidgetFactoriesExtensionInter
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
{
|
||||
private $widgetServices = array();
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @var WidgetFactoryInterface[]
|
||||
*/
|
||||
private $widgetFactories;
|
||||
|
||||
|
||||
/**
|
||||
* The service which will manage the widgets
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const WIDGET_MANAGER = 'chill.main.twig.widget';
|
||||
|
||||
|
||||
/**
|
||||
* the method wich register the widget into give service.
|
||||
*/
|
||||
const WIDGET_MANAGER_METHOD_REGISTER = 'addWidget';
|
||||
|
||||
|
||||
/**
|
||||
* the value of the `name` key in service definitions's tag
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const WIDGET_SERVICE_TAG_NAME = 'chill_widget';
|
||||
|
||||
|
||||
/**
|
||||
* the key used to collect the alias in the service definition's tag.
|
||||
* the alias must be
|
||||
* the key used to collect the alias in the service definition's tag.
|
||||
* the alias must be
|
||||
* injected into the configuration under 'alias' key.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const WIDGET_SERVICE_TAG_ALIAS = 'alias';
|
||||
|
||||
|
||||
/**
|
||||
* the key used to collect the authorized place in the service definition's tag
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const WIDGET_SERVICE_TAG_PLACES = 'place';
|
||||
|
||||
|
||||
/**
|
||||
* the key to use to order widget for a given place
|
||||
*/
|
||||
const WIDGET_CONFIG_ORDER = 'order';
|
||||
|
||||
|
||||
/**
|
||||
* the key to use to identify widget for a given place
|
||||
*/
|
||||
@ -118,24 +118,25 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
|
||||
/**
|
||||
* process the configuration and the container to add the widget available
|
||||
*
|
||||
*
|
||||
* @param ContainerBuilder $container
|
||||
* @param string $extension the extension of your bundle
|
||||
* @param string $containerWidgetConfigParameterName the key under which we can use the widget configuration
|
||||
* @throws \LogicException
|
||||
* @throws \UnexpectedValueException if the given extension does not implement HasWidgetExtensionInterface
|
||||
* @throws \InvalidConfigurationException if there are errors in the config
|
||||
*/
|
||||
public function doProcess(ContainerBuilder $container, $extension,
|
||||
$containerWidgetConfigParameterName)
|
||||
{
|
||||
public function doProcess(
|
||||
ContainerBuilder $container,
|
||||
$extension,
|
||||
$containerWidgetConfigParameterName
|
||||
) {
|
||||
if (!$container->hasDefinition(self::WIDGET_MANAGER)) {
|
||||
throw new \LogicException("the service ".self::WIDGET_MANAGER." should".
|
||||
" be present. It is required by ".self::class);
|
||||
}
|
||||
|
||||
|
||||
$managerDefinition = $container->getDefinition(self::WIDGET_MANAGER);
|
||||
|
||||
|
||||
// collect the widget factories
|
||||
/* @var $extensionClass HasWidgetFactoriesExtensionInterface */
|
||||
$extensionClass = $container->getExtension($extension);
|
||||
@ -148,19 +149,19 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
HasWidgetFactoriesExtensionInterface::class,
|
||||
get_class($extensionClass)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$this->widgetFactories = $extensionClass->getWidgetFactories();
|
||||
|
||||
|
||||
// collect the availabled tagged services
|
||||
$this->collectTaggedServices($container);
|
||||
|
||||
|
||||
// collect the widgets and their config :
|
||||
$widgetParameters = $container->getParameter($containerWidgetConfigParameterName);
|
||||
|
||||
|
||||
// and add them to the delegated_block
|
||||
foreach($widgetParameters as $place => $widgets) {
|
||||
|
||||
|
||||
foreach ($widgets as $param) {
|
||||
$alias = $param[self::WIDGET_CONFIG_ALIAS];
|
||||
// check that the service exists
|
||||
@ -168,43 +169,43 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
throw new InvalidConfigurationException(sprintf("The alias %s".
|
||||
" is not defined.", $alias));
|
||||
}
|
||||
|
||||
|
||||
// check that the widget is allowed at this place
|
||||
if (!$this->isPlaceAllowedForWidget($place, $alias, $container)) {
|
||||
throw new \InvalidConfigurationException(sprintf(
|
||||
throw new InvalidConfigurationException(sprintf(
|
||||
"The widget with alias %s is not allowed at place %s",
|
||||
$alias,
|
||||
$alias,
|
||||
$place
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
// get the order, eventually corrected
|
||||
$order = $this->cacheAndGetOrdering($place, $param[self::WIDGET_CONFIG_ORDER]);
|
||||
|
||||
$order = $this->cacheAndGetOrdering($place, $param[self::WIDGET_CONFIG_ORDER]);
|
||||
|
||||
// register the widget with config to the service, using the method
|
||||
// `addWidget`
|
||||
if ($this->widgetServices[$alias] instanceof WidgetFactoryInterface) {
|
||||
/* @var $factory WidgetFactoryInterface */
|
||||
$factory = $this->widgetServices[$alias];
|
||||
// get the config (under the key which equals to widget_alias
|
||||
$config = isset($param[$factory->getWidgetAlias()]) ?
|
||||
$config = isset($param[$factory->getWidgetAlias()]) ?
|
||||
$param[$factory->getWidgetAlias()] : array();
|
||||
// register the service into the container
|
||||
$serviceId =$this->registerServiceIntoContainer($container,
|
||||
$serviceId =$this->registerServiceIntoContainer($container,
|
||||
$factory, $place, $order, $config);
|
||||
|
||||
|
||||
$managerDefinition->addMethodCall(self::WIDGET_MANAGER_METHOD_REGISTER,
|
||||
array(
|
||||
$place,
|
||||
$order,
|
||||
new Reference($serviceId),
|
||||
$place,
|
||||
$order,
|
||||
new Reference($serviceId),
|
||||
$config
|
||||
));
|
||||
} else {
|
||||
$managerDefinition->addMethodCall(self::WIDGET_MANAGER_METHOD_REGISTER,
|
||||
array(
|
||||
$place,
|
||||
$order,
|
||||
$place,
|
||||
$order,
|
||||
new Reference($this->widgetServices[$alias]),
|
||||
array() // the config is alway an empty array
|
||||
));
|
||||
@ -212,10 +213,10 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* register the service into container.
|
||||
*
|
||||
*
|
||||
* @param ContainerBuilder $container
|
||||
* @param WidgetFactoryInterface $factory
|
||||
* @param string $place
|
||||
@ -231,28 +232,28 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
array $config
|
||||
) {
|
||||
$serviceId = $factory->getServiceId($container, $place, $order, $config);
|
||||
$definition = $factory->createDefinition($container, $place,
|
||||
$definition = $factory->createDefinition($container, $place,
|
||||
$order, $config);
|
||||
$container->setDefinition($serviceId, $definition);
|
||||
|
||||
|
||||
return $serviceId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* cache of ordering by place.
|
||||
*
|
||||
*
|
||||
* @internal used by function cacheAndGetOrdering
|
||||
* @var array
|
||||
*/
|
||||
private $cacheOrdering = array();
|
||||
|
||||
|
||||
/**
|
||||
* check if the ordering has already be used for the given $place and,
|
||||
* if yes, correct the ordering by incrementation of 1 until the ordering
|
||||
* has not be used.
|
||||
*
|
||||
*
|
||||
* recursive method.
|
||||
*
|
||||
*
|
||||
* @param string $place
|
||||
* @param float $ordering
|
||||
* @return float
|
||||
@ -262,7 +263,7 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
if (!array_key_exists($place, $this->cacheOrdering)) {
|
||||
$this->cacheOrdering[$place] = array();
|
||||
}
|
||||
|
||||
|
||||
// check if the order exists
|
||||
if (array_search($ordering, $this->cacheOrdering[$place])) {
|
||||
// if the order exists, increment of 1 and try again
|
||||
@ -270,14 +271,14 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
} else {
|
||||
// cache the ordering
|
||||
$this->cacheOrdering[$place][] = $ordering;
|
||||
|
||||
|
||||
return $ordering;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get the places where the service is allowed
|
||||
*
|
||||
*
|
||||
* @param Definition $definition
|
||||
* @return unknown
|
||||
*/
|
||||
@ -288,7 +289,7 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
->getAllowedPlaces())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
$definition = $container->findDefinition($this->widgetServices[$widgetAlias]);
|
||||
|
||||
@ -300,17 +301,17 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method collect all service tagged with `self::WIDGET_SERVICE_TAG`, and
|
||||
* add also the widget defined by factories
|
||||
*
|
||||
*
|
||||
* This method also check that the service is correctly tagged with `alias` and
|
||||
* `places`, or the factory give a correct alias and more than one place.
|
||||
*
|
||||
*
|
||||
* @param ContainerBuilder $container
|
||||
* @throws InvalidConfigurationException
|
||||
* @throws InvalidArgumentException
|
||||
@ -320,13 +321,13 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
// first, check the service tagged in service definition
|
||||
foreach ($container->findTaggedServiceIds(self::WIDGET_SERVICE_TAG_NAME) as $id => $attrs) {
|
||||
foreach ($attrs as $attr) {
|
||||
|
||||
|
||||
// check the alias is set
|
||||
if (!isset($attr[self::WIDGET_SERVICE_TAG_ALIAS])) {
|
||||
throw new InvalidConfigurationException("you should add an ".self::WIDGET_SERVICE_TAG_ALIAS.
|
||||
" key on the service ".$id);
|
||||
}
|
||||
|
||||
|
||||
// check the place is set
|
||||
if (!isset($attr[self::WIDGET_SERVICE_TAG_PLACES])) {
|
||||
throw new InvalidConfigurationException(sprintf(
|
||||
@ -335,54 +336,54 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
$id
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
// check the alias does not exists yet
|
||||
if (array_key_exists($attr[self::WIDGET_SERVICE_TAG_ALIAS], $this->widgetServices)) {
|
||||
throw new InvalidArgumentException("a service has already be defined with the ".
|
||||
self::WIDGET_SERVICE_TAG_ALIAS." ".$attr[self::WIDGET_SERVICE_TAG_ALIAS]);
|
||||
}
|
||||
|
||||
|
||||
// register the service as available
|
||||
$this->widgetServices[$attr[self::WIDGET_SERVICE_TAG_ALIAS]] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// add the services defined by factories
|
||||
foreach($this->widgetFactories as $factory) {
|
||||
/* @var $factory WidgetFactoryInterface */
|
||||
$alias = $factory->getWidgetAlias();
|
||||
|
||||
|
||||
// check the alias is not empty
|
||||
if (empty($alias)) {
|
||||
throw new \LogicException(sprintf(
|
||||
"the widget factory %s returns an empty alias",
|
||||
get_class($factory)));
|
||||
}
|
||||
|
||||
|
||||
// check the places are not empty
|
||||
if (!is_array($factory->getAllowedPlaces())) {
|
||||
throw new \UnexpectedValueException("the method 'getAllowedPlaces' "
|
||||
. "should return a non-empty array. Unexpected value on ".
|
||||
get_class($factory));
|
||||
}
|
||||
|
||||
|
||||
if (count($factory->getAllowedPlaces()) == 0) {
|
||||
throw new \LengthException("The method 'getAllowedPlaces' should "
|
||||
. "return a non-empty array, but returned 0 elements on ".
|
||||
get_class($factory).'::getAllowedPlaces()');
|
||||
}
|
||||
|
||||
|
||||
// check the alias does not exists yet
|
||||
if (array_key_exists($alias, $this->widgetServices)) {
|
||||
throw new InvalidArgumentException("a service has already be defined with the ".
|
||||
self::WIDGET_SERVICE_TAG_ALIAS." ".$alias);
|
||||
}
|
||||
|
||||
|
||||
// register the factory as available
|
||||
$this->widgetServices[$factory->getWidgetAlias()] = $factory;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,58 +1,43 @@
|
||||
<?php
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
* Copyright (C) 2018 Champs-Libres Coopérative <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Doctrine\DQL;
|
||||
|
||||
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
|
||||
use Doctrine\ORM\Query\AST\PathExpression;
|
||||
use Doctrine\ORM\Query\Lexer;
|
||||
use Doctrine\ORM\Query\Parser;
|
||||
|
||||
/**
|
||||
* DQL function for OVERLAPS function in postgresql
|
||||
*
|
||||
* If a value is null in period start, it will be replaced by -infinity.
|
||||
*
|
||||
* If a value is null in period start, it will be replaced by -infinity.
|
||||
* If a value is null in period end, it will be replaced by infinity
|
||||
*
|
||||
*/
|
||||
class OverlapsI extends FunctionNode
|
||||
{
|
||||
private $firstPeriodStart;
|
||||
|
||||
|
||||
private $firstPeriodEnd;
|
||||
|
||||
|
||||
private $secondPeriodStart;
|
||||
|
||||
|
||||
private $secondPeriodEnd;
|
||||
|
||||
|
||||
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
|
||||
{
|
||||
return '('
|
||||
.$this->makeCase($sqlWalker, $this->firstPeriodStart, 'start').', '
|
||||
.$this->makeCase($sqlWalker, $this->firstPeriodEnd, 'end').
|
||||
') OVERLAPS ('
|
||||
.$this->makeCase($sqlWalker, $this->secondPeriodStart, 'start').', '
|
||||
.$this->makeCase($sqlWalker, $this->secondPeriodEnd, 'end').')'
|
||||
;
|
||||
return sprintf(
|
||||
'(%s, %s) OVERLAPS (%s, %s)',
|
||||
$this->makeCase($sqlWalker, $this->firstPeriodStart, 'start'),
|
||||
$this->makeCase($sqlWalker, $this->firstPeriodEnd, 'end'),
|
||||
$this->makeCase($sqlWalker, $this->secondPeriodStart, 'start'),
|
||||
$this->makeCase($sqlWalker, $this->secondPeriodEnd, 'end')
|
||||
);
|
||||
}
|
||||
|
||||
protected function makeCase($sqlWalker, $part, $position)
|
||||
|
||||
protected function makeCase($sqlWalker, $part, string $position): string
|
||||
{
|
||||
//return $part->dispatch($sqlWalker);
|
||||
|
||||
switch ($position) {
|
||||
case 'start' :
|
||||
$p = '-infinity';
|
||||
@ -60,51 +45,51 @@ class OverlapsI extends FunctionNode
|
||||
case 'end':
|
||||
$p = 'infinity';
|
||||
break;
|
||||
default:
|
||||
throw new \Exception('Unexpected position value.');
|
||||
}
|
||||
|
||||
if ($part instanceof \Doctrine\ORM\Query\AST\PathExpression) {
|
||||
return 'CASE WHEN '
|
||||
.' '.$part->dispatch($sqlWalker).' IS NOT NULL '
|
||||
. 'THEN '.
|
||||
$part->dispatch($sqlWalker)
|
||||
. ' ELSE '.
|
||||
"'".$p."'::date "
|
||||
. 'END';
|
||||
} else {
|
||||
return 'CASE WHEN '
|
||||
.' '.$part->dispatch($sqlWalker).'::date IS NOT NULL '
|
||||
. 'THEN '.
|
||||
$part->dispatch($sqlWalker)
|
||||
. '::date ELSE '.
|
||||
"'".$p."'::date "
|
||||
. 'END';
|
||||
|
||||
if ($part instanceof PathExpression) {
|
||||
return sprintf(
|
||||
"CASE WHEN %s IS NOT NULL THEN %s ELSE '%s'::date END",
|
||||
$part->dispatch($sqlWalker),
|
||||
$part->dispatch($sqlWalker),
|
||||
$p
|
||||
);
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
"CASE WHEN %s::date IS NOT NULL THEN %s::date ELSE '%s'::date END",
|
||||
$part->dispatch($sqlWalker),
|
||||
$part->dispatch($sqlWalker),
|
||||
$p
|
||||
);
|
||||
}
|
||||
|
||||
public function parse(\Doctrine\ORM\Query\Parser $parser)
|
||||
public function parse(Parser $parser): void
|
||||
{
|
||||
$parser->match(Lexer::T_IDENTIFIER);
|
||||
|
||||
|
||||
$parser->match(Lexer::T_OPEN_PARENTHESIS);
|
||||
|
||||
|
||||
$this->firstPeriodStart = $parser->StringPrimary();
|
||||
|
||||
|
||||
$parser->match(Lexer::T_COMMA);
|
||||
|
||||
|
||||
$this->firstPeriodEnd = $parser->StringPrimary();
|
||||
|
||||
|
||||
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
|
||||
|
||||
|
||||
$parser->match(Lexer::T_COMMA);
|
||||
|
||||
|
||||
$parser->match(Lexer::T_OPEN_PARENTHESIS);
|
||||
|
||||
|
||||
$this->secondPeriodStart = $parser->StringPrimary();
|
||||
|
||||
|
||||
$parser->match(Lexer::T_COMMA);
|
||||
|
||||
|
||||
$this->secondPeriodEnd = $parser->StringPrimary();
|
||||
|
||||
|
||||
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
|
||||
}
|
||||
}
|
||||
|
@ -4,13 +4,9 @@ namespace Chill\MainBundle\Doctrine\Model;
|
||||
|
||||
use \JsonSerializable;
|
||||
|
||||
/**
|
||||
* Description of Point
|
||||
*
|
||||
*/
|
||||
class Point implements JsonSerializable {
|
||||
private ?float $lat = null;
|
||||
private ?float $lon = null;
|
||||
private ?float $lat;
|
||||
private ?float $lon;
|
||||
public static string $SRID = '4326';
|
||||
|
||||
private function __construct(?float $lon, ?float $lat)
|
||||
@ -22,6 +18,7 @@ class Point implements JsonSerializable {
|
||||
public function toGeoJson(): string
|
||||
{
|
||||
$array = $this->toArrayGeoJson();
|
||||
|
||||
return \json_encode($array);
|
||||
}
|
||||
|
||||
@ -33,60 +30,53 @@ class Point implements JsonSerializable {
|
||||
public function toArrayGeoJson(): array
|
||||
{
|
||||
return [
|
||||
"type" => "Point",
|
||||
"coordinates" => [ $this->lon, $this->lat ]
|
||||
'type' => 'Point',
|
||||
'coordinates' => [$this->lon, $this->lat],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toWKT(): string
|
||||
{
|
||||
return 'SRID='.self::$SRID.';POINT('.$this->lon.' '.$this->lat.')';
|
||||
return sprintf("SRID=%s;POINT(%s %s)", self::$SRID, $this->lon, $this->lat);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param type $geojson
|
||||
* @return Point
|
||||
*/
|
||||
public static function fromGeoJson(string $geojson): Point
|
||||
public static function fromGeoJson(string $geojson): self
|
||||
{
|
||||
$a = json_decode($geojson);
|
||||
//check if the geojson string is correct
|
||||
if (NULL === $a or !isset($a->type) or !isset($a->coordinates)){
|
||||
|
||||
if (null === $a) {
|
||||
throw PointException::badJsonString($geojson);
|
||||
}
|
||||
|
||||
if ($a->type != 'Point'){
|
||||
if (null === $a->type || null === $a->coordinates) {
|
||||
throw PointException::badJsonString($geojson);
|
||||
}
|
||||
|
||||
if ($a->type !== 'Point'){
|
||||
throw PointException::badGeoType();
|
||||
}
|
||||
|
||||
$lat = $a->coordinates[1];
|
||||
$lon = $a->coordinates[0];
|
||||
[$lon, $lat] = $a->coordinates;
|
||||
|
||||
return Point::fromLonLat($lon, $lat);
|
||||
}
|
||||
|
||||
public static function fromLonLat(float $lon, float $lat): Point
|
||||
public static function fromLonLat(float $lon, float $lat): self
|
||||
{
|
||||
if (($lon > -180 && $lon < 180) && ($lat > -90 && $lat < 90))
|
||||
{
|
||||
if (($lon > -180 && $lon < 180) && ($lat > -90 && $lat < 90)) {
|
||||
return new Point($lon, $lat);
|
||||
} else {
|
||||
throw PointException::badCoordinates($lon, $lat);
|
||||
}
|
||||
|
||||
throw PointException::badCoordinates($lon, $lat);
|
||||
}
|
||||
|
||||
public static function fromArrayGeoJson(array $array): Point
|
||||
public static function fromArrayGeoJson(array $array): self
|
||||
{
|
||||
if ($array['type'] == 'Point' &&
|
||||
isset($array['coordinates']))
|
||||
{
|
||||
if ($array['type'] === 'Point' && isset($array['coordinates'])) {
|
||||
return self::fromLonLat($array['coordinates'][0], $array['coordinates'][1]);
|
||||
}
|
||||
|
||||
throw new \Exception('Unable to build a point from input data.');
|
||||
}
|
||||
|
||||
public function getLat(): float
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Doctrine\Type;
|
||||
|
||||
use Chill\MainBundle\Doctrine\Model\Point;
|
||||
@ -7,40 +9,32 @@ use Doctrine\DBAL\Types\Type;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Chill\MainBundle\Doctrine\Model\PointException;
|
||||
|
||||
|
||||
/**
|
||||
* A Type for Doctrine to implement the Geography Point type
|
||||
* implemented by Postgis on postgis+postgresql databases
|
||||
*
|
||||
*/
|
||||
class PointType extends Type {
|
||||
|
||||
const POINT = 'point';
|
||||
class PointType extends Type
|
||||
{
|
||||
public const POINT = 'point';
|
||||
|
||||
/**
|
||||
*
|
||||
* @param array $fieldDeclaration
|
||||
* @param AbstractPlatform $platform
|
||||
* @return string
|
||||
*/
|
||||
public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
|
||||
public function getSQLDeclaration(array $column, AbstractPlatform $platform)
|
||||
{
|
||||
return 'geometry(POINT,'.Point::$SRID.')';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param type $value
|
||||
* @param AbstractPlatform $platform
|
||||
* @return ?Point
|
||||
*/
|
||||
public function convertToPHPValue($value, AbstractPlatform $platform)
|
||||
{
|
||||
if ($value === NULL){
|
||||
return NULL;
|
||||
} else {
|
||||
return Point::fromGeoJson($value);
|
||||
}
|
||||
|
||||
return Point::fromGeoJson($value);
|
||||
}
|
||||
|
||||
public function getName()
|
||||
@ -52,9 +46,9 @@ class PointType extends Type {
|
||||
{
|
||||
if ($value === NULL){
|
||||
return NULL;
|
||||
} else {
|
||||
return $value->toWKT();
|
||||
}
|
||||
|
||||
return $value->toWKT();
|
||||
}
|
||||
|
||||
public function canRequireSQLConversion()
|
||||
|
@ -1,19 +1,19 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@ -23,12 +23,11 @@ namespace Chill\MainBundle\Entity;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(name="centers")
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class Center implements HasCenterInterface
|
||||
{
|
||||
@ -46,9 +45,10 @@ class Center implements HasCenterInterface
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="string", length=255)
|
||||
* @Serializer\Groups({"docgen:read"})
|
||||
*/
|
||||
private $name;
|
||||
|
||||
private string $name = '';
|
||||
|
||||
/**
|
||||
* @var Collection
|
||||
*
|
||||
@ -58,8 +58,8 @@ class Center implements HasCenterInterface
|
||||
* )
|
||||
*/
|
||||
private $groupCenters;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Center constructor.
|
||||
*/
|
||||
@ -67,7 +67,7 @@ class Center implements HasCenterInterface
|
||||
{
|
||||
$this->groupCenters = new \Doctrine\Common\Collections\ArrayCollection();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
@ -75,7 +75,7 @@ class Center implements HasCenterInterface
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return $this
|
||||
@ -85,7 +85,7 @@ class Center implements HasCenterInterface
|
||||
$this->name = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
@ -93,7 +93,7 @@ class Center implements HasCenterInterface
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return ArrayCollection|Collection
|
||||
*/
|
||||
@ -101,7 +101,7 @@ class Center implements HasCenterInterface
|
||||
{
|
||||
return $this->groupCenters;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param GroupCenter $groupCenter
|
||||
* @return $this
|
||||
@ -111,7 +111,7 @@ class Center implements HasCenterInterface
|
||||
$this->groupCenters->add($groupCenter);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
@ -119,7 +119,7 @@ class Center implements HasCenterInterface
|
||||
{
|
||||
return $this->getName();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return $this|Center
|
||||
*/
|
||||
|
@ -1,22 +1,6 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a suite of a modules, Chill is a software for social workers
|
||||
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Entity;
|
||||
|
||||
@ -28,38 +12,30 @@ use Doctrine\Common\Collections\ArrayCollection;
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(name="role_scopes")
|
||||
* @ORM\Cache(usage="NONSTRICT_READ_WRITE", region="acl_cache_region")
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class RoleScope
|
||||
{
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Id
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="string", length=255)
|
||||
*/
|
||||
private $role;
|
||||
|
||||
private ?string $role = null;
|
||||
|
||||
/**
|
||||
* @var Scope
|
||||
*
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity="Chill\MainBundle\Entity\Scope",
|
||||
* inversedBy="roleScopes")
|
||||
* @ORM\JoinColumn(nullable=true, name="scope_id")
|
||||
* @ORM\Cache(usage="NONSTRICT_READ_WRITE")
|
||||
*/
|
||||
private $scope;
|
||||
|
||||
private ?Scope $scope = null;
|
||||
|
||||
/**
|
||||
* @var Collection
|
||||
*
|
||||
@ -68,59 +44,37 @@ class RoleScope
|
||||
* mappedBy="roleScopes")
|
||||
*/
|
||||
private $permissionsGroups;
|
||||
|
||||
|
||||
/**
|
||||
* RoleScope constructor.
|
||||
*/
|
||||
|
||||
public function __construct() {
|
||||
$this->new = true;
|
||||
$this->permissionsGroups = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRole()
|
||||
public function getRole(): ?string
|
||||
{
|
||||
return $this->role;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Scope
|
||||
*/
|
||||
public function getScope()
|
||||
public function getScope(): ?Scope
|
||||
{
|
||||
return $this->scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type $role
|
||||
* @return RoleScope
|
||||
*/
|
||||
public function setRole($role)
|
||||
|
||||
public function setRole(?string $role = null): self
|
||||
{
|
||||
$this->role = $role;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Scope $scope
|
||||
* @return RoleScope
|
||||
*/
|
||||
public function setScope(Scope $scope = null)
|
||||
public function setScope(?Scope $scope = null): self
|
||||
{
|
||||
$this->scope = $scope;
|
||||
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Chill\MainBundle\Entity\UserJob;
|
||||
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* User
|
||||
@ -16,7 +16,7 @@ use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(name="users")
|
||||
* @ORM\Cache(usage="NONSTRICT_READ_WRITE", region="acl_cache_region")
|
||||
* @DiscriminatorMap(typeProperty="type", mapping={
|
||||
* @Serializer\DiscriminatorMap(typeProperty="type", mapping={
|
||||
* "user"=User::class
|
||||
* })
|
||||
*/
|
||||
@ -51,6 +51,7 @@ class User implements AdvancedUserInterface {
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=200)
|
||||
* @Serializer\Groups({"docgen:read"})
|
||||
*/
|
||||
private string $label = '';
|
||||
|
||||
@ -58,8 +59,9 @@ class User implements AdvancedUserInterface {
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="string", length=150, nullable=true)
|
||||
* @Serializer\Groups({"docgen:read"})
|
||||
*/
|
||||
private $email;
|
||||
private ?string $email = null;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
@ -123,6 +125,7 @@ class User implements AdvancedUserInterface {
|
||||
/**
|
||||
* @var Center|null
|
||||
* @ORM\ManyToOne(targetEntity=Center::class)
|
||||
* @Serializer\Groups({"docgen:read"})
|
||||
*/
|
||||
private ?Center $mainCenter = null;
|
||||
|
||||
|
@ -1,48 +1,25 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Champs-Libres <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Export\Formatter;
|
||||
|
||||
use Chill\MainBundle\Export\ExportInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use Chill\MainBundle\Export\ExportManager;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
|
||||
// command to get the report with curl : curl --user "center a_social:password" "http://localhost:8000/fr/exports/generate/count_person?export[filters][person_gender_filter][enabled]=&export[filters][person_nationality_filter][enabled]=&export[filters][person_nationality_filter][form][nationalities]=&export[aggregators][person_nationality_aggregator][order]=1&export[aggregators][person_nationality_aggregator][form][group_by_level]=country&export[submit]=&export[_token]=RHpjHl389GrK-bd6iY5NsEqrD5UKOTHH40QKE9J1edU" --globoff
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
* Command to get the report with curl:
|
||||
* curl --user "center a_social:password" "http://localhost:8000/fr/exports/generate/count_person?export[filters][person_gender_filter][enabled]=&export[filters][person_nationality_filter][enabled]=&export[filters][person_nationality_filter][form][nationalities]=&export[aggregators][person_nationality_aggregator][order]=1&export[aggregators][person_nationality_aggregator][form][group_by_level]=country&export[submit]=&export[_token]=RHpjHl389GrK-bd6iY5NsEqrD5UKOTHH40QKE9J1edU" --globoff
|
||||
* @deprecated this formatter is not used any more.
|
||||
*/
|
||||
class CSVFormatter implements FormatterInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
protected TranslatorInterface $translator;
|
||||
|
||||
protected $result;
|
||||
|
||||
@ -85,11 +62,7 @@ class CSVFormatter implements FormatterInterface
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @uses appendAggregatorForm
|
||||
* @param FormBuilderInterface $builder
|
||||
* @param type $exportAlias
|
||||
* @param array $aggregatorAliases
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, $exportAlias, array $aggregatorAliases)
|
||||
{
|
||||
@ -172,20 +145,35 @@ class CSVFormatter implements FormatterInterface
|
||||
* If two aggregators have the same order, the second given will be placed
|
||||
* after. This is not significant for the first ordering.
|
||||
*
|
||||
* @param type $formatterData
|
||||
* @return type
|
||||
*/
|
||||
protected function orderingHeaders($formatterData)
|
||||
protected function orderingHeaders(array $formatterData)
|
||||
{
|
||||
$this->formatterData = $formatterData;
|
||||
uasort($this->formatterData, function($a, $b) {
|
||||
uasort(
|
||||
$this->formatterData,
|
||||
static fn(array $a, array $b): int => ($a['order'] <= $b['order'] ? -1 : 1)
|
||||
);
|
||||
}
|
||||
|
||||
return ($a['order'] <= $b['order'] ? -1 : 1);
|
||||
});
|
||||
private function findColumnPosition(&$columnHeaders, $columnToFind): int
|
||||
{
|
||||
$i = 0;
|
||||
foreach($columnHeaders as $set) {
|
||||
if ($set === $columnToFind) {
|
||||
return $i;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
//we didn't find it, adding the column
|
||||
$columnHeaders[] = $columnToFind;
|
||||
|
||||
return $i++;
|
||||
}
|
||||
|
||||
protected function generateContent()
|
||||
{
|
||||
$line = null;
|
||||
$rowKeysNb = count($this->getRowHeaders());
|
||||
$columnKeysNb = count($this->getColumnHeaders());
|
||||
$resultsKeysNb = count($this->export->getQueryKeys($this->exportData));
|
||||
@ -196,21 +184,6 @@ class CSVFormatter implements FormatterInterface
|
||||
$contentData = array();
|
||||
$content = array();
|
||||
|
||||
function findColumnPosition(&$columnHeaders, $columnToFind) {
|
||||
$i = 0;
|
||||
foreach($columnHeaders as $set) {
|
||||
if ($set === $columnToFind) {
|
||||
return $i;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
//we didn't find it, adding the column
|
||||
$columnHeaders[] = $columnToFind;
|
||||
|
||||
return $i++;
|
||||
}
|
||||
|
||||
// create a file pointer connected to the output stream
|
||||
$output = fopen('php://output', 'w');
|
||||
|
||||
@ -244,7 +217,7 @@ class CSVFormatter implements FormatterInterface
|
||||
// add the column headers
|
||||
/* @var $columns string[] the column for this row */
|
||||
$columns = array_slice($row, $rowKeysNb, $columnKeysNb);
|
||||
$columnPosition = findColumnPosition($columnHeaders, $columns);
|
||||
$columnPosition = $this->findColumnPosition($columnHeaders, $columns);
|
||||
|
||||
//fill with blank at the position given by the columnPosition + nbRowHeaders
|
||||
for ($i=0; $i < $columnPosition; $i++) {
|
||||
|
@ -229,7 +229,7 @@ class SpreadSheetFormatter implements FormatterInterface
|
||||
$this->getContentType($this->formatterData['format']));
|
||||
|
||||
$this->tempfile = \tempnam(\sys_get_temp_dir(), '');
|
||||
$this->generatecontent();
|
||||
$this->generateContent();
|
||||
|
||||
$f = \fopen($this->tempfile, 'r');
|
||||
$response->setContent(\stream_get_contents($f));
|
||||
|
@ -51,8 +51,10 @@ class CenterTransformer implements DataTransformerInterface
|
||||
}
|
||||
}
|
||||
|
||||
$ids = [];
|
||||
|
||||
if ($this->multiple) {
|
||||
$ids = \explode(',', $id);
|
||||
$ids = explode(',', $id);
|
||||
} else {
|
||||
$ids[] = (int) $id;
|
||||
}
|
||||
@ -68,9 +70,9 @@ class CenterTransformer implements DataTransformerInterface
|
||||
|
||||
if ($this->multiple) {
|
||||
return new ArrayCollection($centers);
|
||||
} else {
|
||||
return $centers[0];
|
||||
}
|
||||
|
||||
return $centers[0];
|
||||
}
|
||||
|
||||
public function transform($center)
|
||||
|
@ -1,48 +1,25 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2018 Champs Libres Cooperative <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Form\Type\DataTransformer;
|
||||
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class DateIntervalTransformer implements DataTransformerInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @param \DateInterval $value
|
||||
* @throws UnexpectedTypeException
|
||||
*/
|
||||
public function transform($value)
|
||||
{
|
||||
if (empty($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
if (!$value instanceof \DateInterval) {
|
||||
throw new UnexpectedTypeException($value, \DateInterval::class);
|
||||
}
|
||||
|
||||
|
||||
if ($value->d > 0) {
|
||||
// we check for weeks (weeks are converted to 7 days)
|
||||
if ($value->d % 7 === 0) {
|
||||
@ -50,43 +27,49 @@ class DateIntervalTransformer implements DataTransformerInterface
|
||||
'n' => $value->d / 7,
|
||||
'unit' => 'W'
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
'n' => $value->d,
|
||||
'unit' => 'D'
|
||||
];
|
||||
}
|
||||
} elseif ($value->m > 0) {
|
||||
|
||||
return [
|
||||
'n' => $value->d,
|
||||
'unit' => 'D'
|
||||
];
|
||||
}
|
||||
|
||||
if ($value->m > 0) {
|
||||
return [
|
||||
'n' => $value->m,
|
||||
'unit' => 'M'
|
||||
];
|
||||
} elseif ($value->y > 0) {
|
||||
}
|
||||
|
||||
if ($value->y > 0) {
|
||||
return [
|
||||
'n' => $value->y,
|
||||
'unit' => 'Y'
|
||||
];
|
||||
}
|
||||
|
||||
throw new TransformationFailedException('the date interval does not '
|
||||
. 'contains any days, months or years');
|
||||
|
||||
throw new TransformationFailedException(
|
||||
'The date interval does not contains any days, months or years.'
|
||||
);
|
||||
}
|
||||
|
||||
public function reverseTransform($value)
|
||||
{
|
||||
if (empty($value) or empty($value['n'])) {
|
||||
if (empty($value) || empty($value['n'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
$string = 'P'.$value['n'].$value['unit'];
|
||||
|
||||
|
||||
try {
|
||||
return new \DateInterval($string);
|
||||
} catch (\Exception $e) {
|
||||
throw new TransformationFailedException("Could not transform value "
|
||||
. "into DateInterval", 1542, $e);
|
||||
throw new TransformationFailedException(
|
||||
'Could not transform value into DateInterval',
|
||||
1542,
|
||||
$e
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,50 +1,23 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
* Copyright (C) 2016 Champs-Libres Coopérative <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Pagination;
|
||||
|
||||
/**
|
||||
* PageGenerator associated with a Paginator
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
* @author Champs Libres <info@champs-libres.coop>
|
||||
* PageGenerator associated with a Paginator.
|
||||
*/
|
||||
class PageGenerator implements \Iterator
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var Paginator
|
||||
*/
|
||||
protected $paginator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $current = 1;
|
||||
|
||||
public function __construct(Paginator $paginator)
|
||||
protected Paginator $paginator;
|
||||
|
||||
protected int $current = 1;
|
||||
|
||||
public function __construct(Paginator $paginator)
|
||||
{
|
||||
$this->paginator = $paginator;;
|
||||
}
|
||||
|
||||
|
||||
public function current()
|
||||
{
|
||||
return $this->paginator->getPage($current);
|
||||
@ -67,7 +40,7 @@ class PageGenerator implements \Iterator
|
||||
|
||||
public function valid()
|
||||
{
|
||||
return $this->current > 0
|
||||
return $this->current > 0
|
||||
&& $this->current <= $this->paginator->countPages();
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Repository;
|
||||
|
||||
use Chill\MainBundle\Entity\GroupCenter;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user