diff --git a/.changes/unreleased/Fixed-20230621-132851.yaml b/.changes/unreleased/Fixed-20230621-132851.yaml
deleted file mode 100644
index 89fb7cdd9..000000000
--- a/.changes/unreleased/Fixed-20230621-132851.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Fixed
-body: '[Accompanying period comments]: order comments from the most recent to the
- oldest, in the list'
-time: 2023-06-21T13:28:51.282714011+02:00
-custom:
- Issue: ""
diff --git a/.changes/unreleased/Fixed-20230621-135912.yaml b/.changes/unreleased/Fixed-20230621-135912.yaml
deleted file mode 100644
index 676d1c21b..000000000
--- a/.changes/unreleased/Fixed-20230621-135912.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-kind: Fixed
-body: 'Api: filter social action to keep only the currently activated'
-time: 2023-06-21T13:59:12.57760217+02:00
-custom:
- Issue: ""
diff --git a/.changes/unreleased/Fixed-20230621-141828.yaml b/.changes/unreleased/Fixed-20230621-141828.yaml
deleted file mode 100644
index 2c7f94488..000000000
--- a/.changes/unreleased/Fixed-20230621-141828.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-kind: Fixed
-body: Fix deletion and re-creation of filiation relationship
-time: 2023-06-21T14:18:28.437876316+02:00
-custom:
- Issue: "82"
diff --git a/.changes/unreleased/Fixed-20230628-170055.yaml b/.changes/unreleased/Fixed-20230628-170055.yaml
new file mode 100644
index 000000000..7f9ec3028
--- /dev/null
+++ b/.changes/unreleased/Fixed-20230628-170055.yaml
@@ -0,0 +1,6 @@
+kind: Fixed
+body: '[export] Rename label for CurrentActionFilter (on accompanying period work)
+ to make precision between "ouvert" and "sans date de fin"'
+time: 2023-06-28T17:00:55.206937751+02:00
+custom:
+ Issue: ""
diff --git a/.changes/unreleased/Fixed-20230629-124412.yaml b/.changes/unreleased/Fixed-20230629-124412.yaml
new file mode 100644
index 000000000..7fc3d3eb0
--- /dev/null
+++ b/.changes/unreleased/Fixed-20230629-124412.yaml
@@ -0,0 +1,6 @@
+kind: Fixed
+body: Force the db to have either a person_location or a address_location, and avoid
+ to have both also internally in the entity
+time: 2023-06-29T12:44:12.019663991+02:00
+custom:
+ Issue: ""
diff --git a/.changes/unreleased/Fixed-20230629-231503.yaml b/.changes/unreleased/Fixed-20230629-231503.yaml
new file mode 100644
index 000000000..e021d1fda
--- /dev/null
+++ b/.changes/unreleased/Fixed-20230629-231503.yaml
@@ -0,0 +1,5 @@
+kind: Fixed
+body: '[export] set rolling date on person age aggregator'
+time: 2023-06-29T23:15:03.20841309+02:00
+custom:
+ Issue: ""
diff --git a/.changes/unreleased/Fixed-20230630-171119.yaml b/.changes/unreleased/Fixed-20230630-171119.yaml
new file mode 100644
index 000000000..f3185ace2
--- /dev/null
+++ b/.changes/unreleased/Fixed-20230630-171119.yaml
@@ -0,0 +1,5 @@
+kind: Fixed
+body: '[export] fix list when a person locating a course is without address'
+time: 2023-06-30T17:11:19.454081914+02:00
+custom:
+ Issue: ""
diff --git a/.changes/unreleased/Fixed-20230630-171153.yaml b/.changes/unreleased/Fixed-20230630-171153.yaml
new file mode 100644
index 000000000..c09bd93d0
--- /dev/null
+++ b/.changes/unreleased/Fixed-20230630-171153.yaml
@@ -0,0 +1,5 @@
+kind: Fixed
+body: '[export] remove unused condition on course about duration participation'
+time: 2023-06-30T17:11:53.076615549+02:00
+custom:
+ Issue: ""
diff --git a/.changes/v2.2.2.md b/.changes/v2.2.2.md
new file mode 100644
index 000000000..61d194b6d
--- /dev/null
+++ b/.changes/v2.2.2.md
@@ -0,0 +1,5 @@
+## v2.2.2 - 2023-06-26
+### Fixed
+* [Accompanying period comments]: order comments from the most recent to the oldest, in the list
+* Api: filter social action to keep only the currently activated
+* ([#82](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/82)) Fix deletion and re-creation of filiation relationship
diff --git a/.changes/v2.3.0.md b/.changes/v2.3.0.md
new file mode 100644
index 000000000..827a338de
--- /dev/null
+++ b/.changes/v2.3.0.md
@@ -0,0 +1,42 @@
+## v2.3.0 - 2023-06-27
+### Feature
+* ([#110](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/110)) Edit saved exports options: the saved exports options (forms, filters, aggregators) are now editable.
+* ([#103](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/103)) Get an unified list of document in person and accompanying period context
+* [export] Set the default date of calculation of the accompanying period's list as "today"
+* Force accompanying period user history to be unique for the same period and stardate/enddate [:warning: may encounter migration issue]
+
+ If some issue is encountered during migration, use this SQL to find the line which are in conflict, examine the problem and delete some of the concerning line
+*
+ ```sql
+ -- to see the line which are in conflict with another one
+ SELECT o.*
+ FROM chill_person_accompanying_period_user_history o
+ JOIN chill_person_accompanying_period_user_history c ON o.id < c.id AND o.accompanyingperiod_id = c.accompanyingperiod_id
+ WHERE tsrange(o.startdate, o.enddate, '[)') && tsrange(c.startdate, c.enddate, '[)')
+ ORDER BY accompanyingperiod_id;
+ -- to examine line in conflict for a given accompanyingperiod_id (given by the previous query)
+ SELECT * FROM chill_person_accompanying_period_user_history WHERE accompanyingperiod_id = IIIIDDDD order by startdate, enddate;
+ ```
+* Rename label of filter in French: "parcours actif" => "parcours ouvert", and "filtrer les parcours ouverts" => "Filtrer les parcours dont la date d'ouverture"
+
+### Traduction francophone des principaux changements
+
+* Les exports enregistrés sont éditables par l'utilisateur;
+* L'onglet "Document" dans les parcours et les dossiers d'usager affiche désormais les documents ajoutés à différents endroits.
+
+ Pour les parcours, il s'agit de:
+
+ - documents ajoutés directement dans le parcours;
+ - documents des échanges;
+ - documents des rendez-vous;
+ - documents des évaluations;
+ - documents directement ajoutés dans le dossier des usagers concernés par le parcours;
+
+ Pour les usagers, il s'agit de:
+
+ - documents des échanges;
+ - documents des parcours;
+ - documents des rendez-vous;
+ - documents des actions, des échanges, des rendez-vous, des évaluations ajoutés dans les parcours.
+* Dans la liste des parcours, la date de calcul des éléments associés est "aujourd'hui" par défaut.
+* Dans les exports, renommage des libellés des filtres: "parcours actif" => "parcours ouvert", et "filtrer les parcours ouverts" => "Filtrer les parcours dont la date d'ouverture"
diff --git a/.changie.yaml b/.changie.yaml
index ba5454ce7..8a25ed695 100644
--- a/.changie.yaml
+++ b/.changie.yaml
@@ -5,8 +5,11 @@ changelogPath: CHANGELOG.md
versionExt: md
versionFormat: '## {{.Version}} - {{.Time.Format "2006-01-02"}}'
kindFormat: '### {{.Kind}}'
+# Note: it is possible to add a `.custom.Long` text manually into the yaml file produced by `changie new`. This will add a long description.
changeFormat: >-
- * {{ if not (eq .Custom.Issue "") }}([#{{ .Custom.Issue }}](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/{{ .Custom.Issue }})) {{ end }}{{.Body}}
+ * {{ if not (eq .Custom.Issue "") }}([#{{ .Custom.Issue }}](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/{{ .Custom.Issue }})) {{ end }}{{.Body}} {{ if not (eq .Custom.Long "") }}
+
+ {{ .Custom.Long }}{{ end }}
custom:
- key: Issue
label: Issue number (on chill-bundles repository) (optional)
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3f1d75ed5..aa1eff8b1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -34,6 +34,7 @@ variables:
stages:
- Composer install
- Tests
+ - Deploy
build:
stage: Composer install
@@ -121,3 +122,14 @@ unit_tests:
paths:
- bin
- tests/app/vendor/
+
+release:
+ stage: Deploy
+ image: registry.gitlab.com/gitlab-org/release-cli:latest
+ rules:
+ - if: $CI_COMMIT_TAG
+ script:
+ - echo "running release_job"
+ release:
+ tag_name: '$CI_COMMIT_TAG'
+ description: "./.changes/v$CI_COMMIT_TAG.md"
diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php
index 4b5bf98ee..31d64e600 100644
--- a/.php-cs-fixer.dist.php
+++ b/.php-cs-fixer.dist.php
@@ -13,6 +13,7 @@ $finder = PhpCsFixer\Finder::create();
$finder
->in(__DIR__.'/src')
+ ->in(__DIR__.'/utils')
->append([__FILE__])
->exclude(['docs/', 'tests/app'])
->notPath('tests/app')
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e223fa116..93ff93556 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,55 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
and is generated by [Changie](https://github.com/miniscruff/changie).
+## v2.3.0 - 2023-06-27
+### Feature
+* ([#110](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/110)) Edit saved exports options: the saved exports options (forms, filters, aggregators) are now editable.
+* ([#103](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/103)) Get an unified list of document in person and accompanying period context
+* [export] Set the default date of calculation of the accompanying period's list as "today"
+* Force accompanying period user history to be unique for the same period and stardate/enddate [:warning: may encounter migration issue]
+
+ If some issue is encountered during migration, use this SQL to find the line which are in conflict, examine the problem and delete some of the concerning line
+*
+ ```sql
+ -- to see the line which are in conflict with another one
+ SELECT o.*
+ FROM chill_person_accompanying_period_user_history o
+ JOIN chill_person_accompanying_period_user_history c ON o.id < c.id AND o.accompanyingperiod_id = c.accompanyingperiod_id
+ WHERE tsrange(o.startdate, o.enddate, '[)') && tsrange(c.startdate, c.enddate, '[)')
+ ORDER BY accompanyingperiod_id;
+ -- to examine line in conflict for a given accompanyingperiod_id (given by the previous query)
+ SELECT * FROM chill_person_accompanying_period_user_history WHERE accompanyingperiod_id = IIIIDDDD order by startdate, enddate;
+ ```
+* Rename label of filter in French: "parcours actif" => "parcours ouvert", and "filtrer les parcours ouverts" => "Filtrer les parcours dont la date d'ouverture"
+
+### Traduction francophone des principaux changements
+
+* Les exports enregistrés sont éditables par l'utilisateur;
+* L'onglet "Document" dans les parcours et les dossiers d'usager affiche désormais les documents ajoutés à différents endroits.
+
+ Pour les parcours, il s'agit de:
+
+ - documents ajoutés directement dans le parcours;
+ - documents des échanges;
+ - documents des rendez-vous;
+ - documents des évaluations;
+ - documents directement ajoutés dans le dossier des usagers concernés par le parcours;
+
+ Pour les usagers, il s'agit de:
+
+ - documents des échanges;
+ - documents des parcours;
+ - documents des rendez-vous;
+ - documents des actions, des échanges, des rendez-vous, des évaluations ajoutés dans les parcours.
+* Dans la liste des parcours, la date de calcul des éléments associés est "aujourd'hui" par défaut.
+* Dans les exports, renommage des libellés des filtres: "parcours actif" => "parcours ouvert", et "filtrer les parcours ouverts" => "Filtrer les parcours dont la date d'ouverture"
+
+## v2.2.2 - 2023-06-26
+### Fixed
+* [Accompanying period comments]: order comments from the most recent to the oldest, in the list
+* Api: filter social action to keep only the currently activated
+* ([#82](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/82)) Fix deletion and re-creation of filiation relationship
+
## v2.2.1 - 2023-06-19
### Fixed
* ([#114](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/114)) [notification on document evaluation] fix entityId and return path when adding a notification on a document in an evaluation
diff --git a/composer.json b/composer.json
index f6d3eb27a..a128b1b77 100644
--- a/composer.json
+++ b/composer.json
@@ -67,6 +67,7 @@
"fakerphp/faker": "^1.13",
"jangregor/phpstan-prophecy": "^1.0",
"nelmio/alice": "^3.8",
+ "nikic/php-parser": "^4.15",
"phpspec/prophecy-phpunit": "^2.0",
"phpstan/extension-installer": "^1.2",
"phpstan/phpstan": "^1.9",
@@ -103,14 +104,16 @@
"Chill\\ReportBundle\\": "src/Bundle/ChillReportBundle",
"Chill\\TaskBundle\\": "src/Bundle/ChillTaskBundle",
"Chill\\ThirdPartyBundle\\": "src/Bundle/ChillThirdPartyBundle",
- "Chill\\WopiBundle\\": "src/Bundle/ChillWopiBundle/src"
+ "Chill\\WopiBundle\\": "src/Bundle/ChillWopiBundle/src",
+ "Chill\\Utils\\Rector\\": "utils/rector/src"
}
},
"autoload-dev": {
"psr-4": {
"App\\": "tests/app/src/",
"Chill\\DocGeneratorBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests",
- "Chill\\WopiBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests"
+ "Chill\\WopiBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests",
+ "Chill\\Utils\\Rector\\Tests\\": "utils/rector/tests"
}
},
"config": {
diff --git a/docs/source/_static/code/exports/BirthdateFilter.php b/docs/source/_static/code/exports/BirthdateFilter.php
index 64c1d53a9..e25d8b42f 100644
--- a/docs/source/_static/code/exports/BirthdateFilter.php
+++ b/docs/source/_static/code/exports/BirthdateFilter.php
@@ -62,7 +62,6 @@ class BirthdateFilter implements ExportElementValidatedInterface, FilterInterfac
{
$builder->add('date_from', DateType::class, [
'label' => 'Born after this date',
- 'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
@@ -70,12 +69,15 @@ class BirthdateFilter implements ExportElementValidatedInterface, FilterInterfac
$builder->add('date_to', DateType::class, [
'label' => 'Born before this date',
- 'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
]);
}
+ public function getFormDefaultData(): array
+ {
+ return ['date_from' => new DateTime(), 'date_to' => new DateTime()];
+ }
// here, we create a simple string which will describe the action of
// the filter in the Response
diff --git a/docs/source/_static/code/exports/CountPerson.php b/docs/source/_static/code/exports/CountPerson.php
index afe19c73b..be800e52c 100644
--- a/docs/source/_static/code/exports/CountPerson.php
+++ b/docs/source/_static/code/exports/CountPerson.php
@@ -36,6 +36,10 @@ class CountPerson implements ExportInterface
{
// this export does not add any form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getAllowedFormattersTypes()
{
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
index 56b7c2228..62dbe0468 100644
--- a/phpstan.neon.dist
+++ b/phpstan.neon.dist
@@ -2,6 +2,7 @@ parameters:
level: 5
paths:
- src/
+ - utils/
tmpDir: .cache/
reportUnmatchedIgnoredErrors: false
excludePaths:
diff --git a/phpunit.rector.xml b/phpunit.rector.xml
new file mode 100644
index 000000000..f8d9d3a11
--- /dev/null
+++ b/phpunit.rector.xml
@@ -0,0 +1,29 @@
+
+
+
+
+ utils/rector/tests
+
+
+
+
+
+ utils/rector/src
+
+
+
diff --git a/rector.php b/rector.php
index ec9a0c684..c2e752c32 100644
--- a/rector.php
+++ b/rector.php
@@ -24,6 +24,9 @@ return static function (RectorConfig $rectorConfig): void {
LevelSetList::UP_TO_PHP_74
]);
+ // chill rules
+ $rectorConfig->rule(\Chill\Utils\Rector\Rector\ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector::class);
+
// skip some path...
$rectorConfig->skip([
// make rector stuck for some files
diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByActivityNumberAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByActivityNumberAggregator.php
index 5c6656009..c23db738e 100644
--- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByActivityNumberAggregator.php
+++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByActivityNumberAggregator.php
@@ -40,6 +40,10 @@ class ByActivityNumberAggregator implements AggregatorInterface
{
// No form needed
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data)
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByCreatorAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByCreatorAggregator.php
index 69149737b..917459de3 100644
--- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByCreatorAggregator.php
+++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByCreatorAggregator.php
@@ -52,6 +52,10 @@ class ByCreatorAggregator implements AggregatorInterface
{
// no form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data)
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialActionAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialActionAggregator.php
index 89732412d..1a75357ae 100644
--- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialActionAggregator.php
+++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialActionAggregator.php
@@ -57,6 +57,10 @@ class BySocialActionAggregator implements AggregatorInterface
{
// no form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data)
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialIssueAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialIssueAggregator.php
index 158e87664..9100a8c8f 100644
--- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialIssueAggregator.php
+++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialIssueAggregator.php
@@ -57,6 +57,10 @@ class BySocialIssueAggregator implements AggregatorInterface
{
// no form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data)
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByThirdpartyAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByThirdpartyAggregator.php
index c3ca6d59c..ac05b153c 100644
--- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByThirdpartyAggregator.php
+++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByThirdpartyAggregator.php
@@ -57,6 +57,10 @@ class ByThirdpartyAggregator implements AggregatorInterface
{
// no form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data)
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/CreatorScopeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/CreatorScopeAggregator.php
index 2c7ec1483..a4b5258e2 100644
--- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/CreatorScopeAggregator.php
+++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/CreatorScopeAggregator.php
@@ -57,6 +57,10 @@ class CreatorScopeAggregator implements AggregatorInterface
{
// no form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data)
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php
index b4b23dc0b..4ede5b4c4 100644
--- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php
+++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php
@@ -29,14 +29,6 @@ class DateAggregator implements AggregatorInterface
private const DEFAULT_CHOICE = 'year';
- private TranslatorInterface $translator;
-
- public function __construct(
- TranslatorInterface $translator
- ) {
- $this->translator = $translator;
- }
-
public function addRole(): ?string
{
return null;
@@ -84,9 +76,12 @@ class DateAggregator implements AggregatorInterface
'multiple' => false,
'expanded' => true,
'empty_data' => self::DEFAULT_CHOICE,
- 'data' => self::DEFAULT_CHOICE,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return ['frequency' => self::DEFAULT_CHOICE];
+ }
public function getLabels($key, array $values, $data)
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/LocationTypeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/LocationTypeAggregator.php
index ec4ce6315..c72609e2c 100644
--- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/LocationTypeAggregator.php
+++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/LocationTypeAggregator.php
@@ -57,6 +57,10 @@ class LocationTypeAggregator implements AggregatorInterface
{
// no form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data)
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityTypeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityTypeAggregator.php
index 7cd16718e..a74428b4a 100644
--- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityTypeAggregator.php
+++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityTypeAggregator.php
@@ -60,6 +60,10 @@ class ActivityTypeAggregator implements AggregatorInterface
{
// no form required for this aggregator
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data): Closure
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUserAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUserAggregator.php
index 9bde692c6..2fab2af83 100644
--- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUserAggregator.php
+++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUserAggregator.php
@@ -58,6 +58,10 @@ class ActivityUserAggregator implements AggregatorInterface
{
// nothing to add
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, $values, $data): Closure
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersAggregator.php
index 139f2743e..e1e9f161d 100644
--- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersAggregator.php
+++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersAggregator.php
@@ -56,6 +56,10 @@ class ActivityUsersAggregator implements AggregatorInterface
{
// nothing to add on the form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data)
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php
index 5741a0e58..721078989 100644
--- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php
+++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php
@@ -55,6 +55,10 @@ class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorI
{
// nothing to add in the form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data)
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php
index 15da300be..d7932e9e8 100644
--- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php
+++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php
@@ -55,6 +55,10 @@ class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\Aggregato
{
// nothing to add in the form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data)
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/PersonAggregators/ActivityReasonAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/PersonAggregators/ActivityReasonAggregator.php
index eaccf95cb..2537f2cf6 100644
--- a/src/Bundle/ChillActivityBundle/Export/Aggregator/PersonAggregators/ActivityReasonAggregator.php
+++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/PersonAggregators/ActivityReasonAggregator.php
@@ -110,6 +110,10 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
]
);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data)
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/SentReceivedAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/SentReceivedAggregator.php
index 5f772e156..ae1dae375 100644
--- a/src/Bundle/ChillActivityBundle/Export/Aggregator/SentReceivedAggregator.php
+++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/SentReceivedAggregator.php
@@ -47,6 +47,10 @@ class SentReceivedAggregator implements AggregatorInterface
{
// No form needed
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data): callable
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityDuration.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityDuration.php
index 34771d077..6930784d3 100644
--- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityDuration.php
+++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityDuration.php
@@ -39,6 +39,10 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface
public function buildForm(FormBuilderInterface $builder)
{
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getAllowedFormattersTypes(): array
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityVisitDuration.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityVisitDuration.php
index df21362cd..f1e926c64 100644
--- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityVisitDuration.php
+++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityVisitDuration.php
@@ -40,6 +40,10 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac
{
// TODO: Implement buildForm() method.
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getAllowedFormattersTypes(): array
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/CountActivity.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/CountActivity.php
index 6b7b1562d..d473a925a 100644
--- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/CountActivity.php
+++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/CountActivity.php
@@ -39,6 +39,10 @@ class CountActivity implements ExportInterface, GroupedExportInterface
public function buildForm(FormBuilderInterface $builder)
{
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getAllowedFormattersTypes(): array
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/ListActivity.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/ListActivity.php
index 026e16f90..9ed6bcda2 100644
--- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/ListActivity.php
+++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/ListActivity.php
@@ -44,6 +44,10 @@ class ListActivity implements ListInterface, GroupedExportInterface
{
$this->helper->buildForm($builder);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getAllowedFormattersTypes()
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityDuration.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityDuration.php
index e916cab54..8adb3b77f 100644
--- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityDuration.php
+++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityDuration.php
@@ -40,6 +40,10 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface
{
// TODO: Implement buildForm() method.
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getAllowedFormattersTypes(): array
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityVisitDuration.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityVisitDuration.php
index 18a47289c..cc424e68b 100644
--- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityVisitDuration.php
+++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityVisitDuration.php
@@ -40,6 +40,10 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac
{
// TODO: Implement buildForm() method.
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getAllowedFormattersTypes(): array
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/CountActivity.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/CountActivity.php
index 4246df173..6360251b3 100644
--- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/CountActivity.php
+++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/CountActivity.php
@@ -35,6 +35,10 @@ class CountActivity implements ExportInterface, GroupedExportInterface
public function buildForm(FormBuilderInterface $builder)
{
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getAllowedFormattersTypes()
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/ListActivity.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/ListActivity.php
index 60110c9a8..d14111ba7 100644
--- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/ListActivity.php
+++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/ListActivity.php
@@ -88,6 +88,10 @@ class ListActivity implements ListInterface, GroupedExportInterface
])],
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getAllowedFormattersTypes()
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/StatActivityDuration.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/StatActivityDuration.php
index 050034954..e68d47cd3 100644
--- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/StatActivityDuration.php
+++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/StatActivityDuration.php
@@ -53,6 +53,10 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
public function buildForm(FormBuilderInterface $builder)
{
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getAllowedFormattersTypes()
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ActivityTypeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ActivityTypeFilter.php
index c6616a4c6..4ffc3b38c 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ActivityTypeFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ActivityTypeFilter.php
@@ -68,6 +68,10 @@ class ActivityTypeFilter implements FilterInterface
'expanded' => true,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string'): array
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ByCreatorFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ByCreatorFilter.php
index 322393f32..add9c7c3d 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ByCreatorFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ByCreatorFilter.php
@@ -52,6 +52,10 @@ class ByCreatorFilter implements FilterInterface
'multiple' => true,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string'): array
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialActionFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialActionFilter.php
index d0c1b0fc7..08f6bbbc3 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialActionFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialActionFilter.php
@@ -60,6 +60,10 @@ class BySocialActionFilter implements FilterInterface
'multiple' => true,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string'): array
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialIssueFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialIssueFilter.php
index bbb882a65..bd6e2ef4a 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialIssueFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialIssueFilter.php
@@ -60,6 +60,10 @@ class BySocialIssueFilter implements FilterInterface
'multiple' => true,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string'): array
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/EmergencyFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/EmergencyFilter.php
index b79c2ca10..807ba3903 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/EmergencyFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/EmergencyFilter.php
@@ -68,9 +68,12 @@ class EmergencyFilter implements FilterInterface
'multiple' => false,
'expanded' => true,
'empty_data' => self::DEFAULT_CHOICE,
- 'data' => self::DEFAULT_CHOICE,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return ['accepted_emergency' => self::DEFAULT_CHOICE];
+ }
public function describeAction($data, $format = 'string'): array
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/HasNoActivityFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/HasNoActivityFilter.php
index 570f42ae0..b5dab4009 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/HasNoActivityFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/HasNoActivityFilter.php
@@ -44,6 +44,10 @@ class HasNoActivityFilter implements FilterInterface
{
//no form needed
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string'): array
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationFilter.php
index 3d69d1633..312f3a6a0 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationFilter.php
@@ -46,6 +46,10 @@ class LocationFilter implements FilterInterface
'label' => 'pick location',
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string'): array
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationTypeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationTypeFilter.php
index 5fe928b6c..1c3415460 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationTypeFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationTypeFilter.php
@@ -65,6 +65,10 @@ class LocationTypeFilter implements FilterInterface
//'label' => false,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string'): array
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/SentReceivedFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/SentReceivedFilter.php
index 8daa7a781..0f2a1c7e4 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/SentReceivedFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/SentReceivedFilter.php
@@ -69,9 +69,12 @@ class SentReceivedFilter implements FilterInterface
'multiple' => false,
'expanded' => true,
'empty_data' => self::DEFAULT_CHOICE,
- 'data' => self::DEFAULT_CHOICE,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return ['accepted_sentreceived' => self::DEFAULT_CHOICE];
+ }
public function describeAction($data, $format = 'string'): array
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserFilter.php
index 6350f3ace..9ae988579 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserFilter.php
@@ -61,6 +61,10 @@ class UserFilter implements FilterInterface
'label' => 'Creators',
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string'): array
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserScopeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserScopeFilter.php
index 4319c100a..adb1e94f1 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserScopeFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserScopeFilter.php
@@ -71,6 +71,10 @@ class UserScopeFilter implements FilterInterface
'expanded' => true,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string'): array
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ActivityDateFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ActivityDateFilter.php
index f2216c929..e582acc12 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/ActivityDateFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/ActivityDateFilter.php
@@ -80,11 +80,9 @@ class ActivityDateFilter implements FilterInterface
$builder
->add('date_from', PickRollingDateType::class, [
'label' => 'Activities after this date',
- 'data' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START),
])
->add('date_to', PickRollingDateType::class, [
'label' => 'Activities before this date',
- 'data' => new RollingDate(RollingDate::T_TODAY),
]);
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
@@ -127,6 +125,10 @@ class ActivityDateFilter implements FilterInterface
}
});
}
+ public function getFormDefaultData(): array
+ {
+ return ['date_from' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), 'date_to' => new RollingDate(RollingDate::T_TODAY)];
+ }
public function describeAction($data, $format = 'string')
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ActivityTypeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ActivityTypeFilter.php
index b9d39c3ce..8dfcb543c 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/ActivityTypeFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/ActivityTypeFilter.php
@@ -78,6 +78,10 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
],
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string')
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ActivityUsersFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ActivityUsersFilter.php
index 2f6cd8462..a63ca2629 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/ActivityUsersFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/ActivityUsersFilter.php
@@ -56,6 +56,10 @@ class ActivityUsersFilter implements FilterInterface
'label' => 'Users',
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string')
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/PersonFilters/ActivityReasonFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/PersonFilters/ActivityReasonFilter.php
index c55d579e4..31cfde6b6 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/PersonFilters/ActivityReasonFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/PersonFilters/ActivityReasonFilter.php
@@ -82,6 +82,10 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
'expanded' => false,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string')
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/PersonFilters/PersonHavingActivityBetweenDateFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/PersonFilters/PersonHavingActivityBetweenDateFilter.php
index e3c85fe9c..490b5fd0c 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/PersonFilters/PersonHavingActivityBetweenDateFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/PersonFilters/PersonHavingActivityBetweenDateFilter.php
@@ -112,7 +112,6 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
{
$builder->add('date_from', DateType::class, [
'label' => 'Implied in an activity after this date',
- 'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
@@ -120,7 +119,6 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
$builder->add('date_to', DateType::class, [
'label' => 'Implied in an activity before this date',
- 'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
@@ -130,7 +128,6 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
'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',
@@ -176,6 +173,10 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
}
});
}
+ public function getFormDefaultData(): array
+ {
+ return ['date_from' => new DateTime(), 'date_to' => new DateTime(), 'reasons' => $this->activityReasonRepository->findAll()];
+ }
public function describeAction($data, $format = 'string')
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/UsersJobFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/UsersJobFilter.php
index b52ef441c..e85b2d247 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/UsersJobFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/UsersJobFilter.php
@@ -60,6 +60,10 @@ class UsersJobFilter implements FilterInterface
'expanded' => true,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string')
{
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/UsersScopeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/UsersScopeFilter.php
index 61b12264e..07ff509ce 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/UsersScopeFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/UsersScopeFilter.php
@@ -67,6 +67,10 @@ class UsersScopeFilter implements FilterInterface
'expanded' => true,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string')
{
diff --git a/src/Bundle/ChillActivityBundle/Repository/ActivityDocumentACLAwareRepository.php b/src/Bundle/ChillActivityBundle/Repository/ActivityDocumentACLAwareRepository.php
new file mode 100644
index 000000000..ce70409ba
--- /dev/null
+++ b/src/Bundle/ChillActivityBundle/Repository/ActivityDocumentACLAwareRepository.php
@@ -0,0 +1,198 @@
+buildBaseFetchQueryActivityDocumentLinkedToPersonFromPersonContext($person, $startDate, $endDate, $content);
+
+ return $this->addFetchQueryByPersonACL($query, $person);
+ }
+
+ public function buildBaseFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery
+ {
+ $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class);
+ $activityMetadata = $this->em->getClassMetadata(Activity::class);
+
+ $query = new FetchQuery(
+ PersonActivityGenericDocProvider::KEY,
+ sprintf('jsonb_build_object(\'id\', stored_obj.%s, \'activity_id\', activity.%s)', $storedObjectMetadata->getSingleIdentifierColumnName(), $activityMetadata->getSingleIdentifierColumnName()),
+ sprintf('stored_obj.%s', $storedObjectMetadata->getColumnName('createdAt')),
+ sprintf('%s AS stored_obj', $storedObjectMetadata->getSchemaName().'.'.$storedObjectMetadata->getTableName())
+ );
+
+ $query->addJoinClause(
+ 'JOIN public.activity_storedobject activity_doc ON activity_doc.storedobject_id = stored_obj.id'
+ );
+
+ $query->addJoinClause(
+ 'JOIN public.activity activity ON activity.id = activity_doc.activity_id'
+ );
+
+ $query->addWhereClause(
+ sprintf('activity.%s = ?', $activityMetadata->getSingleAssociationJoinColumnName('person')),
+ [$person->getId()],
+ [Types::INTEGER]
+ );
+
+ return $this->addWhereClauses($query, $startDate, $endDate, $content);
+ }
+
+ public function buildFetchQueryActivityDocumentLinkedToAccompanyingPeriodFromPersonContext(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery
+ {
+ $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class);
+ $activityMetadata = $this->em->getClassMetadata(Activity::class);
+
+ $query = new FetchQuery(
+ AccompanyingPeriodActivityGenericDocProvider::KEY,
+ sprintf('jsonb_build_object(\'id\', stored_obj.%s, \'activity_id\', activity.%s)', $storedObjectMetadata->getSingleIdentifierColumnName(), $activityMetadata->getSingleIdentifierColumnName()),
+ sprintf('stored_obj.%s', $storedObjectMetadata->getColumnName('createdAt')),
+ sprintf('%s AS stored_obj', $storedObjectMetadata->getSchemaName().'.'.$storedObjectMetadata->getTableName())
+ );
+
+ $query->addJoinClause(
+ 'JOIN public.activity_storedobject activity_doc ON activity_doc.storedobject_id = stored_obj.id'
+ );
+
+ $query->addJoinClause(
+ 'JOIN public.activity activity ON activity.id = activity_doc.activity_id'
+ );
+
+ // add documents of activities from parcours context
+ $or = [];
+ $orParams = [];
+ $orTypes = [];
+ foreach ($person->getAccompanyingPeriodParticipations() as $participation) {
+ if (!$this->security->isGranted(ActivityVoter::SEE, $participation->getAccompanyingPeriod())) {
+ continue;
+ }
+
+ $or[] = sprintf(
+ '(activity.%s = ? AND stored_obj.%s BETWEEN ?::date AND COALESCE(?::date, \'infinity\'::date))',
+ $activityMetadata->getSingleAssociationJoinColumnName('accompanyingPeriod'),
+ $storedObjectMetadata->getColumnName('createdAt')
+ );
+ $orParams = [...$orParams, $participation->getAccompanyingPeriod()->getId(),
+ DateTimeImmutable::createFromInterface($participation->getStartDate()),
+ null === $participation->getEndDate() ? null : DateTimeImmutable::createFromInterface($participation->getEndDate())];
+ $orTypes = [...$orTypes, Types::INTEGER, Types::DATE_IMMUTABLE, Types::DATE_IMMUTABLE];
+ }
+
+ if ([] === $or) {
+ $query->addWhereClause('TRUE = FALSE');
+
+ return $query;
+ }
+
+ $query->addWhereClause(sprintf('(%s)', implode(' OR ', $or)), $orParams, $orTypes);
+
+ return $this->addWhereClauses($query, $startDate, $endDate, $content);
+ }
+
+ private function addWhereClauses(FetchQuery $query, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery
+ {
+ $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class);
+
+ if (null !== $startDate) {
+ $query->addWhereClause(
+ sprintf('stored_obj.%s >= ?', $storedObjectMetadata->getColumnName('createdAt')),
+ [$startDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $endDate) {
+ $query->addWhereClause(
+ sprintf('stored_obj.%s < ?', $storedObjectMetadata->getColumnName('createdAt')),
+ [$endDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $content and '' !== $content) {
+ $query->addWhereClause(
+ 'stored_obj.title ilike ?',
+ ['%' . $content . '%'],
+ [Types::STRING]
+ );
+ }
+
+ return $query;
+ }
+
+ private function addFetchQueryByPersonACL(FetchQuery $fetchQuery, Person $person): FetchQuery
+ {
+ $activityMetadata = $this->em->getClassMetadata(Activity::class);
+
+ $reachableScopes = [];
+
+ foreach ($this->centerResolverManager->resolveCenters($person) as $center) {
+ $reachableScopes = [
+ ...$reachableScopes,
+ ...$this->authorizationHelperForCurrentUser->getReachableScopes(ActivityVoter::SEE, $center)
+ ];
+ }
+
+ if ([] === $reachableScopes) {
+ $fetchQuery->addWhereClause('FALSE = TRUE');
+
+ return $fetchQuery;
+ }
+
+ $fetchQuery->addWhereClause(
+ sprintf(
+ 'activity.%s IN (%s)',
+ $activityMetadata->getSingleAssociationJoinColumnName('scope'),
+ implode(', ', array_fill(0, count($reachableScopes), '?'))
+ ),
+ array_map(static fn (Scope $s) => $s->getId(), $reachableScopes),
+ array_fill(0, count($reachableScopes), Types::INTEGER)
+ );
+
+ return $fetchQuery;
+ }
+}
diff --git a/src/Bundle/ChillActivityBundle/Repository/ActivityDocumentACLAwareRepositoryInterface.php b/src/Bundle/ChillActivityBundle/Repository/ActivityDocumentACLAwareRepositoryInterface.php
new file mode 100644
index 000000000..9f4a9c0f8
--- /dev/null
+++ b/src/Bundle/ChillActivityBundle/Repository/ActivityDocumentACLAwareRepositoryInterface.php
@@ -0,0 +1,37 @@
+
+
+
+ {% if document.isPending %}
+
{{ 'docgen.Doc generation is pending'|trans }}
+ {% elseif document.isFailure %}
+
{{ 'docgen.Doc generation failed'|trans }}
+ {% endif %}
+
+
+ {% if activity.accompanyingPeriod is not null and context == 'person' %}
+
+ {{ activity.accompanyingPeriod.id }}
+
+ {% endif %}
+
+
+
+ {{ activity.type.name | localize_translatable_string }}
+ {% if activity.emergency %}
+ {{ 'Emergency'|trans|upper }}
+ {% endif %}
+
+
+
+
+ {{ document.title|chill_print_or_message("No title") }}
+
+ {% if document.hasTemplate %}
+
+
{{ document.template.name|localize_translatable_string }}
+
+ {% endif %}
+
+
+
+
+
+ {{ document.createdAt|format_date('short') }}
+
+
+
+
+
+
+
+
+ {{ mmm.createdBy(document) }}
+
+
+ {% if is_granted('CHILL_ACTIVITY_SEE_DETAILS', activity) %}
+ -
+ {{ document|chill_document_button_group(document.title, is_granted('CHILL_ACTIVITY_UPDATE', activity), {small: false}) }}
+
+ {% endif %}
+ {% if is_granted('CHILL_ACTIVITY_SEE', activity)%}
+ -
+
+
+ {% endif %}
+ {% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %}
+ -
+
+
+ {% endif %}
+
+
+
+
diff --git a/src/Bundle/ChillActivityBundle/Service/GenericDoc/Providers/AccompanyingPeriodActivityGenericDocProvider.php b/src/Bundle/ChillActivityBundle/Service/GenericDoc/Providers/AccompanyingPeriodActivityGenericDocProvider.php
new file mode 100644
index 000000000..334b5d2df
--- /dev/null
+++ b/src/Bundle/ChillActivityBundle/Service/GenericDoc/Providers/AccompanyingPeriodActivityGenericDocProvider.php
@@ -0,0 +1,114 @@
+em->getClassMetadata(StoredObject::class);
+ $activityMetadata = $this->em->getClassMetadata(Activity::class);
+
+ $query = new FetchQuery(
+ self::KEY,
+ sprintf("jsonb_build_object('id', doc_obj.%s, 'activity_id', activity.%s)", $storedObjectMetadata->getSingleIdentifierColumnName(), $activityMetadata->getSingleIdentifierColumnName()),
+ 'doc_obj.'.$storedObjectMetadata->getColumnName('createdAt'),
+ $storedObjectMetadata->getSchemaName().'.'.$storedObjectMetadata->getTableName().' AS doc_obj'
+ );
+
+ $query->addJoinClause(
+ 'JOIN public.activity_storedobject activity_doc ON activity_doc.storedobject_id = doc_obj.id'
+ );
+
+ $query->addJoinClause(
+ 'JOIN public.activity activity ON activity.id = activity_doc.activity_id'
+ );
+
+ $query->addWhereClause(
+ 'activity.accompanyingperiod_id = ?',
+ [$accompanyingPeriod->getId()],
+ [Types::INTEGER]
+ );
+
+ if (null !== $startDate) {
+ $query->addWhereClause(
+ sprintf('doc_obj.%s >= ?', $storedObjectMetadata->getColumnName('createdAt')),
+ [$startDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $endDate) {
+ $query->addWhereClause(
+ sprintf('doc_obj.%s < ?', $storedObjectMetadata->getColumnName('createdAt')),
+ [$endDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $content) {
+ $query->addWhereClause(
+ 'doc_obj.title ilike ?',
+ ['%' . $content . '%'],
+ [Types::STRING]
+ );
+ }
+
+ return $query;
+ }
+
+ /**
+ * @param AccompanyingPeriod $accompanyingPeriod
+ * @return bool
+ */
+ public function isAllowedForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): bool
+ {
+ return $this->security->isGranted(ActivityVoter::SEE, $accompanyingPeriod);
+ }
+
+ public function isAllowedForPerson(Person $person): bool
+ {
+ return $this->security->isGranted(AccompanyingPeriodVoter::SEE, $person);
+ }
+
+ public function buildFetchQueryForPerson(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null, ?string $origin = null): FetchQueryInterface
+ {
+ return $this->activityDocumentACLAwareRepository
+ ->buildFetchQueryActivityDocumentLinkedToAccompanyingPeriodFromPersonContext($person, $startDate, $endDate, $content);
+ }
+}
diff --git a/src/Bundle/ChillActivityBundle/Service/GenericDoc/Providers/PersonActivityGenericDocProvider.php b/src/Bundle/ChillActivityBundle/Service/GenericDoc/Providers/PersonActivityGenericDocProvider.php
new file mode 100644
index 000000000..cf96449ab
--- /dev/null
+++ b/src/Bundle/ChillActivityBundle/Service/GenericDoc/Providers/PersonActivityGenericDocProvider.php
@@ -0,0 +1,53 @@
+personActivityDocumentACLAwareRepository->buildFetchQueryActivityDocumentLinkedToPersonFromPersonContext(
+ $person,
+ $startDate,
+ $endDate,
+ $content
+ );
+ }
+
+ /**
+ * @param Person $person
+ * @return bool
+ */
+ public function isAllowedForPerson(Person $person): bool
+ {
+ return $this->security->isGranted(ActivityVoter::SEE, $person);
+ }
+}
diff --git a/src/Bundle/ChillActivityBundle/Service/GenericDoc/Renderers/AccompanyingPeriodActivityGenericDocRenderer.php b/src/Bundle/ChillActivityBundle/Service/GenericDoc/Renderers/AccompanyingPeriodActivityGenericDocRenderer.php
new file mode 100644
index 000000000..c465dbca1
--- /dev/null
+++ b/src/Bundle/ChillActivityBundle/Service/GenericDoc/Renderers/AccompanyingPeriodActivityGenericDocRenderer.php
@@ -0,0 +1,52 @@
+objectRepository = $storedObjectRepository;
+ $this->activityRepository = $activityRepository;
+ }
+
+ public function supports(GenericDocDTO $genericDocDTO, $options = []): bool
+ {
+ return $genericDocDTO->key === AccompanyingPeriodActivityGenericDocProvider::KEY || $genericDocDTO->key === PersonActivityGenericDocProvider::KEY;
+ }
+
+ public function getTemplate(GenericDocDTO $genericDocDTO, $options = []): string
+ {
+ return '@ChillActivity/GenericDoc/activity_document.html.twig';
+ }
+
+ public function getTemplateData(GenericDocDTO $genericDocDTO, $options = []): array
+ {
+ return [
+ 'activity' => $this->activityRepository->find($genericDocDTO->identifiers['activity_id']),
+ 'document' => $this->objectRepository->find($genericDocDTO->identifiers['id']),
+ 'context' => $genericDocDTO->getContext(),
+ ];
+ }
+}
diff --git a/src/Bundle/ChillActivityBundle/Tests/Repository/ActivityDocumentACLAwareRepositoryTest.php b/src/Bundle/ChillActivityBundle/Tests/Repository/ActivityDocumentACLAwareRepositoryTest.php
new file mode 100644
index 000000000..ce4f318e3
--- /dev/null
+++ b/src/Bundle/ChillActivityBundle/Tests/Repository/ActivityDocumentACLAwareRepositoryTest.php
@@ -0,0 +1,126 @@
+entityManager = self::$container->get(EntityManagerInterface::class);
+ $this->centerResolverManager = self::$container->get(CenterResolverManagerInterface::class);
+ $this->authorizationHelperForCurrentUser = self::$container->get(AuthorizationHelperForCurrentUserInterface::class);
+ $this->security = self::$container->get(Security::class);
+ }
+
+ /**
+ * @dataProvider provideDataForPerson
+ */
+ public function testBuildFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, array $reachableScopes, bool $_unused, ?\DateTimeImmutable $startDate, ?\DateTimeImmutable $endDate, ?string $content): void
+ {
+ $authorizationHelper = $this->prophesize(AuthorizationHelperForCurrentUserInterface::class);
+ $authorizationHelper->getReachableScopes(ActivityVoter::SEE, Argument::any())
+ ->willReturn($reachableScopes);
+
+ $repository = new ActivityDocumentACLAwareRepository(
+ $this->entityManager,
+ $this->centerResolverManager,
+ $authorizationHelper->reveal(),
+ $this->security
+ );
+
+ $query = $repository->buildFetchQueryActivityDocumentLinkedToPersonFromPersonContext($person, $startDate, $endDate, $content);
+ ['sql' => $sql, 'params' => $params, 'types' => $types] = (new FetchQueryToSqlBuilder())->toSql($query);
+
+ $nb = $this->entityManager->getConnection()->fetchOne("SELECT COUNT(*) FROM ({$sql}) sq", $params, $types);
+
+ self::assertIsInt($nb);
+ }
+
+ /**
+ * @dataProvider provideDataForPerson
+ */
+ public function testBuildFetchQueryActivityDocumentLinkedToAccompanyingPeriodFromPersonContext(Person $person, array $_unused, bool $canSeePeriod, ?\DateTimeImmutable $startDate, ?\DateTimeImmutable $endDate, ?string $content): void
+ {
+ $security = $this->prophesize(Security::class);
+ $security->isGranted(ActivityVoter::SEE, Argument::type(AccompanyingPeriod::class))
+ ->willReturn($canSeePeriod);
+
+ $repository = new ActivityDocumentACLAwareRepository(
+ $this->entityManager,
+ $this->centerResolverManager,
+ $this->authorizationHelperForCurrentUser,
+ $security->reveal()
+ );
+
+ $query = $repository->buildFetchQueryActivityDocumentLinkedToAccompanyingPeriodFromPersonContext($person, $startDate, $endDate, $content);
+
+ ['sql' => $sql, 'params' => $params, 'types' => $types] = (new FetchQueryToSqlBuilder())->toSql($query);
+
+ $nb = $this->entityManager->getConnection()->fetchOne("SELECT COUNT(*) FROM ({$sql}) sq", $params, $types);
+
+ self::assertIsInt($nb);
+ }
+
+ public function provideDataForPerson(): iterable
+ {
+ $this->setUp();
+
+ if (null === $person = $this->entityManager->createQuery("SELECT p FROM " . Person::class . " p WHERE SIZE(p.accompanyingPeriodParticipations) > 0 ")
+ ->setMaxResults(1)
+ ->getSingleResult()) {
+ throw new \RuntimeException("no person in dtabase");
+ }
+
+ if ([] === $scopes = $this->entityManager->createQuery("SELECT s FROM " . Scope::class . " s ")->setMaxResults(5)->getResult()) {
+ throw new \RuntimeException("no scopes in database");
+ }
+
+ yield [$person, [], true, null, null, null];
+ yield [$person, $scopes, true, null, null, null];
+ yield [$person, $scopes, true, new \DateTimeImmutable("1 month ago"), null, null];
+ yield [$person, $scopes, true, new \DateTimeImmutable("1 month ago"), new \DateTimeImmutable("1 week ago"), null];
+ yield [$person, $scopes, true, new \DateTimeImmutable("1 month ago"), new \DateTimeImmutable("1 week ago"), "content"];
+ yield [$person, $scopes, true, null, new \DateTimeImmutable("1 week ago"), "content"];
+ yield [$person, [], true, new \DateTimeImmutable("1 month ago"), new \DateTimeImmutable("1 week ago"), "content"];
+ }
+
+}
diff --git a/src/Bundle/ChillActivityBundle/config/services.yaml b/src/Bundle/ChillActivityBundle/config/services.yaml
index d55f86d4f..18be76ec9 100644
--- a/src/Bundle/ChillActivityBundle/config/services.yaml
+++ b/src/Bundle/ChillActivityBundle/config/services.yaml
@@ -38,3 +38,6 @@ services:
Chill\ActivityBundle\Service\EntityInfo\:
resource: '../Service/EntityInfo/'
+
+ Chill\ActivityBundle\Service\GenericDoc\:
+ resource: '../Service/GenericDoc/'
diff --git a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml
index 1229494bb..c53a04f31 100644
--- a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml
+++ b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml
@@ -380,3 +380,8 @@ export:
is sent: envoyé
is received: reçu
Group activity by sentreceived: Grouper les échanges par envoyé / reçu
+
+generic_doc:
+ filter:
+ keys:
+ accompanying_period_activity_document: Document des échanges des parcours
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByActivityTypeAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByActivityTypeAggregator.php
index 32418e3c3..8ae43534d 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByActivityTypeAggregator.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByActivityTypeAggregator.php
@@ -50,6 +50,10 @@ class ByActivityTypeAggregator implements AggregatorInterface
{
// No form needed
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data)
{
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php
index d2fe7c2f2..f09a704e2 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php
@@ -57,6 +57,10 @@ class ByUserJobAggregator implements AggregatorInterface
{
// nothing to add in the form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data)
{
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php
index 6c06ee756..3dd465db2 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php
@@ -57,6 +57,10 @@ class ByUserScopeAggregator implements AggregatorInterface
{
// nothing to add in the form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data)
{
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/AvgAsideActivityDuration.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/AvgAsideActivityDuration.php
index f3db629cb..2b28062f6 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/AvgAsideActivityDuration.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/AvgAsideActivityDuration.php
@@ -34,6 +34,10 @@ class AvgAsideActivityDuration implements ExportInterface, GroupedExportInterfac
public function buildForm(FormBuilderInterface $builder)
{
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getAllowedFormattersTypes(): array
{
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/CountAsideActivity.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/CountAsideActivity.php
index 9204fad4b..91210f764 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/CountAsideActivity.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/CountAsideActivity.php
@@ -34,6 +34,10 @@ class CountAsideActivity implements ExportInterface, GroupedExportInterface
public function buildForm(FormBuilderInterface $builder)
{
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getAllowedFormattersTypes(): array
{
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php
index aee168174..b46e120b5 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php
@@ -73,6 +73,10 @@ final class ListAsideActivity implements ListInterface, GroupedExportInterface
public function buildForm(FormBuilderInterface $builder)
{
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getAllowedFormattersTypes()
{
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/SumAsideActivityDuration.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/SumAsideActivityDuration.php
index af17a2591..741f129f1 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/SumAsideActivityDuration.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/SumAsideActivityDuration.php
@@ -34,6 +34,10 @@ class SumAsideActivityDuration implements ExportInterface, GroupedExportInterfac
public function buildForm(FormBuilderInterface $builder)
{
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getAllowedFormattersTypes(): array
{
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByActivityTypeFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByActivityTypeFilter.php
index 3ad8e0e93..3d389f5b3 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByActivityTypeFilter.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByActivityTypeFilter.php
@@ -76,6 +76,10 @@ class ByActivityTypeFilter implements FilterInterface
},
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string'): array
{
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByDateFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByDateFilter.php
index 7a1b6f4dc..98a254bc4 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByDateFilter.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByDateFilter.php
@@ -72,11 +72,9 @@ class ByDateFilter implements FilterInterface
$builder
->add('date_from', PickRollingDateType::class, [
'label' => 'export.filter.Aside activities after this date',
- 'data' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START),
])
->add('date_to', PickRollingDateType::class, [
'label' => 'export.filter.Aside activities before this date',
- 'data' => new RollingDate(RollingDate::T_TODAY),
]);
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
@@ -119,6 +117,10 @@ class ByDateFilter implements FilterInterface
}
});
}
+ public function getFormDefaultData(): array
+ {
+ return ['date_from' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), 'date_to' => new RollingDate(RollingDate::T_TODAY)];
+ }
public function describeAction($data, $format = 'string'): array
{
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserFilter.php
index 795c813cd..2858d3417 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserFilter.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserFilter.php
@@ -53,6 +53,10 @@ class ByUserFilter implements FilterInterface
'label' => 'Creators',
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string'): array
{
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php
index 86194b123..55f477768 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php
@@ -60,6 +60,10 @@ class ByUserJobFilter implements FilterInterface
'expanded' => true,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string')
{
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php
index 4342e11eb..8fa51866d 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php
@@ -67,6 +67,10 @@ class ByUserScopeFilter implements FilterInterface
'expanded' => true,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string')
{
diff --git a/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml b/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml
index cc428390c..25d07bd22 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml
+++ b/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml
@@ -176,11 +176,12 @@ export:
agent_id: Utilisateur
creator_id: Créateur
main_scope: Service principal de l'utilisateur
- main_center: Centre principal de l'utilisteur
+ main_center: Centre principal de l'utilisateur
aside_activity_type: Catégorie d'activité annexe
date: Date
duration: Durée
note: Note
+ id: Identifiant
Exports of aside activities: Exports des activités annexes
Count aside activities: Nombre d'activités annexes
diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/AgentAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/AgentAggregator.php
index e1de9f399..1b1b170b8 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/AgentAggregator.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/AgentAggregator.php
@@ -58,6 +58,10 @@ final class AgentAggregator implements AggregatorInterface
{
// no form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data): Closure
{
diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/CancelReasonAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/CancelReasonAggregator.php
index 611cb6d79..a9967c470 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/CancelReasonAggregator.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/CancelReasonAggregator.php
@@ -59,6 +59,10 @@ class CancelReasonAggregator implements AggregatorInterface
{
// no form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data): Closure
{
diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php
index 23292a5b0..51291b49e 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php
@@ -58,6 +58,10 @@ final class JobAggregator implements AggregatorInterface
{
// no form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data): Closure
{
diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/LocationAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/LocationAggregator.php
index 940000f47..952d0c5d5 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/LocationAggregator.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/LocationAggregator.php
@@ -52,6 +52,10 @@ final class LocationAggregator implements AggregatorInterface
{
// no form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data): Closure
{
diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/LocationTypeAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/LocationTypeAggregator.php
index 6574e3934..a9b369af0 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/LocationTypeAggregator.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/LocationTypeAggregator.php
@@ -58,6 +58,10 @@ final class LocationTypeAggregator implements AggregatorInterface
{
// no form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data): Closure
{
diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/MonthYearAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/MonthYearAggregator.php
index 7b2a5e898..b3c2aaf19 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/MonthYearAggregator.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/MonthYearAggregator.php
@@ -40,6 +40,10 @@ class MonthYearAggregator implements AggregatorInterface
{
// No form needed
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data): Closure
{
diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php
index 3aff3e0d8..01874b0e2 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php
@@ -58,6 +58,10 @@ final class ScopeAggregator implements AggregatorInterface
{
// no form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data): Closure
{
diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/UrgencyAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/UrgencyAggregator.php
index ad5910461..66ab8b42e 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/UrgencyAggregator.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/UrgencyAggregator.php
@@ -56,6 +56,10 @@ class UrgencyAggregator implements AggregatorInterface
{
// no form
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getLabels($key, array $values, $data): Closure
{
diff --git a/src/Bundle/ChillCalendarBundle/Export/Export/CountCalendars.php b/src/Bundle/ChillCalendarBundle/Export/Export/CountCalendars.php
index 9d3f00f99..e0391948e 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Export/CountCalendars.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Export/CountCalendars.php
@@ -36,6 +36,10 @@ class CountCalendars implements ExportInterface, GroupedExportInterface
{
// No form necessary
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getAllowedFormattersTypes(): array
{
diff --git a/src/Bundle/ChillCalendarBundle/Export/Export/StatCalendarAvgDuration.php b/src/Bundle/ChillCalendarBundle/Export/Export/StatCalendarAvgDuration.php
index 14dd42d6b..dcbfb695b 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Export/StatCalendarAvgDuration.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Export/StatCalendarAvgDuration.php
@@ -36,6 +36,10 @@ class StatCalendarAvgDuration implements ExportInterface, GroupedExportInterface
{
// no form needed
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getAllowedFormattersTypes(): array
{
diff --git a/src/Bundle/ChillCalendarBundle/Export/Export/StatCalendarSumDuration.php b/src/Bundle/ChillCalendarBundle/Export/Export/StatCalendarSumDuration.php
index 1d31bfa26..7f509a896 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Export/StatCalendarSumDuration.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Export/StatCalendarSumDuration.php
@@ -36,6 +36,10 @@ class StatCalendarSumDuration implements ExportInterface, GroupedExportInterface
{
// no form needed
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function getAllowedFormattersTypes(): array
{
diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/AgentFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/AgentFilter.php
index b58cee594..0cef89c20 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Filter/AgentFilter.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Filter/AgentFilter.php
@@ -63,6 +63,10 @@ class AgentFilter implements FilterInterface
'expanded' => true,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string'): array
{
diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/BetweenDatesFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/BetweenDatesFilter.php
index 59019ac03..4260ecd99 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Filter/BetweenDatesFilter.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Filter/BetweenDatesFilter.php
@@ -60,12 +60,12 @@ class BetweenDatesFilter implements FilterInterface
public function buildForm(FormBuilderInterface $builder)
{
$builder
- ->add('date_from', PickRollingDateType::class, [
- 'data' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START),
- ])
- ->add('date_to', PickRollingDateType::class, [
- 'data' => new RollingDate(RollingDate::T_TODAY),
- ]);
+ ->add('date_from', PickRollingDateType::class, [])
+ ->add('date_to', PickRollingDateType::class, []);
+ }
+ public function getFormDefaultData(): array
+ {
+ return ['date_from' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), 'date_to' => new RollingDate(RollingDate::T_TODAY)];
}
public function describeAction($data, $format = 'string'): array
diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/CalendarRangeFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/CalendarRangeFilter.php
index d6c38e163..5ffb7c01f 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Filter/CalendarRangeFilter.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Filter/CalendarRangeFilter.php
@@ -69,9 +69,12 @@ class CalendarRangeFilter implements FilterInterface
'multiple' => false,
'expanded' => true,
'empty_data' => self::DEFAULT_CHOICE,
- 'data' => self::DEFAULT_CHOICE,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return ['hasCalendarRange' => self::DEFAULT_CHOICE];
+ }
public function describeAction($data, $format = 'string'): array
{
diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php
index 69fb24447..d02bb8e9d 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php
@@ -76,6 +76,10 @@ class JobFilter implements FilterInterface
'expanded' => true,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string'): array
{
diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php
index 08d9ae023..d8a40da72 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php
@@ -76,6 +76,10 @@ class ScopeFilter implements FilterInterface
'expanded' => true,
]);
}
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
public function describeAction($data, $format = 'string')
{
diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/chill/chill.js b/src/Bundle/ChillCalendarBundle/Resources/public/chill/chill.js
new file mode 100644
index 000000000..56a8ce563
--- /dev/null
+++ b/src/Bundle/ChillCalendarBundle/Resources/public/chill/chill.js
@@ -0,0 +1 @@
+import './scss/badge.scss';
diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/chill/scss/badge.scss b/src/Bundle/ChillCalendarBundle/Resources/public/chill/scss/badge.scss
new file mode 100644
index 000000000..ffcda8f0f
--- /dev/null
+++ b/src/Bundle/ChillCalendarBundle/Resources/public/chill/scss/badge.scss
@@ -0,0 +1,25 @@
+@import '~ChillPersonAssets/chill/scss/mixins.scss';
+@import '~ChillMainAssets/module/bootstrap/shared';
+
+.badge-calendar {
+ display: inline-block;
+ background-color: #f3f3f3;
+
+ .title_label {
+ @include chill_badge($chill-l-gray);
+ }
+
+ .title_action {
+ padding: var(--bs-badge-padding-y) var(--bs-badge-padding-x);
+ margin-right: 1rem;
+
+ font-size: var(--bs-badge-font-size);
+ font-weight: var(--bs-badge-font-weight);
+ line-height: 1;
+ color: var(--bs-badge-color);
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ }
+}
+
diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/chill/scss/calendar.scss b/src/Bundle/ChillCalendarBundle/Resources/public/chill/scss/calendar.scss
index a2c0c4b89..ce54b0fa8 100644
--- a/src/Bundle/ChillCalendarBundle/Resources/public/chill/scss/calendar.scss
+++ b/src/Bundle/ChillCalendarBundle/Resources/public/chill/scss/calendar.scss
@@ -17,4 +17,4 @@ span.calendarRangeItems {
text-decoration: none;
padding: 3px;
}
-}
\ No newline at end of file
+}
diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/GenericDoc/calendar_document.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/GenericDoc/calendar_document.html.twig
new file mode 100644
index 000000000..facf5be50
--- /dev/null
+++ b/src/Bundle/ChillCalendarBundle/Resources/views/GenericDoc/calendar_document.html.twig
@@ -0,0 +1,75 @@
+{% import "@ChillDocStore/Macro/macro.html.twig" as m %}
+{% import "@ChillDocStore/Macro/macro_mimeicon.html.twig" as mm %}
+{% import '@ChillPerson/Macro/updatedBy.html.twig' as mmm %}
+
+{% set c = document.calendar %}
+
+
+
+
+ {% if document.storedObject.isPending %}
+
{{ 'docgen.Doc generation is pending'|trans }}
+ {% elseif document.storedObject.isFailure %}
+
{{ 'docgen.Doc generation failed'|trans }}
+ {% endif %}
+
+
+ {% if c.accompanyingPeriod is not null and context == 'person' %}
+
+ {{ c.accompanyingPeriod.id }}
+
+ {% endif %}
+
+
+
+
+ {{ 'Calendar'|trans }}
+ {% if c.endDate.diff(c.startDate).days >= 1 %}
+ {{ c.startDate|format_datetime('short', 'short') }}
+ - {{ c.endDate|format_datetime('short', 'short') }}
+ {% else %}
+ {{ c.startDate|format_datetime('short', 'short') }}
+ - {{ c.endDate|format_datetime('none', 'short') }}
+ {% endif %}
+
+
+
+
+
+ {{ document.storedObject.title|chill_print_or_message("No title") }}
+
+ {% if document.storedObject.hasTemplate %}
+
+
{{ document.storedObject.template.name|localize_translatable_string }}
+
+ {% endif %}
+
+
+
+
+
+ {{ document.storedObject.createdAt|format_date('short') }}
+
+
+
+
+
+
+
+ {{ mmm.createdBy(document) }}
+
+
+ {% if is_granted('CHILL_CALENDAR_DOC_SEE', document) %}
+ -
+ {{ document.storedObject|chill_document_button_group(document.storedObject.title, is_granted('CHILL_CALENDAR_CALENDAR_EDIT', c)) }}
+
+ {% endif %}
+ {% if is_granted('CHILL_CALENDAR_CALENDAR_EDIT', c) %}
+ -
+
+
+ {% endif %}
+
+
+
+
diff --git a/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Providers/AccompanyingPeriodCalendarGenericDocProvider.php b/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Providers/AccompanyingPeriodCalendarGenericDocProvider.php
new file mode 100644
index 000000000..c33ccd853
--- /dev/null
+++ b/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Providers/AccompanyingPeriodCalendarGenericDocProvider.php
@@ -0,0 +1,192 @@
+em->getClassMetadata(CalendarDoc::class);
+ $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class);
+ $calendarMetadata = $this->em->getClassMetadata(Calendar::class);
+
+ $query = new FetchQuery(
+ self::KEY,
+ sprintf("jsonb_build_object('id', cd.%s)", $classMetadata->getColumnName('id')),
+ 'cd.'.$storedObjectMetadata->getColumnName('createdAt'),
+ $classMetadata->getSchemaName().'.'.$classMetadata->getTableName().' AS cd'
+ );
+ $query->addJoinClause(
+ sprintf(
+ 'JOIN %s doc_store ON doc_store.%s = cd.%s',
+ $storedObjectMetadata->getSchemaName().'.'.$storedObjectMetadata->getTableName(),
+ $storedObjectMetadata->getColumnName('id'),
+ $classMetadata->getSingleAssociationJoinColumnName('storedObject')
+ )
+ );
+
+ $query->addJoinClause(
+ sprintf(
+ 'JOIN %s calendar ON calendar.%s = cd.%s',
+ $calendarMetadata->getSchemaName().'.'.$calendarMetadata->getTableName(),
+ $calendarMetadata->getColumnName('id'),
+ $classMetadata->getSingleAssociationJoinColumnName('calendar')
+ )
+ );
+
+ $query->addWhereClause(
+ sprintf(
+ 'calendar.%s = ?',
+ $calendarMetadata->getAssociationMapping('accompanyingPeriod')['joinColumns'][0]['name']
+ ),
+ [$accompanyingPeriod->getId()],
+ [Types::INTEGER]
+ );
+
+ return $query;
+ }
+
+ public function isAllowedForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): bool
+ {
+ return $this->security->isGranted(CalendarVoter::SEE, $accompanyingPeriod);
+ }
+
+ public function buildFetchQueryForPerson(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null, ?string $origin = null): FetchQueryInterface
+ {
+ $classMetadata = $this->em->getClassMetadata(CalendarDoc::class);
+ $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class);
+ $calendarMetadata = $this->em->getClassMetadata(Calendar::class);
+
+ $query = new FetchQuery(
+ self::KEY,
+ sprintf("jsonb_build_object('id', cd.%s)", $classMetadata->getColumnName('id')),
+ 'cd.'.$storedObjectMetadata->getColumnName('createdAt'),
+ $classMetadata->getSchemaName().'.'.$classMetadata->getTableName().' AS cd'
+ );
+ $query->addJoinClause(
+ sprintf(
+ 'JOIN %s doc_store ON doc_store.%s = cd.%s',
+ $storedObjectMetadata->getSchemaName().'.'.$storedObjectMetadata->getTableName(),
+ $storedObjectMetadata->getColumnName('id'),
+ $classMetadata->getSingleAssociationJoinColumnName('storedObject')
+ )
+ );
+
+ $query->addJoinClause(
+ sprintf(
+ 'JOIN %s calendar ON calendar.%s = cd.%s',
+ $calendarMetadata->getSchemaName().'.'.$calendarMetadata->getTableName(),
+ $calendarMetadata->getColumnName('id'),
+ $classMetadata->getSingleAssociationJoinColumnName('calendar')
+ )
+ );
+
+ // get the documents associated with accompanying periods in which person participates
+ $or = [];
+ $orParams = [];
+ $orTypes = [];
+ foreach ($person->getAccompanyingPeriodParticipations() as $participation) {
+ if (!$this->security->isGranted(CalendarVoter::SEE, $participation->getAccompanyingPeriod())) {
+ continue;
+ }
+
+ $or[] = sprintf(
+ '(calendar.%s = ? AND cd.%s BETWEEN ?::date AND COALESCE(?::date, \'infinity\'::date))',
+ $calendarMetadata->getSingleAssociationJoinColumnName('accompanyingPeriod'),
+ $storedObjectMetadata->getColumnName('createdAt')
+ );
+ $orParams = [...$orParams, $participation->getAccompanyingPeriod()->getId(),
+ DateTimeImmutable::createFromInterface($participation->getStartDate()),
+ null === $participation->getEndDate() ? null : DateTimeImmutable::createFromInterface($participation->getEndDate())];
+ $orTypes = [...$orTypes, Types::INTEGER, Types::DATE_IMMUTABLE, Types::DATE_IMMUTABLE];
+ }
+
+ if ([] === $or) {
+ $query->addWhereClause('TRUE = FALSE');
+
+ return $query;
+ }
+ return $this->addWhereClausesToQuery($query, $startDate, $endDate, $content);
+ }
+
+ public function isAllowedForPerson(Person $person): bool
+ {
+ // check that the person is allowed to see an accompanying period. If yes, the
+ // ACL on each accompanying period will be checked when the query is build
+ return $this->security->isGranted(AccompanyingPeriodVoter::SEE, $person);
+ }
+
+ private function addWhereClausesToQuery(FetchQuery $query, ?DateTimeImmutable $startDate, ?DateTimeImmutable $endDate, ?string $content): FetchQuery
+ {
+ $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class);
+
+ if (null !== $startDate) {
+ $query->addWhereClause(
+ sprintf('doc_store.%s >= ?', $storedObjectMetadata->getColumnName('createdAt')),
+ [$startDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $endDate) {
+ $query->addWhereClause(
+ sprintf('doc_store.%s < ?', $storedObjectMetadata->getColumnName('createdAt')),
+ [$endDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $content) {
+ $query->addWhereClause(
+ sprintf('doc_store.%s ilike ?', $storedObjectMetadata->getColumnName('title')),
+ ['%' . $content . '%'],
+ [Types::STRING]
+ );
+ }
+
+ return $query;
+ }
+
+
+}
diff --git a/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Providers/PersonCalendarGenericDocProvider.php b/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Providers/PersonCalendarGenericDocProvider.php
new file mode 100644
index 000000000..f5d4b3cbb
--- /dev/null
+++ b/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Providers/PersonCalendarGenericDocProvider.php
@@ -0,0 +1,126 @@
+em->getClassMetadata(StoredObject::class);
+
+ if (null !== $startDate) {
+ $query->addWhereClause(
+ sprintf('doc_store.%s >= ?', $storedObjectMetadata->getColumnName('createdAt')),
+ [$startDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $endDate) {
+ $query->addWhereClause(
+ sprintf('doc_store.%s < ?', $storedObjectMetadata->getColumnName('createdAt')),
+ [$endDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $content) {
+ $query->addWhereClause(
+ sprintf('doc_store.%s ilike ?', $storedObjectMetadata->getColumnName('title')),
+ ['%' . $content . '%'],
+ [Types::STRING]
+ );
+ }
+
+ return $query;
+ }
+
+ /**
+ * @throws MappingException
+ */
+ public function buildFetchQueryForPerson(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null, ?string $origin = null): FetchQueryInterface
+ {
+ $classMetadata = $this->em->getClassMetadata(CalendarDoc::class);
+ $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class);
+ $calendarMetadata = $this->em->getClassMetadata(Calendar::class);
+
+ $query = new FetchQuery(
+ self::KEY,
+ sprintf("jsonb_build_object('id', cd.%s)", $classMetadata->getColumnName('id')),
+ 'cd.'.$storedObjectMetadata->getColumnName('createdAt'),
+ $classMetadata->getSchemaName().'.'.$classMetadata->getTableName().' AS cd'
+ );
+ $query->addJoinClause(
+ sprintf(
+ 'JOIN %s doc_store ON doc_store.%s = cd.%s',
+ $storedObjectMetadata->getSchemaName().'.'.$storedObjectMetadata->getTableName(),
+ $storedObjectMetadata->getColumnName('id'),
+ $classMetadata->getSingleAssociationJoinColumnName('storedObject')
+ )
+ );
+
+ $query->addJoinClause(
+ sprintf(
+ 'JOIN %s calendar ON calendar.%s = cd.%s',
+ $calendarMetadata->getSchemaName().'.'.$calendarMetadata->getTableName(),
+ $calendarMetadata->getColumnName('id'),
+ $classMetadata->getSingleAssociationJoinColumnName('calendar')
+ )
+ );
+
+ $query->addWhereClause(
+ sprintf('calendar.%s = ?', $calendarMetadata->getSingleAssociationJoinColumnName('person')),
+ [$person->getId()],
+ [Types::INTEGER]
+ );
+
+ return $this->addWhereClausesToQuery($query, $startDate, $endDate, $content);
+ }
+
+ /**
+ * @param Person $person
+ * @return bool
+ */
+ public function isAllowedForPerson(Person $person): bool
+ {
+ return $this->security->isGranted(CalendarVoter::SEE, $person);
+ }
+}
diff --git a/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Renderers/AccompanyingPeriodCalendarGenericDocRenderer.php b/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Renderers/AccompanyingPeriodCalendarGenericDocRenderer.php
new file mode 100644
index 000000000..b15c091c6
--- /dev/null
+++ b/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Renderers/AccompanyingPeriodCalendarGenericDocRenderer.php
@@ -0,0 +1,46 @@
+repository = $calendarDocRepository;
+ }
+
+ public function supports(GenericDocDTO $genericDocDTO, $options = []): bool
+ {
+ return $genericDocDTO->key === AccompanyingPeriodCalendarGenericDocProvider::KEY || $genericDocDTO->key === PersonCalendarGenericDocProvider::KEY;
+ }
+
+ public function getTemplate(GenericDocDTO $genericDocDTO, $options = []): string
+ {
+ return '@ChillCalendar/GenericDoc/calendar_document.html.twig';
+ }
+
+ public function getTemplateData(GenericDocDTO $genericDocDTO, $options = []): array
+ {
+ return [
+ 'document' => $this->repository->find($genericDocDTO->identifiers['id']),
+ 'context' => $genericDocDTO->getContext(),
+ ];
+ }
+}
diff --git a/src/Bundle/ChillCalendarBundle/chill.webpack.config.js b/src/Bundle/ChillCalendarBundle/chill.webpack.config.js
index e82210087..9d45a3142 100644
--- a/src/Bundle/ChillCalendarBundle/chill.webpack.config.js
+++ b/src/Bundle/ChillCalendarBundle/chill.webpack.config.js
@@ -1,6 +1,8 @@
// this file loads all assets from the Chill calendar bundle
module.exports = function(encore, entries) {
+ entries.push(__dirname + '/Resources/public/chill/chill.js');
+
encore.addAliases({
ChillCalendarAssets: __dirname + '/Resources/public'
});
diff --git a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml
index eb02be280..c56d7835f 100644
--- a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml
+++ b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml
@@ -43,6 +43,7 @@ crud:
title_edit: Modifier le motif d'annulation
chill_calendar:
+ Document: Document d'un rendez-vous
form:
The main user is mandatory. He will organize the appointment.: L'utilisateur principal est obligatoire. Il est l'organisateur de l'événement.
Create for referrer: Créer pour le référent
@@ -65,6 +66,7 @@ chill_calendar:
Document outdated: La date et l'heure du rendez-vous ont été modifiés après la création du document
+
remote_ms_graph:
freebusy_statuses:
busy: Occupé
@@ -145,3 +147,9 @@ CHILL_CALENDAR_CALENDAR_EDIT: Modifier les rendez-vous
CHILL_CALENDAR_CALENDAR_DELETE: Supprimer les rendez-vous
CHILL_CALENDAR_CALENDAR_SEE: Voir les rendez-vous
+
+generic_doc:
+ filter:
+ keys:
+ accompanying_period_calendar_document: Document des rendez-vous des parcours
+ person_calendar_document: Document des rendez-vous de l'usager
diff --git a/src/Bundle/ChillDocStoreBundle/ChillDocStoreBundle.php b/src/Bundle/ChillDocStoreBundle/ChillDocStoreBundle.php
index 81c71f45f..8dcbe72c3 100644
--- a/src/Bundle/ChillDocStoreBundle/ChillDocStoreBundle.php
+++ b/src/Bundle/ChillDocStoreBundle/ChillDocStoreBundle.php
@@ -11,8 +11,21 @@ declare(strict_types=1);
namespace Chill\DocStoreBundle;
+use Chill\DocStoreBundle\GenericDoc\GenericDocForAccompanyingPeriodProviderInterface;
+use Chill\DocStoreBundle\GenericDoc\GenericDocForPersonProviderInterface;
+use Chill\DocStoreBundle\GenericDoc\Twig\GenericDocRendererInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class ChillDocStoreBundle extends Bundle
{
+ public function build(ContainerBuilder $container)
+ {
+ $container->registerForAutoconfiguration(GenericDocForAccompanyingPeriodProviderInterface::class)
+ ->addTag('chill_doc_store.generic_doc_accompanying_period_provider');
+ $container->registerForAutoconfiguration(GenericDocForPersonProviderInterface::class)
+ ->addTag('chill_doc_store.generic_doc_person_provider');
+ $container->registerForAutoconfiguration(GenericDocRendererInterface::class)
+ ->addTag('chill_doc_store.generic_doc_renderer');
+ }
}
diff --git a/src/Bundle/ChillDocStoreBundle/Controller/DocumentAccompanyingCourseController.php b/src/Bundle/ChillDocStoreBundle/Controller/DocumentAccompanyingCourseController.php
index 1bc3db221..384eeb510 100644
--- a/src/Bundle/ChillDocStoreBundle/Controller/DocumentAccompanyingCourseController.php
+++ b/src/Bundle/ChillDocStoreBundle/Controller/DocumentAccompanyingCourseController.php
@@ -39,10 +39,6 @@ class DocumentAccompanyingCourseController extends AbstractController
protected TranslatorInterface $translator;
- private AccompanyingCourseDocumentRepository $courseRepository;
-
- private PaginatorFactory $paginatorFactory;
-
/**
* DocumentAccompanyingCourseController constructor.
*/
@@ -50,14 +46,10 @@ class DocumentAccompanyingCourseController extends AbstractController
TranslatorInterface $translator,
EventDispatcherInterface $eventDispatcher,
AuthorizationHelper $authorizationHelper,
- PaginatorFactory $paginatorFactory,
- AccompanyingCourseDocumentRepository $courseRepository
) {
$this->translator = $translator;
$this->eventDispatcher = $eventDispatcher;
$this->authorizationHelper = $authorizationHelper;
- $this->paginatorFactory = $paginatorFactory;
- $this->courseRepository = $courseRepository;
}
/**
@@ -82,7 +74,7 @@ class DocumentAccompanyingCourseController extends AbstractController
return $this->redirect($request->query->get('returnPath'));
}
- return $this->redirectToRoute('accompanying_course_document_index', ['course' => $course->getId()]);
+ return $this->redirectToRoute('chill_docstore_generic-doc_by-period_index', ['id' => $course->getId()]);
}
return $this->render(
@@ -136,40 +128,6 @@ class DocumentAccompanyingCourseController extends AbstractController
);
}
- /**
- * @Route("/", name="accompanying_course_document_index", methods="GET")
- */
- public function index(AccompanyingPeriod $course): Response
- {
- $em = $this->getDoctrine()->getManager();
-
- if (null === $course) {
- throw $this->createNotFoundException('Accompanying period not found');
- }
-
- $this->denyAccessUnlessGranted(AccompanyingCourseDocumentVoter::SEE, $course);
-
- $total = $this->courseRepository->countByCourse($course);
- $pagination = $this->paginatorFactory->create($total);
-
- $documents = $this->courseRepository
- ->findBy(
- ['course' => $course],
- ['date' => 'DESC', 'id' => 'DESC'],
- $pagination->getItemsPerPage(),
- $pagination->getCurrentPageFirstItemNumber()
- );
-
- return $this->render(
- 'ChillDocStoreBundle:AccompanyingCourseDocument:index.html.twig',
- [
- 'documents' => $documents,
- 'accompanyingCourse' => $course,
- 'pagination' => $pagination,
- ]
- );
- }
-
/**
* @Route("/new", name="accompanying_course_document_new", methods="GET|POST")
*/
@@ -202,7 +160,7 @@ class DocumentAccompanyingCourseController extends AbstractController
$this->addFlash('success', $this->translator->trans('The document is successfully registered'));
- return $this->redirectToRoute('accompanying_course_document_index', ['course' => $course->getId()]);
+ return $this->redirectToRoute('chill_docstore_generic-doc_by-period_index', ['id' => $course->getId()]);
}
if ($form->isSubmitted() && !$form->isValid()) {
diff --git a/src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php b/src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php
index 6fcb6a8e5..20e8e9b03 100644
--- a/src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php
+++ b/src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php
@@ -45,10 +45,6 @@ class DocumentPersonController extends AbstractController
protected TranslatorInterface $translator;
- private PaginatorFactory $paginatorFactory;
-
- private PersonDocumentACLAwareRepositoryInterface $personDocumentACLAwareRepository;
-
/**
* DocumentPersonController constructor.
*/
@@ -56,14 +52,10 @@ class DocumentPersonController extends AbstractController
TranslatorInterface $translator,
EventDispatcherInterface $eventDispatcher,
AuthorizationHelper $authorizationHelper,
- PaginatorFactory $paginatorFactory,
- PersonDocumentACLAwareRepositoryInterface $personDocumentACLAwareRepository
) {
$this->translator = $translator;
$this->eventDispatcher = $eventDispatcher;
$this->authorizationHelper = $authorizationHelper;
- $this->paginatorFactory = $paginatorFactory;
- $this->personDocumentACLAwareRepository = $personDocumentACLAwareRepository;
}
/**
@@ -88,7 +80,7 @@ class DocumentPersonController extends AbstractController
return $this->redirect($request->query->get('returnPath'));
}
- return $this->redirectToRoute('person_document_index', ['person' => $person->getId()]);
+ return $this->redirectToRoute('chill_docstore_generic-doc_by-person_index', ['id' => $person->getId()]);
}
return $this->render(
@@ -160,45 +152,6 @@ class DocumentPersonController extends AbstractController
);
}
- /**
- * @Route("/", name="person_document_index", methods="GET")
- */
- public function index(Person $person): Response
- {
- $em = $this->getDoctrine()->getManager();
-
- if (null === $person) {
- throw $this->createNotFoundException('Person not found');
- }
-
- $this->denyAccessUnlessGranted(PersonVoter::SEE, $person);
-
- $total = $this->personDocumentACLAwareRepository->countByPerson($person);
- $pagination = $this->paginatorFactory->create($total);
-
- $documents = $this->personDocumentACLAwareRepository->findByPerson(
- $person,
- ['date' => 'DESC', 'id' => 'DESC'],
- $pagination->getItemsPerPage(),
- $pagination->getCurrentPageFirstItemNumber()
- );
-
- $event = new PrivacyEvent($person, [
- 'element_class' => PersonDocument::class,
- 'action' => 'index',
- ]);
- $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
-
- return $this->render(
- 'ChillDocStoreBundle:PersonDocument:index.html.twig',
- [
- 'documents' => $documents,
- 'person' => $person,
- 'pagination' => $pagination,
- ]
- );
- }
-
/**
* @Route("/new", name="person_document_new", methods="GET|POST")
*/
@@ -233,7 +186,7 @@ class DocumentPersonController extends AbstractController
$this->addFlash('success', $this->translator->trans('The document is successfully registered'));
- return $this->redirectToRoute('person_document_index', ['person' => $person->getId()]);
+ return $this->redirectToRoute('chill_docstore_generic-doc_by-person_index', ['id' => $person->getId()]);
}
if ($form->isSubmitted() && !$form->isValid()) {
diff --git a/src/Bundle/ChillDocStoreBundle/Controller/GenericDocForAccompanyingPeriodController.php b/src/Bundle/ChillDocStoreBundle/Controller/GenericDocForAccompanyingPeriodController.php
new file mode 100644
index 000000000..70c41db50
--- /dev/null
+++ b/src/Bundle/ChillDocStoreBundle/Controller/GenericDocForAccompanyingPeriodController.php
@@ -0,0 +1,98 @@
+security->isGranted(AccompanyingCourseDocumentVoter::SEE, $accompanyingPeriod)) {
+ throw new AccessDeniedHttpException("not allowed to see the documents for accompanying period");
+ }
+
+ $filterBuilder = $this->filterOrderHelperFactory
+ ->create(self::class)
+ ->addSearchBox()
+ ->addDateRange('dateRange', 'generic_doc.filter.date-range');
+
+ if ([] !== $places = $this->manager->placesForAccompanyingPeriod($accompanyingPeriod)) {
+ $filterBuilder->addCheckbox('places', $places, [], array_map(
+ static fn (string $k) => 'generic_doc.filter.keys.' . $k,
+ $places
+ ));
+ }
+
+ $filter = $filterBuilder
+ ->build();
+
+ ['to' => $endDate, 'from' => $startDate ] = $filter->getDateRangeData('dateRange');
+ $content = $filter->getQueryString();
+
+ $nb = $this->manager->countDocForAccompanyingPeriod(
+ $accompanyingPeriod,
+ $startDate,
+ $endDate,
+ $content,
+ $filter->hasCheckBox('places') ? array_values($filter->getCheckboxData('places')) : []
+ );
+ $paginator = $this->paginator->create($nb);
+
+ $documents = $this->manager->findDocForAccompanyingPeriod(
+ $accompanyingPeriod,
+ $paginator->getCurrentPageFirstItemNumber(),
+ $paginator->getItemsPerPage(),
+ $startDate,
+ $endDate,
+ $content,
+ $filter->hasCheckBox('places') ? array_values($filter->getCheckboxData('places')) : []
+ );
+
+ return new Response($this->twig->render(
+ '@ChillDocStore/GenericDoc/accompanying_period_list.html.twig',
+ [
+ 'accompanyingCourse' => $accompanyingPeriod,
+ 'pagination' => $paginator,
+ 'documents' => iterator_to_array($documents),
+ 'filter' => $filter,
+ ]
+ ));
+ }
+
+}
diff --git a/src/Bundle/ChillDocStoreBundle/Controller/GenericDocForPerson.php b/src/Bundle/ChillDocStoreBundle/Controller/GenericDocForPerson.php
new file mode 100644
index 000000000..3484e0904
--- /dev/null
+++ b/src/Bundle/ChillDocStoreBundle/Controller/GenericDocForPerson.php
@@ -0,0 +1,95 @@
+security->isGranted(PersonDocumentVoter::SEE, $person)) {
+ throw new AccessDeniedHttpException("not allowed to see the documents for person");
+ }
+
+ $filterBuilder = $this->filterOrderHelperFactory
+ ->create(self::class)
+ ->addSearchBox()
+ ->addDateRange('dateRange', 'generic_doc.filter.date-range');
+
+ if ([] !== $places = $this->manager->placesForPerson($person)) {
+ $filterBuilder->addCheckbox('places', $places, [], array_map(
+ static fn (string $k) => 'generic_doc.filter.keys.' . $k,
+ $places
+ ));
+ }
+
+ $filter = $filterBuilder
+ ->build();
+
+ ['to' => $endDate, 'from' => $startDate ] = $filter->getDateRangeData('dateRange');
+ $content = $filter->getQueryString();
+
+ $nb = $this->manager->countDocForPerson(
+ $person,
+ $startDate,
+ $endDate,
+ $content,
+ $filter->hasCheckBox('places') ? array_values($filter->getCheckboxData('places')) : []
+ );
+ $paginator = $this->paginator->create($nb);
+
+ $documents = $this->manager->findDocForPerson(
+ $person,
+ $paginator->getCurrentPageFirstItemNumber(),
+ $paginator->getItemsPerPage(),
+ $startDate,
+ $endDate,
+ $content,
+ $filter->hasCheckBox('places') ? array_values($filter->getCheckboxData('places')) : []
+ );
+
+ return new Response($this->twig->render(
+ '@ChillDocStore/GenericDoc/person_list.html.twig',
+ [
+ 'person' => $person,
+ 'pagination' => $paginator,
+ 'documents' => iterator_to_array($documents),
+ 'filter' => $filter,
+ ]
+ ));
+ }
+
+}
diff --git a/src/Bundle/ChillDocStoreBundle/GenericDoc/FetchQuery.php b/src/Bundle/ChillDocStoreBundle/GenericDoc/FetchQuery.php
new file mode 100644
index 000000000..30e07a841
--- /dev/null
+++ b/src/Bundle/ChillDocStoreBundle/GenericDoc/FetchQuery.php
@@ -0,0 +1,233 @@
+
+ */
+ private array $joins = [];
+
+ /**
+ * @var list>
+ */
+ private array $joinParams = [];
+
+ /**
+ * @var array>
+ */
+ private array $joinTypes = [];
+
+ /**
+ * @var array
+ */
+ private array $wheres = [];
+
+ /**
+ * @var array>
+ */
+ private array $whereParams = [];
+
+ /**
+ * @var array>
+ */
+ private array $whereTypes = [];
+
+ public function __construct(
+ private readonly string $selectKeyString,
+ private readonly string $selectIdentifierJsonB,
+ private readonly string $selectDate,
+ private string $from = '',
+ private array $selectIdentifierParams = [],
+ private array $selectIdentifierTypes = [],
+ private array $selectDateParams = [],
+ private array $selectDateTypes = [],
+ ) {
+ }
+
+ public function addJoinClause(string $sql, array $params = [], array $types = []): int
+ {
+ $this->joins[] = $sql;
+ $this->joinParams[] = $params;
+ $this->joinTypes[] = $types;
+
+ return count($this->joins) - 1;
+ }
+
+ public function addWhereClause(string $sql, array $params = [], array $types = []): int
+ {
+ $this->wheres[] = $sql;
+ $this->whereParams[] = $params;
+ $this->whereTypes[] = $types;
+
+ return count($this->wheres) - 1;
+ }
+
+ public function removeWhereClause(int $index): void
+ {
+ if (!array_key_exists($index, $this->wheres)) {
+ throw new \UnexpectedValueException("this index does not exists");
+ }
+
+ unset($this->wheres[$index], $this->whereParams[$index], $this->whereTypes[$index]);
+
+ }
+
+ public function removeJoinClause(int $index): void
+ {
+ if (!array_key_exists($index, $this->joins)) {
+ throw new \UnexpectedValueException("this index does not exists");
+ }
+
+ unset($this->joins[$index], $this->joinParams[$index], $this->joinTypes[$index]);
+
+ }
+
+ public function getSelectKeyString(): string
+ {
+ return $this->selectKeyString;
+ }
+
+ public function getSelectIdentifierJsonB(): string
+ {
+ return $this->selectIdentifierJsonB;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getSelectIdentifierParams(): array
+ {
+ return $this->selectIdentifierParams;
+ }
+
+ public function getSelectIdentifiersTypes(): array
+ {
+ return $this->selectIdentifierTypes;
+ }
+
+ public function getSelectDate(): string
+ {
+ return $this->selectDate;
+ }
+
+ public function getSelectDateTypes(): array
+ {
+ return $this->selectDateTypes;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getSelectDateParams(): array
+ {
+ return $this->selectDateParams;
+ }
+
+ public function getFromQuery(): string
+ {
+ return $this->from . " " . implode(' ', $this->joins);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getFromQueryParams(): array
+ {
+ $result = [];
+
+ foreach ($this->joinParams as $params) {
+ $result = [...$result, ...$params];
+ }
+
+ return $result;
+ }
+
+ public function getFromQueryTypes(): array
+ {
+ $result = [];
+
+ foreach ($this->joinTypes as $types) {
+ $result = [...$result, ...$types];
+ }
+
+ return $result;
+ }
+
+ public function getWhereQuery(): string
+ {
+ return implode(' AND ', $this->wheres);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getWhereQueryParams(): array
+ {
+ $result = [];
+
+ foreach ($this->whereParams as $params) {
+ $result = [...$result, ...$params];
+ }
+
+ return $result;
+ }
+
+ public function getWhereQueryTypes(): array
+ {
+ $result = [];
+
+ foreach ($this->whereTypes as $types) {
+ $result = [...$result, ...$types];
+ }
+
+ return $result;
+ }
+
+ public function setSelectIdentifierParams(array $selectIdentifierParams): self
+ {
+ $this->selectIdentifierParams = $selectIdentifierParams;
+
+ return $this;
+ }
+
+ public function setSelectDateParams(array $selectDateParams): self
+ {
+ $this->selectDateParams = $selectDateParams;
+
+ return $this;
+ }
+
+ public function setFrom(string $from): self
+ {
+ $this->from = $from;
+
+ return $this;
+ }
+
+ public function setSelectIdentifierTypes(array $selectIdentifierTypes): self
+ {
+ $this->selectIdentifierTypes = $selectIdentifierTypes;
+
+ return $this;
+ }
+
+ public function setSelectDateTypes(array $selectDateTypes): self
+ {
+ $this->selectDateTypes = $selectDateTypes;
+
+ return $this;
+ }
+}
diff --git a/src/Bundle/ChillDocStoreBundle/GenericDoc/FetchQueryInterface.php b/src/Bundle/ChillDocStoreBundle/GenericDoc/FetchQueryInterface.php
new file mode 100644
index 000000000..e46795457
--- /dev/null
+++ b/src/Bundle/ChillDocStoreBundle/GenericDoc/FetchQueryInterface.php
@@ -0,0 +1,67 @@
+
+ */
+ public function getSelectIdentifierParams(): array;
+
+ /**
+ * @return list
+ */
+ public function getSelectIdentifiersTypes(): array;
+
+ public function getSelectDate(): string;
+
+ /**
+ * @return list
+ */
+ public function getSelectDateParams(): array;
+
+ /**
+ * @return list
+ */
+ public function getSelectDateTypes(): array;
+
+ public function getFromQuery(): string;
+
+ /**
+ * @return list
+ */
+ public function getFromQueryParams(): array;
+
+ /**
+ * @return list
+ */
+ public function getFromQueryTypes(): array;
+
+ public function getWhereQuery(): string;
+
+ /**
+ * @return list
+ */
+ public function getWhereQueryParams(): array;
+
+ /**
+ * @return list
+ */
+ public function getWhereQueryTypes(): array;
+}
diff --git a/src/Bundle/ChillDocStoreBundle/GenericDoc/FetchQueryToSqlBuilder.php b/src/Bundle/ChillDocStoreBundle/GenericDoc/FetchQueryToSqlBuilder.php
new file mode 100644
index 000000000..2c0c59cff
--- /dev/null
+++ b/src/Bundle/ChillDocStoreBundle/GenericDoc/FetchQueryToSqlBuilder.php
@@ -0,0 +1,57 @@
+, types: list}
+ */
+ public function toSql(FetchQueryInterface $query): array
+ {
+ $sql = strtr(self::SQL, [
+ '{{ key }}' => $query->getSelectKeyString(),
+ '{{ identifiers }}' => $query->getSelectIdentifierJsonB(),
+ '{{ date }}' => $query->getSelectDate(),
+ '{{ from }}' => $query->getFromQuery(),
+ '{{ where }}' => '' === ($w = $query->getWhereQuery()) ? '' : 'WHERE ' . $w,
+ ]);
+
+ $params = [
+ ...$query->getSelectIdentifierParams(),
+ ...$query->getSelectDateParams(),
+ ...$query->getFromQueryParams(),
+ ...$query->getWhereQueryParams()
+ ];
+
+ $types = [
+ ...$query->getSelectIdentifiersTypes(),
+ ...$query->getSelectDateTypes(),
+ ...$query->getFromQueryTypes(),
+ ...$query->getWhereQueryTypes(),
+ ];
+
+ return ['sql' => $sql, 'params' => $params, 'types' => $types];
+ }
+}
diff --git a/src/Bundle/ChillDocStoreBundle/GenericDoc/GenericDocDTO.php b/src/Bundle/ChillDocStoreBundle/GenericDoc/GenericDocDTO.php
new file mode 100644
index 000000000..fe9bf7e4f
--- /dev/null
+++ b/src/Bundle/ChillDocStoreBundle/GenericDoc/GenericDocDTO.php
@@ -0,0 +1,31 @@
+linked instanceof AccompanyingPeriod ? 'accompanying-period' : 'person';
+ }
+}
diff --git a/src/Bundle/ChillDocStoreBundle/GenericDoc/GenericDocForAccompanyingPeriodProviderInterface.php b/src/Bundle/ChillDocStoreBundle/GenericDoc/GenericDocForAccompanyingPeriodProviderInterface.php
new file mode 100644
index 000000000..0d3cb1c32
--- /dev/null
+++ b/src/Bundle/ChillDocStoreBundle/GenericDoc/GenericDocForAccompanyingPeriodProviderInterface.php
@@ -0,0 +1,31 @@
+
+ */
+ private iterable $providersForAccompanyingPeriod,
+
+ /**
+ * @var iterable
+ */
+ private iterable $providersForPerson,
+ private Connection $connection,
+ ) {
+ $this->builder = new FetchQueryToSqlBuilder();
+ }
+
+ /**
+ * @param list $places
+ * @throws Exception
+ */
+ public function countDocForAccompanyingPeriod(
+ AccompanyingPeriod $accompanyingPeriod,
+ ?\DateTimeImmutable $startDate = null,
+ ?\DateTimeImmutable $endDate = null,
+ ?string $content = null,
+ array $places = []
+ ): int {
+ ['sql' => $sql, 'params' => $params, 'types' => $types] = $this->buildUnionQuery($accompanyingPeriod, $startDate, $endDate, $content, $places);
+
+ return $this->countDoc($sql, $params, $types);
+ }
+
+ private function countDoc(string $sql, array $params, array $types): int
+ {
+ if ($sql === '') {
+ return 0;
+ }
+
+ $countSql = "SELECT count(*) AS c FROM ({$sql}) AS sq";
+ $result = $this->connection->executeQuery($countSql, $params, $types);
+
+ $number = $result->fetchOne();
+
+ if (false === $number) {
+ throw new \UnexpectedValueException("number of documents failed to load");
+ }
+
+ return $number;
+ }
+
+ public function countDocForPerson(
+ Person $person,
+ ?\DateTimeImmutable $startDate = null,
+ ?\DateTimeImmutable $endDate = null,
+ ?string $content = null,
+ array $places = []
+ ): int {
+ ['sql' => $sql, 'params' => $params, 'types' => $types] = $this->buildUnionQuery($person, $startDate, $endDate, $content, $places);
+
+ return $this->countDoc($sql, $params, $types);
+ }
+
+ /**
+ * @param list $places places to search. When empty, search in all places
+ * @return iterable
+ * @throws Exception
+ */
+ public function findDocForAccompanyingPeriod(
+ AccompanyingPeriod $accompanyingPeriod,
+ int $offset = 0,
+ int $limit = 20,
+ ?\DateTimeImmutable $startDate = null,
+ ?\DateTimeImmutable $endDate = null,
+ ?string $content = null,
+ array $places = []
+ ): iterable {
+ ['sql' => $sql, 'params' => $params, 'types' => $types] = $this->buildUnionQuery($accompanyingPeriod, $startDate, $endDate, $content, $places);
+
+ return $this->findDocs($accompanyingPeriod, $sql, $params, $types, $offset, $limit);
+ }
+
+ /**
+ * @throws \JsonException
+ * @throws Exception
+ */
+ private function findDocs(AccompanyingPeriod|Person $linked, string $sql, array $params, array $types, int $offset, int $limit): iterable
+ {
+ if ($sql === '') {
+ return [];
+ }
+
+ $runSql = "{$sql} ORDER BY doc_date DESC LIMIT ? OFFSET ?";
+ $runParams = [...$params, ...[$limit, $offset]];
+ $runTypes = [...$types, ...[Types::INTEGER, Types::INTEGER]];
+
+ foreach ($this->connection->iterateAssociative($runSql, $runParams, $runTypes) as $row) {
+ yield new GenericDocDTO(
+ $row['key'],
+ json_decode($row['identifiers'], true, 512, JSON_THROW_ON_ERROR),
+ new \DateTimeImmutable($row['doc_date']),
+ $linked,
+ );
+ }
+ }
+
+ /**
+ * @param list $places places to search. When empty, search in all places
+ * @return iterable
+ */
+ public function findDocForPerson(
+ Person $person,
+ int $offset = 0,
+ int $limit = 20,
+ ?\DateTimeImmutable $startDate = null,
+ ?\DateTimeImmutable $endDate = null,
+ ?string $content = null,
+ array $places = []
+ ): iterable {
+ ['sql' => $sql, 'params' => $params, 'types' => $types] = $this->buildUnionQuery($person, $startDate, $endDate, $content, $places);
+
+ return $this->findDocs($person, $sql, $params, $types, $offset, $limit);
+ }
+
+ public function placesForPerson(Person $person): array
+ {
+ ['sql' => $sql, 'params' => $params, 'types' => $types] = $this->buildUnionQuery($person);
+
+ return $this->places($sql, $params, $types);
+ }
+
+ public function placesForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): array
+ {
+ ['sql' => $sql, 'params' => $params, 'types' => $types] = $this->buildUnionQuery($accompanyingPeriod);
+
+ return $this->places($sql, $params, $types);
+ }
+
+ private function places(string $sql, array $params, array $types): array
+ {
+ if ($sql === '') {
+ return [];
+ }
+
+ $runSql = "SELECT DISTINCT key FROM ({$sql}) AS sq ORDER BY key";
+
+ $keys = [];
+
+ foreach ($this->connection->iterateAssociative($runSql, $params, $types) as $k) {
+ $keys[] = $k['key'];
+ }
+
+ return $keys;
+ }
+
+ /**
+ * @param list $places places to search. When empty, search in all places
+ */
+ private function buildUnionQuery(
+ AccompanyingPeriod|Person $linked,
+ ?\DateTimeImmutable $startDate = null,
+ ?\DateTimeImmutable $endDate = null,
+ ?string $content = null,
+ array $places = [],
+ ): array {
+ $queries = [];
+
+ if ($linked instanceof AccompanyingPeriod) {
+ foreach ($this->providersForAccompanyingPeriod as $provider) {
+ if (!$provider->isAllowedForAccompanyingPeriod($linked)) {
+ continue;
+ }
+ $queries[] = $provider->buildFetchQueryForAccompanyingPeriod($linked, $startDate, $endDate, $content);
+ }
+ } else {
+ foreach ($this->providersForPerson as $provider) {
+ if (!$provider->isAllowedForPerson($linked)) {
+ continue;
+ }
+ $queries[] = $provider->buildFetchQueryForPerson($linked, $startDate, $endDate, $content);
+ }
+ }
+ $sql = [];
+ $params = [];
+ $types = [];
+
+ foreach ($queries as $query) {
+ if ([] !== $places and !in_array($query->getSelectKeyString(), $places, true)) {
+ continue;
+ }
+
+ ['sql' => $q, 'params' => $p, 'types' => $t ] = $this->builder->toSql($query);
+
+ $sql[] = $q;
+ $params = [...$params, ...$p];
+ $types = [...$types, ...$t];
+ }
+
+ return ['sql' => implode(' UNION ', $sql), 'params' => $params, 'types' => $types];
+ }
+}
diff --git a/src/Bundle/ChillDocStoreBundle/GenericDoc/Providers/AccompanyingCourseDocumentGenericDocProvider.php b/src/Bundle/ChillDocStoreBundle/GenericDoc/Providers/AccompanyingCourseDocumentGenericDocProvider.php
new file mode 100644
index 000000000..fd36f7976
--- /dev/null
+++ b/src/Bundle/ChillDocStoreBundle/GenericDoc/Providers/AccompanyingCourseDocumentGenericDocProvider.php
@@ -0,0 +1,147 @@
+entityManager->getClassMetadata(AccompanyingCourseDocument::class);
+
+ $query = new FetchQuery(
+ self::KEY,
+ sprintf('jsonb_build_object(\'id\', %s)', $classMetadata->getIdentifierColumnNames()[0]),
+ $classMetadata->getColumnName('date'),
+ $classMetadata->getSchemaName() . '.' . $classMetadata->getTableName()
+ );
+
+ $query->addWhereClause(
+ sprintf('%s = ?', $classMetadata->getSingleAssociationJoinColumnName('course')),
+ [$accompanyingPeriod->getId()],
+ [Types::INTEGER]
+ );
+
+ return $this->addWhereClause($query, $startDate, $endDate, $content);
+ }
+
+ public function isAllowedForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): bool
+ {
+ return $this->security->isGranted(AccompanyingCourseDocumentVoter::SEE, $accompanyingPeriod);
+ }
+
+ public function buildFetchQueryForPerson(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null, ?string $origin = null): FetchQueryInterface
+ {
+ $classMetadata = $this->entityManager->getClassMetadata(AccompanyingCourseDocument::class);
+
+ $query = new FetchQuery(
+ self::KEY,
+ sprintf('jsonb_build_object(\'id\', %s)', $classMetadata->getIdentifierColumnNames()[0]),
+ $classMetadata->getColumnName('date'),
+ $classMetadata->getSchemaName() . '.' . $classMetadata->getTableName() . ' AS acc_course_document'
+ );
+
+ $atLeastOne = false;
+ $or = [];
+ $orParams = [];
+ $orTypes = [];
+
+ foreach ($person->getAccompanyingPeriodParticipations() as $participation) {
+ if (!$this->security->isGranted(AccompanyingCourseDocumentVoter::SEE, $participation->getAccompanyingPeriod())) {
+ continue;
+ }
+
+ $atLeastOne = true;
+
+ $or[] = sprintf(
+ "(acc_course_document.%s = ? AND acc_course_document.%s BETWEEN ? AND COALESCE(?, 'infinity'::date))",
+ $classMetadata->getSingleAssociationJoinColumnName('course'),
+ $classMetadata->getColumnName('date')
+ );
+ $orParams = [...$orParams, $participation->getAccompanyingPeriod()->getId(), $participation->getStartDate(), $participation->getEndDate()];
+ $orTypes = [...$orTypes, Types::INTEGER, Types::DATE_MUTABLE, Types::DATE_MUTABLE];
+ }
+
+ if (!$atLeastOne) {
+ // there aren't any period allowed to be seen. Add an unreachable condition
+ $query->addWhereClause('TRUE = FALSE');
+
+ return $query;
+ }
+
+ $query->addWhereClause('(' . implode(' OR ', $or) . ')', $orParams, $orTypes);
+
+ return $this->addWhereClause($query, $startDate, $endDate, $content);
+ }
+
+ public function isAllowedForPerson(Person $person): bool
+ {
+ return $this->security->isGranted(AccompanyingPeriodVoter::SEE, $person);
+ }
+
+ private function addWhereClause(FetchQuery $query, ?\DateTimeImmutable $startDate = null, ?\DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery
+ {
+ $classMetadata = $this->entityManager->getClassMetadata(AccompanyingCourseDocument::class);
+
+ if (null !== $startDate) {
+ $query->addWhereClause(
+ sprintf('? <= %s', $classMetadata->getColumnName('date')),
+ [$startDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $endDate) {
+ $query->addWhereClause(
+ sprintf('? >= %s', $classMetadata->getColumnName('date')),
+ [$endDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $content and '' !== $content) {
+ $query->addWhereClause(
+ sprintf(
+ '(%s ilike ? OR %s ilike ?)',
+ $classMetadata->getColumnName('title'),
+ $classMetadata->getColumnName('description')
+ ),
+ ['%' . $content . '%', '%' . $content . '%'],
+ [Types::STRING, Types::STRING]
+ );
+ }
+
+ return $query;
+ }
+
+}
diff --git a/src/Bundle/ChillDocStoreBundle/GenericDoc/Providers/PersonDocumentGenericDocProvider.php b/src/Bundle/ChillDocStoreBundle/GenericDoc/Providers/PersonDocumentGenericDocProvider.php
new file mode 100644
index 000000000..613f8d758
--- /dev/null
+++ b/src/Bundle/ChillDocStoreBundle/GenericDoc/Providers/PersonDocumentGenericDocProvider.php
@@ -0,0 +1,65 @@
+personDocumentACLAwareRepository->buildFetchQueryForPerson(
+ $person,
+ $startDate,
+ $endDate,
+ $content
+ );
+ }
+
+ public function isAllowedForPerson(Person $person): bool
+ {
+ return $this->security->isGranted(PersonDocumentVoter::SEE, $person);
+ }
+
+ public function buildFetchQueryForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod, ?\DateTimeImmutable $startDate = null, ?\DateTimeImmutable $endDate = null, ?string $content = null, ?string $origin = null): FetchQueryInterface
+ {
+ return $this->personDocumentACLAwareRepository->buildFetchQueryForAccompanyingPeriod($accompanyingPeriod, $startDate, $endDate, $content);
+ }
+
+ public function isAllowedForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): bool
+ {
+ // we assume that the user is allowed to see at least one person of the course
+ // this will be double checked when running the query
+ return true;
+ }
+}
diff --git a/src/Bundle/ChillDocStoreBundle/GenericDoc/Renderer/AccompanyingCourseDocumentGenericDocRenderer.php b/src/Bundle/ChillDocStoreBundle/GenericDoc/Renderer/AccompanyingCourseDocumentGenericDocRenderer.php
new file mode 100644
index 000000000..c32620030
--- /dev/null
+++ b/src/Bundle/ChillDocStoreBundle/GenericDoc/Renderer/AccompanyingCourseDocumentGenericDocRenderer.php
@@ -0,0 +1,59 @@
+key === AccompanyingCourseDocumentGenericDocProvider::KEY
+ || $genericDocDTO->key === PersonDocumentGenericDocProvider::KEY;
+ }
+
+ public function getTemplate(GenericDocDTO $genericDocDTO, $options = []): string
+ {
+ return '@ChillDocStore/List/list_item.html.twig';
+ }
+
+ public function getTemplateData(GenericDocDTO $genericDocDTO, $options = []): array
+ {
+ if (AccompanyingCourseDocumentGenericDocProvider::KEY === $genericDocDTO->key) {
+ return [
+ 'document' => $doc = $this->accompanyingCourseDocumentRepository->find($genericDocDTO->identifiers['id']),
+ 'accompanyingCourse' => $doc->getCourse(),
+ 'options' => $options,
+ 'context' => $genericDocDTO->getContext(),
+ ];
+ }
+ // this is a person
+ return [
+ 'document' => $doc = $this->personDocumentRepository->find($genericDocDTO->identifiers['id']),
+ 'person' => $doc->getPerson(),
+ 'options' => $options,
+ 'context' => $genericDocDTO->getContext(),
+ ];
+ }
+}
diff --git a/src/Bundle/ChillDocStoreBundle/GenericDoc/Twig/GenericDocExtension.php b/src/Bundle/ChillDocStoreBundle/GenericDoc/Twig/GenericDocExtension.php
new file mode 100644
index 000000000..308d85cd7
--- /dev/null
+++ b/src/Bundle/ChillDocStoreBundle/GenericDoc/Twig/GenericDocExtension.php
@@ -0,0 +1,28 @@
+ true,
+ 'is_safe' => ['html'],
+ ])
+ ];
+ }
+}
diff --git a/src/Bundle/ChillDocStoreBundle/GenericDoc/Twig/GenericDocExtensionRuntime.php b/src/Bundle/ChillDocStoreBundle/GenericDoc/Twig/GenericDocExtensionRuntime.php
new file mode 100644
index 000000000..2dee0ed0b
--- /dev/null
+++ b/src/Bundle/ChillDocStoreBundle/GenericDoc/Twig/GenericDocExtensionRuntime.php
@@ -0,0 +1,50 @@
+
+ */
+ private iterable $renderers,
+ ) {
+ }
+
+ /**
+ * @throws RuntimeError
+ * @throws SyntaxError
+ * @throws LoaderError
+ */
+ public function renderGenericDoc(Environment $twig, GenericDocDTO $genericDocDTO, array $options = []): string
+ {
+ foreach ($this->renderers as $renderer) {
+ if ($renderer->supports($genericDocDTO)) {
+ return $twig->render(
+ $renderer->getTemplate($genericDocDTO, $options),
+ $renderer->getTemplateData($genericDocDTO, $options),
+ );
+ }
+ }
+
+ throw new \LogicException("no renderer found");
+ }
+
+}
diff --git a/src/Bundle/ChillDocStoreBundle/GenericDoc/Twig/GenericDocRendererInterface.php b/src/Bundle/ChillDocStoreBundle/GenericDoc/Twig/GenericDocRendererInterface.php
new file mode 100644
index 000000000..940001f4a
--- /dev/null
+++ b/src/Bundle/ChillDocStoreBundle/GenericDoc/Twig/GenericDocRendererInterface.php
@@ -0,0 +1,24 @@
+security->isGranted(AccompanyingCourseDocumentVoter::SEE, $course)) {
$menu->addChild($this->translator->trans('Documents'), [
- 'route' => 'accompanying_course_document_index',
+ 'route' => 'chill_docstore_generic-doc_by-period_index',
'routeParameters' => [
- 'course' => $course->getId(),
+ 'id' => $course->getId(),
],
])
->setExtras([
@@ -80,9 +80,9 @@ final class MenuBuilder implements LocalMenuBuilderInterface
if ($this->security->isGranted(PersonDocumentVoter::SEE, $person)) {
$menu->addChild($this->translator->trans('Documents'), [
- 'route' => 'person_document_index',
+ 'route' => 'chill_docstore_generic-doc_by-person_index',
'routeParameters' => [
- 'person' => $person->getId(),
+ 'id' => $person->getId(),
],
])
->setExtras([
diff --git a/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepository.php b/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepository.php
index 23dcc4e0b..26a42b894 100644
--- a/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepository.php
+++ b/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepository.php
@@ -12,30 +12,33 @@ declare(strict_types=1);
namespace Chill\DocStoreBundle\Repository;
use Chill\DocStoreBundle\Entity\PersonDocument;
+use Chill\DocStoreBundle\GenericDoc\FetchQuery;
+use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface;
+use Chill\DocStoreBundle\GenericDoc\Providers\PersonDocumentGenericDocProvider;
use Chill\DocStoreBundle\Security\Authorization\PersonDocumentVoter;
+use Chill\MainBundle\Entity\Scope;
+use Chill\MainBundle\Security\Authorization\AuthorizationHelperForCurrentUserInterface;
use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface;
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher;
+use Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface;
+use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface;
+use Chill\PersonBundle\Entity\AccompanyingPeriod;
+use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
use Chill\PersonBundle\Entity\Person;
+use DateTimeImmutable;
+use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Security\Core\Security;
-class PersonDocumentACLAwareRepository implements PersonDocumentACLAwareRepositoryInterface
+final readonly class PersonDocumentACLAwareRepository implements PersonDocumentACLAwareRepositoryInterface
{
- private AuthorizationHelperInterface $authorizationHelper;
-
- private CenterResolverDispatcher $centerResolverDispatcher;
-
- private EntityManagerInterface $em;
-
- private Security $security;
-
- public function __construct(EntityManagerInterface $em, AuthorizationHelperInterface $authorizationHelper, CenterResolverDispatcher $centerResolverDispatcher, Security $security)
- {
- $this->em = $em;
- $this->authorizationHelper = $authorizationHelper;
- $this->centerResolverDispatcher = $centerResolverDispatcher;
- $this->security = $security;
+ public function __construct(
+ private EntityManagerInterface $em,
+ private CenterResolverManagerInterface $centerResolverManager,
+ private AuthorizationHelperForCurrentUserInterface $authorizationHelperForCurrentUser,
+ private Security $security,
+ ) {
}
public function buildQueryByPerson(Person $person): QueryBuilder
@@ -49,6 +52,128 @@ class PersonDocumentACLAwareRepository implements PersonDocumentACLAwareReposito
return $qb;
}
+
+ public function buildFetchQueryForPerson(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQueryInterface
+ {
+ $query = $this->buildBaseFetchQueryForPerson($person, $startDate, $endDate, $content);
+
+ return $this->addFetchQueryByPersonACL($query, $person);
+ }
+
+ public function buildFetchQueryForAccompanyingPeriod(AccompanyingPeriod $period, ?\DateTimeImmutable $startDate = null, ?\DateTimeImmutable $endDate = null, ?string $content = null): FetchQueryInterface
+ {
+ $personDocMetadata = $this->em->getClassMetadata(PersonDocument::class);
+ $participationMetadata = $this->em->getClassMetadata(AccompanyingPeriodParticipation::class);
+
+ $query = new FetchQuery(
+ PersonDocumentGenericDocProvider::KEY,
+ sprintf('jsonb_build_object(\'id\', person_document.%s)', $personDocMetadata->getSingleIdentifierColumnName()),
+ sprintf('person_document.%s', $personDocMetadata->getColumnName('date')),
+ sprintf('%s AS person_document', $personDocMetadata->getSchemaName().'.'.$personDocMetadata->getTableName())
+ );
+
+ $query->addJoinClause(
+ sprintf(
+ 'JOIN %s AS participation ON participation.%s = person_document.%s '.
+ 'AND person_document.%s BETWEEN participation.%s AND COALESCE(participation.%s, \'infinity\'::date)',
+ $participationMetadata->getTableName(),
+ $participationMetadata->getSingleAssociationJoinColumnName('person'),
+ $personDocMetadata->getSingleAssociationJoinColumnName('person'),
+ $personDocMetadata->getColumnName('date'),
+ $participationMetadata->getColumnName('startDate'),
+ $participationMetadata->getColumnName('endDate')
+ )
+ );
+
+ $query->addWhereClause(
+ sprintf('participation.%s = ?', $participationMetadata->getSingleAssociationJoinColumnName('accompanyingPeriod')),
+ [$period->getId()],
+ [Types::INTEGER]
+ );
+
+ // can we see the document for this person ?
+ $orPersonId = [];
+ foreach ($period->getParticipations() as $participation) {
+ if (!$this->security->isGranted(PersonDocumentVoter::SEE, $participation->getPerson())) {
+ continue;
+ }
+ $orPersonId[] = $participation->getPerson()->getId();
+
+ }
+
+ if ([] === $orPersonId) {
+ $query->addWhereClause('FALSE = TRUE');
+
+ return $query;
+ }
+
+ $query->addWhereClause(
+ sprintf(
+ 'participation.%s IN (%s)',
+ $participationMetadata->getSingleAssociationJoinColumnName('person'),
+ implode(', ', array_fill(0, count($orPersonId), '?'))
+ ),
+ $orPersonId,
+ array_fill(0, count($orPersonId), Types::INTEGER)
+ );
+
+ return $this->addFilterClauses($query, $startDate, $endDate, $content);
+ }
+
+ public function buildBaseFetchQueryForPerson(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery
+ {
+ $personDocMetadata = $this->em->getClassMetadata(PersonDocument::class);
+
+ $query = new FetchQuery(
+ PersonDocumentGenericDocProvider::KEY,
+ sprintf('jsonb_build_object(\'id\', person_document.%s)', $personDocMetadata->getSingleIdentifierColumnName()),
+ sprintf('person_document.%s', $personDocMetadata->getColumnName('date')),
+ sprintf('%s AS person_document', $personDocMetadata->getSchemaName().'.'.$personDocMetadata->getTableName())
+ );
+
+ $query->addWhereClause(
+ sprintf('person_document.%s = ?', $personDocMetadata->getSingleAssociationJoinColumnName('person')),
+ [$person->getId()],
+ [Types::INTEGER]
+ );
+
+ return $this->addFilterClauses($query, $startDate, $endDate, $content);
+ }
+
+ private function addFilterClauses(FetchQuery $query, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery
+ {
+ $personDocMetadata = $this->em->getClassMetadata(PersonDocument::class);
+
+ if (null !== $startDate) {
+ $query->addWhereClause(
+ sprintf('? <= %s', $personDocMetadata->getColumnName('date')),
+ [$startDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $endDate) {
+ $query->addWhereClause(
+ sprintf('? >= %s', $personDocMetadata->getColumnName('date')),
+ [$endDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $content and '' !== $content) {
+ $query->addWhereClause(
+ sprintf(
+ '(%s ilike ? OR %s ilike ?)',
+ $personDocMetadata->getColumnName('title'),
+ $personDocMetadata->getColumnName('description')
+ ),
+ ['%' . $content . '%', '%' . $content . '%'],
+ [Types::STRING, Types::STRING]
+ );
+ }
+ return $query;
+ }
+
public function countByPerson(Person $person): int
{
$qb = $this->buildQueryByPerson($person)->select('COUNT(d)');
@@ -75,16 +200,58 @@ class PersonDocumentACLAwareRepository implements PersonDocumentACLAwareReposito
private function addACL(QueryBuilder $qb, Person $person): void
{
- $center = $this->centerResolverDispatcher->resolveCenter($person);
+ $reachableScopes = [];
- $reachableScopes = $this->authorizationHelper
- ->getReachableScopes(
- $this->security->getUser(),
- PersonDocumentVoter::SEE,
- $center
- );
+ foreach ($this->centerResolverManager->resolveCenters($person) as $center) {
+ $reachableScopes = [
+ ...$reachableScopes,
+ ...$this->authorizationHelperForCurrentUser
+ ->getReachableScopes(
+ PersonDocumentVoter::SEE,
+ $center
+ )
+ ];
+ }
+
+ if ([] === $reachableScopes) {
+ $qb->andWhere("'FALSE' = 'TRUE'");
+
+ return;
+ }
$qb->andWhere($qb->expr()->in('d.scope', ':scopes'))
->setParameter('scopes', $reachableScopes);
}
+
+ private function addFetchQueryByPersonACL(FetchQuery $fetchQuery, Person $person): FetchQuery
+ {
+ $personDocMetadata = $this->em->getClassMetadata(PersonDocument::class);
+
+ $reachableScopes = [];
+
+ foreach ($this->centerResolverManager->resolveCenters($person) as $center) {
+ $reachableScopes = [
+ ...$reachableScopes,
+ ...$this->authorizationHelperForCurrentUser->getReachableScopes(PersonDocumentVoter::SEE, $center)
+ ];
+ }
+
+ if ([] === $reachableScopes) {
+ $fetchQuery->addWhereClause('FALSE = TRUE');
+
+ return $fetchQuery;
+ }
+
+ $fetchQuery->addWhereClause(
+ sprintf(
+ 'person_document.%s IN (%s)',
+ $personDocMetadata->getSingleAssociationJoinColumnName('scope'),
+ implode(', ', array_fill(0, count($reachableScopes), '?'))
+ ),
+ array_map(static fn (Scope $s) => $s->getId(), $reachableScopes),
+ array_fill(0, count($reachableScopes), Types::INTEGER)
+ );
+
+ return $fetchQuery;
+ }
}
diff --git a/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepositoryInterface.php b/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepositoryInterface.php
index 6c4bd2e9a..f1bc70812 100644
--- a/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepositoryInterface.php
+++ b/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepositoryInterface.php
@@ -11,11 +11,33 @@ declare(strict_types=1);
namespace Chill\DocStoreBundle\Repository;
+use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface;
+use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
interface PersonDocumentACLAwareRepositoryInterface
{
+ /**
+ * @deprecated use fetch query for listing and counting person documents
+ */
public function countByPerson(Person $person): int;
+ /**
+ * @deprecated use fetch query for listing and counting person documents
+ */
public function findByPerson(Person $person, array $orderBy = [], int $limit = 20, int $offset = 0): array;
+
+ public function buildFetchQueryForPerson(
+ Person $person,
+ ?\DateTimeImmutable $startDate = null,
+ ?\DateTimeImmutable $endDate = null,
+ ?string $content = null
+ ): FetchQueryInterface;
+
+ public function buildFetchQueryForAccompanyingPeriod(
+ AccompanyingPeriod $period,
+ ?\DateTimeImmutable $startDate = null,
+ ?\DateTimeImmutable $endDate = null,
+ ?string $content = null
+ ): FetchQueryInterface;
}
diff --git a/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentRepository.php b/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentRepository.php
new file mode 100644
index 000000000..40afdc220
--- /dev/null
+++ b/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentRepository.php
@@ -0,0 +1,57 @@
+
+ */
+readonly class PersonDocumentRepository implements ObjectRepository
+{
+ private EntityRepository $repository;
+
+ public function __construct(
+ private EntityManagerInterface $entityManager
+ ) {
+ $this->repository = $this->entityManager->getRepository($this->getClassName());
+ }
+
+ public function find($id): ?PersonDocument
+ {
+ return $this->repository->find($id);
+ }
+
+ public function findAll()
+ {
+ return $this->repository->findAll();
+ }
+
+ public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null)
+ {
+ return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
+ }
+
+ public function findOneBy(array $criteria): ?PersonDocument
+ {
+ return $this->repository->findOneBy($criteria);
+ }
+
+ public function getClassName(): string
+ {
+ return PersonDocument::class;
+ }
+}
diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/delete.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/delete.html.twig
index c9bb608cf..d6f23d09d 100644
--- a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/delete.html.twig
+++ b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/delete.html.twig
@@ -31,8 +31,8 @@
'title' : 'Delete document ?'|trans,
'display_content' : block('docdescription'),
'confirm_question' : 'Are you sure you want to remove this document ?'|trans,
- 'cancel_route' : 'accompanying_course_document_index',
- 'cancel_parameters' : {'course' : accompanyingCourse.id, 'id': document.id},
+ 'cancel_route' : 'chill_docstore_generic-doc_by-period_index',
+ 'cancel_parameters' : {'id' : accompanyingCourse.id},
'form' : delete_form
} ) }}
{% endblock %}
diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/edit.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/edit.html.twig
index 0ca5661fc..326814502 100644
--- a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/edit.html.twig
+++ b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/edit.html.twig
@@ -21,7 +21,7 @@
diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/index.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/index.html.twig
deleted file mode 100644
index 7a013260c..000000000
--- a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/index.html.twig
+++ /dev/null
@@ -1,52 +0,0 @@
-{% extends "@ChillPerson/AccompanyingCourse/layout.html.twig" %}
-
-{% set activeRouteKey = '' %}
-
-{% block title %}
- {{ 'Documents' }}
-{% endblock %}
-
-{% block js %}
- {{ parent() }}
- {{ encore_entry_script_tags('mod_docgen_picktemplate') }}
- {{ encore_entry_script_tags('mod_entity_workflow_pick') }}
- {{ encore_entry_script_tags('mod_document_action_buttons_group') }}
-{% endblock %}
-
-{% block css %}
- {{ parent() }}
- {{ encore_entry_link_tags('mod_docgen_picktemplate') }}
- {{ encore_entry_link_tags('mod_entity_workflow_pick') }}
- {{ encore_entry_link_tags('mod_document_action_buttons_group') }}
-{% endblock %}
-
-{% block content %}
-
-
{{ 'Documents' }}
-
- {% if documents|length == 0 %}
-
{{ 'No documents'|trans }}
- {% else %}
-
- {% for document in documents %}
- {% include '@ChillDocStore/List/list_item.html.twig' %}
- {% endfor %}
-
- {% endif %}
-
- {{ chill_pagination(pagination) }}
-
-
-
- {% if is_granted('CHILL_ACCOMPANYING_COURSE_DOCUMENT_CREATE', accompanyingCourse) %}
-
- {% endif %}
-
-
-{% endblock %}
diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/new.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/new.html.twig
index 01be1a5d7..3fb692c78 100644
--- a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/new.html.twig
+++ b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/new.html.twig
@@ -25,7 +25,7 @@