Compare commits

..

2 Commits

Author SHA1 Message Date
8423c6c99c fix banners: resolve_center is always an iterable 2021-11-22 10:55:38 +01:00
03feb78037 fix down migration 2021-11-22 10:49:56 +01:00
2676 changed files with 125444 additions and 139684 deletions

View File

@@ -18,10 +18,3 @@ max_line_length = 80
[COMMIT_EDITMSG]
max_line_length = 0
<<<<<<< Updated upstream
=======
[*.{js, vue, ts}]
indent_size = 2
indent_style = space
>>>>>>> Stashed changes

64
.env Normal file
View File

@@ -0,0 +1,64 @@
##
## Manually dump .env files in .env.local.php with
## `$ composer symfony:dump-env prod`
##
## Project environment
APP_ENV=dev
## Enable debug
APP_DEBUG=true
## Locale
LOCALE=fr
## Framework secret
APP_SECRET=ThisTokenIsNotSoSecretChangeIt
## Symfony/swiftmailer
MAILER_TRANSPORT=smtp
MAILER_HOST=smtp
MAILER_PORT=1025
MAILER_CRYPT=
MAILER_AUTH=
MAILER_USER=
MAILER_PASSWORD=
MAILER_URL=${MAILER_TRANSPORT}://${MAILER_HOST}:${MAILER_PORT}?encryption=${MAILER_CRYPT}&auth_mode=${MAILER_AUTH}&username=${MAILER_USER}&password=${MAILER_PASSWORD}
## Notifications
NOTIFICATION_HOST=localhost:8001
NOTIFICATION_FROM_EMAIL=admin@chill.social
NOTIFICATION_FROM_NAME=Chill
## Gelf
GELF_HOST=gelf
GELF_PORT=12201
## OVH OpenStack Storage User/Role
OS_USERNAME=
OS_PASSWORD=
OS_TENANT_ID=
OS_REGION_NAME=GRA
OS_AUTH_URL=https://auth.cloud.ovh.net/v2.0/
## OVH OpenStack Storage Container
ASYNC_UPLOAD_TEMP_URL_KEY=
ASYNC_UPLOAD_TEMP_URL_BASE_PATH=
ASYNC_UPLOAD_TEMP_URL_CONTAINER=
## Redis Cache
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT}
## Twilio
TWILIO_SID=~
TWILIO_SECRET=~
## DOCKER IMAGES REGISTRY
#IMAGE_PHP=
#IMAGE_NGINX=
## DOCKER IMAGES VERSION
#VERSION=test
VERSION=prod

View File

@@ -3,3 +3,4 @@
# Run tests from root to adapt your own environment
KERNEL_CLASS='App\Kernel'
APP_SECRET='$ecretf0rt3st'
DATABASE_URL=postgresql://postgres:postgres@db:5432/postgres?serverVersion=12&charset=utf8

4
.gitignore vendored
View File

@@ -1,5 +1,4 @@
.composer/*
composer
composer.phar
composer.lock
docs/build/
@@ -21,6 +20,3 @@ docs/build/
.phpunit.result.cache
###< phpunit/phpunit ###
/.php-cs-fixer.cache
/.idea/
/.psalm/

View File

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

View File

@@ -1,79 +0,0 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
/** @var \drupol\PhpCsFixerConfigsPhp\Config\Php73 $config */
$config = require __DIR__ . '/tests/app/vendor/drupol/php-conventions/config/php73/php_cs_fixer.config.php';
$config
->getFinder()
->ignoreDotFiles(false)
->notPath('tests/app')
->name(['.php_cs.dist.php']);
$rules = $config->getRules();
$riskyRules = [
'ternary_to_elvis_operator' => false,
'php_unit_mock_short_will_return' => false,
'php_unit_set_up_tear_down_visibility' => false,
'php_unit_construct' => false,
'php_unit_dedicate_assert' => false,
'php_unit_expectation' => false,
'php_unit_mock' => false,
'php_unit_namespaced' => false,
'php_unit_no_expectation_annotation' => false,
'php_unit_test_case_static_method_calls' => false,
'php_unit_test_annotation' => false,
// 'final_internal_class' => false,
// 'strict_param' => false,
// 'declare_strict_types' => false,
// 'strict_comparison' => false,
// 'no_unreachable_default_argument_value' => false,
// 'ereg_to_preg' => false,
// 'ordered_interfaces' => false,
// 'error_suppression' => false,
// 'non_printable_character' => false,
// 'ordered_traits' => false,
// 'no_useless_sprintf' => false,
// 'dir_constant' => false,
// 'no_alias_functions' => false,
// 'implode_call' => false,
// 'combine_nested_dirname' => false,
// 'pow_to_exponentiation' => false,
// 'comment_to_phpdoc' => false,
// 'no_unset_on_property' => false,
// 'native_constant_invocation' => false,
// 'function_to_constant' => false,
// 'is_null' => false,
// 'native_function_invocation' => false,
// 'no_trailing_whitespace_in_string' => false,
// 'array_push' => false,
// 'fopen_flag_order' => false,
// 'fopen_flags' => false,
// 'logical_operators' => false,
// 'modernize_types_casting' => false,
// 'no_homoglyph_names' => false,
// 'no_unneeded_final_method' => false,
// 'random_api_migration' => false,
// 'static_lambda' => false,
// 'set_type_to_cast' => false,
// 'string_line_ending' => false,
// 'psr_autoloading' => false,
];
$rules = array_merge(
$rules,
$riskyRules
);
$rules['header_comment']['header'] = trim(file_get_contents(__DIR__ . '/resource/header.txt'));
return $config->setRules($rules);

View File

@@ -12,495 +12,6 @@ and this project adheres to
<!-- write down unreleased development here -->
## Test releases
### 2.0.0-beta2
* [workflow]: Fixed: the notification is sent when the user is added to the first step.
* [budget] Feature: allow to desactivate some charges and resources, adding an `active` key in the configuration
* [person] Feature: on Evaluation, allow to configure an URL from the admin
### 2022-06
* [workflow]: added pagination to workflow list page
* [homepage_widget]: null error on tasks widget fixed
* [person-thirdparty]: fix quick-add of names that consist of multiple parts (eg. De Vlieger) within onthefly modal person/thirdparty
* [search]: Order of birthdate fields changed in advanced search to avoid confusion.
* [workflow]: Constraint added to workflow (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/675)
* [household]: Reposition and cut button for enfant hors menage have been deleted (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/620)
* [admin]: Add crud for composition type in admin (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/611)
### 2022-05-30
* fix creating a new AccompanyingPeriodWorkEvaluationDocument when replacing the document (the workflow was lost)
### 2022-05-27
* [storedobject] add title field on StoredObject entity + use it in activity documents (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/604)
* [main] add a "read more..." on comment embeddable when overflown (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/604)
* [person] add closing motive to closed acc course (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/603)
* [person] household filiation: fetch person info when unfolding person (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/586)
* [admin] repair edit of social action in the admin (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/601)
* [admin]: add select2 to Goal form type entity fields (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/702)
* [main] allow hide permissions group list menu (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/577)
* [main] allow hide change user password menu (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/577)
* [main] filter user jobs by active jobs (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/577)
* [main] add civility to User (entity, migration and form type) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/577)
* [admin] refactorisation of the admin section: reorganisation of the menu, translations, form types, new entities (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/592)
* [admin] add admin section for languages and countries (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/596)
* [activity] activity admin: translations + remove label field for comment on admin activity type (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/587)
* [main] admin user_job: improvements (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/588)
* [address] can add extra address info even if noAddress (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/576)
### 2022-05-06
* [person] add civility when creating a person (with the on-the-fly component or in the php form) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/557)
* [person] add address when creating a person (with the on-the-fly component or in the php form) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/557)
* [person] add household creation API point (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/557)
### 2021-04-29
* [person] prevent circular references in PersonDocGenNormalizer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/527)
* [person] add maritalStatusComment to PersonDocGenNormalizer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/582)
* Load relationships without gender in french fixtures
* Add command to remove old draft accompanying periods
* [parcours]: If users assings him/herself as referrer and job is not null. Update parcours job (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/578)
### 2021-04-28
* [address] fix bug when editing address: update location and addressreferenceId + better update of the map in edition (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/593)
* [main] avoid address reference search on undefined post code (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/561)
* [person] prevent duplicate relationship in filiation/household graph (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/560)
* [Documents] Validate storedObject and allow for null data (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/565)
* [parcours]: Comments can be unpinned + edit/delete for all users that are allowed to edit parcours (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/566)
### 2021-04-26
* [Datepickers] datepickers fixed when using keyboard to enter date (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/545)
* [social_action] Display 'agents traitants' in parcours resumé and social action list (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/568)
* [Person_search] Closed parcours shown within an accordeon that can be opened/closed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/574)
### 2021-04-24
* [notification email on course designation] allow raw string in email content generation
* [Accompanying period work] list evaluations associated to a work by startDate, and then by id, from the most recent to older
* [Documents] Change wording 'créer' to 'enregistrer' (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/634)
* [Parcours]: The number of 'mes parcours' displayed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/572)
* [Hompage_widget]: Renaming of tabs and removal of social actions tab (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/570)
* [activity]: Ignore thirdparties when creating a social action via an activity (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/573)
* [parcours]: change wording of warning message and button when user is not associated to a household yet (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/590#note_918370943)
* [Accompanying period work evaluations] list documents associated to a work by creation date, and then by id, from the most recent to older
* [Course comment] add validationConstraint NotNull and NotBlank on comment content, to avoid sql error
* [Notifications] delay the sending of notificaiton to kernel.terminate
* [Notifications / Period user change] fix the sending of notification when user changes
* [Activity form] invert 'incoming' and 'receiving' in Activity form
* [Activity form] keep the same order for 'attendee' field in new and edit form
* [list with period] use "sameas" test operator to introduce requestor in list
* [notification email on course designation] allow raw string in email content generation
* [Accompanying period work] list evaluations associated to a work by startDate, and then by id, from the most recent to older
* [evaluation_document] changing date to datetime in order to display the time at which document was created (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/569)
### 2021-04-13
* [person] household address: add a form for editing the validFrom date (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/541)
* [person] householdmemberseditor: fix composition type bug in select form (vuejs) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/543)
* [docgen] add more persons choices in docgen for course: amongst requestor (if person), resources of course (if person), and PersonResource (if person);
* [docgen] add a new context with a list of activities in course
* [docgen] add a comment in budget lines
* [notifications] allow to send a notification to an email address. The address receive an access link
* [adresses] add constraints in database to avoid errors later: postcode not null, and validfrom <= validto
* [accompanying work editor] add a label on document title input
### 2021-04-07
* notification list: move action buttons outside of the toggle
* fix detecting of non-read notification
* filter users which are disabled in search user api
* order query for location and add pagination in list
* allow every person which has part for a workflow to see the workflow page
* able to see the workflow if the evaluation document has been deleted
* hardcode the list of supported mime types for edition with collabora
* list of accompanying course: allow to see the pinned comment in list_item
### 2021-04-06
* [main] notification toggle read: correct js syntax for compilation in production (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/548)
* [parcours] Display of interlocuteurs changed to flex-table in parcours edit page to prevent cut-off of information (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/535)
* [activity] espace entre les boutons pour supprimer les documents
### continuous release in February and March
* Creation of PickCivilityType, and implementation in PersonType and ThirdpartyType
* [person] Accompanying course evaluation documents: disable the WOPI edit link if mimetype not supported and if no keyInfos
(https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/585)
* [activity] display error messages above the form in creating a new location (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/481)
* [activity] show required field in activity edit/new by an asterix in the vuejs fields (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/494)
* [ACL] fix allow to see the course, event if the scope'course does not contains the scope's user
* [search] enforce limit of results for fetching rsults by search api https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/576
* [activity] Fix delete button for document (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/554)
* [activity] Add return path the document generation (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/553)
* [person] add person ressource to person docgen normaliser (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/517)
* [person] AccompanyingCourseWorkEdit: fix deleting evaluation documents (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/546)
* [person] AccompanyingCourseWorkEdit: download existing documents (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/512)
* [person] AccompanyingCourseWorkEdit: replace document by a new one (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/511)
* [person] AccompanyingPeriodWork: add referrers to work, add doctrine event listener to add logged user to referrers collection and display a referrers list in work list (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/502)
* [person] AccompanyingPeriodWorkEvaluation: fix circular reference when serialising (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/495)
* [person] order accompanying period by opening date in search persons, person and household period lists (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/493)
* [parcours] autosave of the pinned comment for draft accompanying course (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/477)
* [main] filter user job in undispatch acc period to assign (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/472)
* [main] filter user job in undispatch acc period to assign (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/472)
* [person] Add url in accompanying period work evaluations entity and form (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/476)
* [person] Add document generation in admin and in person/{id}/document (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/464)
* [activity] do not override location if already exist (when validating new activity) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/470)
* [parcours] Toggle emergency/intensity only by referrer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/442)
* [docstore] Add an API entrypoint for StoredObject (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/466)
* [person] Add the possibility of uploading existing documents to AccPeriodWorkEvaluationDocument (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/466)
* [person] Add title to AccPeriodWorkEvaluationDocument (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/466)
* [person] Order social issues by the field "ordering" (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/388)
* [Person/Household list] when listing other simultaneous members of an household, exclude the members on person, not on members (avoid to show two membersship with the same person)
* [draft periods] add a delete button (if acl granted) on each draft period listed on draft period page (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/463)
* [Person] Display suffixText in RenderPerson, PersonText.vue, RenderPersonBox.vue (was made for displaying "enfant confie") (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/441)
* [budget]: budget enabled for persons and households (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/469)
* [person] residential address: show residential address or info in PersonRenderBox, refactor Residential Address (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/439)
* [thirdparty] Add a contact to a thirdparty from within onTheFly (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/345)
* [documents] Improve flex-table item-col placement when long buttons and long metadata
* [thirdparty] Fix display of multiple contact badges so they wrap onto next line (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/482)
* [confidential] Fix position of toggle button so it does not cover text nor fall outside of box (no issue)
* [parcours] Fix edit of both thirdparty and contact name (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/474)
* [template] do not list inactive templates (for doc generator)
* [household] bugfix if position of member is null, renderbox no longer throws an error (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/480)
* [parcours] location cannot be removed if linked to a user (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/478)
* [person] email added to twig personRenderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/490)
* [activity] Only youngest descendant is kept for social issues and actions (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/471)
* [person] Add link to current household in person banner (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/484)
* [address] person badge in address history changed to open OnTheFly with all person info (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/489)
* [person] Change 'personne' with 'usager' and '&' with 'ET' (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/499)
* [thirdparty] Add parameter condition to display centers or not (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/500)
* [phonenumber] Remove placeholder in phonenumber field (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/496)
* [person_resource] separate create page created to avoid confusion (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/504)
* [contact] add contact button color changed plus the pipe at the side removed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/506)
* [thirdparty] For contacts show current civility/profession in edit form + fix saving of edited information (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/491)
* [household] create-edit household composition placed in separate page to avoid confusion (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/505)
* [blur] Improved positioning of toggle icon (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/486)
* [thirdparty] add firstname field to thirdparty 'child' or 'contact' types (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/508)
* [household] create-edit household composition placed in separate page to avoid confusion (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/505)
* [blur] Improved positioning of toggle icon (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/486)
* [parcours] List of parcours for a specific user so they can be reassigned in case of absence (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/509)
* [thirdparty] Thirdparty view page, english text translated (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/534)
* [social_action] Translation changed in evaluation section (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/512)
* [filiation] Possible to add person (or create onthefly) to add to filiation graph + add relation (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/519)
* [household] Within parcours listing page of household add create button (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/560)
* [person_resource] bugfix when adding thirdparty or freetext resource + prevent personOwner themselves to be added. (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/526)
* [aside_activity] style correction + sticky-form create button (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/529)
* [budget] order within the menu adjusted (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/592)
* [onthefly] fix create person. Bug was noticed in filiation (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/591)
* [parcours] Create document buttons made sticky (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/532)
* [person] Trailing guillemet removed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/530)
* [notification] Display of social action within workflow notification set to display block (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/537)
* [onthefly] trim trailing whitespace in email of person and thirdparty (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/542)
* [action] Only youngest descendant is kept for social issues and actions (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/471)
## Test releases
### test release 2022-02-21
* [notifications] Word 'un' changed to number '1' for notifications in user menu (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/483)
* [documents] 'gabarit' changed to 'modèle' (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/405)
* [person_resources] Menu name and order changed (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/460)
* workflow: fix sending notifications
* [thirdparty] Extend the thirdparty search to thirdparty children (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/448)
* [person]: AddPersons: allow creation of person or thirdparty only (no users) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/422)
* [person]: AddPersons: allow creation of person or thirdparty depending on allowed types (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/422)
* [person]: AddPersons: add suggestion of name when creating new person or thirdparty (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/422)
* [main] Address: fix small bug: when modifying an address without street (isNoAddress), also check errors if street is an empty string as back-end change null value to empty string for street (and streetNumber)
* [main] Address: stronger client-side validation of addresses (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/449)
* [person] accompanying course: filter suggested entities by open participations (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/415)
[activity] can click through the cross icon for removing person in concerned group (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/476)
[activity] correct associated persons by considering only open participations (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/476)
* [person_resources]: Renderboxes used to display person/thirdparty info (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/465)
* [Household]: Add end date in HouseholdMember form for 'enfant hors menage' (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/434)
* [homepage_widget]: If no sender then display as 'notification automatique' (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/435)
* [parcours]: Order social activities and only display most recent three in parcours resumé (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/481)
* [3party]: 3party: redirect to parent when contact (child) is opened in view page
* [parcours / addresses]: launch an event when a person change address (either through changing household or because the household is associated to a new address). If the person is localising a course, the course location go back to a temporarily address.
* [thirdparty]: address/phonenumber/email/fonction displayed in thirdpartyrenderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/401)
* [thirdparty_contact]: in search results the 'qualité' is displayed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/465)
* [bug]: fix confidential toggle of address in thirdpartyrenderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/460)
### test release 2022-02-14
* AddPersons: remove ul-li html tags from AddPersons (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/419)
* [doc-generator] do not set required fields for mainPerson, person1, person2 (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement#456)
* [doc-generation] add age and obele in the mainPerson, person1 and person2 list + add obele in person renderString if addAge (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/370)
* [person] accompanying course work: fix on-the-fly update of thirdParty
* fix normalisation of accompanying course requestor api (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/378)
* [person] add a returnPath when clicking on some Person or ThirdParty badge (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/427)
* [person] accompanying course work: fix on-the-fly update of thirdParty
* [on-the-fly] close modal only after validation
* [person] correct thirdparty PATCH url + add email and altnames in AddPerson and serializer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/433)
* change order for accompanying course work list
* [parcours]: Mes parcours brouillon added to user menu (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/440)
* [Documents]: List view adapted to display more information (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/414)
* [person]: style fix in parcours listing per person. (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/432)
* [parcours]: Only the referrer can toggle the intensity of the parcours (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/442)
* [household]: display address of current household (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/415)
* ajoute un ordre dans les localisation (api)
* [pick entity]: fix translations in modal (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/419)
* [homepage_widget]: fix translation on emergency badge (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/440)
* [person]: create person and household added to button dropdown (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/454)
* display full address in address.text in normalization. Adapt AddressRenderBox
* [address]: Correction residential address 'depuis le' (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/459)
* [Documents]: List view adapted to display more information (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/414)
* [Thirdparty_contact]: address blurred if confidential in view page (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/450)
* [thirdparty] Add a contact to a thirdparty from within onTheFly (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/345)
### test release 2021-02-01
* renommer "dossier numéro" en "parcours numéro" dans les résultats de recherche
* renomme date de début en date d'ouverture dans le formulaire parcours
* [homepage widget] improve content tables, improve counter pluralization with style on number
* [notification lists] add comments counter information
* [workflows] fix popover header with previous transition
* [parcours]: validation + message for closing parcours adjusted.
* [household]: household composition double edit button replaced by a delete action (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/426)
[fast_actions] improve fast-actions buttons override mechanism, fix https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/413
[homepage widget] add vue homepage_widget with asynchone loading, give a global view resume of the user concerned actions, notifications, etc.
* [person]: Comment on marital status is possible even if marital status is not defined (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/421)
* [parcours]: In the list of person results the requestor is not displayed if defined as anonymous (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/424)
* [bugfix]: modal closes and newly created person/thirdparty is selected when multiple persons/thirdparties are created through the modal (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/429)
* [person_resource]: Onthefly button added to view person/thirdparty and badge differentiation for a contact-thirdparty (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/428)
* [workflow][notification] improve how notifications and workflows are 'attached' to entities: contextual list, counter, buttons and vue modal
* [AddAddress] disable multiselect search, and rely only on most pertinent Cities and Street computed backend
* [fast_actions] improve fast-actions buttons override mechanism, fix https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/413
* [homepage widget] add vue homepage_widget with asynchone loading, give a global view resume of the user concerned actions, notifications, etc.
* [thirdparty] Add a contact to a thirdparty from within onTheFly (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/345)
* [homepage widget] add vue homepage_widget with asynchone loading, give a global view resume of the user concerned actions, notifications, etc.
### test release 2021-01-31
* [person] accompanying course: optimisation: do not fetch some resources for the banner (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/409)
* [person] accompanying course: close modal when edit participation (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/420)
* [person] accompanying course: treat validation error when editing on-the-fly entities (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/420)
* [activity] show activity attendee (présence) in the activity list (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/412)
* [activity] admin: change validation rule for social action visible field (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/413)
* [parcours]: component added to change the opening date of a parcours (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/411)
* [search]: listing of parcours display changed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/410)
* [user]: page with accompanying periods to which is user is referent (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/408)
* [person] age added to renderstring + renderbox/ vue component created to display person text (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/389)
* [household member editor] allow to push to existing household
### test release 2021-01-28
* [person] improve filiations vis graph: disable physics, use chill colors for persons-households-course, increase label of relations, remove labels on household arrows and other improvements (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/286, https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/362)
* [activity] Order activity by date and by id (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/364)
* [main] increase length of 4 Address fields (change to TEXT, no size limits) (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/277)
* [main] Add confidential option for address, in edit and view (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/165)
* [person] name suggestions within create person form when person is created departing from a search input (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/377)
* [person] Add residential address entity, form and list for each person
* [aside_activity]: dynamicUserPickerType used (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/399)
* dispatching list
### test release 2021-01-26
* [parcours] comments truncated if too long + link added (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/406)
* [person]: possibility to add person resources (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/382)
* [person ressources]: module added
### test release 2022-01-24
* [person] name suggestions within create person form when person is created departing from a search input (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/377)
* [notification: formulaire création] descend la box avec la description dans le bas du formulaire
* [notification for activity]: fix link to activity
* [notification] add "URGENT" before accompanying course with emergency = true
* [notification] add a "read more" button on system notification
* [notification] add `[Chill]` in the subject of each notification, automatically
* [notification] add a counter for notification in activity list and accompanying period list, and search results
* [parcours] bugfix if deathdate is not defined (eg. for a thirdparty) parcours is still displayed. Gave error before.
* [workflow] add breadcrumb to show steps
* [popover] add popover html popup mechanism (used by workflow breadcrumb)
* [templates] improve updatedBy macro in item metadatas
* [parcours]: bug fix when comment is pinned all other comments remain in the collection (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/385)
* [workflow]
* add My workflow section with my opened subscriptions
* apply workflow on documents, accompanyingCourseWork and Evaluations
* [wopi-link] a new vue component allow to open wopi link in a fullscreen chill-themed modal
### test release 2022-01-19
* vuejs: add dead information on all on-the-fly person render boxes, in vis graph and other templates (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/271)
* [thirdparty] fix bug in 3rd party view: types was replaced by thirdPartyTypes
* [main] location form type: fix unmapped address field (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/246)
* [activity] fix wrong import of js assets for adding and viewing documents in activity (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/83 & https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/176)
* [person]: space added between deathdate and age in twig renderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/380)
* [forms] dynamic picker types for user/person/thirdparty types created (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/386)
### test release 2022-01-17
* [main] Add editableByUser field to locationType entity, adapt the admin template and add this condition in the location-type endpoint (see https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/297)
* [main] Add mainLocation field to User entity and add it in user form type
* rewrite page which allow to select activity
* [main] Add mainLocation field to User entity and add it in user form type
* [course list in person context] show full username/label for ref
* [accompanying period work] remove the possibility to generate document from an accompanying period work
* vuejs: add validation on required fields for AddPerson, Address and Location components
* vuejs: treat 422 validation errors in locations and AddPerson components
* [person]: space added between deathdate and age in twig renderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/380)
## Test releases
* vuejs: add validation on required fields for AddPerson, Address and Location components
* vuejs: treat 422 validation errors in locations and AddPerson components
* [person]: space added between deathdate and age in twig renderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/380)
### test release 2022-01-12
* fix thirdparty normalizer on telephone field: https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/322
### test release 2022-01-11
* vuejs: translate in French all multiselect widgets
* [address] define address lines according postal standards for France and Belgium (default) and change AddressRender, chill_entity_render_box and AddressRenderBox.vue
* [household] change translations (champs-libres/departement-de-la-vendee/accent-suivi-developpement#109)
* [household] add address i18n in household component (champs-libres/departement-de-la-vendee/accent-suivi-developpement#158)
* [household] add on the fly i18n in household component
* [household] redirect to the household page when a household is created from a person (champs-libres/departement-de-la-vendee/accent-suivi-developpement#175)
* [household] household member editor: display alert if some members have already an household (champs-libres/departement-de-la-vendee/accent-suivi-developpement#172)
* [household] household member editor: do not add in new members if the member is included in the members of household (champs-libres/departement-de-la-vendee/accent-suivi-developpement#123)
* [household] household member editor: remove markNoAddress button (champs-libres/departement-de-la-vendee/accent-suivi-developpement#109)
* [person]: ordering fields in add person (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/61)
* [person]: Add email and alt names in add person (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/61)
* [accompanyingCourse] Add a delete action and delete buttons to delete a accompanying course when step = DRAFT (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/64)
* [accompanyingCourse] Add a administrative location in the accompanying course, set the user current location as default, allow to select a location in a select field and do not allow to confirm the accompanying course if location is empty.
* [accompanyingCourse] Add the administrative location in the available variables for document generation
* AddAddress: optimize loading: wait for the user finish typing;
* UserPicker: fix bug with deprecated role
* docgen: add base context + tests
* docgen: add age for person
* [household menu] fix filiation order https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/265
* [AddAddress]: optimize loading: wait for the user finish typing;
* [UserPicker]: fix bug with deprecated role
* [docgen]: add base context + tests
* [docgen]: add age for person
* [task]: fix dropdown menu style + fix bug in singleTaskController (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/338)
* Household: fix bug when moving person on the same day (see https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/281)
* Household: show date validFrom and validTo when moving
* address reference: add index for refid
* [accompanyingCourse_work] fix styles conflicts + fix bug with remove goal (remove goals one at a time)
* [accompanyingCourse] improve masonry on resume page, add origin
* [notification] new notification interface, can be associated to AccompanyingCourse/Period, Activities.
* List notifications, show, and comment in User section
* Notify button and contextual notification box on associated objects pages
* [accompanyingCourse] add a comment for each resource associated. A modal allow to save comment. Comment is displayed in on-the-fly show modal of the accompanyingCourse context (edit page + resume page).
### test release 2021-12-14
* [asideactivity] creation of aside activity category fixed (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/262)
* [vendee/person] fix typo "situation professionelle" => "situation professionnelle"
* [main] add availableForUsers condition from locationType in the location API endpoint (champs-libres/departement-de-la-vendee/accent-suivi-developpement#248)
* [main] add the current location of the user as API point + add it in the activity location list (champs-libres/departement-de-la-vendee/accent-suivi-developpement#247)
* [activity] improve show/new/edit templates, fix SEE and SEE_DETAILS acl
* [badges] create specific badge for TMS, and make person/thirdparty badges clickable with on-the-fly modal in :
* concerned groups items (activity, calendar)
* accompanyingCourseWork lists
* accompanyingCourse lists
* [acompanyingCourse] add initial comment on Resume page
* [person] create button full width (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/330)
### test release 2021-12-11
* [main] add order field to civility
* [main] change address format in case the country is France, in Address render box and address normalizer
* [person] add validator for accompanying period with a test on social issues (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/76)
* [activity] fix visibility for location
* [origin] fix origin: use correctly the translatable strings
* /!\ everyone must update the origin table. As there is only one row, execute `update chill_person_accompanying_period_origin set label = jsonb_build_object('fr', 'appel téléphonique');`
* [person] redirect bug fixed.
* [action] add an unrelated issue within action creation.
* [origin] fix origin: use correctly the translatable strings
* /!\ everyone must update the origin table. As there is only one row, execute `update chill_person_accompanying_period_origin set label = jsonb_build_object('fr', 'appel téléphonique');`
* [main] change order of civilities in civility fixtures (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191)
* [person] set min attr in the minimum of children field (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191)
* [person] add marital status date in person view (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191)
* [person] show number of children + allow set number of children to null (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191)
* [person] show acceptSMS option (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191)
* [person] add death information in person render box in twig and vue render boxes (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191)
* [asideactivity] creation of aside activity category fixed (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/262)
* [vendee/person] fix typo "situation professionelle" => "situation professionnelle"
* [accompanyingcourse_work] Changes in layout/behavior of edit form (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/321)
* [badge-entity] design coherency between pills badge-person and 3 kinds of badge-thirdparty
* [AddPersons] suggestions row are clickable, not only checkbox
### test release 2021-12-06
* [main] address: use search API end points for getting postal code and reference address (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/316)
* [main] address: in edit mode, select the encoded values in multiselect for address reference and city (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/316)
* [person search] fix bug when using birthdate after and birthdate before
* [person search] increase pertinence when lastname begins with search pattern
* [activity/actions] Améliore la cohérence du design entre
* la page résumé d'un parcours (liste d'actions récentes et liste d'activités récentes)
* la page liste des actions
* la page liste des activités (contexte personne / contexte parcours)
* [household] field to edit wheter person is titulaire of household or not removed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/322)
* [activity] create work if a work with same social action is not associated to the activity
* [visgraph] improve and fix bugs on vis-network relationship graph
* [bugfix] posting of birth- and deathdate through api fixed.
* [suggestions] improve suggestions lists
### Test release 2021-11-19 - bis
* [household] do not allow to create two addresses on the same date
* [activity] handle case when there is no social action associated to social issue
* [activity] layout for issues / actions
* [activity][bugfix] in edit mode, the form will now load the social action list
### Test release 2021-11-29
* [person] suggest entities (person | thirdparty) when creating/editing the accompanying course (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/119)
* [activity] add custom validation on the Activity class, based on what is required from the ActivityType (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/188)
* [main] translate multiselect messages when selecting/creating address
* [main] set the coordinates of the city when creating a new address OR choosing "pas d'adresse complète"
* Use the user.label in accompanying course banner, instead of username;
* fix: show validation message when closing accompanying course;
* [thirdparty] link from modal to thirdparty detail page fixed (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/228)
* [assets] new asset to style suggestions lists (with add/remove item link) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/258)
* [accompanyingCourseWorkEdit] improves hyphenation and line breaks for long badges
* [acompanyingCourse] improve Resume page
* complete all needed informations,
* actions and activities are clickables,
* better placement with js masonry blocks on top of content area,
* https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/101
* https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/295
* [activity/calendar] on show page, concerned groups of persons table adapt itself to isVisibles options
* [activity] remove the "plus" button in activity list
* [activity] check ACL on activity list in person context
* [list for accompanying course in person] filter list using ACL
* [validation] toasts are displayed for errors when modifying accompanying course (generalization required).
* [period] only the user can enable confidentiality
* add an endpoint for checking permissions. See https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/232
* [activity] for a new activity: suggest and create on-the-fly locations based on the accompanying course location + location of the suggested parties
* [calendar] for a new rdv: suggest and create on-the-fly locations based on the accompanying course location + location of the suggested parties
* [period] Validation added when period is confidential and confirmed -> user cannot be null.
## Test releases
### Test release 2021-11-22
* [activity] delete admin_user_show in twig template because this route is not defined and should be defined
* [activity] suggest requestor, user and ressources for adding persons|user|3rdparty
* [calendar] suggest persons, professionals and invites for adding persons|3rdparty|user
* [activity] take into account the restrictions on person|thirdparties|users visibilities defined in ActivityType
* [main] Add currentLocation to the User entity + add a page for selecting this location + add in the user menu (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/133)
* [activity] add user current location as default location for a new activity (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/133)
* [task] Select2 field in task form to allow search for a user (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/167)
* remove "search by phone configuration option": search by phone is now executed by default
* remplacer le classement par ordre alphabétique par un classement par ordre de pertinence, qui tient compte:
@@ -517,11 +28,9 @@ and this project adheres to
* [person] create an accompanying course: add client-side validation if no origin (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/210)
* [person] fix bounds for computing current person address: the new address appears immediatly
* [docgen] create a normalizer and serializer for normalization on doc format
* [person normalization] the key center is now "centers" and is an array. Empty array if no center
* [accompanyingCourse] Ability to close accompanying course (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/296)
* [task] Select2 field in task form to allow search for a user (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/167)
* [list result] show all courses, except ones with period closed
* [accompanyingCourse] improve banner with small carousel to display slide social-issues or slide associated persons (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/69)
## Test releases
### Test release 2021-11-15
@@ -539,8 +48,6 @@ and this project adheres to
* [person] do not ask for center any more on person creation
* [3party] do not ask for center any more on 3party creation
## Test releases
### Test release 2021-11-08
* [person]: Display the name of a user when searching after a User (TMS)
@@ -607,7 +114,7 @@ and this project adheres to
* fast creation buttons
* add ordering for types
* [AccompanyingCourse Resume page] dashboard for AccompanyingCourseWork and for Activities;
* [AccompanyingCourse Resume page] badge-title for AccompanyingCourseWork and for Activities;
* Improve badges behaviour with small screens;
* [ThirdParty]:

View File

@@ -2,14 +2,7 @@
en cours de rédaction
## Translations
Par bundle, toutes les traductions des pages twig se trouvent dans un seul fichier `translations/messages.fr.yaml`.
## Emplacement des fichiers
Les controllers, form type & templates twig sont placés à la racine des dossiers `Controller`, `Form` & `Ressources/views`, respectivement. Pour les pages Admin, on ne les mets plus dans des sous-dossiers Admin.
## Assets: nommage des entrypoints
Trois types d'entrypoint:
@@ -63,28 +56,28 @@ Arborescence:
Comment s'échaffaudent les styles dans Chill ?
1. l'entrypoint **mod_bootstrap** (module bootstrap) est le premier niveau. Toutes les parties(modules) de bootstrap sont convoquées dans le fichier ```bootstrap.js``` situé dans ```ChillMainBundle/Resources/public/module/bootstrap```.
* Au début, ce fichier importe le fichier ```variables.scss``` qui détermine la plupart des réglages bootstrap tels qu'on les a personnalisés. Ce fichier surcharge l'original, et de nombreuses variables y sont adaptées pour Chill.
1. l'entrypoint **mod_bootstrap** (module bootstrap) est le premier niveau. Toutes les parties(modules) de bootstrap sont convoquées dans le fichier ```bootstrap.js``` situé dans ```ChillMainBundle/Resources/public/module/bootstrap```.
* Au début, ce fichier importe le fichier ```variables.scss``` qui détermine la plupart des réglages bootstrap tels qu'on les a personnalisés. Ce fichier surcharge l'original, et de nombreuses variables y sont adaptées pour Chill.
* On veillera à ce qu'on puisse toujours comparer ce fichier à l'original de bootstrap. En cas de mise à jour de bootstrap, il faudra générer un diff, et adapter ce diff sur le fichier variable de la nouvelle version.
* A la fin on importe le fichier ```custom.scss```, qui comprends des adaptations de bootstrap pour le préparer à notre thème Chill.
* A la fin on importe le fichier ```custom.scss```, qui comprends des adaptations de bootstrap pour le préparer à notre thème Chill.
* ce ```custom.scss``` peut être splitté en plus petits fichiers avec des ```@import 'custom/...'```
* L'idée est que cette première couche bootstrap règle un partie importante des styles de l'application, en particulier ce qui touche aux position du layout, aux points de bascules responsive, aux marges et écarts appliqués par défauts aux éléments qu'on manipule.
2. l'entrypoint **chill** est le second niveau. Il contient le thème Chill qui est reconnaissable à l'application.
* Chaque bundle a un dossier ```Resources/public/chill``` dans lequel on peut trouver une feuille sass principale, qui est éventuellement splittée avec des ```@imports```. Toutes ces feuilles sont compilées dans un unique entrypoint Chill, c'est le thème de l'application. Celui-ci surcharge bootstrap.
* La feuille chillmain.scss devrait contenir les cascades de styles les plus générales, celles qui sont appliquées à de nombreux endroits de l'application.
* La feuille chillmain.scss devrait contenir les cascades de styles les plus générales, celles qui sont appliquées à de nombreux endroits de l'application.
* La feuille chillperson.scss va aussi retrouver des styles propres aux différents contextes des personnes: person, household et accompanyingcourse.
* Certains bundles plus secondaires ne contiennent que des styles spécifiques à leur fonctionnement.
3. les entrypoints **vue_** sont utilisés pour des composants vue. Les fichiers vue peuvent contenir un bloc de styles scss. Ce sont des styles qui ne concernent que le composant et son héritage, le tag ```scoped``` précise justement sa portée (voir la doc).
4. les entrypoints **page_** sont utilisés pour ajouter des assets spécifiques à certaines pages, le plus souvent des scripts et des styles.
4. les entrypoints **page_** sont utilisés pour ajouter des assets spécifiques à certaines pages, le plus souvent des scripts et des styles.
## Taguer du code html et construire la cascade de styles
L'exemple suivant montre comment taguer sans excès un élément de code. On remarque que:
* il n'est pas nécessaire de taguer toutes les classes intérieures,
* il n'est pas nécessaire de taguer toutes les classes intérieures,
* il ne faut pas répéter la classe parent dans toutes les classes enfants. La cascade sass va permettre de saisir le html avec souplesse sans alourdir la structure des balises.
* souvent la première classe sera déclinée par plusieurs classes qui commencent de la même manière: ```bloc-dark``` ajoute juste la version sombre de ```bloc```, on ne met pas ```bloc dark```, car on ne souhaite pas que la classe ```dark``` de ```bloc``` interagisse avec la même classe ```dark``` de ```table```. On aura donc un élément ```bloc bloc-dark``` et un élément ```table table-dark```.
@@ -101,11 +94,11 @@ L'exemple suivant montre comment taguer sans excès un élément de code. On rem
</div>
```
Finalement, il importe ici de définir ce qu'est un bloc, ce qu'est une zone d'actions et ce qu'est un bouton. Ces 3 éléments existent de manière autonome, ce sont les seuls qu'on tagge.
Finalement, il importe ici de définir ce qu'est un bloc, ce qu'est une zone d'actions et ce qu'est un bouton. Ces 3 éléments existent de manière autonome, ce sont les seuls qu'on tagge.
Par exemple pour mettre un style au titre on précise juste h3 dans la cascade bloc.
```scss
```sass
div.bloc {
// un bloc générique, utilisé à plusieurs endroits
&.bloc-dark {
@@ -120,12 +113,12 @@ div.bloc {
}
}
div.mon-bloc {
// des exceptions spécifiques à mon-bloc,
// des exceptions spécifiques à mon-bloc,
// qui sont des adaptations de bloc
}
ul.record_actions {
// va uniformiser tous les record_actions de l'application
// va uniformiser tous les record_actions de l'application
li {
//...
}
@@ -153,20 +146,19 @@ Ces règles n'ont pas toujours été utilisées par le passé. Elles sont souhai
Les routes sont nommées de cette manière:
`chill_(api|crud)_bundle_(api)_entite_action`
`chill_bundle_entite_action`
1. d'abord chill_ (pour tous les modules chill)
2. ensuite `crud` ou `api`, optionnel, automatiquement ajouté si la route est générée par la configuration
3. ensuite une string qui indique le bundle (`main`, `person`, `activity`, ...)
4. ensuite, `api`, si la route est une route d'api.
5. ensuite une string qui indique sur quelle entité porte la route, voire également les sous-entités
6. ensuite une action (`list`, `view`, `edit`, `new`, ...)
2. ensuite une string qui est identique, par bundle
3. si le point est un point d'api (json), alors ajouter la string `api`
4. ensuite une string qui indique sur quelle entité porte la route, voire également les sous-entités
5. ensuite une action (`list`, `view`, `edit`, `new`, ...)
Le fait d'indiquer `api` en quatrième position permet de distinguer les routes d'api qui sont générées par la configuration (qui sont toutes préfixées par `chill_api`, de celles générées manuellement. (Exemple: `chill_api_household__index`, et `chill_person_api_household_members_move`)
Le fait d'indiquer `api` en 3 permet de distinguer les routes d'api qui sont générées par la configuration (qui sont toutes préfixées par `chill_api`, de celles générées manuellement. (Exemple: `chill_api_household__index`, et `chill_person_api_household_members_move`)
Si les points 4 et 5 sont inexistants, alors ils sont remplacés par d'autres éléments de manière à garantir l'unicité de la route, et sa bonne compréhension.
### Nommage des URL
### URL
Les URL respectent également une convention:
@@ -227,14 +219,6 @@ Les éléments suivants devraient se trouver dans la liste:
Ces éléments peuvent être entrecoupés de l'identifiant d'une entité. Dans ce cas, cet identifiant se place juste après l'entité auquel il se rapporte.
#### Pour les URL de l'espace Admin
Même conventions que dans les autres pages html de l'application, **mais `admin` est ajouté en deuxième position**. Soit:
`/{_locale}/admin/bundle/entity/{id}/action`
## Règles UI chill
### Titre des pages
@@ -276,7 +260,7 @@ Exemple:
address|chill_entity_render_box
```
Justification:
Justification:
* des éléments sont parfois personnalisés par installation (par exemple, le nom de chaque utilisateur sera suivi par le nom du service)
* pour rationaliser et rendre semblable les affichages
@@ -286,13 +270,13 @@ A prevoir:
* toujours trois positions:
* inline
* block
* block
* item (dans un tableau, une ligne)
> block et item sont en fait la même option passée au render_box: render: bloc. Il y a aussi raw pour le inline, et label pour une titraille configurable avec des options.
> quand on passe loption render: bloc, on peut placer le render_box dans une boucle for plus large qui fonctionne avec la classe flex-table ou la classe flex-bloc, ce qui donnera un affichage en rangée (table) ou en blocs. [name=Mathieu]
> quand on passe loption render: bloc, on peut placer le render_box dans une boucle for plus large qui fonctionne avec la classe flex-table ou la classe flex-bloc, ce qui donnera un affichage en rangée (table) ou en blocs. [name=Mathieu]
#### En vue
@@ -308,13 +292,13 @@ A chaque fois qu'on indique le nom d'une personne, un parcours, un ménage, il y
Ces éléments sont toujours proposé par des `render_box` par défaut. Des options permettent de les désactiver dans des cas particuliers
> à discuter, quelques réflexion:
> quelle est la logique qui domine pour les boutons ? on a symbolisé les 4 actions du crud par des couleurs: bleu(show) orange(edit) vert(create) et rouge(delete).
> Est-ce que c'est ça qui prime, et comment ça s'articule avec la logique des pictos ?
> à discuter, quelques réflexion:
> quelle est la logique qui domine pour les boutons ? on a symbolisé les 4 actions du crud par des couleurs: bleu(show) orange(edit) vert(create) et rouge(delete).
> Est-ce que c'est ça qui prime, et comment ça s'articule avec la logique des pictos ?
> Par exemple, il pourrait être logique d'utiliser l'oeil bleu pour voir l'objet, qu'il s'agisse d'une personne ou d'un parcours, ce serait plutôt le contexte, et l'infobulle (title) qui préciserait le contexte.
> Je pense que les pictos de boutons doivent faire référence à l'action, mais pas à l'objet. Autrement dit je n'utiliserais jamais l'icone du ménage ou du parcours dans les boutons.
> Pour représenter les ménages et les parcours, je pense qu'il faudrait trouver autre chose que forkawesome. Si c'est des pictos, trouver un motif différents et de tailles différente. Réfléchir à un couplage picto-couleur-forme différent, qui exprime le contexte et qui se distingue bien des boutons.
> Idem pour les badges, il faut une palette de badge qui couvre tous les besoins: socialIssue, socialActions, socialReason, members, etc. [name=Mathieu]
> Idem pour les badges, il faut une palette de badge qui couvre tous les besoins: socialIssue, socialActions, socialReason, members, etc. [name=Mathieu]
### Formulaires
@@ -366,7 +350,7 @@ A chaque fois qu'un élément est créé par un formulaire, un message flash doi
> "L'élément a été créé"
Le nom de l'élément peut être remplacé par quelque chose de plus pertinent:
Le nom de l'élément peut être remplacé par quelque chose de plus pertinent:
> * L'activité a été créée
> * Le rendez-vous a été créé
@@ -378,7 +362,7 @@ Le nom de l'élément peut être remplacé par quelque chose de plus pertinent:
A chaque fois qu'un élément est enregistré, un message flash doit apparaitre:
> * Les données ont été modifiées
>
>
#### Erreur sur un formulaire (erreur de validation)
@@ -393,35 +377,7 @@ Les erreurs doivent apparaitre attachée au champ qui les concerne. Toutefois, i
A chaque fois qu'un lien est indiqué, vérifier si on ne doit pas utiliser la fonction `chill_return_path`, `chill_forward_return_path` ou `chill_return_path_or`.
* depuis la page liste, vers l'ouverture d'un élément, ou le bouton création => utiliser `chill_path_add_return_path`
* dans ces pages d'éditions,
* dans ces pages d'éditions,
* utiliser `chill_return_path_or` dans le bouton "Cancel";
* pour les boutons "enregistrer et voir" et "Enregistrer et fermer" => ?
### Assets pour les listes de suggestion
Créer une liste de suggestions à ajouter (tout l'item est cliquable)
```html
<ul class="list-suggest add-items">
<li>
<span>item</span>
</li>
</ul>
```
Créer une liste de suggestions à enlever (avec une croix rouge cliquable, l'ancre a est vide)
```html
<ul class="list-suggest remove-items">
<li>
<span>
item
</span>
</li>
</ul>
```
Créer un titre enlevable (avec une croix rouge cliquable, l'ancre a est vide)
```html
<div class="item-title">
<span>title</span>
</div>
```
Les classes `cols` ou `inline` peuvent être ajoutées à côté de `list-suggest` pour modifier la disposition de la liste.
Dans le dernier exemple, on met une classe `removable` sur le span, si on veut pouvoir enlever l'élément.

View File

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

View File

@@ -1,87 +1,80 @@
{
"name": "chill-project/chill-bundles",
"description": "Most used bundles for chill-project",
"license": "AGPL-3.0-only",
"type": "library",
"description": "Most used bundles for chill-project",
"keywords": [
"chill",
"social worker"
],
"license": "AGPL-3.0-only",
"require": {
"php": "^7.4",
"champs-libres/async-uploader-bundle": "dev-sf4#d57134aee8e504a83c902ff0cf9f8d36ac418290",
"champs-libres/wopi-bundle": "dev-master#6dd8e0a14e00131eb4b889ecc30270ee4a0e5224",
"champs-libres/wopi-lib": "dev-master#8615f4a45a39fc2b6a98765ea835fcfd39618787",
"champs-libres/async-uploader-bundle": "dev-sf4",
"champs-libres/wopi-bundle": "dev-master",
"composer/package-versions-deprecated": "^1.10",
"doctrine/doctrine-bundle": "^2.1",
"doctrine/doctrine-migrations-bundle": "^3.0",
"doctrine/orm": "^2.7",
"erusev/parsedown": "^1.7",
"graylog2/gelf-php": "^1.5",
"knplabs/knp-menu": "^3.1",
"knplabs/knp-menu-bundle": "^3.0",
"knplabs/knp-time-bundle": "^1.12",
"league/csv": "^9.7.1",
"nyholm/psr7": "^1.4",
"ocramius/package-versions": "^1.10 || ^2",
"odolbeau/phone-number-bundle": "^3.6",
"phpoffice/phpspreadsheet": "^1.16",
"ramsey/uuid-doctrine": "^1.7",
"sensio/framework-extra-bundle": "^5.5",
"spomky-labs/base64url": "^2.0",
"symfony/asset": "^4.4",
"symfony/browser-kit": "^4.4",
"symfony/css-selector": "^4.4",
"symfony/expression-language": "^4.4",
"symfony/form": "^4.4",
"symfony/framework-bundle": "^4.4",
"symfony/http-foundation": "^4.4",
"symfony/intl": "^4.4",
"symfony/mailer": "^5.4",
"symfony/mime": "^5.4",
"symfony/asset": "4.*",
"symfony/browser-kit": "^5.2",
"symfony/css-selector": "^5.2",
"symfony/expression-language": "4.*",
"symfony/form": "4.*",
"symfony/intl": "4.*",
"symfony/mime": "^4 || ^5",
"symfony/monolog-bundle": "^3.5",
"symfony/security-bundle": "^4.4",
"symfony/serializer": "^5.3",
"symfony/security-bundle": "4.*",
"symfony/serializer": "^5.2",
"symfony/swiftmailer-bundle": "^3.5",
"symfony/templating": "^4.4",
"symfony/translation": "^4.4",
"symfony/templating": "4.*",
"symfony/translation": "4.*",
"symfony/twig-bundle": "^4.4",
"symfony/validator": "^4.4",
"symfony/web-link": "*",
"symfony/validator": "4.*",
"symfony/webpack-encore-bundle": "^1.11",
"symfony/workflow": "^4.4",
"symfony/yaml": "^4.4",
"twig/extra-bundle": "^3.0",
"symfony/workflow": "4.*",
"symfony/yaml": "4.*",
"twig/extra-bundle": "^2.12 || ^3.0",
"twig/intl-extra": "^3.0",
"twig/markdown-extra": "^3.3",
"twig/string-extra": "^3.3",
"twig/twig": "^3.0"
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.3",
"drupol/php-conventions": "^5",
"fakerphp/faker": "^1.13",
"nelmio/alice": "^3.8",
"phpspec/prophecy-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": ">= 7.5",
"symfony/debug-bundle": "^5.1",
"symfony/dotenv": "^4.4",
"symfony/maker-bundle": "^1.20",
"symfony/phpunit-bridge": "^4.4",
"symfony/stopwatch": "^4.4",
"symfony/var-dumper": "^4.4",
"symfony/web-profiler-bundle": "^4.4"
"twig/twig": "^2.12 || ^3.0"
},
"conflict": {
"symfony/symfony": "*"
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.3",
"fakerphp/faker": "^1.13",
"nelmio/alice": "^3.8",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan": "^1.0",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^7.0",
"symfony/debug-bundle": "^5.1",
"symfony/dotenv": "^5.1",
"symfony/maker-bundle": "^1.20",
"symfony/phpunit-bridge": "^5.2",
"symfony/stopwatch": "^5.1",
"symfony/var-dumper": "4.*",
"symfony/web-profiler-bundle": "^5.0"
},
"config": {
"bin-dir": "bin",
"vendor-dir": "tests/app/vendor"
},
"autoload": {
"psr-4": {
"Chill\\ActivityBundle\\": "src/Bundle/ChillActivityBundle",
"Chill\\AsideActivityBundle\\": "src/Bundle/ChillAsideActivityBundle/src",
"Chill\\BudgetBundle\\": "src/Bundle/ChillBudgetBundle",
"Chill\\CalendarBundle\\": "src/Bundle/ChillCalendarBundle",
"Chill\\CustomFieldsBundle\\": "src/Bundle/ChillCustomFieldsBundle",
"Chill\\DocGeneratorBundle\\": "src/Bundle/ChillDocGeneratorBundle",
"Chill\\DocStoreBundle\\": "src/Bundle/ChillDocStoreBundle",
"Chill\\EventBundle\\": "src/Bundle/ChillEventBundle",
"Chill\\FamilyMemberBundle\\": "src/Bundle/ChillFamilyMemberBundle",
@@ -90,34 +83,24 @@
"Chill\\ReportBundle\\": "src/Bundle/ChillReportBundle",
"Chill\\TaskBundle\\": "src/Bundle/ChillTaskBundle",
"Chill\\ThirdPartyBundle\\": "src/Bundle/ChillThirdPartyBundle",
"Chill\\AsideActivityBundle\\": "src/Bundle/ChillAsideActivityBundle/src",
"Chill\\DocGeneratorBundle\\": "src/Bundle/ChillDocGeneratorBundle",
"Chill\\CalendarBundle\\": "src/Bundle/ChillCalendarBundle",
"Chill\\WopiBundle\\": "src/Bundle/ChillWopiBundle/src"
}
},
"autoload-dev": {
"psr-4": {
"App\\": "tests/app/src/",
"Chill\\DocGeneratorBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests",
"Chill\\WopiBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests"
"Chill\\DocGeneratorBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests"
}
},
"config": {
"allow-plugins": {
"composer/package-versions-deprecated": true,
"ergebnis/composer-normalize": true,
"ocramius/package-versions": true,
"phpro/grumphp": true,
"phpstan/extension-installer": true,
"roave/you-are-using-it-wrong": true
},
"bin-dir": "bin",
"optimize-autoloader": true,
"sort-packages": true,
"vendor-dir": "tests/app/vendor"
},
"minimum-stability": "dev",
"prefer-stable": true,
"scripts": {
"auto-scripts": {
"assets:install %PUBLIC_DIR%": "symfony-cmd",
"cache:clear": "symfony-cmd"
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd"
}
}
}

View File

@@ -1,126 +1,123 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\PersonBundle\Export\Filter;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\MainBundle\Export\FilterInterface;
use DateTime;
use Doctrine\ORM\Query\Expr;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraints;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Doctrine\ORM\Query\Expr;
use Chill\MainBundle\Form\Type\Export\FilterType;
use Symfony\Component\Form\FormError;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
class BirthdateFilter implements ExportElementValidatedInterface, FilterInterface
class BirthdateFilter implements FilterInterface, ExportElementValidatedInterface
{
// add specific role for this filter
// add specific role for this filter
public function addRole()
{
// we do not need any new role for this filter, so we return null
return null;
}
// here, we alter the query created by Export
public function alterQuery(\Doctrine\ORM\QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
// we create the clause here
$clause = $qb->expr()->between(
'person.birthdate',
':date_from',
':date_to'
);
// we have to take care **not to** remove previous clauses...
if ($where instanceof Expr\Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->add('where', $where);
// we add parameters from $data. $data contains the parameters from the form
$qb->setParameter('date_from', $data['date_from']);
$qb->setParameter('date_to', $data['date_to']);
}
// we give information on which type of export this filter applies
public function applyOn()
{
return 'person';
}
// we build a form to collect some parameters from the users
public function buildForm(\Symfony\Component\Form\FormBuilderInterface $builder)
{
$builder->add('date_from', DateType::class, [
'label' => 'Born after this date',
'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
]);
$builder->add('date_to', DateType::class, [
'label' => 'Born before this date',
'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
]);
}
// here, we create a simple string which will describe the action of
// the filter in the Response
public function describeAction($data, $format = 'string')
{
return ['Filtered by person\'s birtdate: '
. 'between %date_from% and %date_to%', [
'%date_from%' => $data['date_from']->format('d-m-Y'),
'%date_to%' => $data['date_to']->format('d-m-Y'),
], ];
}
public function getTitle()
{
return 'Filter by person\'s birthdate';
}
// we build a form to collect some parameters from the users
public function buildForm(\Symfony\Component\Form\FormBuilderInterface $builder)
{
$builder->add('date_from', DateType::class, array(
'label' => "Born after this date",
'data' => new \DateTime(),
'attr' => array('class' => 'datepicker'),
'widget'=> 'single_text',
'format' => 'dd-MM-yyyy',
));
$builder->add('date_to', DateType::class, array(
'label' => "Born before this date",
'data' => new \DateTime(),
'attr' => array('class' => 'datepicker'),
'widget'=> 'single_text',
'format' => 'dd-MM-yyyy',
));
}
// the form created above must be validated. The process of validation
// is executed here. This function is added by the interface
// `ExportElementValidatedInterface`, and can be ignore if there is
// is executed here. This function is added by the interface
// `ExportElementValidatedInterface`, and can be ignore if there is
// no need for a validation
public function validateForm($data, ExecutionContextInterface $context)
{
{
$date_from = $data['date_from'];
$date_to = $data['date_to'];
if (null === $date_from) {
$date_to = $data['date_to'];
if ($date_from === null) {
$context->buildViolation('The "date from" should not be empty')
//->atPath('date_from')
->addViolation();
}
if (null === $date_to) {
if ($date_to === null) {
$context->buildViolation('The "date to" should not be empty')
//->atPath('date_to')
->addViolation();
}
if (
(null !== $date_from && null !== $date_to)
&& $date_from >= $date_to
($date_from !== null && $date_to !== null)
&&
$date_from >= $date_to
) {
$context->buildViolation('The date "date to" should be after the '
. 'date given in "date from" field')
->addViolation();
}
}
// here, we alter the query created by Export
public function alterQuery(\Doctrine\ORM\QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
// we create the clause here
$clause = $qb->expr()->between('person.birthdate', ':date_from',
':date_to');
// we have to take care **not to** remove previous clauses...
if ($where instanceof Expr\Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->add('where', $where);
// we add parameters from $data. $data contains the parameters from the form
$qb->setParameter('date_from', $data['date_from']);
$qb->setParameter('date_to', $data['date_to']);
}
// here, we create a simple string which will describe the action of
// the filter in the Response
public function describeAction($data, $format = 'string')
{
return array('Filtered by person\'s birtdate: '
. 'between %date_from% and %date_to%', array(
'%date_from%' => $data['date_from']->format('d-m-Y'),
'%date_to%' => $data['date_to']->format('d-m-Y')
));
}
}

View File

@@ -1,119 +1,118 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\PersonBundle\Export\Export;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Doctrine\ORM\Query;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Symfony\Component\Security\Core\Role\Role;
use Chill\PersonBundle\Export\Declarations;
use Chill\MainBundle\Export\FormatterInterface;
use Doctrine\ORM\EntityManagerInterface;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class CountPerson implements ExportInterface
{
/**
*
* @var EntityManagerInterface
*/
protected $entityManager;
public function __construct(
EntityManagerInterface $em
) {
EntityManagerInterface $em
)
{
$this->entityManager = $em;
}
public function buildForm(FormBuilderInterface $builder)
{
// this export does not add any form
}
public function getAllowedFormattersTypes()
{
return [FormatterInterface::TYPE_TABULAR];
}
public function getDescription()
{
return 'Count peoples by various parameters.';
}
public function getLabels($key, array $values, $data)
{
// the Closure which will be executed by the formatter.
return function ($value) {
switch ($value) {
case '_header':
// we have to process specifically the '_header' string,
// which will be used by the formatter to show a column title
return $this->getTitle();
default:
// for all value, we do not process them and return them
// immediatly
return $value;
}
};
}
public function getQueryKeys($data)
{
// this array match the result keys in the query. We have only
// one column.
return ['export_result'];
}
public function getResult($qb, $data)
{
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getTitle()
{
return 'Count peoples';
}
public function getType()
{
return Declarations::PERSON_TYPE;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
public function getDescription()
{
// we gather all center the user choose.
$centers = array_map(static function ($el) {
return $el['center'];
}, $acl);
$qb = $this->entityManager->createQueryBuilder();
$qb->select('COUNT(person.id) AS export_result')
->from('ChillPersonBundle:Person', 'person')
->join('person.center', 'center')
->andWhere('center IN (:authorized_centers)')
->setParameter('authorized_centers', $centers);
return $qb;
return "Count peoples by various parameters.";
}
public function getTitle()
{
return "Count peoples";
}
public function requiredRole()
{
return new Role(PersonVoter::STATS);
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = array())
{
// we gather all center the user choose.
$centers = array_map(function($el) { return $el['center']; }, $acl);
$qb = $this->entityManager->createQueryBuilder();
$qb->select('COUNT(person.id) AS export_result')
->from('ChillPersonBundle:Person', 'person')
->join('person.center', 'center')
->andWhere('center IN (:authorized_centers)')
->setParameter('authorized_centers', $centers);
;
return $qb;
}
public function getResult($qb, $data)
{
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getQueryKeys($data)
{
// this array match the result keys in the query. We have only
// one column.
return array('export_result');
}
public function getLabels($key, array $values, $data)
{
// the Closure which will be executed by the formatter.
return function($value) {
switch($value) {
case '_header':
// we have to process specifically the '_header' string,
// which will be used by the formatter to show a column title
return $this->getTitle();
default:
// for all value, we do not process them and return them
// immediatly
return $value;
};
}
public function getAllowedFormattersTypes()
{
return array(FormatterInterface::TYPE_TABULAR);
}
public function buildForm(FormBuilderInterface $builder) {
// this export does not add any form
}
public function supportsModifiers()
{
// explain the export manager which formatters and filters are allowed
return [Declarations::PERSON_TYPE, Declarations::PERSON_IMPLIED_IN];
return array(Declarations::PERSON_TYPE, Declarations::PERSON_IMPLIED_IN);
}
}

View File

@@ -10,17 +10,17 @@
Exports
*******
Export is an important issue within the Chill software : users should be able to :
Export is an important issue for the Chill software : users should be able to :
- compute statistics about their activity ;
- list "things" which are a part of their activities.
- list "things" which make part of their activities.
The `main bundle`_ provides a powerful framework to build custom queries with re-usable parts across differents bundles.
.. contents:: Table of content
:local:
.. seealso::
.. seealso::
`The issue where this framework was discussed <https://git.framasoft.org/Chill-project/Chill-Main/issues/9>`_
Provides some information about the pursued features and architecture.
@@ -32,37 +32,37 @@ Concepts
Some vocabulary: 3 "Export elements"
------------------------------------
Four terms are used for this framework :
Four terms are used for this framework :
Exports
provide some basic operation on the data. Two kinds of exports are available :
exports
provides some basic operation on the date. Two kind of exports are available :
- computed data : it may be "the number of people", "the number of activities", "the duration of activities", ...
- list data : it may be "the list of people", "the list of activities", ...
- list data : it may be "the list of people", "the list of activity", ...
Filters
The filters create a filter on the data: it removes some information the user doesn't want to introduce in the computation done by the export.
filters
The filters make a filter on the date: it removes some information the user doesn't want to introduce in the computation done by export. In other word, filters make a filter...
Example of a filter: "people under 18 years olds", "activities between the 1st of June and the 31st December", ...
Example of filter: "people under 18 years olds", "activities between the 1st of June and the 31st December", ...
Aggregators
The aggregator aggregates the data into some group (some software use the term 'bucket').
aggregators
The aggregator aggregates the data into some group (some software use the term 'bucket').
Example of an aggregator : "group people by gender", "group people by nationality", "group activity by type", ...
Example of aggregator : "group people by gender", "group people by nationality", "group activity by type", ...
Formatters
The formatters format the data into a :class:`Symfony\Component\HttpFoundation\Response`, which will be returned "as is" by the controller to the web client.
formatters
The formatters format the data into a :class:`Symfony\Component\HttpFoundation\Response`, which will be returned "as is" by the controller to the web client.
Example of a formatter: "format data as CSV", "format data as an ods spreadsheet", ...
Example of formatter: "format data as CSV", "format data as ods spreadsheet", ...
Anatomy of an export
---------------------
An export can be thought of as a sentence where each part of this sentence refers to one or multiple export elements. Examples :
An export may be explained as a sentence, where each part of this sentence refers to one or multiple exports element. Examples :
**Example 1**: Count the number of people having at least one activity in the last 12 month, and group them by nationality and gender, and format them in a CSV spreadsheet.
Here :
Here :
- *count the number of people* is the export part
- *having at least one activity* is the filter part
@@ -72,10 +72,10 @@ Here :
Note that :
- Aggregators, filters, exports and formatters are cross-bundle. Here the bundle *activity* provides a filter which is applied on an export provided by the person bundle ;
- Multiple aggregator or filter for one export may exist. Currently, only one export is allowed.
- aggregators, filters, exports and aggregators are cross-bundle. Here the bundle *activity* provides a filter which apply on an export provided by the person bundle ;
- there may exists multiple aggregator or filter for one export. Currently, only one export is allowed.
The result might be :
The result might be :
+-----------------------+----------------+---------------------------+
| Nationality | Gender | Number of people |
@@ -89,9 +89,9 @@ The result might be :
| France | Female | 150 |
+-----------------------+----------------+---------------------------+
**Example 2**: Count the average duration of an activity with type "meeting", which occurs between the 1st of June and the 31st of December, group them by week, and format the data in an OpenDocument spreadsheet.
**Example 2**: Count the average duration of an activity with type "meeting", which occurs between the 1st of June and the 31st of December, group them by week, and format the data in a OpenDocument spreadsheet.
Here :
Here :
- *count the average duration of an activity* is the export part
- *activity with type meeting* is a filter part
@@ -102,7 +102,7 @@ Here :
The result might be :
+-----------------------+----------------------+
| Week | Number of activities |
| Week | Number of activities |
+=======================+======================+
| 2015-10 | 10 |
+-----------------------+----------------------+
@@ -116,77 +116,77 @@ The result might be :
Authorization and exports
-------------------------
Exports, filters and aggregators should not show data the user is not allowed to see within the application.
Exports, filters and aggregators should not make see data the user is not allowed to see.
In other words, developers are required to take care of user authorization for each export.
There should be a specific role that grants permission to users who are allowed to build exports. For more simplicity, this role should apply on a center, and should not require special circles.
It should exists a special role that should be granted to users which are allowed to build exports. For more simplicity, this role should apply on center, and should not requires special circles.
How does the magic work ?
How does the magic works ?
===========================
To build an export, we rely on the capacity of the database to execute queries with aggregate (i.e. GROUP BY) and filter (i.e. WHERE) instructions.
An export is an SQL query which is initiated by an export, and modified by aggregators and filters.
.. note::
.. note::
**Example**: Count the number of people having at least one activity in the last 12 month, and group them by nationality and gender
1. The report initiates the query
1. The report initiate the query
.. code-block:: SQL
SELECT count(people.*) FROM people
2. The filter adds a where and join clause :
2. The filter add a where and join clause :
.. code-block:: SQL
SELECT count(people.*) FROM people
RIGHT JOIN activity
SELECT count(people.*) FROM people
RIGHT JOIN activity
WHERE activity.date IS BETWEEN now AND 6 month ago
3. The aggregator "nationality" adds a GROUP BY clause and a column in the SELECT statement:
3. The aggregator "nationality" add a GROUP BY clause and a column in the SELECT statement:
.. code-block:: sql
SELECT people.nationality, count(people.*) FROM people
RIGHT JOIN activity
WHERE activity.date IS BETWEEN now AND 6 month ago
SELECT people.nationality, count(people.*) FROM people
RIGHT JOIN activity
WHERE activity.date IS BETWEEN now AND 6 month ago
GROUP BY nationality
4. The aggregator "gender" does the same job as the nationality aggregator : it adds a GROUP BY clause and a column in the SELECT statement :
4. The aggregator "gender" do the same job as the nationality aggregator : it adds a GROUP BY clause and a column in the SELECT statement :
.. code-block:: sql
SELECT people.nationality, people.gender, count(people.*)
FROM people RIGHT JOIN activity
WHERE activity.date IS BETWEEN now AND 6 month ago
SELECT people.nationality, people.gender, count(people.*)
FROM people RIGHT JOIN activity
WHERE activity.date IS BETWEEN now AND 6 month ago
GROUP BY nationality, gender
Each filter, aggregator and filter may collect parameters from the user through a form. This form is appended to the export form. Here is an example.
Each filter, aggregator and filter may collect parameters from the user by providing a form. This form is appended to the export form. Here is an example.
.. figure:: /_static/screenshots/development/export_form-fullpage.png
The screenshot shows the export form for ``CountPeople`` (Nombre de personnes). The filter by date of birth is checked (*Filtrer par date de naissance de la personne*), which triggers a subform, which is provided by the :class:`Chill\PersonBundle\Export\Filter\BirthdateFilter`. The other unchecked filter does not show the subform.
The screenshot show the export form for ``CountPeople`` (Nombre de personnes). The filter by date of birth is checked (*Filtrer par date de naissance de la personne*), which allow to show a subform, which is provided by the :class:`Chill\PersonBundle\Export\Filter\BirthdateFilter`. The other filter, which are unchecked, does not show the subform.
Two aggregators are also checked : by Country of birth (*Aggréger les personnes par pays de naissance*, the corresponding class is :class:`Chill\PersonBundle\Export\Aggregator\CountryOfBirthAggregator`, which also triggers a subform. The aggregator by gender (*Aggréger les personnes par genre*) is also checked, but there is no corresponding subform.
Two aggregators are also checked : by Country of birth (*Aggréger les personnes par pays de naissance*, corresponding class is :class:`Chill\PersonBundle\Export\Aggregator\CountryOfBirthAggregator`, which also open a subform. The aggregator by gender (*Aggréger les personnes par genre*) is also checked, but there is no corresponding subform.
The Export Manager
------------------
The Export manager (:class:`Chill\MainBundle\Export\ExportManager` is the central class which registers all exports, aggregators, filters and formatters.
The Export manager (:class:`Chill\MainBundle\Export\ExportManager` is the central class which register all exports, aggregators, filters and formatters.
The export manager is also responsible for orchestrating the whole export process, producing a :class:`Symfony\FrameworkBundle\HttpFoundation\Request` for each export request.
The export manager is also responsible for orchestrating the whole export process, producing a :class:`Symfony\FrameworkBundle\HttpFoundation\Request` to each export request.
The export form step
--------------------
The form step allows you to build a form, combining different parts of the module.
The form step allow to build a form, aggregating different parts of the module.
The building of forms is split into different subforms, where each one is responsible for rendering their part of the form (aggregators, filters, and export).
The building of forms is separated between different subform, which are responsible for rendering their part of the form (aggregators, filters, and export).
.. figure:: /_static/puml/exports/form_steps.png
:scale: 40%
@@ -194,12 +194,12 @@ The building of forms is split into different subforms, where each one is respon
The formatter form step
-----------------------
The formatter form is processed *after* the user filled the export form. It is built the same way, but receives the data entered by the user on the previous step as parameters (i.e. export form). It may then adapt it accordingly (example: show a list of columns selected in aggregators).
The formatter form is processed *after* the user filled the export form. It is built the same way, but receive in parameters the data entered by the user on the previous step (i.e. export form). It may then adapt it accordingly (example: show a list of columns selected in aggregators).
Processing the export
---------------------
The export process can be explained by this schema :
The export process may be explained by this schema :
.. figure:: /_static/puml/exports/processing_export.png
:scale: 40%
@@ -219,20 +219,20 @@ This is an example of the ``CountPerson`` export :
:language: php
:linenos:
* **Line 36**: the ``getType`` function returns a string. This string will be used to find the aggregtors and filters which will apply to this export.
* **Line 41**: a simple description to help users understand what your export does.
* **Line 36**: the ``getType`` function return a string. This string will be used to find the aggregtors and filters which will apply to this export.
* **Line 41**: a simple description to help user to understand what your export does.
* **Line 46**: The title of the export. A summary of what your export does.
* **Line 51**: The list of roles required to execute this export.
* **Line 51**: The list of roles requires to execute this export.
* **Line 56**: We initiate the query here...
* **Line 59**: We have to filter the query with centers the users checked in the form. We process the $acl variable to get all ``Center`` objects in one array
* **Line 63**: We create the query with a query builder.
* **Line 74**: We return the result, but make sure to hydrate the results as an array.
* **Line 103**: return the list of formatter types which are allowed to be applied on this filter
* **Line 59**: We have to filter the query with centers the users checked in the form. We process the $acl variable to get all ``Center`` object in one array
* **Line 63**: We create the query, with a query builder.
* **Line 74**: We simply returns the result, but take care of hydrating the results as an array.
* **Line 103**: return the list of formatters types which are allowed to apply on this filter
Filters
-------
This is an example of the *filter by birthdate*. This filter asks some information through a form (`buildForm` is not empty), and this form must be validated. To perform this validation, we implement a new Interface: :class:`Chill\MainBundle\Export\ExportElementValidatedInterface`:
This is an example of the *filter by birthdate*. This filter ask some information in a form (`buildForm` is not empty), and this form must be validated. To performs this validations, we implement a new Interface: :class:`Chill\MainBundle\Export\ExportElementValidatedInterface`:
.. literalinclude:: /_static/code/exports/BirthdateFilter.php
:language: php

View File

@@ -32,7 +32,7 @@ Then, render the pagination using the dedicated twig function.
{% block title 'Item list'|trans %}
{% block content %}
{% block personcontent %}
<table>

View File

@@ -1,49 +1,42 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\MyBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class example extends Controller
{
public function yourAction()
class ItemController extends Controller {
public function yourAction()
{
$em = $this->getDoctrine()->getManager();
// first, get the number of total item are available
$total = $em
->createQuery('SELECT COUNT (item.id) FROM ChillMyBundle:Item item')
->getSingleScalarResult();
->createQuery("SELECT COUNT (item.id) FROM ChillMyBundle:Item item")
->getSingleScalarResult();
// get the PaginatorFactory
$paginatorFactory = $this->get('chill_main.paginator_factory');
// create a pagination instance. This instance is only valid for
// create a pagination instance. This instance is only valid for
// the current route and parameters
$paginator = $paginatorFactory->create($total);
// launch your query on item. Limit the query to the results
// for the current page using the paginator
$items = $em->createQuery('SELECT item FROM ChillMyBundle:Item item WHERE <your clause>')
$items = $em->createQuery("SELECT item FROM ChillMyBundle:Item item WHERE <your clause>")
// use the paginator to get the first item number
->setFirstResult($paginator->getCurrentPage()->getFirstItemNumber())
// use the paginator to get the number of items to display
->setMaxResults($paginator->getItemsPerPage());
return $this->render(
'ChillMyBundle:Item:list.html.twig',
[
return $this->render('ChillMyBundle:Item:list.html.twig', array(
'items' => $items,
'paginator' => $paginator,
]
);
'paginator' => $paginator
);
}
}

View File

@@ -1,53 +1,43 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\HealthBundle\Controller;
use Chill\HealthBundle\Security\Authorization\ConsultationVoter;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Symfony\Component\Security\Core\Role\Role;
class ConsultationController extends Controller
{
/**
*
* @param int $id personId
*
* @throws type
*
* @return \Symfony\Component\HttpFoundation\Response
* @throws type
*/
public function listAction($id)
{
/** @var \Chill\PersonBundle\Entity\Person $person */
/* @var $person \Chill\PersonBundle\Entity\Person */
$person = $this->get('chill.person.repository.person')
->find($id);
if (null === $person) {
throw $this->createNotFoundException('The person is not found');
if ($person === null) {
throw $this->createNotFoundException("The person is not found");
}
$this->denyAccessUnlessGranted(PersonVoter::SEE, $person);
/** @var \Chill\MainBundle\Security\Authorization\AuthorizationHelper $authorizationHelper */
/* @var $authorizationHelper \Chill\MainBundle\Security\Authorization\AuthorizationHelper */
$authorizationHelper = $this->get('chill.main.security.'
. 'authorization.helper');
$circles = $authorizationHelper->getReachableCircles(
$this->getUser(),
new Role(ConsultationVoter::SEE),
$this->getUser(),
new Role(ConsultationVoter::SEE),
$person->getCenter()
);
// create a query which take circles into account
);
// create a query which take circles into account
$consultations = $this->getDoctrine()->getManager()
->createQuery('SELECT c FROM ChillHealthBundle:Consultation c '
. 'WHERE c.patient = :person AND c.circle IN(:circles) '
@@ -55,10 +45,11 @@ class ConsultationController extends Controller
->setParameter('person', $person)
->setParameter('circles', $circles)
->getResult();
return $this->render('ChillHealthBundle:Consultation:list.html.twig', [
'person' => $person,
'consultations' => $consultations,
]);
return $this->render('ChillHealthBundle:Consultation:list.html.twig', array(
'person' => $person,
'consultations' => $consultations
));
}
}

View File

@@ -156,7 +156,7 @@ This layout extend `ChillMainBundle::layoutWithVerticalMenu.html.twig` add the p
It proposes 1 new block :
* content
* personcontent
* where to display the information of the person

View File

@@ -1,63 +1,64 @@
<?php
# Chill\MainBundle\DependencyInjection\Configuration.php
namespace Chill\MainBundle\DependencyInjection;
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Chill\MainBundle\DependencyInjection\Widget\AddWidgetConfigurationTrait;
use Symfony\Component\DependencyInjection\ContainerBuilder;
declare(strict_types=1);
/**
* Configure the main bundle
*/
class Configuration implements ConfigurationInterface
{
use AddWidgetConfigurationTrait;
/**
*
* @var ContainerBuilder
*/
private $containerBuilder;
namespace Chill\MainBundle\DependencyInjection;
public function __construct(array $widgetFactories = array(),
ContainerBuilder $containerBuilder)
{
// we register here widget factories (see below)
$this->setWidgetFactories($widgetFactories);
// we will need the container builder later...
$this->containerBuilder = $containerBuilder;
}
/**
* {@inheritDoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('chill_main');
use Chill\MainBundle\DependencyInjection\Widget\AddWidgetConfigurationTrait;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
$rootNode
->children()
/**
* Configure the main bundle.
*/
class ChillMainConfiguration implements ConfigurationInterface
{
use AddWidgetConfigurationTrait;
// ...
/**
* @var ContainerBuilder
*/
private $containerBuilder;
->arrayNode('widgets')
->canBeDisabled()
->children()
// we declare here all configuration for homepage place
->append($this->addWidgetsConfiguration('homepage', $this->containerBuilder))
->end() // end of widgets/children
->end() // end of widgets
->end() // end of root/children
->end() // end of root
;
public function __construct(
array $widgetFactories,
ContainerBuilder $containerBuilder
) {
// we register here widget factories (see below)
$this->setWidgetFactories($widgetFactories);
// we will need the container builder later...
$this->containerBuilder = $containerBuilder;
}
return $treeBuilder;
}
}
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('chill_main');
$rootNode
->children()
// ...
->arrayNode('widgets')
->canBeDisabled()
->children()
// we declare here all configuration for homepage place
->append($this->addWidgetsConfiguration('homepage', $this->containerBuilder))
->end() // end of widgets/children
->end() // end of widgets
->end() // end of root/children
->end() // end of root
;
return $treeBuilder;
}
}

View File

@@ -1,19 +1,16 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
#Chill\MainBundle\DependencyInjection\ChillMainExtension.php
namespace Chill\MainBundle\DependencyInjection;
use Chill\MainBundle\DependencyInjection\Widget\Factory\WidgetFactoryInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Chill\MainBundle\DependencyInjection\Widget\Factory\WidgetFactoryInterface;
use Chill\MainBundle\DependencyInjection\Configuration;
/**
* This class load config for chillMainExtension.
@@ -21,42 +18,42 @@ use Symfony\Component\HttpKernel\DependencyInjection\Extension;
class ChillMainExtension extends Extension implements Widget\HasWidgetFactoriesExtensionInterface
{
/**
* widget factory.
*
* widget factory
*
* @var WidgetFactoryInterface[]
*/
protected $widgetFactories = [];
protected $widgetFactories = array();
public function addWidgetFactory(WidgetFactoryInterface $factory)
{
$this->widgetFactories[] = $factory;
}
public function getConfiguration(array $config, ContainerBuilder $container)
{
return new Configuration($this->widgetFactories, $container);
}
/**
*
* @return WidgetFactoryInterface[]
*/
public function getWidgetFactories()
{
return $this->widgetFactories;
}
public function load(array $configs, ContainerBuilder $container)
{
// configuration for main bundle
$configuration = $this->getConfiguration($configs, $container);
$config = $this->processConfiguration($configuration, $configs);
// add the key 'widget' without the key 'enable'
$container->setParameter(
'chill_main.widgets',
['homepage' => $config['widgets']['homepage']]
);
$container->setParameter('chill_main.widgets',
array('homepage' => $config['widgets']['homepage']));
// ...
// ...
}
public function getConfiguration(array $config, ContainerBuilder $container)
{
return new Configuration($this->widgetFactories, $container);
}
}

View File

@@ -1,73 +1,69 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
# Chill/PersonBundle/Widget/PersonListWidgetFactory
namespace Chill\PersonBundle\Widget;
use Chill\MainBundle\DependencyInjection\Widget\Factory\AbstractWidgetFactory;
use Symfony\Component\Config\Definition\Builder\NodeBuilder;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\Definition\Builder\NodeBuilder;
/**
* add configuration for the person_list widget.
*/
class ChillPersonAddAPersonListWidgetFactory extends AbstractWidgetFactory
class PersonListWidgetFactory extends AbstractWidgetFactory
{
/*
* append the option to the configuration
* see http://symfony.com/doc/current/components/config/definition.html
*
*/
/*
* append the option to the configuration
* see http://symfony.com/doc/current/components/config/definition.html
*
*/
public function configureOptions($place, NodeBuilder $node)
{
$node->booleanNode('only_active')
->defaultTrue()
->end();
->defaultTrue()
->end();
$node->integerNode('number_of_items')
->defaultValue(50)
->end();
$node->scalarNode('filtering_class')
->defaultNull()
->end();
->defaultNull()
->end();
}
/**
* return an array with the allowed places where the widget can be rendered.
*
* @return string[]
*/
/*
* return an array with the allowed places where the widget can be rendered
*
* @return string[]
*/
public function getAllowedPlaces()
{
return ['homepage'];
return array('homepage');
}
/*
* return the widget alias
*
* @return string
*/
public function getWidgetAlias()
{
return 'person_list';
}
/*
* return the service id for the service which will render the widget.
*
* this service must implements `Chill\MainBundle\Templating\Widget\WidgetInterface`
*
* the service must exists in the container, and it is not required that the service
*
* the service must exists in the container, and it is not required that the service
* has the `chill_main` tag.
*/
public function getServiceId(ContainerBuilder $containerBuilder, $place, $order, array $config)
{
return 'chill_person.widget.person_list';
}
/**
* return the widget alias.
*
* @return string
*/
public function getWidgetAlias()
{
return 'person_list';
}
}

View File

@@ -1,73 +1,66 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
# Chill/PersonBundle/Widget/PersonListWidget.php
namespace Chill\PersonBundle\Widget;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Templating\Widget\WidgetInterface;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use DateTime;
use Doctrine\DBAL\Types\Type;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\Expr;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Role\Role;
use Doctrine\DBAL\Types\Type;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Symfony\Component\Security\Core\User\UserInterface;
use Twig_Environment;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Symfony\Component\Security\Core\Role\Role;
use Doctrine\ORM\EntityManager;
/**
* add a widget with person list.
*
* add a widget with person list.
*
* The configuration is defined by `PersonListWidgetFactory`
*/
class ChillPersonAddAPersonWidget implements WidgetInterface
class PersonListWidget implements WidgetInterface
{
/**
* the authorization helper.
*
* @var AuthorizationHelper;
* Repository for persons
*
* @var EntityRepository
*/
protected $authorizationHelper;
protected $personRepository;
/**
* The entity manager.
* The entity manager
*
* @var EntityManager
*/
protected $entityManager;
/**
* Repository for persons.
*
* @var EntityRepository
* the authorization helper
*
* @var AuthorizationHelper;
*/
protected $personRepository;
protected $authorizationHelper;
/**
*
* @var TokenStorage
*/
protected $tokenStorage;
/**
*
* @var UserInterface
*/
protected $user;
public function __construct(
EntityRepository $personRepostory,
EntityManager $em,
AuthorizationHelper $authorizationHelper,
TokenStorage $tokenStorage
) {
EntityRepository $personRepostory,
EntityManager $em,
AuthorizationHelper $authorizationHelper,
TokenStorage $tokenStorage
) {
$this->personRepository = $personRepostory;
$this->authorizationHelper = $authorizationHelper;
$this->tokenStorage = $tokenStorage;
@@ -75,24 +68,27 @@ class ChillPersonAddAPersonWidget implements WidgetInterface
}
/**
*
* @param type $place
*
* @param array $context
* @param array $config
* @return string
*/
public function render(Twig_Environment $env, $place, array $context, array $config)
{
public function render(\Twig_Environment $env, $place, array $context, array $config)
{
$qb = $this->personRepository
->createQueryBuilder('person');
->createQueryBuilder('person');
// show only the person from the authorized centers
$and = $qb->expr()->andX();
$centers = $this->authorizationHelper
->getReachableCenters($this->getUser(), new Role(PersonVoter::SEE));
->getReachableCenters($this->getUser(), new Role(PersonVoter::SEE));
$and->add($qb->expr()->in('person.center', ':centers'));
$qb->setParameter('centers', $centers);
// add the "only active" where clause
if (true === $config['only_active']) {
if ($config['only_active'] === true) {
$qb->join('person.accompanyingPeriods', 'ap');
$or = new Expr\Orx();
// add the case where closingDate IS NULL
@@ -102,30 +98,32 @@ class ChillPersonAddAPersonWidget implements WidgetInterface
$or->add($andWhenClosingDateIsNull);
// add the case when now is between opening date and closing date
$or->add(
(new Expr())->between(':now', 'ap.openingDate', 'ap.closingDate')
);
(new Expr())->between(':now', 'ap.openingDate', 'ap.closingDate')
);
$and->add($or);
$qb->setParameter('now', new DateTime(), Type::DATE);
$qb->setParameter('now', new \DateTime(), Type::DATE);
}
// adding the where clause to the query
$qb->where($and);
$qb->setFirstResult(0)->setMaxResults($config['number_of_items']);
$persons = $qb->getQuery()->getResult();
return $env->render(
'ChillPersonBundle:Widget:homepage_person_list.html.twig',
['persons' => $persons]
);
array('persons' => $persons)
);
}
/**
*
* @return UserInterface
*/
private function getUser()
{
// return a user
}
}

View File

@@ -1,48 +1,51 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
# Chill/PersonBundle/DependencyInjection/ChillPersonExtension.php
namespace Chill\PersonBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Chill\MainBundle\DependencyInjection\MissingBundleException;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
/**
* This is the class that loads and manages your bundle configuration.
* This is the class that loads and manages your bundle configuration
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
*/
class ChillPersonExtension extends Extension implements PrependExtensionInterface
{
/**
* {@inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
// ...
// ...
}
/**
* Add a widget "add a person" on the homepage, automatically.
*
*
* Add a widget "add a person" on the homepage, automatically
*
* @param \Chill\PersonBundle\DependencyInjection\containerBuilder $container
*/
public function prepend(ContainerBuilder $container)
public function prepend(ContainerBuilder $container)
{
$container->prependExtensionConfig('chill_main', [
'widgets' => [
'homepage' => [
[
$container->prependExtensionConfig('chill_main', array(
'widgets' => array(
'homepage' => array(
array(
'widget_alias' => 'add_person',
'order' => 2,
],
],
],
]);
'order' => 2
)
)
)
));
}
}

View File

@@ -65,17 +65,6 @@ This script will :
4. build assets
.. note::
In some cases it can happen that an old image (chill_base_php or chill_php) stored in the docker cache will make the script fail. To solve this problem you have to delete the image and the container, before the make init :
.. code-block:: bash
docker-compose images php
docker rmi -f chill_php:prod
docker-compose rm php
4. Start the project
====================
@@ -104,29 +93,6 @@ The password is always ``password``.
Now, read `Operations` below.
Prepare for development
***********************
Add a Gitlab token to ensure that you get always the source code:
1. generate a gitlab token there: https://gitlab.com/oauth/token
2. run this command (in php container, at the app's root): :code:`composer config gitlab-token.gitlab.com <your token>`
The auth token should appears now in the directory :code:`.composer`:
.. code-block: bash
$ cat .composer/auth.json
{
"gitlab-token": {
"gitlab.com": "<your token>"
}
}
See also "how to switch branch and get new dependencies".
Operations
**********
@@ -234,25 +200,6 @@ How to run webpack interactively
Executing :code:`bash docker-node.sh` will open a terminal in a node container, with volumes mounted.
How to switch the branch for chill-bundles, and get new dependencies
====================================================================
During development, you will switch to new branches for chill-bundles. As long as the dependencies are equals, this does not cause any problem. But sometimes, a new branch introduces a new dependency, and you must download it.
In order to do that without pain, use those steps:
0. Ensuire you have a token, set
1. at the app's root, update the `composer.json` to your current branch:
.. code-block:: json
{
"require": {
"chill-bundles": "dev-<my-branch>@dev"
}
2. mount into the php container, and run `composer update`
Build the documentation API
===========================

View File

@@ -1,40 +0,0 @@
imports:
- {
resource: tests/app/vendor/drupol/php-conventions/config/php73/grumphp.yml,
}
parameters:
tasks.phpcsfixer.config: .php_cs.dist.php
tasks.license.name: AGPL-3.0
tasks.license.holder: Champs-Libres
tasks.license.date_from: 2001
tasks.phpcsfixer.allow_risky: true
tasks.phpcsfixer.diff: true
tasks.phpstan.level: 1
tasks.phpstan.blocking: true
tasks.phpstan.ignore_patterns:
- "/.github/"
- "/.idea/"
- "/build/"
- "/benchmarks/"
- "/docs/"
- "/node_modules/"
- "/resource/"
- "/spec/"
- "/var/"
- "/vendor/"
- "/tests/app"
# Psalm
tasks.psalm.blocking: true
tasks.psalm.ignore_patterns:
- "/.github/"
- "/.idea/"
- "/build/"
- "/benchmarks/"
- "/node_modules/"
- "/resource/"
- "/spec/"
- "/var/"
- "/vendor/"

3
package.json.txt Normal file
View File

@@ -0,0 +1,3 @@
add npm/yarn dependency in package.json :
"select2-bootstrap-theme": "0.1.0-beta.10",

View File

@@ -10,6 +10,16 @@ parameters:
count: 1
path: src/Bundle/ChillCustomFieldsBundle/Controller/CustomFieldsGroupController.php
-
message: "#^Instantiated class PhpOffice\\\\PhpWord\\\\TemplateProcessor not found\\.$#"
count: 1
path: src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorController.php
-
message: "#^Instantiated class PhpOffice\\\\PhpWord\\\\TemplateProcessor not found\\.$#"
count: 1
path: src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorTemplateController.php
-
message: "#^Variable \\$participation might not be defined\\.$#"
count: 3
@@ -80,6 +90,11 @@ parameters:
count: 1
path: src/Bundle/ChillPersonBundle/Form/ChoiceLoader/PersonChoiceLoader.php
-
message: "#^Foreach overwrites \\$action with its value variable\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
-
message: "#^Foreach overwrites \\$action with its value variable\\.$#"
count: 1

View File

@@ -5,6 +5,11 @@ parameters:
count: 1
path: src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php
-
message: "#^Access to an undefined property Chill\\\\PersonBundle\\\\Entity\\\\Person\\:\\:\\$currentHouseholdParticipationAt\\.$#"
count: 3
path: src/Bundle/ChillPersonBundle/Entity/Person.php
-
message: "#^Access to an undefined property Chill\\\\PersonBundle\\\\Entity\\\\Household\\\\PersonHouseholdAddress\\:\\:\\$relation\\.$#"
count: 1
@@ -20,6 +25,41 @@ parameters:
count: 1
path: src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php
-
message: "#^Access to an undefined property Chill\\\\PersonBundle\\\\Household\\\\MembersEditorFactory\\:\\:\\$validator\\.$#"
count: 2
path: src/Bundle/ChillPersonBundle/Household/MembersEditorFactory.php
-
message: "#^Parameter \\$action of method Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\AccompanyingPeriodWorkRepository\\:\\:buildQueryBySocialActionWithDescendants\\(\\) has invalid type Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\SocialAction\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
-
message: "#^Parameter \\$action of method Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\AccompanyingPeriodWorkRepository\\:\\:countBySocialActionWithDescendants\\(\\) has invalid type Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\SocialAction\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
-
message: "#^Undefined variable\\: \\$action$#"
count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
-
message: "#^Undefined variable\\: \\$limit$#"
count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
-
message: "#^Undefined variable\\: \\$offset$#"
count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
-
message: "#^Undefined variable\\: \\$orderBy$#"
count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
-
message: "#^Variable variables are not allowed\\.$#"
count: 4
@@ -30,6 +70,11 @@ parameters:
count: 1
path: src/Bundle/ChillPersonBundle/Serializer/Normalizer/MembersEditorNormalizer.php
-
message: "#^Undefined variable\\: \\$value$#"
count: 1
path: src/Bundle/ChillPersonBundle/Validator/Constraints/AccompanyingPeriod/LocationValidityValidator.php
-
message: "#^Undefined variable\\: \\$choiceSlug$#"
count: 1

View File

@@ -1,940 +0,0 @@
parameters:
ignoreErrors:
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 2
path: src/Bundle/ChillActivityBundle/Controller/ActivityController.php
-
message: "#^Call to deprecated method setType\\(\\) of class Chill\\\\ActivityBundle\\\\Entity\\\\Activity\\.$#"
count: 1
path: src/Bundle/ChillActivityBundle/DataFixtures/ORM/LoadActivity.php
-
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
count: 1
path: src/Bundle/ChillActivityBundle/Entity/ActivityReason.php
-
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
count: 1
path: src/Bundle/ChillActivityBundle/Entity/ActivityReasonCategory.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityReasonAggregator.php
-
message: """
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Aggregator\\\\ActivityReasonAggregator\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityReasonAggregator.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityTypeAggregator.php
-
message: """
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Aggregator\\\\ActivityTypeAggregator\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityTypeAggregator.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUserAggregator.php
-
message: """
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Aggregator\\\\ActivityUserAggregator\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUserAggregator.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Export/CountActivity.php
-
message: """
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Export\\\\CountActivity\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Export/CountActivity.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Export/ListActivity.php
-
message: """
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Export\\\\ListActivity\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Export/ListActivity.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Export/StatActivityDuration.php
-
message: """
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Export\\\\StatActivityDuration\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Export/StatActivityDuration.php
-
message: """
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Filter\\\\ActivityDateFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Filter/ActivityDateFilter.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Filter/ActivityReasonFilter.php
-
message: """
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Filter\\\\ActivityReasonFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Filter/ActivityReasonFilter.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Filter/ActivityTypeFilter.php
-
message: """
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Filter\\\\ActivityTypeFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Filter/ActivityTypeFilter.php
-
message: """
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Filter\\\\PersonHavingActivityBetweenDateFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Export/Filter/PersonHavingActivityBetweenDateFilter.php
-
message: """
#^Fetching class constant class of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Form/ActivityType.php
-
message: """
#^Call to deprecated method getReachableScopes\\(\\) of class Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AuthorizationHelper\\:
Use getReachableCircles$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php
-
message: """
#^Parameter \\$centerResolverDispatcher of method Chill\\\\ActivityBundle\\\\Repository\\\\ActivityACLAwareRepository\\:\\:__construct\\(\\) has typehint with deprecated interface Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcherInterface\\:
Use CenterResolverManager and its interface CenterResolverManagerInterface$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillActivityBundle/Timeline/TimelineActivityProvider.php
-
message: """
#^Parameter \\$templating of method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldChoice\\:\\:__construct\\(\\) has typehint with deprecated class Symfony\\\\Bridge\\\\Twig\\\\TwigEngine\\:
since version 4\\.3, to be removed in 5\\.0; use Twig instead\\.$#
"""
count: 1
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldChoice.php
-
message: "#^Used function LogicException not found\\.$#"
count: 1
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldChoice.php
-
message: """
#^Parameter \\$templating of method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldDate\\:\\:__construct\\(\\) has typehint with deprecated class Symfony\\\\Bundle\\\\TwigBundle\\\\TwigEngine\\:
since version 4\\.3, to be removed in 5\\.0; use Twig instead\\.$#
"""
count: 1
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldDate.php
-
message: """
#^Parameter \\$twigEngine of method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldLongChoice\\:\\:__construct\\(\\) has typehint with deprecated class Symfony\\\\Bridge\\\\Twig\\\\TwigEngine\\:
since version 4\\.3, to be removed in 5\\.0; use Twig instead\\.$#
"""
count: 1
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldLongChoice.php
-
message: """
#^Parameter \\$templating of method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldNumber\\:\\:__construct\\(\\) has typehint with deprecated class Symfony\\\\Bundle\\\\TwigBundle\\\\TwigEngine\\:
since version 4\\.3, to be removed in 5\\.0; use Twig instead\\.$#
"""
count: 1
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldNumber.php
-
message: """
#^Parameter \\$templating of method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldText\\:\\:__construct\\(\\) has typehint with deprecated class Symfony\\\\Bundle\\\\TwigBundle\\\\TwigEngine\\:
since version 4\\.3, to be removed in 5\\.0; use Twig instead\\.$#
"""
count: 1
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldText.php
-
message: """
#^Parameter \\$templating of method Chill\\\\CustomFieldsBundle\\\\CustomFields\\\\CustomFieldTitle\\:\\:__construct\\(\\) has typehint with deprecated class Symfony\\\\Bundle\\\\TwigBundle\\\\TwigEngine\\:
since version 4\\.3, to be removed in 5\\.0; use Twig instead\\.$#
"""
count: 1
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldTitle.php
-
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
count: 1
path: src/Bundle/ChillCustomFieldsBundle/Entity/CustomField.php
-
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
count: 1
path: src/Bundle/ChillCustomFieldsBundle/Entity/CustomFieldsGroup.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 6
path: src/Bundle/ChillEventBundle/Controller/EventController.php
-
message: """
#^Fetching class constant class of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillEventBundle/Form/EventType.php
-
message: """
#^Fetching class constant class of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillEventBundle/Form/Type/PickEventType.php
-
message: """
#^Call to deprecated method getReachableScopes\\(\\) of class Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AuthorizationHelper\\:
Use getReachableCircles$#
"""
count: 1
path: src/Bundle/ChillEventBundle/Search/EventSearch.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillFamilyMembersBundle/Security/Voter/FamilyMemberVoter.php
-
message: """
#^Parameter \\$role of method Chill\\\\MainBundle\\\\CRUD\\\\Controller\\\\CRUDController\\:\\:getReachableCenters\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillMainBundle/CRUD/Controller/CRUDController.php
-
message: """
#^Call to deprecated method getLanguageBundle\\(\\) of class Symfony\\\\Component\\\\Intl\\\\Intl\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use \\{@see Languages\\} or \\{@see Scripts\\} instead\\.$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Command/LoadAndUpdateLanguagesCommand.php
-
message: """
#^Call to deprecated method getRegionBundle\\(\\) of class Symfony\\\\Component\\\\Intl\\\\Intl\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use \\{@see Countries\\} instead\\.$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Command/LoadCountriesCommand.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Controller/PermissionsGroupController.php
-
message: """
#^Parameter \\$role of anonymous function has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Controller/PermissionsGroupController.php
-
message: """
#^Call to deprecated method getLanguageBundle\\(\\) of class Symfony\\\\Component\\\\Intl\\\\Intl\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use \\{@see Languages\\} or \\{@see Scripts\\} instead\\.$#
"""
count: 2
path: src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadLanguages.php
-
message: """
#^Class Chill\\\\MainBundle\\\\Entity\\\\User implements deprecated interface Symfony\\\\Component\\\\Security\\\\Core\\\\User\\\\AdvancedUserInterface\\:
since Symfony 4\\.1$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Entity/User.php
-
message: """
#^Return type of method Chill\\\\MainBundle\\\\Entity\\\\User\\:\\:getRoles\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Entity/User.php
-
message: """
#^Return type of method Chill\\\\MainBundle\\\\Export\\\\DirectExportInterface\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Export/DirectExportInterface.php
-
message: """
#^Return type of method Chill\\\\MainBundle\\\\Export\\\\ExportInterface\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Export/ExportInterface.php
-
message: """
#^Call to deprecated method getReachableScopes\\(\\) of class Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AuthorizationHelper\\:
Use getReachableCircles$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Export/ExportManager.php
-
message: """
#^Return type of method Chill\\\\MainBundle\\\\Export\\\\ModifierInterface\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Export/ModifierInterface.php
-
message: """
#^Class Chill\\\\MainBundle\\\\Form\\\\Event\\\\CustomizeFormEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:
since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Form/Event/CustomizeFormEvent.php
-
message: """
#^Fetching class constant class of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Form/Type/ScopePickerType.php
-
message: """
#^Fetching class constant class of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Form/Type/UserPickerType.php
-
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
count: 2
path: src/Bundle/ChillMainBundle/Repository/NotificationRepository.php
-
message: """
#^Parameter \\$attribute of method Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AuthorizationHelper\\:\\:userHasAccess\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php
-
message: """
#^Parameter \\$centerResolverDispatcher of method Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AuthorizationHelper\\:\\:__construct\\(\\) has typehint with deprecated interface Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcherInterface\\:
Use CenterResolverManager and its interface CenterResolverManagerInterface$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php
-
message: """
#^Parameter \\$role of method Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AuthorizationHelper\\:\\:getReachableCircles\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php
-
message: """
#^Parameter \\$centerResolverDispatcher of method Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\DefaultVoterHelper\\:\\:__construct\\(\\) has typehint with deprecated interface Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcherInterface\\:
Use CenterResolverManager and its interface CenterResolverManagerInterface$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelper.php
-
message: """
#^Parameter \\$centerResolverDispatcher of method Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\DefaultVoterHelperFactory\\:\\:__construct\\(\\) has typehint with deprecated interface Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcherInterface\\:
Use CenterResolverManager and its interface CenterResolverManagerInterface$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelperFactory.php
-
message: """
#^Parameter \\$centerResolverDispatcher of method Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\DefaultVoterHelperGenerator\\:\\:__construct\\(\\) has typehint with deprecated interface Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcherInterface\\:
Use CenterResolverManager and its interface CenterResolverManagerInterface$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelperGenerator.php
-
message: """
#^Class Chill\\\\MainBundle\\\\Security\\\\PasswordRecover\\\\PasswordRecoverEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:
since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverEvent.php
-
message: """
#^Class Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcher implements deprecated interface Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcherInterface\\:
Use CenterResolverManager and its interface CenterResolverManagerInterface$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverDispatcher.php
-
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/Templating/ChillTwigRoutingHelper.php
-
message: """
#^Class Chill\\\\MainBundle\\\\Templating\\\\Events\\\\DelegatedBlockRenderingEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:
since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$#
"""
count: 1
path: src/Bundle/ChillMainBundle/Templating/Events/DelegatedBlockRenderingEvent.php
-
message: """
#^Class Chill\\\\PersonBundle\\\\Actions\\\\ActionEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:
since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Actions/ActionEvent.php
-
message: """
#^Call to deprecated method getCurrentAccompanyingPeriod\\(\\) of class Chill\\\\PersonBundle\\\\Entity\\\\Person\\:
since 1\\.1 use `getOpenedAccompanyingPeriod instead$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:
since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
-
message: """
#^Class Chill\\\\PersonBundle\\\\Controller\\\\AccompanyingCourseController extends deprecated class Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\Controller\\:
since Symfony 4\\.2, use "Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\AbstractController" instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php
-
message: """
#^Call to deprecated method getCurrentAccompanyingPeriod\\(\\) of class Chill\\\\PersonBundle\\\\Entity\\\\Person\\:
since 1\\.1 use `getOpenedAccompanyingPeriod instead$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php
-
message: """
#^Class Chill\\\\PersonBundle\\\\Controller\\\\PersonDuplicateController extends deprecated class Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\Controller\\:
since Symfony 4\\.2, use "Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\AbstractController" instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Controller/PersonDuplicateController.php
-
message: "#^Access to deprecated property \\$proxyAccompanyingPeriodOpenState of class Chill\\\\PersonBundle\\\\Entity\\\\Person\\.$#"
count: 2
path: src/Bundle/ChillPersonBundle/Entity/Person.php
-
message: """
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Aggregator\\\\AgeAggregator\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Export/Aggregator/AgeAggregator.php
-
message: """
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Aggregator\\\\CountryOfBirthAggregator\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Export/Aggregator/CountryOfBirthAggregator.php
-
message: """
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Aggregator\\\\GenderAggregator\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Export/Aggregator/GenderAggregator.php
-
message: """
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Aggregator\\\\NationalityAggregator\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Export/Aggregator/NationalityAggregator.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Export/Export/CountPerson.php
-
message: """
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Export\\\\CountPerson\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Export/Export/CountPerson.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php
-
message: """
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Export\\\\ListPerson\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php
-
message: """
#^Call to deprecated method execute\\(\\) of class Doctrine\\\\DBAL\\\\Statement\\:
Statement\\:\\:execute\\(\\) is deprecated, use Statement\\:\\:executeQuery\\(\\) or executeStatement\\(\\) instead$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Export/Export/ListPersonDuplicate.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Export/Export/ListPersonDuplicate.php
-
message: """
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Export\\\\ListPersonDuplicate\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Export/Export/ListPersonDuplicate.php
-
message: """
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Filter\\\\AccompanyingPeriodClosingFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingPeriodClosingFilter.php
-
message: """
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Filter\\\\AccompanyingPeriodFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingPeriodFilter.php
-
message: """
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Filter\\\\AccompanyingPeriodOpeningFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingPeriodOpeningFilter.php
-
message: """
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Filter\\\\BirthdateFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Export/Filter/BirthdateFilter.php
-
message: """
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Filter\\\\GenderFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Export/Filter/GenderFilter.php
-
message: """
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Filter\\\\NationalityFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Export/Filter/NationalityFilter.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Form/AccompanyingPeriodType.php
-
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Form/PersonType.php
-
message: """
#^Fetching class constant class of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Form/Type/PickPersonType.php
-
message: """
#^Class Chill\\\\PersonBundle\\\\Privacy\\\\AccompanyingPeriodPrivacyEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:
since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Privacy/AccompanyingPeriodPrivacyEvent.php
-
message: """
#^Class Chill\\\\PersonBundle\\\\Privacy\\\\PrivacyEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:
since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Privacy/PrivacyEvent.php
-
message: """
#^Parameter \\$centerResolverDispatcher of method Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriodACLAwareRepository\\:\\:__construct\\(\\) has typehint with deprecated interface Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcherInterface\\:
Use CenterResolverManager and its interface CenterResolverManagerInterface$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Widget/PersonListWidget.php
-
message: """
#^Call to deprecated method getReachableScopes\\(\\) of class Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AuthorizationHelper\\:
Use getReachableCircles$#
"""
count: 1
path: src/Bundle/ChillReportBundle/Controller/ReportController.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 3
path: src/Bundle/ChillReportBundle/Controller/ReportController.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillReportBundle/Export/Export/ReportList.php
-
message: """
#^Return type of method Chill\\\\ReportBundle\\\\Export\\\\Export\\\\ReportList\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillReportBundle/Export/Export/ReportList.php
-
message: """
#^Return type of method Chill\\\\ReportBundle\\\\Export\\\\Filter\\\\ReportDateFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillReportBundle/Export/Filter/ReportDateFilter.php
-
message: """
#^Call to deprecated method getReachableScopes\\(\\) of class Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AuthorizationHelper\\:
Use getReachableCircles$#
"""
count: 1
path: src/Bundle/ChillReportBundle/Form/ReportType.php
-
message: """
#^Parameter \\$role of method Chill\\\\ReportBundle\\\\Form\\\\ReportType\\:\\:appendScopeChoices\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillReportBundle/Form/ReportType.php
-
message: """
#^Call to deprecated method getReachableScopes\\(\\) of class Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AuthorizationHelper\\:
Use getReachableCircles$#
"""
count: 1
path: src/Bundle/ChillReportBundle/Search/ReportSearch.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillReportBundle/Search/ReportSearch.php
-
message: """
#^Call to deprecated method getReachableScopes\\(\\) of class Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AuthorizationHelper\\:
Use getReachableCircles$#
"""
count: 2
path: src/Bundle/ChillReportBundle/Timeline/TimelineReportProvider.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 2
path: src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php
-
message: """
#^Parameter \\$centerResolverDispatcher of method Chill\\\\TaskBundle\\\\Controller\\\\SingleTaskController\\:\\:__construct\\(\\) has typehint with deprecated interface Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcherInterface\\:
Use CenterResolverManager and its interface CenterResolverManagerInterface$#
"""
count: 1
path: src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php
-
message: """
#^Parameter \\$role of method Chill\\\\TaskBundle\\\\Controller\\\\SingleTaskController\\:\\:setCreateForm\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php
-
message: """
#^Class Chill\\\\TaskBundle\\\\Event\\\\TaskEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:
since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$#
"""
count: 1
path: src/Bundle/ChillTaskBundle/Event/TaskEvent.php
-
message: """
#^Class Chill\\\\TaskBundle\\\\Event\\\\UI\\\\UIEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:
since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$#
"""
count: 1
path: src/Bundle/ChillTaskBundle/Event/UI/UIEvent.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 4
path: src/Bundle/ChillTaskBundle/Form/SingleTaskListType.php
-
message: """
#^Fetching class constant class of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillTaskBundle/Form/SingleTaskType.php
-
message: """
#^Parameter \\$centerResolverDispatcher of method Chill\\\\TaskBundle\\\\Form\\\\SingleTaskType\\:\\:__construct\\(\\) has typehint with deprecated interface Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcherInterface\\:
Use CenterResolverManager and its interface CenterResolverManagerInterface$#
"""
count: 1
path: src/Bundle/ChillTaskBundle/Form/SingleTaskType.php
-
message: """
#^Parameter \\$centerResolverDispatcher of method Chill\\\\TaskBundle\\\\Repository\\\\SingleTaskAclAwareRepository\\:\\:__construct\\(\\) has typehint with deprecated interface Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcherInterface\\:
Use CenterResolverManager and its interface CenterResolverManagerInterface$#
"""
count: 1
path: src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepository.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillTaskBundle/Repository/SingleTaskRepository.php
-
message: """
#^Class Chill\\\\TaskBundle\\\\Security\\\\Authorization\\\\AuthorizationEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:
since Symfony 4\\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead$#
"""
count: 1
path: src/Bundle/ChillTaskBundle/Security/Authorization/AuthorizationEvent.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 3
path: src/Bundle/ChillTaskBundle/Timeline/TaskLifeCycleEventTimelineProvider.php
-
message: """
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillThirdPartyBundle/Search/ThirdPartySearch.php

View File

@@ -1,5 +1,15 @@
parameters:
ignoreErrors:
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillActivityBundle/DataFixtures/ORM/LoadActivitytACL.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillActivityBundle/Entity/Activity.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
@@ -10,6 +20,11 @@ parameters:
count: 1
path: src/Bundle/ChillActivityBundle/Entity/ActivityReasonCategory.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillActivityBundle/Export/Export/ListActivity.php
-
message: "#^Method Chill\\\\ActivityBundle\\\\Export\\\\Export\\\\StatActivityDuration\\:\\:getDescription\\(\\) should return string but return statement is missing\\.$#"
count: 1
@@ -20,11 +35,56 @@ parameters:
count: 1
path: src/Bundle/ChillActivityBundle/Export/Export/StatActivityDuration.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillActivityBundle/Form/ActivityType.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
path: src/Bundle/ChillActivityBundle/Form/ActivityType.php
-
message: "#^Only booleans are allowed in &&, mixed given on the right side\\.$#"
count: 3
path: src/Bundle/ChillActivityBundle/Form/ActivityType.php
-
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
count: 2
path: src/Bundle/ChillActivityBundle/Form/ActivityType.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillActivityBundle/Menu/AdminMenuBuilder.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillActivityBundle/Security/Authorization/ActivityStatsVoter.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2
path: src/Bundle/ChillActivityBundle/Timeline/TimelineActivityProvider.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillAsideActivityBundle/src/Form/AsideActivityFormType.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillAsideActivityBundle/src/Menu/AdminMenuBuilder.php
-
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
count: 3
@@ -35,16 +95,36 @@ parameters:
count: 2
path: src/Bundle/ChillBudgetBundle/Form/ResourceType.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2
path: src/Bundle/ChillBudgetBundle/Security/Authorization/BudgetElementVoter.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillCalendarBundle/Entity/Calendar.php
-
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
count: 1
path: src/Bundle/ChillCustomFieldsBundle/Command/CreateFieldsOnGroupCommand.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillCustomFieldsBundle/Controller/CustomFieldsGroupController.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/AbstractCustomField.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 3
path: src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldChoice.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 4
@@ -110,11 +190,21 @@ parameters:
count: 1
path: src/Bundle/ChillDocStoreBundle/Entity/DocumentCategory.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillEventBundle/Entity/Participation.php
-
message: "#^Method Chill\\\\EventBundle\\\\Entity\\\\Participation\\:\\:offsetGet\\(\\) should return mixed but return statement is missing\\.$#"
count: 1
path: src/Bundle/ChillEventBundle/Entity/Participation.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillEventBundle/Form/ChoiceLoader/EventChoiceLoader.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
@@ -135,6 +225,11 @@ parameters:
count: 1
path: src/Bundle/ChillEventBundle/Form/StatusType.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillEventBundle/Form/Type/PickEventType.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 2
@@ -145,6 +240,16 @@ parameters:
count: 1
path: src/Bundle/ChillEventBundle/Search/EventSearch.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2
path: src/Bundle/ChillEventBundle/Security/Authorization/EventVoter.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2
path: src/Bundle/ChillEventBundle/Security/Authorization/ParticipationVoter.php
-
message: "#^Casting to string something that's already string\\.$#"
count: 5
@@ -155,6 +260,11 @@ parameters:
count: 2
path: src/Bundle/ChillFamilyMembersBundle/Form/FamilyMemberType.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2
path: src/Bundle/ChillFamilyMembersBundle/Security/Voter/FamilyMemberVoter.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
@@ -175,6 +285,16 @@ parameters:
count: 1
path: src/Bundle/ChillMainBundle/CRUD/Resolver/Resolver.php
-
message: "#^Call to function array_search\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/CRUD/Routing/CRUDRoutesLoader.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2
path: src/Bundle/ChillMainBundle/CRUD/Routing/CRUDRoutesLoader.php
-
message: "#^Method Chill\\\\MainBundle\\\\Command\\\\ChillImportUsersCommand\\:\\:execute\\(\\) should return int but return statement is missing\\.$#"
count: 1
@@ -185,6 +305,11 @@ parameters:
count: 1
path: src/Bundle/ChillMainBundle/Command/ChillImportUsersCommand.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2
path: src/Bundle/ChillMainBundle/Command/ChillUserSendRenewPasswordCodeCommand.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
@@ -195,6 +320,11 @@ parameters:
count: 1
path: src/Bundle/ChillMainBundle/Command/ChillUserSendRenewPasswordCodeCommand.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2
path: src/Bundle/ChillMainBundle/Command/LoadAndUpdateLanguagesCommand.php
-
message: "#^Method Chill\\\\MainBundle\\\\Command\\\\LoadAndUpdateLanguagesCommand\\:\\:execute\\(\\) should return int but return statement is missing\\.$#"
count: 1
@@ -230,6 +360,36 @@ parameters:
count: 1
path: src/Bundle/ChillMainBundle/Controller/PostalCodeController.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2
path: src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadLanguages.php
-
message: "#^Call to function array_search\\(\\) requires parameter \\#3 to be set\\.$#"
count: 5
path: src/Bundle/ChillMainBundle/DependencyInjection/CompilerPass/ExportsCompilerPass.php
-
message: "#^Call to function array_search\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/DependencyInjection/CompilerPass/SearchableServicesCompilerPass.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php
-
message: "#^Call to function array_search\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/DependencyInjection/Widget/AbstractWidgetsCompilerPass.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/DependencyInjection/Widget/AbstractWidgetsCompilerPass.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
@@ -243,8 +403,23 @@ parameters:
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/Entity/Embeddable/CommentEmbeddable.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/Entity/User.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/Entity/User.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 6
path: src/Bundle/ChillMainBundle/Export/ExportManager.php
-
message: "#^Only booleans are allowed in a ternary operator condition, mixed given\\.$#"
count: 1
@@ -275,26 +450,81 @@ parameters:
count: 1
path: src/Bundle/ChillMainBundle/Form/Type/ChillTextareaType.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/Form/Type/ComposedRoleScopeType.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 3
path: src/Bundle/ChillMainBundle/Form/Type/DataTransformer/DateIntervalTransformer.php
-
message: "#^Only booleans are allowed in a negated boolean, mixed given\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ObjectToIdTransformer.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/Form/Type/Export/PickCenterType.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/Form/Type/TranslatableStringFormType.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2
path: src/Bundle/ChillMainBundle/Phonenumber/PhonenumberHelper.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 2
path: src/Bundle/ChillMainBundle/Phonenumber/PhonenumberHelper.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/Search/Entity/SearchUserApiProvider.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2
path: src/Bundle/ChillMainBundle/Security/Authorization/AbstractChillVoter.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2
path: src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelper.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2
path: src/Bundle/ChillMainBundle/Security/ParentRoleHelper.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverEvent.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverVoter.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/Security/PasswordRecover/TokenManager.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 3
path: src/Bundle/ChillMainBundle/Templating/Entity/AddressRender.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
@@ -305,6 +535,21 @@ parameters:
count: 1
path: src/Bundle/ChillMainBundle/Timeline/TimelineBuilder.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2
path: src/Bundle/ChillMainBundle/Validation/Validator/RoleScopeScopePresence.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/Validation/Validator/ValidPhonenumber.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
@@ -330,11 +575,51 @@ parameters:
count: 1
path: src/Bundle/ChillPersonBundle/Command/ChillPersonMoveCommand.php
-
message: "#^Call to function array_search\\(\\) requires parameter \\#3 to be set\\.$#"
count: 3
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 3
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 6
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Controller/PersonController.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/DependencyInjection/CompilerPass/AccompanyingPeriodTimelineCompilerPass.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Entity/Person.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 2
path: src/Bundle/ChillPersonBundle/Entity/PersonPhone.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2
path: src/Bundle/ChillPersonBundle/Export/AbstractAccompanyingPeriodExportElement.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
@@ -345,11 +630,26 @@ parameters:
count: 1
path: src/Bundle/ChillPersonBundle/Export/Aggregator/NationalityAggregator.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 3
path: src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 2
path: src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Export/Filter/GenderFilter.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Form/ChoiceLoader/PersonChoiceLoader.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
@@ -370,6 +670,26 @@ parameters:
count: 1
path: src/Bundle/ChillPersonBundle/Form/Type/PersonPhoneType.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Form/Type/PickPersonType.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Household/MembersEditor.php
-
message: "#^Method Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\AccompanyingPeriodWorkRepository\\:\\:buildQueryBySocialActionWithDescendants\\(\\) has invalid return type Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\QueryBuilder\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 2
path: src/Bundle/ChillPersonBundle/Repository/PersonRepository.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 3
@@ -380,26 +700,71 @@ parameters:
count: 1
path: src/Bundle/ChillPersonBundle/Search/PersonSearch.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Search/SearchPersonApiProvider.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Serializer/Normalizer/AccompanyingPeriodWorkDenormalizer.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 2
path: src/Bundle/ChillPersonBundle/Templating/Entity/ClosingMotiveRender.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Timeline/AbstractTimelineAccompanyingPeriod.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillReportBundle/DataFixtures/ORM/LoadReportACL.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillReportBundle/DataFixtures/ORM/LoadReports.php
-
message: "#^Method Chill\\\\ReportBundle\\\\DataFixtures\\\\ORM\\\\LoadReports\\:\\:getRandomChoice\\(\\) should return array\\<string\\>\\|string but return statement is missing\\.$#"
count: 1
path: src/Bundle/ChillReportBundle/DataFixtures/ORM/LoadReports.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 4
path: src/Bundle/ChillReportBundle/Export/Export/ReportList.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 2
path: src/Bundle/ChillReportBundle/Export/Export/ReportList.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillReportBundle/Security/Authorization/ReportVoter.php
-
message: "#^Method Chill\\\\ReportBundle\\\\Security\\\\Authorization\\\\ReportVoter\\:\\:supports\\(\\) should return bool but return statement is missing\\.$#"
count: 1
path: src/Bundle/ChillReportBundle/Security/Authorization/ReportVoter.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 4
path: src/Bundle/ChillReportBundle/Timeline/TimelineReportProvider.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillTaskBundle/DataFixtures/ORM/LoadTaskACL.php
-
message: "#^Casting to string something that's already string\\.$#"
count: 3
@@ -425,11 +790,31 @@ parameters:
count: 1
path: src/Bundle/ChillTaskBundle/Timeline/SingleTaskTaskLifeCycleEventTimelineProvider.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillTaskBundle/Timeline/TaskLifeCycleEventTimelineProvider.php
-
message: "#^Method Chill\\\\TaskBundle\\\\Timeline\\\\TaskLifeCycleEventTimelineProvider\\:\\:getTransitionByName\\(\\) should return Symfony\\\\Component\\\\Workflow\\\\Transition but return statement is missing\\.$#"
count: 1
path: src/Bundle/ChillTaskBundle/Timeline/TaskLifeCycleEventTimelineProvider.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillThirdPartyBundle/DependencyInjection/CompilerPass/ThirdPartyTypeCompilerPass.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 4
path: src/Bundle/ChillThirdPartyBundle/Entity/ThirdParty.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillThirdPartyBundle/Form/ChoiceLoader/ThirdPartyChoiceLoader.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
@@ -440,8 +825,28 @@ parameters:
count: 1
path: src/Bundle/ChillThirdPartyBundle/Repository/ThirdPartyRepository.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillThirdPartyBundle/Search/ThirdPartyApiSearch.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
path: src/Bundle/ChillThirdPartyBundle/Search/ThirdPartyApiSearch.php
-
message: "#^Method Chill\\\\ThirdPartyBundle\\\\Search\\\\ThirdPartySearch\\:\\:renderResult\\(\\) should return string but return statement is missing\\.$#"
count: 1
path: src/Bundle/ChillThirdPartyBundle/Search/ThirdPartySearch.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
path: src/Bundle/ChillThirdPartyBundle/Security/Voter/ThirdPartyVoter.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
path: src/Bundle/ChillThirdPartyBundle/Templating/Entity/ThirdPartyRender.php

View File

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

View File

@@ -2,7 +2,7 @@
<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="tests/app/vendor/phpunit/phpunit/phpunit.xsd"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="tests/app/tests/bootstrap.php"
@@ -40,9 +40,6 @@
<testsuite name="DocGeneratorBundle">
<directory suffix="Test.php">src/Bundle/ChillDocGeneratorBundle/tests/</directory>
</testsuite>
<testsuite name="WopiBundle">
<directory suffix="Test.php">src/Bundle/ChillWopiBundle/tests/</directory>
</testsuite>
</testsuites>
<listeners>

File diff suppressed because it is too large Load Diff

View File

@@ -1,28 +0,0 @@
<?xml version="1.0"?>
<psalm
errorLevel="7"
resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config tests/app/vendor/vimeo/psalm/config.xsd"
errorBaseline="psalm-baseline.xml"
cacheDirectory="./.psalm"
>
<projectFiles>
<directory name="src" />
<ignoreFiles>
<directory name="./tests/" />
</ignoreFiles>
</projectFiles>
<!-- suppress error around parameter bags - see https://github.com/symfony/symfony/issues/45609#issuecomment-1056816975 -->
<!-- maybe to desactivate with php 8.1 ? -->
<issueHandlers>
<UndefinedDocblockClass>
<errorLevel type="suppress">
<referencedClass name="UnitEnum" />
</errorLevel>
</UndefinedDocblockClass>
</issueHandlers>
</psalm>

View File

@@ -1,5 +0,0 @@
Chill is a software for social workers
For the full copyright and license information, please view
the LICENSE file that was distributed with this source code.

View File

@@ -1,14 +1,5 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;

View File

@@ -1,78 +1,62 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Controller;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Form\ActivityType;
use Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface;
use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\ActivityBundle\Repository\ActivityTypeCategoryRepository;
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
use Chill\MainBundle\Repository\LocationRepository;
use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Privacy\PrivacyEvent;
use Chill\PersonBundle\Repository\AccompanyingPeriodRepository;
use Chill\PersonBundle\Repository\PersonRepository;
use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Psr\Log\LoggerInterface;
use RuntimeException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Form\ActivityType;
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
use Symfony\Component\Serializer\SerializerInterface;
use function array_key_exists;
final class ActivityController extends AbstractController
{
private AccompanyingPeriodRepository $accompanyingPeriodRepository;
private ActivityACLAwareRepositoryInterface $activityACLAwareRepository;
private ActivityRepository $activityRepository;
private ActivityTypeCategoryRepository $activityTypeCategoryRepository;
private ActivityTypeRepository $activityTypeRepository;
private CenterResolverManagerInterface $centerResolver;
private EntityManagerInterface $entityManager;
private EventDispatcherInterface $eventDispatcher;
private LocationRepository $locationRepository;
private LoggerInterface $logger;
private PersonRepository $personRepository;
private SerializerInterface $serializer;
private ActivityACLAwareRepositoryInterface $activityACLAwareRepository;
private ActivityTypeRepository $activityTypeRepository;
private ThirdPartyRepository $thirdPartyRepository;
private PersonRepository $personRepository;
private LocationRepository $locationRepository;
private EntityManagerInterface $entityManager;
private ActivityRepository $activityRepository;
private AccompanyingPeriodRepository $accompanyingPeriodRepository;
private ActivityTypeCategoryRepository $activityTypeCategoryRepository;
public function __construct(
ActivityACLAwareRepositoryInterface $activityACLAwareRepository,
ActivityTypeRepository $activityTypeRepository,
@@ -85,8 +69,7 @@ final class ActivityController extends AbstractController
EntityManagerInterface $entityManager,
EventDispatcherInterface $eventDispatcher,
LoggerInterface $logger,
SerializerInterface $serializer,
CenterResolverManagerInterface $centerResolver
SerializerInterface $serializer
) {
$this->activityACLAwareRepository = $activityACLAwareRepository;
$this->activityTypeRepository = $activityTypeRepository;
@@ -100,178 +83,6 @@ final class ActivityController extends AbstractController
$this->eventDispatcher = $eventDispatcher;
$this->logger = $logger;
$this->serializer = $serializer;
$this->centerResolver = $centerResolver;
}
/**
* Deletes a Activity entity.
*
* @param mixed $id
*/
public function deleteAction(Request $request, $id)
{
$view = null;
[$person, $accompanyingPeriod] = $this->getEntity($request);
$activity = $this->activityRepository->find($id);
if (!$activity) {
throw $this->createNotFoundException('Unable to find Activity entity.');
}
if ($activity->getAccompanyingPeriod() instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:confirm_deleteAccompanyingCourse.html.twig';
$accompanyingPeriod = $activity->getAccompanyingPeriod();
} else {
$view = 'ChillActivityBundle:Activity:confirm_deletePerson.html.twig';
}
// TODO
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_DELETE', $activity);
$form = $this->createDeleteForm($activity->getId(), $person, $accompanyingPeriod);
if ($request->getMethod() === Request::METHOD_DELETE) {
$form->handleRequest($request);
if ($form->isValid()) {
$this->logger->notice('An activity has been removed', [
'by_user' => $this->getUser()->getUsername(),
'activity_id' => $activity->getId(),
'person_id' => $activity->getPerson() ? $activity->getPerson()->getId() : null,
'comment' => $activity->getComment()->getComment(),
'scope_id' => $activity->getScope() ? $activity->getScope()->getId() : null,
'reasons_ids' => $activity->getReasons()
->map(
static fn (ActivityReason $ar): int => $ar->getId()
)
->toArray(),
'type_id' => $activity->getActivityType()->getId(),
'duration' => $activity->getDurationTime() ? $activity->getDurationTime()->format('U') : null,
'date' => $activity->getDate()->format('Y-m-d'),
'attendee' => $activity->getAttendee(),
]);
$this->entityManager->remove($activity);
$this->entityManager->flush();
$this->addFlash('success', $this->get('translator')
->trans('The activity has been successfully removed.'));
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
return $this->redirectToRoute('chill_activity_activity_list', $params);
}
}
if (null === $view) {
throw $this->createNotFoundException('Template not found');
}
return $this->render($view, [
'activity' => $activity,
'delete_form' => $form->createView(),
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
]);
}
/**
* Displays a form to edit an existing Activity entity.
*/
public function editAction(int $id, Request $request): Response
{
$view = null;
$entity = $this->activityRepository->find($id);
if (null === $entity) {
throw $this->createNotFoundException('Unable to find Activity entity.');
}
$accompanyingPeriod = $entity->getAccompanyingPeriod();
$person = $entity->getPerson();
if ($entity->getAccompanyingPeriod() instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:editAccompanyingCourse.html.twig';
$accompanyingPeriod = $entity->getAccompanyingPeriod();
} else {
$view = 'ChillActivityBundle:Activity:editPerson.html.twig';
}
// TODO
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity);
$form = $this->createForm(ActivityType::class, $entity, [
'center' => $this->centerResolver->resolveCenters($entity)[0] ?? null,
'role' => new Role('CHILL_ACTIVITY_UPDATE'),
'activityType' => $entity->getActivityType(),
'accompanyingPeriod' => $accompanyingPeriod,
]);
if ($form->has('documents')) {
$form->add('gendocTemplateId', HiddenType::class, [
'mapped' => false,
'data' => null,
'attr' => [
// required for js
'data-template-id' => 'data-template-id',
],
]);
}
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->persist($entity);
$this->entityManager->flush();
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
$params['id'] = $entity->getId();
if ($form->has('gendocTemplateId') && null !== $form['gendocTemplateId']->getData()) {
return $this->redirectToRoute(
'chill_docgenerator_generate_from_template',
[
'template' => $form->get('gendocTemplateId')->getData(),
'entityClassName' => Activity::class,
'entityId' => $entity->getId(),
'returnPath' => $this->generateUrl('chill_activity_activity_edit', $params),
]
);
}
$this->addFlash('success', $this->get('translator')->trans('Success : activity updated!'));
return $this->redirectToRoute('chill_activity_activity_show', $params);
}
$deleteForm = $this->createDeleteForm($entity->getId(), $person, $accompanyingPeriod);
/*
* TODO
$event = new PrivacyEvent($person, array(
'element_class' => Activity::class,
'element_id' => $entity->getId(),
'action' => 'edit'
));
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
*/
if (null === $view) {
throw $this->createNotFoundException('Template not found');
}
$activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']);
return $this->render($view, [
'entity' => $entity,
'edit_form' => $form->createView(),
'delete_form' => $deleteForm->createView(),
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
'activity_json' => $activity_array,
]);
}
/**
@@ -288,11 +99,11 @@ final class ActivityController extends AbstractController
if ($person instanceof Person) {
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $person);
$activities = $this->activityACLAwareRepository
->findByPerson($person, ActivityVoter::SEE, 0, null, ['date' => 'DESC', 'id' => 'DESC']);
->findByPerson($person, ActivityVoter::SEE, 0, null);
$event = new PrivacyEvent($person, [
'element_class' => Activity::class,
'action' => 'list',
'action' => 'list'
]);
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
@@ -301,7 +112,7 @@ final class ActivityController extends AbstractController
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $accompanyingPeriod);
$activities = $this->activityACLAwareRepository
->findByAccompanyingPeriod($accompanyingPeriod, ActivityVoter::SEE, 0, null, ['date' => 'DESC', 'id' => 'DESC']);
->findByAccompanyingPeriod($accompanyingPeriod, ActivityVoter::SEE);
$view = 'ChillActivityBundle:Activity:listAccompanyingCourse.html.twig';
}
@@ -310,181 +121,12 @@ final class ActivityController extends AbstractController
$view,
[
'activities' => $activities,
'person' => $person,
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
]
);
}
public function newAction(Request $request): Response
{
$view = null;
[$person, $accompanyingPeriod] = $this->getEntity($request);
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:newAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:newPerson.html.twig';
}
$activityType_id = $request->get('activityType_id', 0);
$activityType = $this->activityTypeRepository->find($activityType_id);
if (isset($activityType) && !$activityType->isActive()) {
throw new InvalidArgumentException('Activity type must be active');
}
$activityData = null;
if ($request->query->has('activityData')) {
$activityData = $request->query->get('activityData');
}
if (
!$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType
|| !$activityType->isActive()
) {
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
if (null !== $activityData) {
$params['activityData'] = $activityData;
}
return $this->redirectToRoute('chill_activity_activity_select_type', $params);
}
$entity = new Activity();
$entity->setUser($this->getUser());
if ($person instanceof Person) {
$entity->setPerson($person);
}
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$entity->setAccompanyingPeriod($accompanyingPeriod);
}
$entity->setActivityType($activityType);
$entity->setDate(new DateTime('now'));
if ($request->query->has('activityData')) {
$activityData = $request->query->get('activityData');
if (array_key_exists('durationTime', $activityData)) {
$durationTimeInMinutes = $activityData['durationTime'];
$hours = floor($durationTimeInMinutes / 60);
$minutes = $durationTimeInMinutes % 60;
$duration = DateTime::createFromFormat('H:i', $hours . ':' . $minutes);
if ($duration) {
$entity->setDurationTime($duration);
}
}
if (array_key_exists('date', $activityData)) {
$date = DateTime::createFromFormat('Y-m-d', $activityData['date']);
if ($date) {
$entity->setDate($date);
}
}
if (array_key_exists('personsId', $activityData)) {
foreach ($activityData['personsId'] as $personId) {
$concernedPerson = $this->personRepository->find($personId);
$entity->addPerson($concernedPerson);
}
}
if (array_key_exists('professionalsId', $activityData)) {
foreach ($activityData['professionalsId'] as $professionalsId) {
$professional = $this->thirdPartyRepository->find($professionalsId);
$entity->addThirdParty($professional);
}
}
if (array_key_exists('location', $activityData)) {
$location = $this->locationRepository->find($activityData['location']);
$entity->setLocation($location);
}
if (array_key_exists('comment', $activityData)) {
$comment = new CommentEmbeddable();
$comment->setComment($activityData['comment']);
$comment->setUserId($this->getUser()->getid());
$comment->setDate(new DateTime('now'));
$entity->setComment($comment);
}
}
$this->denyAccessUnlessGranted(ActivityVoter::CREATE, $entity);
$form = $this->createForm(ActivityType::class, $entity, [
'center' => $this->centerResolver->resolveCenters($entity)[0] ?? null,
'role' => new Role('CHILL_ACTIVITY_CREATE'),
'activityType' => $entity->getActivityType(),
'accompanyingPeriod' => $accompanyingPeriod,
]);
if ($form->has('documents')) {
$form->add('gendocTemplateId', HiddenType::class, [
'mapped' => false,
'data' => null,
'attr' => [
// required for js
'data-template-id' => 'data-template-id',
],
]);
}
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->persist($entity);
$this->entityManager->flush();
if ($form->has('gendocTemplateId') && null !== $form['gendocTemplateId']->getData()) {
return $this->redirectToRoute(
'chill_docgenerator_generate_from_template',
[
'template' => $form->get('gendocTemplateId')->getData(),
'entityClassName' => Activity::class,
'entityId' => $entity->getId(),
'returnPath' => $this->generateUrl('chill_activity_activity_edit', [
'id' => $entity->getId(),
]),
]
);
}
$this->addFlash('success', $this->get('translator')->trans('Success : activity created!'));
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
$params['id'] = $entity->getId();
return $this->redirectToRoute('chill_activity_activity_show', $params);
}
if (null === $view) {
throw $this->createNotFoundException('Template not found');
}
$activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']);
$defaultLocation = $this->getUser()->getCurrentLocation();
return $this->render($view, [
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
'entity' => $entity,
'form' => $form->createView(),
'activity_json' => $activity_array,
'default_location' => $defaultLocation,
]);
}
public function selectTypeAction(Request $request): Response
{
$view = null;
@@ -517,7 +159,7 @@ final class ActivityController extends AbstractController
];
}
if (null === $view) {
if ($view === null) {
throw $this->createNotFoundException('Template not found');
}
@@ -529,32 +171,168 @@ final class ActivityController extends AbstractController
]);
}
public function showAction(Request $request, int $id): Response
public function newAction(Request $request): Response
{
$view = null;
[$person, $accompanyingPeriod] = $this->getEntity($request);
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:newAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:newPerson.html.twig';
}
$activityType_id = $request->get('activityType_id', 0);
$activityType = $this->activityTypeRepository->find($activityType_id);
if (isset($activityType) && !$activityType->isActive()) {
throw new \InvalidArgumentException('Activity type must be active');
}
$activityData = null;
if ($request->query->has('activityData')) {
$activityData = $request->query->get('activityData');
}
if (!$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType ||
!$activityType->isActive()) {
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
if (null !== $activityData) {
$params['activityData'] = $activityData;
}
return $this->redirectToRoute('chill_activity_activity_select_type', $params);
}
$entity = new Activity();
$entity->setUser($this->getUser());
if ($person instanceof Person) {
$entity->setPerson($person);
}
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$entity->setAccompanyingPeriod($accompanyingPeriod);
}
$entity->setType($activityType);
$entity->setDate(new \DateTime('now'));
if ($request->query->has('activityData')) {
$activityData = $request->query->get('activityData');
if (array_key_exists('durationTime', $activityData)) {
$durationTimeInMinutes = $activityData['durationTime'];
$hours = floor($durationTimeInMinutes / 60);
$minutes = $durationTimeInMinutes % 60;
$duration = \DateTime::createFromFormat("H:i", $hours.':'.$minutes);
if ($duration) {
$entity->setDurationTime($duration);
}
}
if (array_key_exists('date', $activityData)) {
$date = \DateTime::createFromFormat('Y-m-d', $activityData['date']);
if ($date) {
$entity->setDate($date);
}
}
if (array_key_exists('personsId', $activityData)) {
foreach($activityData['personsId'] as $personId){
$concernedPerson = $this->personRepository->find($personId);
$entity->addPerson($concernedPerson);
}
}
if (array_key_exists('professionalsId', $activityData)) {
foreach($activityData['professionalsId'] as $professionalsId){
$professional = $this->thirdPartyRepository->find($professionalsId);
$entity->addThirdParty($professional);
}
}
if (array_key_exists('location', $activityData)) {
$location = $this->locationRepository->find($activityData['location']);
$entity->setLocation($location);
}
if (array_key_exists('comment', $activityData)) {
$comment = new CommentEmbeddable();
$comment->setComment($activityData['comment']);
$comment->setUserId($this->getUser()->getid());
$comment->setDate(new \DateTime('now'));
$entity->setComment($comment);
}
}
// TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_CREATE', $entity);
$form = $this->createForm(ActivityType::class, $entity, [
'center' => $entity->getCenter(),
'role' => new Role('CHILL_ACTIVITY_CREATE'),
'activityType' => $entity->getType(),
'accompanyingPeriod' => $accompanyingPeriod,
])->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->persist($entity);
$this->entityManager->flush();
$this->addFlash('success', $this->get('translator')->trans('Success : activity created!'));
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
$params['id'] = $entity->getId();
return $this->redirectToRoute('chill_activity_activity_show', $params);
}
if ($view === null) {
throw $this->createNotFoundException('Template not found');
}
$activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']);
return $this->render($view, [
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
'entity' => $entity,
'form' => $form->createView(),
'activity_json' => $activity_array
]);
}
public function showAction(Request $request, $id): Response
{
$view = null;
[$person, $accompanyingPeriod] = $this->getEntity($request);
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:showAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:showPerson.html.twig';
}
$entity = $this->activityRepository->find($id);
if (null === $entity) {
throw $this->createNotFoundException('Unable to find Activity entity.');
}
$accompanyingPeriod = $entity->getAccompanyingPeriod();
$person = $entity->getPerson();
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:showAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:showPerson.html.twig';
} else {
throw new RuntimeException('the activity should be linked with a period or person');
}
if (null !== $accompanyingPeriod) {
// @TODO: Properties created dynamically.
$entity->personsAssociated = $entity->getPersonsAssociated();
$entity->personsNotAssociated = $entity->getPersonsNotAssociated();
$entity->personsAssociated = $entity->getPersonsAssociated();
$entity->personsNotAssociated = $entity->getPersonsNotAssociated();
}
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $entity);
// TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_SEE', $entity);
$deleteForm = $this->createDeleteForm($entity->getId(), $person, $accompanyingPeriod);
@@ -566,33 +344,160 @@ final class ActivityController extends AbstractController
'action' => 'show'
));
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
*/
*/
if (null === $view) {
if ($view === null) {
throw $this->createNotFoundException('Template not found');
}
return $this->render($view, [
'person' => $person,
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
'entity' => $entity,
'entity' => $entity,
'delete_form' => $deleteForm->createView(),
]);
}
private function buildParamsToUrl(?Person $person, ?AccompanyingPeriod $accompanyingPeriod): array
/**
* Displays a form to edit an existing Activity entity.
*/
public function editAction($id, Request $request): Response
{
$params = [];
$view = null;
if (null !== $person) {
$params['person_id'] = $person->getId();
[$person, $accompanyingPeriod] = $this->getEntity($request);
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:editAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:editPerson.html.twig';
}
if (null !== $accompanyingPeriod) {
$params['accompanying_period_id'] = $accompanyingPeriod->getId();
$entity = $this->activityRepository->find($id);
if (null === $entity) {
throw $this->createNotFoundException('Unable to find Activity entity.');
}
return $params;
// TODO
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity);
$form = $this->createForm(ActivityType::class, $entity, [
'center' => $entity->getCenter(),
'role' => new Role('CHILL_ACTIVITY_UPDATE'),
'activityType' => $entity->getType(),
'accompanyingPeriod' => $accompanyingPeriod,
])->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->persist($entity);
$this->entityManager->flush();
$this->addFlash('success', $this->get('translator')->trans('Success : activity updated!'));
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
$params['id'] = $entity->getId();
return $this->redirectToRoute('chill_activity_activity_show', $params);
}
$deleteForm = $this->createDeleteForm($entity->getId(), $person, $accompanyingPeriod);
/*
* TODO
$event = new PrivacyEvent($person, array(
'element_class' => Activity::class,
'element_id' => $entity->getId(),
'action' => 'edit'
));
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
*/
if ($view === null) {
throw $this->createNotFoundException('Template not found');
}
$activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']);
return $this->render($view, [
'entity' => $entity,
'edit_form' => $form->createView(),
'delete_form' => $deleteForm->createView(),
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
'activity_json' => $activity_array
]);
}
/**
* Deletes a Activity entity.
*/
public function deleteAction(Request $request, $id)
{
$view = null;
[$person, $accompanyingPeriod] = $this->getEntity($request);
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:confirm_deleteAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:confirm_deletePerson.html.twig';
}
$activity = $this->activityRepository->find($id);
if (!$activity) {
throw $this->createNotFoundException('Unable to find Activity entity.');
}
// TODO
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_DELETE', $activity);
$form = $this->createDeleteForm($activity->getId(), $person, $accompanyingPeriod);
if ($request->getMethod() === Request::METHOD_DELETE) {
$form->handleRequest($request);
if ($form->isValid()) {
$this->logger->notice("An activity has been removed", [
'by_user' => $this->getUser()->getUsername(),
'activity_id' => $activity->getId(),
'person_id' => $activity->getPerson() ? $activity->getPerson()->getId() : null,
'comment' => $activity->getComment()->getComment(),
'scope_id' => $activity->getScope() ? $activity->getScope()->getId() : null,
'reasons_ids' => $activity->getReasons()
->map(
static fn (ActivityReason $ar): int => $ar->getId()
)
->toArray(),
'type_id' => $activity->getType()->getId(),
'duration' => $activity->getDurationTime() ? $activity->getDurationTime()->format('U') : null,
'date' => $activity->getDate()->format('Y-m-d'),
'attendee' => $activity->getAttendee()
]);
$this->entityManager->remove($activity);
$this->entityManager->flush();
$this->addFlash('success', $this->get('translator')
->trans("The activity has been successfully removed."));
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
return $this->redirectToRoute('chill_activity_activity_list', $params);
}
}
if ($view === null) {
throw $this->createNotFoundException('Template not found');
}
return $this->render($view, [
'activity' => $activity,
'delete_form' => $form->createView(),
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
]);
}
/**
@@ -612,13 +517,13 @@ final class ActivityController extends AbstractController
private function getEntity(Request $request): array
{
$person = $accompanyingPeriod = null;
$person = $accompanyingPeriod = null;
if ($request->query->has('person_id')) {
$person_id = $request->get('person_id');
$person = $this->personRepository->find($person_id);
if (null === $person) {
if ($person === null) {
throw $this->createNotFoundException('Person not found');
}
@@ -627,19 +532,34 @@ final class ActivityController extends AbstractController
$accompanying_period_id = $request->get('accompanying_period_id');
$accompanyingPeriod = $this->accompanyingPeriodRepository->find($accompanying_period_id);
if (null === $accompanyingPeriod) {
if ($accompanyingPeriod === null) {
throw $this->createNotFoundException('Accompanying Period not found');
}
// TODO Add permission
// $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
} else {
throw $this->createNotFoundException('Person or Accompanying Period not found');
throw $this->createNotFoundException("Person or Accompanying Period not found");
}
return [
$person,
$accompanyingPeriod,
$accompanyingPeriod
];
}
private function buildParamsToUrl(?Person $person, ?AccompanyingPeriod $accompanyingPeriod): array
{
$params = [];
if (null !== $person) {
$params['person_id'] = $person->getId();
}
if (null !== $accompanyingPeriod) {
$params['accompanying_period_id'] = $accompanyingPeriod->getId();
}
return $params;
}
}

View File

@@ -1,29 +1,38 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Chill\ActivityBundle\Entity\ActivityReasonCategory;
use Chill\ActivityBundle\Form\ActivityReasonCategoryType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
/**
* ActivityReasonCategory controller.
*
*/
class ActivityReasonCategoryController extends AbstractController
{
/**
* Lists all ActivityReasonCategory entities.
*
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('ChillActivityBundle:ActivityReasonCategory')->findAll();
return $this->render('ChillActivityBundle:ActivityReasonCategory:index.html.twig', array(
'entities' => $entities,
));
}
/**
* Creates a new ActivityReasonCategory entity.
*
*/
public function createAction(Request $request)
{
@@ -36,114 +45,13 @@ class ActivityReasonCategoryController extends AbstractController
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('chill_activity_activityreasoncategory_show', ['id' => $entity->getId()]));
return $this->redirect($this->generateUrl('chill_activity_activityreasoncategory_show', array('id' => $entity->getId())));
}
return $this->render('ChillActivityBundle:ActivityReasonCategory:new.html.twig', [
return $this->render('ChillActivityBundle:ActivityReasonCategory:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
]);
}
/**
* Displays a form to edit an existing ActivityReasonCategory entity.
*
* @param mixed $id
*/
public function editAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReasonCategory::class)->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityReasonCategory entity.');
}
$editForm = $this->createEditForm($entity);
return $this->render('ChillActivityBundle:ActivityReasonCategory:edit.html.twig', [
'entity' => $entity,
'edit_form' => $editForm->createView(),
]);
}
/**
* Lists all ActivityReasonCategory entities.
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReasonCategory::class)->findAll();
return $this->render('ChillActivityBundle:ActivityReasonCategory:index.html.twig', [
'entities' => $entities,
]);
}
/**
* Displays a form to create a new ActivityReasonCategory entity.
*/
public function newAction()
{
$entity = new ActivityReasonCategory();
$form = $this->createCreateForm($entity);
return $this->render('ChillActivityBundle:ActivityReasonCategory:new.html.twig', [
'entity' => $entity,
'form' => $form->createView(),
]);
}
/**
* Finds and displays a ActivityReasonCategory entity.
*
* @param mixed $id
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReasonCategory::class)->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityReasonCategory entity.');
}
return $this->render('ChillActivityBundle:ActivityReasonCategory:show.html.twig', [
'entity' => $entity,
]);
}
/**
* Edits an existing ActivityReasonCategory entity.
*
* @param mixed $id
*/
public function updateAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReasonCategory::class)->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityReasonCategory entity.');
}
$editForm = $this->createEditForm($entity);
$editForm->handleRequest($request);
if ($editForm->isValid()) {
$em->flush();
return $this->redirect($this->generateUrl('chill_activity_activityreasoncategory_edit', ['id' => $id]));
}
return $this->render('ChillActivityBundle:ActivityReasonCategory:edit.html.twig', [
'entity' => $entity,
'edit_form' => $editForm->createView(),
]);
'form' => $form->createView(),
));
}
/**
@@ -155,32 +63,116 @@ class ActivityReasonCategoryController extends AbstractController
*/
private function createCreateForm(ActivityReasonCategory $entity)
{
$form = $this->createForm(ActivityReasonCategoryType::class, $entity, [
$form = $this->createForm(ActivityReasonCategoryType::class, $entity, array(
'action' => $this->generateUrl('chill_activity_activityreasoncategory_create'),
'method' => 'POST',
]);
));
$form->add('submit', SubmitType::class, ['label' => 'Create']);
$form->add('submit', SubmitType::class, array('label' => 'Create'));
return $form;
}
/**
* Creates a form to edit a ActivityReasonCategory entity.
* Displays a form to create a new ActivityReasonCategory entity.
*
* @param ActivityReasonCategory $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
public function newAction()
{
$entity = new ActivityReasonCategory();
$form = $this->createCreateForm($entity);
return $this->render('ChillActivityBundle:ActivityReasonCategory:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}
/**
* Finds and displays a ActivityReasonCategory entity.
*
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ChillActivityBundle:ActivityReasonCategory')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityReasonCategory entity.');
}
return $this->render('ChillActivityBundle:ActivityReasonCategory:show.html.twig', array(
'entity' => $entity,
));
}
/**
* Displays a form to edit an existing ActivityReasonCategory entity.
*
*/
public function editAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ChillActivityBundle:ActivityReasonCategory')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityReasonCategory entity.');
}
$editForm = $this->createEditForm($entity);
return $this->render('ChillActivityBundle:ActivityReasonCategory:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
));
}
/**
* Creates a form to edit a ActivityReasonCategory entity.
*
* @param ActivityReasonCategory $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createEditForm(ActivityReasonCategory $entity)
{
$form = $this->createForm(ActivityReasonCategoryType::class, $entity, [
'action' => $this->generateUrl('chill_activity_activityreasoncategory_update', ['id' => $entity->getId()]),
$form = $this->createForm(ActivityReasonCategoryType::class, $entity, array(
'action' => $this->generateUrl('chill_activity_activityreasoncategory_update', array('id' => $entity->getId())),
'method' => 'PUT',
]);
));
$form->add('submit', SubmitType::class, ['label' => 'Update']);
$form->add('submit', SubmitType::class, array('label' => 'Update'));
return $form;
}
/**
* Edits an existing ActivityReasonCategory entity.
*
*/
public function updateAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ChillActivityBundle:ActivityReasonCategory')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityReasonCategory entity.');
}
$editForm = $this->createEditForm($entity);
$editForm->handleRequest($request);
if ($editForm->isValid()) {
$em->flush();
return $this->redirect($this->generateUrl('chill_activity_activityreasoncategory_edit', array('id' => $id)));
}
return $this->render('ChillActivityBundle:ActivityReasonCategory:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
));
}
}

View File

@@ -1,29 +1,38 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Form\ActivityReasonType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
/**
* ActivityReason controller.
*
*/
class ActivityReasonController extends AbstractController
{
/**
* Lists all ActivityReason entities.
*
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('ChillActivityBundle:ActivityReason')->findAll();
return $this->render('ChillActivityBundle:ActivityReason:index.html.twig', array(
'entities' => $entities,
));
}
/**
* Creates a new ActivityReason entity.
*
*/
public function createAction(Request $request)
{
@@ -36,114 +45,13 @@ class ActivityReasonController extends AbstractController
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('chill_activity_activityreason', ['id' => $entity->getId()]));
return $this->redirect($this->generateUrl('chill_activity_activityreason', array('id' => $entity->getId())));
}
return $this->render('ChillActivityBundle:ActivityReason:new.html.twig', [
return $this->render('ChillActivityBundle:ActivityReason:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
]);
}
/**
* Displays a form to edit an existing ActivityReason entity.
*
* @param mixed $id
*/
public function editAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReason::class)->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityReason entity.');
}
$editForm = $this->createEditForm($entity);
return $this->render('ChillActivityBundle:ActivityReason:edit.html.twig', [
'entity' => $entity,
'edit_form' => $editForm->createView(),
]);
}
/**
* Lists all ActivityReason entities.
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReason::class)->findAll();
return $this->render('ChillActivityBundle:ActivityReason:index.html.twig', [
'entities' => $entities,
]);
}
/**
* Displays a form to create a new ActivityReason entity.
*/
public function newAction()
{
$entity = new ActivityReason();
$form = $this->createCreateForm($entity);
return $this->render('ChillActivityBundle:ActivityReason:new.html.twig', [
'entity' => $entity,
'form' => $form->createView(),
]);
}
/**
* Finds and displays a ActivityReason entity.
*
* @param mixed $id
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReason::class)->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityReason entity.');
}
return $this->render('ChillActivityBundle:ActivityReason:show.html.twig', [
'entity' => $entity,
]);
}
/**
* Edits an existing ActivityReason entity.
*
* @param mixed $id
*/
public function updateAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReason::class)->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityReason entity.');
}
$editForm = $this->createEditForm($entity);
$editForm->handleRequest($request);
if ($editForm->isValid()) {
$em->flush();
return $this->redirect($this->generateUrl('chill_activity_activityreason', ['id' => $id]));
}
return $this->render('ChillActivityBundle:ActivityReason:edit.html.twig', [
'entity' => $entity,
'edit_form' => $editForm->createView(),
]);
'form' => $form->createView(),
));
}
/**
@@ -155,32 +63,116 @@ class ActivityReasonController extends AbstractController
*/
private function createCreateForm(ActivityReason $entity)
{
$form = $this->createForm(ActivityReasonType::class, $entity, [
$form = $this->createForm(ActivityReasonType::class, $entity, array(
'action' => $this->generateUrl('chill_activity_activityreason_create'),
'method' => 'POST',
]);
));
$form->add('submit', SubmitType::class, ['label' => 'Create']);
$form->add('submit', SubmitType::class, array('label' => 'Create'));
return $form;
}
/**
* Creates a form to edit a ActivityReason entity.
* Displays a form to create a new ActivityReason entity.
*
* @param ActivityReason $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
public function newAction()
{
$entity = new ActivityReason();
$form = $this->createCreateForm($entity);
return $this->render('ChillActivityBundle:ActivityReason:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}
/**
* Finds and displays a ActivityReason entity.
*
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ChillActivityBundle:ActivityReason')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityReason entity.');
}
return $this->render('ChillActivityBundle:ActivityReason:show.html.twig', array(
'entity' => $entity,
));
}
/**
* Displays a form to edit an existing ActivityReason entity.
*
*/
public function editAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ChillActivityBundle:ActivityReason')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityReason entity.');
}
$editForm = $this->createEditForm($entity);
return $this->render('ChillActivityBundle:ActivityReason:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView()
));
}
/**
* Creates a form to edit a ActivityReason entity.
*
* @param ActivityReason $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createEditForm(ActivityReason $entity)
{
$form = $this->createForm(ActivityReasonType::class, $entity, [
'action' => $this->generateUrl('chill_activity_activityreason_update', ['id' => $entity->getId()]),
$form = $this->createForm(ActivityReasonType::class, $entity, array(
'action' => $this->generateUrl('chill_activity_activityreason_update', array('id' => $entity->getId())),
'method' => 'PUT',
]);
));
$form->add('submit', SubmitType::class, ['label' => 'Update']);
$form->add('submit', SubmitType::class, array('label' => 'Update'));
return $form;
}
/**
* Edits an existing ActivityReason entity.
*
*/
public function updateAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ChillActivityBundle:ActivityReason')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityReason entity.');
}
$editForm = $this->createEditForm($entity);
$editForm->handleRequest($request);
if ($editForm->isValid()) {
$em->flush();
return $this->redirect($this->generateUrl('chill_activity_activityreason', array('id' => $id)));
}
return $this->render('ChillActivityBundle:ActivityReason:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView()
));
}
}

View File

@@ -1,14 +1,5 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Controller;
use Chill\MainBundle\CRUD\Controller\CRUDController;
@@ -18,8 +9,10 @@ use Symfony\Component\HttpFoundation\Request;
class AdminActivityPresenceController extends CRUDController
{
/**
* @param string $action
* @param \Doctrine\ORM\QueryBuilder|mixed $query
*
* @param Request $request
* @param PaginatorInterface $paginator
* @return \Doctrine\ORM\QueryBuilder|mixed
*/
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)

View File

@@ -1,14 +1,5 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Controller;
use Chill\MainBundle\CRUD\Controller\CRUDController;
@@ -18,8 +9,10 @@ use Symfony\Component\HttpFoundation\Request;
class AdminActivityTypeCategoryController extends CRUDController
{
/**
* @param string $action
* @param \Doctrine\ORM\QueryBuilder|mixed $query
*
* @param Request $request
* @param PaginatorInterface $paginator
* @return \Doctrine\ORM\QueryBuilder|mixed
*/
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)

View File

@@ -1,14 +1,5 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Controller;
use Chill\MainBundle\CRUD\Controller\CRUDController;
@@ -18,14 +9,15 @@ use Symfony\Component\HttpFoundation\Request;
class AdminActivityTypeController extends CRUDController
{
/**
* @param string $action
* @param \Doctrine\ORM\QueryBuilder|mixed $query
*
* @param Request $request
* @param PaginatorInterface $paginator
* @return \Doctrine\ORM\QueryBuilder|mixed
*/
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
{
/** @var \Doctrine\ORM\QueryBuilder $query */
return $query->orderBy('e.ordering', 'ASC')
->addOrderBy('e.id', 'ASC');
return $query->orderBy('e.ordering', 'ASC');
}
}

View File

@@ -1,20 +1,33 @@
<?php
/**
/*
* Chill is a software for social workers
* Copyright (C) 2015 Champs Libres <info@champs-libres.coop>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
/**
* Controller for activity configuration.
* Controller for activity configuration
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @author Champs Libres <info@champs-libres.coop>
*/
class AdminController extends AbstractController
{
@@ -22,7 +35,7 @@ class AdminController extends AbstractController
{
return $this->render('ChillActivityBundle:Admin:layout_activity.html.twig');
}
public function redirectToAdminIndexAction()
{
return $this->redirectToRoute('chill_main_admin_central');

View File

@@ -1,36 +1,48 @@
<?php
/**
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\DataFixtures\ORM;
use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\DataFixtures\ORM\LoadScopes;
use Chill\MainBundle\DataFixtures\ORM\LoadUsers;
use Chill\PersonBundle\Entity\Person;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ObjectManager;
use Faker\Factory as FakerFactory;
use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\DataFixtures\ORM\LoadUsers;
use Chill\ActivityBundle\DataFixtures\ORM\LoadActivityReason;
use Chill\ActivityBundle\DataFixtures\ORM\LoadActivityType;
use Chill\MainBundle\DataFixtures\ORM\LoadScopes;
class LoadActivity extends AbstractFixture implements OrderedFixtureInterface
{
use \Symfony\Component\DependencyInjection\ContainerAwareTrait;
private EntityManagerInterface $em;
/**
* @var \Faker\Generator
*/
private $faker;
private EntityManagerInterface $em;
public function __construct(EntityManagerInterface $em)
{
@@ -43,53 +55,30 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface
return 16400;
}
public function load(ObjectManager $manager)
/**
* Return a random scope
*
* @return \Chill\MainBundle\Entity\Scope
*/
private function getRandomScope()
{
$persons = $this->em
->getRepository(Person::class)
->findAll();
foreach ($persons as $person) {
$activityNbr = mt_rand(0, 3);
for ($i = 0; $i < $activityNbr; ++$i) {
$activity = $this->newRandomActivity($person);
if (null !== $activity) {
$manager->persist($activity);
}
}
}
$manager->flush();
}
public function newRandomActivity($person): ?Activity
{
$activity = (new Activity())
->setUser($this->getRandomUser())
->setPerson($person)
->setDate($this->faker->dateTimeThisYear())
->setDurationTime($this->faker->dateTime(36000))
->setType($this->getRandomActivityType())
->setScope($this->getRandomScope());
// ->setAttendee($this->faker->boolean())
for ($i = 0; mt_rand(0, 4) > $i; ++$i) {
$reason = $this->getRandomActivityReason();
if (null !== $reason) {
$activity->addReason($reason);
} else {
return null;
}
}
return $activity;
$scopeRef = LoadScopes::$references[array_rand(LoadScopes::$references)];
return $this->getReference($scopeRef);
}
/**
* Return a random activityReason.
* Return a random activityType
*
* @return \Chill\ActivityBundle\Entity\ActivityType
*/
private function getRandomActivityType()
{
$typeRef = LoadActivityType::$references[array_rand(LoadActivityType::$references)];
return $this->getReference($typeRef);
}
/**
* Return a random activityReason
*
* @return \Chill\ActivityBundle\Entity\ActivityReason
*/
@@ -101,38 +90,57 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface
}
/**
* Return a random activityType.
*
* @return \Chill\ActivityBundle\Entity\ActivityType
*/
private function getRandomActivityType()
{
$typeRef = LoadActivityType::$references[array_rand(LoadActivityType::$references)];
return $this->getReference($typeRef);
}
/**
* Return a random scope.
*
* @return \Chill\MainBundle\Entity\Scope
*/
private function getRandomScope()
{
$scopeRef = LoadScopes::$references[array_rand(LoadScopes::$references)];
return $this->getReference($scopeRef);
}
/**
* Return a random user.
* Return a random user
*
* @return \Chill\MainBundle\Entity\User
*/
private function getRandomUser()
{
$userRef = array_rand(LoadUsers::$refs);
return $this->getReference($userRef);
}
public function newRandomActivity($person): ?Activity
{
$activity = (new Activity())
->setUser($this->getRandomUser())
->setPerson($person)
->setDate($this->faker->dateTimeThisYear())
->setDurationTime($this->faker->dateTime(36000))
->setType($this->getRandomActivityType())
->setScope($this->getRandomScope())
;
// ->setAttendee($this->faker->boolean())
for ($i = 0; $i < rand(0, 4); $i++) {
$reason = $this->getRandomActivityReason();
if (null !== $reason) {
$activity->addReason($reason);
} else {
return null;
}
}
return $activity;
}
public function load(ObjectManager $manager)
{
$persons = $this->em
->getRepository(Person::class)
->findAll();
foreach ($persons as $person) {
$activityNbr = rand(0,3);
for ($i = 0; $i < $activityNbr; $i ++) {
$activity = $this->newRandomActivity($person);
if (null !== $activity) {
$manager->persist($activity);
}
}
}
$manager->flush();
}
}

View File

@@ -1,23 +1,15 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\DataFixtures\ORM;
use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\DataFixtures\ORM\LoadAbstractNotificationsTrait;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\DataFixtures\ORM\LoadAbstractNotificationsTrait;
use Chill\ActivityBundle\DataFixtures\ORM\LoadActivity;
/**
* Load notififications into database.
* Load notififications into database
*/
class LoadActivityNotifications extends AbstractFixture implements DependentFixtureInterface
{
@@ -33,9 +25,9 @@ class LoadActivityNotifications extends AbstractFixture implements DependentFixt
'center a_social',
'center a_administrative',
'center a_direction',
'multi_center',
'multi_center'
],
],
]
];
public function getDependencies()

View File

@@ -1,68 +1,81 @@
<?php
/**
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\DataFixtures\ORM;
use Chill\ActivityBundle\Entity\ActivityReason;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Chill\ActivityBundle\Entity\ActivityReason;
/**
* Description of LoadActivityReason.
* Description of LoadActivityReason
*
* @author Champs-Libres Coop
*/
class LoadActivityReason extends AbstractFixture implements OrderedFixtureInterface
{
public static $references = [];
public function getOrder()
{
return 16300;
}
public static $references = array();
public function load(ObjectManager $manager)
{
$reasons = [
[
'name' => ['fr' => 'Recherche logement', 'en' => 'Housing research', 'nl' => 'Woning zoektoch'],
'category' => 'cat_Housing', ],
'category' => 'cat_Housing'],
[
'name' => ['fr' => 'Problème avec propriétaire', 'en' => 'Landlord problems', 'nl' => 'Huisbaas problemen'],
'category' => 'cat_Housing', ],
'category' => 'cat_Housing'],
[
'name' => ['fr' => 'Retard de payement', 'en' => 'Payement problems', 'nl' => 'Betalings vertragingen'],
'category' => 'cat_Housing', ],
'category' => 'cat_Housing'],
[
'name' => ['fr' => 'Explication législation', 'en' => 'Legislation explanation', 'nl' => 'Legislative uitleg'],
'category' => 'cat_Unemployment procedure', ],
'category' => 'cat_Unemployment procedure'],
[
'name' => ['fr' => 'Coaching entretien d\'activation', 'en' => 'Interview coaching', 'nl' => 'Interview coaching'],
'category' => 'cat_Unemployment procedure', ],
'category' => 'cat_Unemployment procedure'],
[
'name' => ['fr' => 'Récupération des allocations', 'en' => 'Allowance recovery', 'nl' => 'Terugwinning van de uitkeringen'],
'category' => 'cat_Unemployment procedure', ],
'category' => 'cat_Unemployment procedure']
];
foreach ($reasons as $r) {
echo 'Creating activity reason : ' . $r['name']['en'] . "\n";
print "Creating activity reason : " . $r['name']['en'] . "\n";
$activityReason = (new ActivityReason())
->setName(($r['name']))
->setActive(true)
->setCategory($this->getReference($r['category']));
$manager->persist($activityReason);
$reference = 'activity_reason_' . $r['name']['en'];
$reference = 'activity_reason_'.$r['name']['en'];
$this->addReference($reference, $activityReason);
static::$references[] = $reference;
}
$manager->flush();
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,77 +1,71 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use function is_int;
/**
* This is the class that validates and merges configuration from your app/config files.
* This is the class that validates and merges configuration from your app/config files
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
*/
class Configuration implements ConfigurationInterface
{
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder('chill_activity');
$rootNode = $treeBuilder->getRootNode('chill_activity');
$rootNode
->children()
->arrayNode('form')
->canBeEnabled()
->children()
->arrayNode('time_duration')
->isRequired()
->requiresAtLeastOneElement()
->defaultValue(
[
['label' => '5 minutes', 'seconds' => 300],
['label' => '10 minutes', 'seconds' => 600],
['label' => '15 minutes', 'seconds' => 900],
['label' => '20 minutes', 'seconds' => 1200],
['label' => '25 minutes', 'seconds' => 1500],
['label' => '30 minutes', 'seconds' => 1800],
['label' => '45 minutes', 'seconds' => 2700],
['label' => '1 hour', 'seconds' => 3600],
['label' => '1 hour 15', 'seconds' => 4500],
['label' => '1 hour 30', 'seconds' => 5400],
['label' => '1 hour 45', 'seconds' => 6300],
['label' => '2 hours', 'seconds' => 7200],
]
)
->info('The intervals of time to show in activity form')
->prototype('array')
->children()
->scalarNode('seconds')
->info('The number of seconds of this duration. Must be an integer.')
->cannotBeEmpty()
->validate()
->ifTrue(static function ($data) {
return !is_int($data);
})->thenInvalid('The value %s is not a valid integer')
->end()
->end()
->scalarNode('label')
->cannotBeEmpty()
->info('The label to show into fields')
->end()
->end()
->end()
->children()
->arrayNode('form')
->canBeEnabled()
->children()
->arrayNode('time_duration')
->isRequired()
->requiresAtLeastOneElement()
->defaultValue(
array(
[ 'label' => '5 minutes', 'seconds' => 300],
[ 'label' => '10 minutes', 'seconds' => 600],
[ 'label' => '15 minutes', 'seconds' => 900],
[ 'label' => '20 minutes', 'seconds' => 1200],
[ 'label' => '25 minutes', 'seconds' => 1500],
[ 'label' => '30 minutes', 'seconds' => 1800],
[ 'label' => '45 minutes', 'seconds' => 2700],
[ 'label' => '1 hour', 'seconds' => 3600],
[ 'label' => '1 hour 15', 'seconds' => 4500],
[ 'label' => '1 hour 30', 'seconds' => 5400],
[ 'label' => '1 hour 45', 'seconds' => 6300],
[ 'label' => '2 hours', 'seconds' => 7200],
)
)
->info('The intervals of time to show in activity form')
->prototype('array')
->children()
->scalarNode('seconds')
->info("The number of seconds of this duration. Must be an integer.")
->cannotBeEmpty()
->validate()
->ifTrue(function($data) {
return !is_int($data);
})->thenInvalid("The value %s is not a valid integer")
->end()
->end()
->scalarNode('label')
->cannotBeEmpty()
->info("The label to show into fields")
->end()
->end()
->end()
// ->validate()
//
//
// ->ifTrue(function ($data) {
// // test this is an array
// if (!is_array($data)) {
@@ -90,10 +84,11 @@ class Configuration implements ConfigurationInterface
// })
// ->thenInvalid("The data are invalid. The keys must be a string and the value integers")
// ->end()
->end()
->end()
->end()
->end();
->end()
->end()
->end()
->end();
return $treeBuilder;
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -1,43 +1,40 @@
<?php
/**
* Chill is a software for social workers
/*
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
* Copyright (C) 2015, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Chill\ActivityBundle\Entity\ActivityReasonCategory;
/**
* Class ActivityReason.
* Class ActivityReason
*
* @ORM\Entity
* @package Chill\ActivityBundle\Entity
* @ORM\Entity()
* @ORM\Table(name="activityreason")
* @ORM\HasLifecycleCallbacks
* @ORM\HasLifecycleCallbacks()
*/
class ActivityReason
{
/**
* @var bool
* @ORM\Column(type="boolean")
*/
private $active = true;
/**
* @var ActivityReasonCategory
* @ORM\ManyToOne(
* targetEntity="Chill\ActivityBundle\Entity\ActivityReasonCategory",
* inversedBy="reasons")
*/
private $category;
/**
* @var int
* @var integer
*
* @ORM\Id
* @ORM\Column(name="id", type="integer")
@@ -52,17 +49,86 @@ class ActivityReason
private $name;
/**
* Get active.
*
* @return bool
* @var ActivityReasonCategory
* @ORM\ManyToOne(
* targetEntity="Chill\ActivityBundle\Entity\ActivityReasonCategory",
* inversedBy="reasons")
*/
public function getActive()
private $category;
/**
* @var boolean
* @ORM\Column(type="boolean")
*/
private $active = true;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->active;
return $this->id;
}
/**
* Get category.
* Set name
*
* @param array $name
* @return ActivityReason
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return array | string
*/
public function getName($locale = null)
{
if ($locale) {
if (isset($this->name[$locale])) {
return $this->name[$locale];
} else {
foreach ($this->name as $name) {
if (!empty($name)) {
return $name;
}
}
}
return '';
} else {
return $this->name;
}
}
/**
* Set category of the reason. If you set to the reason an inactive
* category, the reason will become inactive
*
* @param ActivityReasonCategory $category
* @return ActivityReason
*/
public function setCategory(ActivityReasonCategory $category)
{
if($this->category !== $category && ! $category->getActive()) {
$this->setActive(False);
}
$this->category = $category;
return $this;
}
/**
* Get category
*
* @return ActivityReasonCategory
*/
@@ -72,46 +138,9 @@ class ActivityReason
}
/**
* Get id.
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Get name.
*
* @param mixed|null $locale
*
* @return array | string
*/
public function getName($locale = null)
{
if ($locale) {
if (isset($this->name[$locale])) {
return $this->name[$locale];
}
foreach ($this->name as $name) {
if (!empty($name)) {
return $name;
}
}
return '';
}
return $this->name;
}
/**
* Set active.
*
* @param bool $active
* Set active
*
* @param boolean $active
* @return ActivityReason
*/
public function setActive($active)
@@ -122,33 +151,13 @@ class ActivityReason
}
/**
* Set category of the reason. If you set to the reason an inactive
* category, the reason will become inactive.
* Get active
*
* @return ActivityReason
* @return boolean
*/
public function setCategory(ActivityReasonCategory $category)
public function getActive()
{
if ($this->category !== $category && !$category->getActive()) {
$this->setActive(false);
}
$this->category = $category;
return $this;
}
/**
* Set name.
*
* @param array $name
*
* @return ActivityReason
*/
public function setName($name)
{
$this->name = $name;
return $this;
return $this->active;
}
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,5 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Entity;
@@ -14,17 +7,12 @@ namespace Chill\ActivityBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Entity()
* @ORM\Table(name="activitytypecategory")
* @ORM\HasLifecycleCallbacks
* @ORM\HasLifecycleCallbacks()
*/
class ActivityTypeCategory
{
/**
* @ORM\Column(type="boolean")
*/
private bool $active = true;
/**
* @ORM\Id
* @ORM\Column(name="id", type="integer")
@@ -38,10 +26,38 @@ class ActivityTypeCategory
private array $name = [];
/**
* @ORM\Column(type="float", options={"default": "0.0"})
* @ORM\Column(type="boolean")
*/
private bool $active = true;
/**
* @ORM\Column(type="float", options={"default"="0.0"})
*/
private float $ordering = 0.0;
public function getId(): ?int
{
return $this->id;
}
/**
* Set name
*/
public function setName(array $name): self
{
$this->name = $name;
return $this;
}
/**
* Get name
*/
public function getName(): array
{
return $this->name;
}
/**
* Get active
* return true if the category type is active.
@@ -51,27 +67,9 @@ class ActivityTypeCategory
return $this->active;
}
public function getId(): ?int
{
return $this->id;
}
/**
* Get name.
*/
public function getName(): array
{
return $this->name;
}
public function getOrdering(): float
{
return $this->ordering;
}
/**
* Is active
* return true if the category type is active.
* return true if the category type is active
*/
public function isActive(): bool
{
@@ -80,7 +78,7 @@ class ActivityTypeCategory
/**
* Set active
* set to true if the category type is active.
* set to true if the category type is active
*/
public function setActive(bool $active): self
{
@@ -89,14 +87,9 @@ class ActivityTypeCategory
return $this;
}
/**
* Set name.
*/
public function setName(array $name): self
public function getOrdering(): float
{
$this->name = $name;
return $this;
return $this->ordering;
}
public function setOrdering(float $ordering): self

View File

@@ -1,74 +0,0 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\EntityListener;
use Chill\ActivityBundle\Entity\Activity;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use function in_array;
class ActivityEntityListener
{
private EntityManagerInterface $em;
private AccompanyingPeriodWorkRepository $workRepository;
public function __construct(EntityManagerInterface $em, AccompanyingPeriodWorkRepository $workRepository)
{
$this->em = $em;
$this->workRepository = $workRepository;
}
public function persistActionToCourse(Activity $activity)
{
if ($activity->getAccompanyingPeriod() instanceof AccompanyingPeriod) {
$period = $activity->getAccompanyingPeriod();
$accompanyingCourseWorks = $this->workRepository->findByAccompanyingPeriod($period);
$periodActions = [];
$now = new DateTimeImmutable();
foreach ($accompanyingCourseWorks as $key => $work) {
// take only the actions which are still opened
if ($work->getEndDate() === null || $work->getEndDate() > ($activity->getDate() ?? $now)) {
$periodActions[$key] = spl_object_hash($work->getSocialAction());
}
}
$associatedPersons = $activity->getPersonsAssociated();
$associatedThirdparties = $activity->getThirdParties();
foreach ($activity->getSocialActions() as $action) {
if (in_array(spl_object_hash($action), $periodActions, true)) {
continue;
}
$newAction = new AccompanyingPeriodWork();
$newAction->setSocialAction($action);
$period->addWork($newAction);
$date = DateTimeImmutable::createFromMutable($activity->getDate());
$newAction->setStartDate($date);
foreach ($associatedPersons as $person) {
$newAction->addPerson($person);
}
$this->em->persist($newAction);
$this->em->flush();
}
}
}
}

View File

@@ -1,83 +0,0 @@
<?php
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator\ACPAggregators;
use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\PersonBundle\Repository\SocialWork\SocialActionRepository;
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
use Closure;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
class BySocialActionAggregator implements AggregatorInterface
{
private SocialActionRender $actionRender;
private SocialActionRepository $actionRepository;
public function __construct(
SocialActionRender $actionRender,
SocialActionRepository $actionRepository
) {
$this->actionRender = $actionRender;
$this->actionRepository = $actionRepository;
}
public function getLabels($key, array $values, $data)
{
return function($value) {
if ('_header' === $value) {
return 'Social action';
}
$sa = $this->actionRepository->find($value);
return $this->actionRender->renderString($sa, []);
};
}
public function getQueryKeys($data): array
{
return ['socialaction_aggregator'];
}
public function buildForm(FormBuilderInterface $builder)
{
// no form
}
public function getTitle(): string
{
return 'Group activity by linked socialaction';
}
public function addRole()
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
if(!in_array('socialaction', $qb->getAllAliases())) {
$qb->join('activity.socialActions', 'socialaction');
}
$qb->addSelect('socialaction.id AS socialaction_aggregator');
$groupBy = $qb->getDQLPart('groupBy');
if (!empty($groupBy)) {
$qb->addGroupBy('socialaction_aggregator');
} else {
$qb->groupBy('socialaction_aggregator');
}
}
public function applyOn(): string
{
return Declarations::ACTIVITY_ACP;
}
}

View File

@@ -1,84 +0,0 @@
<?php
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator\ACPAggregators;
use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
use Closure;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
class BySocialIssueAggregator implements AggregatorInterface
{
private SocialIssueRepository $issueRepository;
private SocialIssueRender $issueRender;
public function __construct(
SocialIssueRepository $issueRepository,
SocialIssueRender $issueRender
) {
$this->issueRepository = $issueRepository;
$this->issueRender = $issueRender;
}
public function getLabels($key, array $values, $data)
{
return function ($value): string {
if ($value === '_header') {
return 'Social issues';
}
$i = $this->issueRepository->find($value);
return $this->issueRender->renderString($i, []);
};
}
public function getQueryKeys($data): array
{
return ['socialissue_aggregator'];
}
public function buildForm(FormBuilderInterface $builder)
{
// no form
}
public function getTitle(): string
{
return 'Group activity by linked socialissue';
}
public function addRole()
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
if (!in_array('socialissue', $qb->getAllAliases())) {
$qb->join('activity.socialIssues', 'socialissue');
}
$qb->addSelect('socialissue.id AS socialissue_aggregator');
$groupBy = $qb->getDQLPart('groupBy');
if (!empty($groupBy)) {
$qb->addGroupBy('socialissue_aggregator');
} else {
$qb->groupBy('socialissue_aggregator');
}
}
public function applyOn(): string
{
return Declarations::ACTIVITY_ACP;
}
}

View File

@@ -1,83 +0,0 @@
<?php
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator\ACPAggregators;
use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
use Chill\ThirdPartyBundle\Templating\Entity\ThirdPartyRender;
use Closure;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
class ByThirdpartyAggregator implements AggregatorInterface
{
private ThirdPartyRepository $thirdPartyRepository;
private ThirdPartyRender $thirdPartyRender;
public function __construct(
ThirdPartyRepository $thirdPartyRepository,
ThirdPartyRender $thirdPartyRender
) {
$this->thirdPartyRepository = $thirdPartyRepository;
$this->thirdPartyRender = $thirdPartyRender;
}
public function getLabels($key, array $values, $data)
{
return function ($value): string {
if ($value === '_header') {
return 'Accepted thirdparty';
}
$tp = $this->thirdPartyRepository->find($value);
return $this->thirdPartyRender->renderString($tp, []);
};
}
public function getQueryKeys($data): array
{
return ['thirdparty_aggregator'];
}
public function buildForm(FormBuilderInterface $builder)
{
// no form
}
public function getTitle(): string
{
return 'Group activity by linked thirdparties';
}
public function addRole()
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
if (!in_array('thirdparty', $qb->getAllAliases())) {
$qb->join('activity.thirdParties', 'thirdparty');
}
$qb->addSelect('thirdparty.id AS thirdparty_aggregator');
$groupBy = $qb->getDQLPart('groupBy');
if (!empty($groupBy)) {
$qb->addGroupBy('thirdparty_aggregator');
} else {
$qb->groupBy('thirdparty_aggregator');
}
}
public function applyOn(): string
{
return Declarations::ACTIVITY_ACP;
}
}

View File

@@ -1,83 +0,0 @@
<?php
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator\ACPAggregators;
use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Repository\UserRepository;
use Chill\MainBundle\Templating\Entity\UserRender;
use Closure;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
class ByUserAggregator implements AggregatorInterface
{
private UserRepository $userRepository;
private UserRender $userRender;
public function __construct(
UserRepository $userRepository,
UserRender $userRender
) {
$this->userRepository = $userRepository;
$this->userRender = $userRender;
}
public function getLabels($key, array $values, $data)
{
return function ($value): string {
if ($value === '_header') {
return 'Accepted users';
}
$u = $this->userRepository->find($value);
return $this->userRender->renderString($u, []);
};
}
public function getQueryKeys($data): array
{
return ['users_aggregator'];
}
public function buildForm(FormBuilderInterface $builder)
{
// no form
}
public function getTitle(): string
{
return 'Group activity by linked users';
}
public function addRole()
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
if (!in_array('user', $qb->getAllAliases())) {
$qb->join('activity.users', 'user');
}
$qb->addSelect('user.id AS users_aggregator');
$groupBy = $qb->getDQLPart('groupBy');
if (!empty($groupBy)) {
$qb->addGroupBy('users_aggregator');
} else {
$qb->groupBy('users_aggregator');
}
}
public function applyOn(): string
{
return Declarations::ACTIVITY_ACP;
}
}

View File

@@ -1,129 +0,0 @@
<?php
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator\ACPAggregators;
use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface;
use Closure;
use Doctrine\ORM\QueryBuilder;
use RuntimeException;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class DateAggregator implements AggregatorInterface
{
private const CHOICES = [
'by month' => 'month',
'by week' => 'week',
'by year' => 'year',
];
private CONST DEFAULT_CHOICE = 'year';
private TranslatorInterface $translator;
public function __construct(
TranslatorInterface $translator
) {
$this->translator = $translator;
}
public function getLabels($key, array $values, $data)
{
return function ($value) use ($data): string {
if ($value === '_header') {
return 'by '. $data['frequency'];
}
switch ($data['frequency']) {
case 'month':
$month = \DateTime::createFromFormat('!m', $value);
return sprintf(
"%02d (%s)",
$value,
$month->format('M')
);
case 'week':
//return $this->translator->trans('for week') .' '. $value ;
case 'year':
//return $this->translator->trans('in year') .' '. $value ;
default:
return $value;
}
};
}
public function getQueryKeys($data): array
{
return ['date_aggregator'];
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('frequency', ChoiceType::class, [
'choices' => self::CHOICES,
'multiple' => false,
'expanded' => true,
'empty_data' => self::DEFAULT_CHOICE,
'data' => self::DEFAULT_CHOICE,
]);
}
public function getTitle(): string
{
return 'Group activity by date';
}
public function addRole()
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$order = null;
switch ($data['frequency']) {
case 'month':
$fmt = 'MM'; break;
case 'week':
$fmt = 'IW'; break;
case 'year':
$fmt = 'YYYY'; $order = 'DESC'; break;
default:
throw new RuntimeException(sprintf("The frequency data '%s' is invalid.", $data['frequency']));
}
$qb->addSelect(sprintf("TO_CHAR(activity.date, '%s') AS date_aggregator", $fmt));
$groupBy = $qb->getDQLPart('groupBy');
if (!empty($groupBy)) {
$qb->addGroupBy('date_aggregator');
} else {
$qb->groupBy('date_aggregator');
}
$orderBy = $qb->getDQLPart('orderBy');
if (!empty($orderBy)) {
$qb->addOrderBy('date_aggregator', $order);
} else {
$qb->orderBy('date_aggregator', $order);
}
}
public function applyOn(): string
{
return Declarations::ACTIVITY_ACP;
}
}

View File

@@ -1,86 +0,0 @@
<?php
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator\ACPAggregators;
use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Repository\LocationTypeRepository;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Closure;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
class LocationTypeAggregator implements AggregatorInterface
{
private LocationTypeRepository $locationTypeRepository;
private TranslatableStringHelper $translatableStringHelper;
public function __construct(
LocationTypeRepository $locationTypeRepository,
TranslatableStringHelper $translatableStringHelper
) {
$this->locationTypeRepository = $locationTypeRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
public function getLabels($key, array $values, $data)
{
return function ($value): string {
if ($value === '_header') {
return 'Accepted locationtype';
}
$lt = $this->locationTypeRepository->find($value);
return $this->translatableStringHelper->localize(
$lt->getTitle()
);
};
}
public function getQueryKeys($data): array
{
return ['locationtype_aggregator'];
}
public function buildForm(FormBuilderInterface $builder)
{
// no form
}
public function getTitle(): string
{
return 'Group activity by locationtype';
}
public function addRole()
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
if (!in_array('location', $qb->getAllAliases())) {
$qb->join('activity.location', 'location');
}
$qb->addSelect('IDENTITY(location.locationType) AS locationtype_aggregator');
$groupBy = $qb->getDQLPart('groupBy');
if (!empty($groupBy)) {
$qb->addGroupBy('locationtype_aggregator');
} else {
$qb->groupBy('locationtype_aggregator');
}
}
public function applyOn(): string
{
return Declarations::ACTIVITY_ACP;
}
}

View File

@@ -1,86 +0,0 @@
<?php
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator\ACPAggregators;
use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Repository\ScopeRepository;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Closure;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
class UserScopeAggregator implements AggregatorInterface
{
private ScopeRepository $scopeRepository;
private TranslatableStringHelper $translatableStringHelper;
public function __construct(
ScopeRepository $scopeRepository,
TranslatableStringHelper $translatableStringHelper
) {
$this->scopeRepository = $scopeRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
public function getLabels($key, array $values, $data)
{
return function ($value): string {
if ($value === '_header') {
return 'Scope';
}
$s = $this->scopeRepository->find($value);
return $this->translatableStringHelper->localize(
$s->getName()
);
};
}
public function getQueryKeys($data): array
{
return ['userscope_aggregator'];
}
public function buildForm(FormBuilderInterface $builder)
{
// no form
}
public function getTitle(): string
{
return 'Group activity by userscope';
}
public function addRole()
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
if (!in_array('user', $qb->getAllAliases())) {
$qb->join('activity.user', 'user');
}
$qb->addSelect('IDENTITY(user.mainScope) AS userscope_aggregator');
$groupBy = $qb->getDQLPart('groupBy');
if (!empty($groupBy)) {
$qb->addGroupBy('userscope_aggregator');
} else {
$qb->groupBy('userscope_aggregator');
}
}
public function applyOn(): string
{
return Declarations::ACTIVITY_ACP;
}
}

View File

@@ -1,34 +1,22 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator\PersonAggregators;
namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Repository\ActivityReasonCategoryRepository;
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use RuntimeException;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Doctrine\ORM\QueryBuilder;
use Chill\MainBundle\Export\AggregatorInterface;
use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\Query\Expr\Join;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use function array_key_exists;
use function count;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
class ActivityReasonAggregator implements AggregatorInterface, ExportElementValidatedInterface
{
@@ -48,47 +36,42 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function alterQuery(QueryBuilder $qb, $data)
{
// add select element
if ('reasons' === $data['level']) {
if ($data['level'] === 'reasons') {
$elem = 'reasons.id';
$alias = 'activity_reasons_id';
} elseif ('categories' === $data['level']) {
} elseif ($data['level'] === 'categories') {
$elem = 'category.id';
$alias = 'activity_categories_id';
} else {
throw new RuntimeException('The data provided are not recognized.');
throw new \RuntimeException('The data provided are not recognized.');
}
$qb->addSelect($elem . ' as ' . $alias);
$qb->addSelect($elem.' as '.$alias);
// make a jointure only if needed
$join = $qb->getDQLPart('join');
if (
(
array_key_exists('activity', $join)
&& !$this->checkJoinAlreadyDefined($join['activity'], 'reasons')
(array_key_exists('activity', $join)
&&
!$this->checkJoinAlreadyDefined($join['activity'], 'reasons')
)
|| (!array_key_exists('activity', $join))
OR
(! array_key_exists('activity', $join))
) {
$qb->add(
'join',
[
'activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons'),
'activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons')
],
true
);
}
// join category if necessary
if ('activity_categories_id' === $alias) {
if ($alias === 'activity_categories_id') {
// add join only if needed
if (!$this->checkJoinAlreadyDefined($qb->getDQLPart('join')['activity'], 'category')) {
$qb->join('reasons.category', 'category');
@@ -105,104 +88,12 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
}
}
public function applyOn(): string
{
return Declarations::ACTIVITY_PERSON;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add(
'level',
ChoiceType::class,
[
'choices' => [
'By reason' => 'reasons',
'By category of reason' => 'categories',
],
'multiple' => false,
'expanded' => true,
'label' => "Reason's level",
]
);
}
public function getLabels($key, array $values, $data)
{
// for performance reason, we load data from db only once
switch ($data['level']) {
case 'reasons':
$this->activityReasonRepository->findBy(['id' => $values]);
break;
case 'categories':
$this->activityReasonCategoryRepository->findBy(['id' => $values]);
break;
default:
throw new RuntimeException(sprintf("The level data '%s' is invalid.", $data['level']));
}
return function ($value) use ($data) {
if ('_header' === $value) {
return 'reasons' === $data['level'] ? 'Group by reasons' : 'Group by categories of reason';
}
switch ($data['level']) {
case 'reasons':
$r = $this->activityReasonRepository->find($value);
return sprintf(
'%s > %s',
$this->translatableStringHelper->localize($r->getCategory()->getName()),
$this->translatableStringHelper->localize($r->getName())
);
case 'categories':
$c = $this->activityReasonCategoryRepository->find($value);
return $this->translatableStringHelper->localize($c->getName());
}
};
}
public function getQueryKeys($data)
{
// add select element
if ('reasons' === $data['level']) {
return ['activity_reasons_id'];
}
if ('categories' === $data['level']) {
return ['activity_categories_id'];
}
throw new RuntimeException('The data provided are not recognised.');
}
public function getTitle()
{
return 'Aggregate by activity reason';
}
public function validateForm($data, ExecutionContextInterface $context)
{
if (null === $data['level']) {
$context
->buildViolation("The reasons's level should not be empty.")
->addViolation();
}
}
/**
* Check if a join between Activity and another alias.
* Check if a join between Activity and another alias
*
* @param Join[] $joins
* @param string $alias the alias to search for
*
* @return bool
* @return boolean
*/
private function checkJoinAlreadyDefined(array $joins, $alias)
{
@@ -214,4 +105,98 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
return false;
}
public function applyOn()
{
return 'activity';
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add(
'level',
ChoiceType::class,
[
'choices' => [
'By reason' => 'reasons',
'By category of reason' => 'categories'
],
'multiple' => false,
'expanded' => true,
'label' => "Reason's level"
]
);
}
public function validateForm($data, ExecutionContextInterface $context)
{
if ($data['level'] === null) {
$context
->buildViolation("The reasons's level should not be empty.")
->addViolation();
}
}
public function getTitle()
{
return 'Aggregate by activity reason';
}
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function getLabels($key, array $values, $data)
{
// for performance reason, we load data from db only once
switch ($data['level']) {
case 'reasons':
$this->activityReasonRepository->findBy(['id' => $values]);
break;
case 'categories':
$this->activityReasonCategoryRepository->findBy(['id' => $values]);
break;
default:
throw new \RuntimeException(sprintf("The level data '%s' is invalid.", $data['level']));
}
return function($value) use ($data) {
if ($value === '_header') {
return $data['level'] === 'reasons' ? 'Group by reasons' : 'Group by categories of reason';
}
switch ($data['level']) {
case 'reasons':
$r = $this->activityReasonRepository->find($value);
return sprintf(
"%s > %s",
$this->translatableStringHelper->localize($r->getCategory()->getName()),
$this->translatableStringHelper->localize($r->getName())
);
case 'categories':
$c = $this->activityReasonCategoryRepository->find($value);
return $this->translatableStringHelper->localize($c->getName());
}
};
}
public function getQueryKeys($data)
{
// add select element
if ($data['level'] === 'reasons') {
return array('activity_reasons_id');
}
if ($data['level'] === 'categories') {
return array ('activity_categories_id');
}
throw new \RuntimeException('The data provided are not recognised.');
}
}

View File

@@ -1,35 +1,26 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Closure;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Doctrine\ORM\QueryBuilder;
use Chill\MainBundle\Export\AggregatorInterface;
use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Doctrine\ORM\Query\Expr\Join;
class ActivityTypeAggregator implements AggregatorInterface
{
public const KEY = 'activity_type_aggregator';
protected ActivityTypeRepository $activityTypeRepository;
protected TranslatableStringHelperInterface $translatableStringHelper;
public const KEY = 'activity_type_aggregator';
public function __construct(
ActivityTypeRepository $activityTypeRepository,
TranslatableStringHelperInterface $translatableStringHelper
@@ -38,31 +29,36 @@ class ActivityTypeAggregator implements AggregatorInterface
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function alterQuery(QueryBuilder $qb, $data)
{
if (!in_array('type', $qb->getAllAliases())) {
$qb->join('activity.activityType', 'type');
}
// add select element
$qb->addSelect(sprintf('IDENTITY(activity.type) AS %s', self::KEY));
$qb->addSelect(sprintf('IDENTITY(activity.activityType) AS %s', self::KEY));
$groupby = $qb->getDQLPart('groupBy');
if (!empty($groupBy)) {
$qb->addGroupBy(self::KEY);
} else {
$qb->groupBy(self::KEY);
}
// add the "group by" part
$qb->addGroupBy(self::KEY);
}
public function applyOn(): string
/**
* Check if a join between Activity and another alias
*
* @param Join[] $joins
* @param string $alias the alias to search for
* @return boolean
*/
private function checkJoinAlreadyDefined(array $joins, $alias)
{
return Declarations::ACTIVITY;
foreach ($joins as $join) {
if ($join->getAlias() === $alias) {
return true;
}
}
return false;
}
public function applyOn()
{
return 'activity';
}
public function buildForm(FormBuilderInterface $builder)
@@ -70,13 +66,23 @@ class ActivityTypeAggregator implements AggregatorInterface
// no form required for this aggregator
}
public function getLabels($key, array $values, $data): Closure
public function getTitle()
{
return 'Aggregate by activity type';
}
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function getLabels($key, array $values, $data): \Closure
{
// for performance reason, we load data from db only once
$this->activityTypeRepository->findBy(['id' => $values]);
return function ($value): string {
if ('_header' === $value) {
return function($value): string {
if ($value === '_header') {
return 'Activity type';
}
@@ -91,27 +97,4 @@ class ActivityTypeAggregator implements AggregatorInterface
return [self::KEY];
}
public function getTitle()
{
return 'Aggregate by activity type';
}
/**
* Check if a join between Activity and another alias.
*
* @param Join[] $joins
* @param string $alias the alias to search for
*
* @return bool
*/
private function checkJoinAlreadyDefined(array $joins, $alias)
{
foreach ($joins as $join) {
if ($join->getAlias() === $alias) {
return true;
}
}
return false;
}
}

View File

@@ -1,25 +1,13 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Repository\UserRepository;
use Chill\MainBundle\Templating\Entity\UserRender;
use Closure;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Doctrine\ORM\QueryBuilder;
use Chill\MainBundle\Export\AggregatorInterface;
use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
class ActivityUserAggregator implements AggregatorInterface
{
@@ -27,14 +15,10 @@ class ActivityUserAggregator implements AggregatorInterface
private UserRepository $userRepository;
private UserRender $userRender;
public function __construct(
UserRepository $userRepository,
UserRender $userRender
UserRepository $userRepository
) {
$this->userRepository = $userRepository;
$this->userRender = $userRender;
}
public function addRole()
@@ -53,7 +37,7 @@ class ActivityUserAggregator implements AggregatorInterface
public function applyOn(): string
{
return Declarations::ACTIVITY;
return 'activity';
}
public function buildForm(FormBuilderInterface $builder)
@@ -61,25 +45,23 @@ class ActivityUserAggregator implements AggregatorInterface
// nothing to add
}
public function getLabels($key, $values, $data): Closure
public function getLabels($key, $values, $data): \Closure
{
// preload users at once
$this->userRepository->findBy(['id' => $values]);
return function ($value) {
if ('_header' === $value) {
return 'Activity user';
return function($value) {
if ($value === '_header') {
return 'activity user';
}
$u = $this->userRepository->find($value);
return $this->userRender->renderString($u, []);
return $this->userRepository->find($value)->getUsername();
};
}
public function getQueryKeys($data)
{
return [self::KEY];
return [ self::KEY ];
}
public function getTitle(): string

View File

@@ -1,24 +0,0 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export;
/**
* This class declare constants used for the export framework.
*/
abstract class Declarations
{
public const ACTIVITY = 'activity';
public const ACTIVITY_ACP = "activity_linked_to_acp";
public const ACTIVITY_PERSON = "activity_linked_to_person";
}

View File

@@ -0,0 +1,96 @@
<?php
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Export;
use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
use Doctrine\ORM\Query;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
class CountActivity implements ExportInterface
{
protected ActivityRepository $activityRepository;
public function __construct(
ActivityRepository $activityRepository
) {
$this->activityRepository = $activityRepository;
}
public function buildForm(FormBuilderInterface $builder)
{
}
public function getDescription()
{
return 'Count activities by various parameters.';
}
public function getTitle()
{
return 'Count activities';
}
public function getType()
{
return 'activity';
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = array())
{
$centers = array_map(static fn($el) => $el['center'], $acl);
$qb = $this
->activityRepository
->createQueryBuilder('activity')
->select('COUNT(activity.id) as export_count_activity')
->join('activity.person', 'person');
$qb
->where($qb->expr()->in('person.center', ':centers'))
->setParameter('centers', $centers);
return $qb;
}
public function supportsModifiers()
{
return ['person', 'activity'];
}
public function requiredRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function getAllowedFormattersTypes()
{
return [FormatterInterface::TYPE_TABULAR];
}
public function getLabels($key, array $values, $data)
{
if ($key !== 'export_count_activity') {
throw new \LogicException("the key $key is not used by this export");
}
return static fn($value) => $value === '_header' ? 'Number of activities' : $value;
}
public function getQueryKeys($data)
{
return ['export_count_activity'];
}
public function getResult($qb, $data)
{
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
}

View File

@@ -1,103 +0,0 @@
<?php
namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Closure;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
class AvgActivityDuration implements ExportInterface, GroupedExportInterface
{
protected EntityRepository $repository;
public function __construct(
EntityManagerInterface $em
) {
$this->repository = $em->getRepository(Activity::class);
}
public function buildForm(FormBuilderInterface $builder)
{
// TODO: Implement buildForm() method.
}
public function getTitle(): string
{
return 'Average activity linked to an accompanying period duration';
}
public function getAllowedFormattersTypes(): array
{
return [FormatterInterface::TYPE_TABULAR];
}
public function getDescription(): string
{
return 'Average activities linked to an accompanying period duration by various parameters.';
}
public function getLabels($key, array $values, $data)
{
if ('export_avg_activity_duration' !== $key) {
throw new LogicException("the key {$key} is not used by this export");
}
return static fn ($value) => '_header' === $value ? 'Average activities linked to an accompanying period duration' : $value;
}
public function getQueryKeys($data): array
{
return ['export_avg_activity_duration'];
}
public function getResult($qb, $data)
{
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getType(): string
{
return Declarations::ACTIVITY;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$qb = $this->repository->createQueryBuilder('activity')
->join('activity.accompanyingPeriod', 'acp')
;
$qb->select('AVG(activity.durationTime) as export_avg_activity_duration');
return $qb;
}
public function requiredRole(): Role
{
return new Role(ActivityStatsVoter::STATS);
}
public function supportsModifiers(): array
{
return [
Declarations::ACTIVITY,
Declarations::ACTIVITY_ACP,
//PersonDeclarations::ACP_TYPE,
];
}
public function getGroup(): string
{
return 'Exports of activities linked to an accompanying period';
}
}

View File

@@ -1,103 +0,0 @@
<?php
namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Closure;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterface
{
protected EntityRepository $repository;
public function __construct(
EntityManagerInterface $em
) {
$this->repository = $em->getRepository(Activity::class);
}
public function buildForm(FormBuilderInterface $builder)
{
// TODO: Implement buildForm() method.
}
public function getTitle(): string
{
return 'Average activity linked to an accompanying period visit duration';
}
public function getAllowedFormattersTypes(): array
{
return [FormatterInterface::TYPE_TABULAR];
}
public function getDescription(): string
{
return 'Average activities linked to an accompanying period visit duration by various parameters.';
}
public function getLabels($key, array $values, $data)
{
if ('export_avg_activity_visit_duration' !== $key) {
throw new LogicException("the key {$key} is not used by this export");
}
return static fn ($value) => '_header' === $value ? 'Average activities linked to an accompanying period visit duration' : $value;
}
public function getQueryKeys($data): array
{
return ['export_avg_activity_visit_duration'];
}
public function getResult($qb, $data)
{
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getType(): string
{
return Declarations::ACTIVITY;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$qb = $this->repository->createQueryBuilder('activity')
->join('activity.accompanyingPeriod', 'acp')
;
$qb->select('AVG(activity.travelTime) as export_avg_activity_visit_duration');
return $qb;
}
public function requiredRole(): Role
{
return new Role(ActivityStatsVoter::STATS);
}
public function supportsModifiers(): array
{
return [
Declarations::ACTIVITY,
Declarations::ACTIVITY_ACP,
//PersonDeclarations::ACP_TYPE,
];
}
public function getGroup(): string
{
return 'Exports of activities linked to an accompanying period';
}
}

View File

@@ -1,110 +0,0 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
class CountActivity implements ExportInterface, GroupedExportInterface
{
protected EntityRepository $repository;
public function __construct(
EntityManagerInterface $em
) {
$this->repository = $em->getRepository(Activity::class);
}
public function buildForm(FormBuilderInterface $builder)
{
}
public function getAllowedFormattersTypes(): array
{
return [FormatterInterface::TYPE_TABULAR];
}
public function getDescription(): string
{
return 'Count activities linked to an accompanying period by various parameters.';
}
public function getLabels($key, array $values, $data)
{
if ('export_count_activity' !== $key) {
throw new LogicException("the key {$key} is not used by this export");
}
return static fn ($value) => '_header' === $value ? 'Number of activities linked to an accompanying period' : $value;
}
public function getQueryKeys($data): array
{
return ['export_count_activity'];
}
public function getResult($qb, $data)
{
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getTitle(): string
{
return 'Count activities linked to an accompanying period';
}
public function getType(): string
{
return Declarations::ACTIVITY;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$qb = $this->repository->createQueryBuilder('activity')
->join('activity.accompanyingPeriod', 'acp')
;
$qb->select('COUNT(activity.id) as export_count_activity');
return $qb;
}
public function requiredRole(): Role
{
return new Role(ActivityStatsVoter::STATS);
}
public function supportsModifiers(): array
{
return [
Declarations::ACTIVITY,
Declarations::ACTIVITY_ACP,
//PersonDeclarations::ACP_TYPE,
];
}
public function getGroup(): string
{
return 'Exports of activities linked to an accompanying period';
}
}

View File

@@ -1,103 +0,0 @@
<?php
namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Closure;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
class SumActivityDuration implements ExportInterface, GroupedExportInterface
{
protected EntityRepository $repository;
public function __construct(
EntityManagerInterface $em
) {
$this->repository = $em->getRepository(Activity::class);
}
public function buildForm(FormBuilderInterface $builder)
{
// TODO: Implement buildForm() method.
}
public function getTitle(): string
{
return 'Sum activity linked to an accompanying period duration';
}
public function getAllowedFormattersTypes(): array
{
return [FormatterInterface::TYPE_TABULAR];
}
public function getDescription(): string
{
return 'Sum activities linked to an accompanying period duration by various parameters.';
}
public function getLabels($key, array $values, $data)
{
if ('export_sum_activity_duration' !== $key) {
throw new LogicException("the key {$key} is not used by this export");
}
return static fn ($value) => '_header' === $value ? 'Sum activities linked to an accompanying period duration' : $value;
}
public function getQueryKeys($data): array
{
return ['export_sum_activity_duration'];
}
public function getResult($qb, $data)
{
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getType(): string
{
return Declarations::ACTIVITY;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$qb = $this->repository->createQueryBuilder('activity')
->join('activity.accompanyingPeriod', 'acp')
;
$qb->select('SUM(activity.durationTime) as export_sum_activity_duration');
return $qb;
}
public function requiredRole(): Role
{
return new Role(ActivityStatsVoter::STATS);
}
public function supportsModifiers(): array
{
return [
Declarations::ACTIVITY,
Declarations::ACTIVITY_ACP,
//PersonDeclarations::ACP_TYPE,
];
}
public function getGroup(): string
{
return 'Exports of activities linked to an accompanying period';
}
}

View File

@@ -1,102 +0,0 @@
<?php
namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Closure;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
class SumActivityVisitDuration implements ExportInterface, GroupedExportInterface
{
protected EntityRepository $repository;
public function __construct(
EntityManagerInterface $em
) {
$this->repository = $em->getRepository(Activity::class);
}
public function buildForm(FormBuilderInterface $builder)
{
// TODO: Implement buildForm() method.
}
public function getTitle(): string
{
return 'Sum activity linked to an accompanying period visit duration';
}
public function getAllowedFormattersTypes(): array
{
return [FormatterInterface::TYPE_TABULAR];
}
public function getDescription(): string
{
return 'Sum activities linked to an accompanying period visit duration by various parameters.';
}
public function getLabels($key, array $values, $data)
{
if ('export_sum_activity_visit_duration' !== $key) {
throw new LogicException("the key {$key} is not used by this export");
}
return static fn ($value) => '_header' === $value ? 'Sum activities linked to an accompanying period visit duration' : $value;
}
public function getQueryKeys($data): array
{
return ['export_sum_activity_visit_duration'];
}
public function getResult($qb, $data)
{
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getType(): string
{
return Declarations::ACTIVITY;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$qb = $this->repository->createQueryBuilder('activity')
->join('activity.accompanyingPeriod', 'acp')
;
$qb->select('SUM(activity.travelTime) as export_sum_activity_visit_duration');
return $qb;
}
public function requiredRole(): Role
{
return new Role(ActivityStatsVoter::STATS);
}
public function supportsModifiers(): array
{
return [
Declarations::ACTIVITY,
Declarations::ACTIVITY_ACP,
//PersonDeclarations::ACP_TYPE,
];
}
public function getGroup(): string
{
return 'Exports of activities linked to an accompanying period';
}
}

View File

@@ -1,115 +0,0 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Export\LinkedToPerson;
use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\ActivityBundle\Export\Declarations;
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
use Doctrine\ORM\Query;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
class CountActivity implements ExportInterface, GroupedExportInterface
{
protected ActivityRepository $activityRepository;
public function __construct(
ActivityRepository $activityRepository
) {
$this->activityRepository = $activityRepository;
}
public function buildForm(FormBuilderInterface $builder)
{
}
public function getAllowedFormattersTypes()
{
return [FormatterInterface::TYPE_TABULAR];
}
public function getDescription()
{
return 'Count activities linked to a person by various parameters.';
}
public function getLabels($key, array $values, $data)
{
if ('export_count_activity' !== $key) {
throw new LogicException("the key {$key} is not used by this export");
}
return static fn ($value) => '_header' === $value ? 'Number of activities linked to a person' : $value;
}
public function getQueryKeys($data)
{
return ['export_count_activity'];
}
public function getResult($qb, $data)
{
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getTitle()
{
return 'Count activities linked to a person';
}
public function getType(): string
{
return Declarations::ACTIVITY;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(static fn ($el) => $el['center'], $acl);
$qb = $this->activityRepository->createQueryBuilder('activity')
->join('activity.person', 'person')
;
$qb->select('COUNT(activity.id) as export_count_activity');
$qb
->where($qb->expr()->in('person.center', ':centers'))
->setParameter('centers', $centers)
;
return $qb;
}
public function requiredRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function supportsModifiers()
{
return [
Declarations::ACTIVITY,
Declarations::ACTIVITY_PERSON,
//PersonDeclarations::PERSON_TYPE,
];
}
public function getGroup(): string
{
return 'Exports of activities linked to a person';
}
}

View File

@@ -1,44 +1,35 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Export\LinkedToPerson;
namespace Chill\ActivityBundle\Export\Export;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\MainBundle\Export\ListInterface;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use DateTime;
use Doctrine\DBAL\Exception\InvalidArgumentException;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Symfony\Component\Form\FormBuilderInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\Constraints\Callback;
use Doctrine\ORM\Query;
use Chill\MainBundle\Export\FormatterInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Chill\ActivityBundle\Export\Declarations;
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
use function array_key_exists;
use function count;
use function in_array;
class ListActivity implements ListInterface, GroupedExportInterface
class ListActivity implements ListInterface
{
private ActivityRepository $activityRepository;
protected EntityManagerInterface $entityManager;
protected TranslatorInterface $translator;
protected TranslatableStringHelperInterface $translatableStringHelper;
protected array $fields = [
'id',
'date',
@@ -50,15 +41,9 @@ class ListActivity implements ListInterface, GroupedExportInterface
'type_name',
'person_firstname',
'person_lastname',
'person_id',
'person_id'
];
protected TranslatableStringHelperInterface $translatableStringHelper;
protected TranslatorInterface $translator;
private ActivityRepository $activityRepository;
public function __construct(
EntityManagerInterface $em,
TranslatorInterface $translator,
@@ -77,17 +62,18 @@ class ListActivity implements ListInterface, GroupedExportInterface
'multiple' => true,
'expanded' => true,
'choices' => array_combine($this->fields, $this->fields),
'label' => 'Fields to include in export',
'label' => 'Fields to include in export',
'constraints' => [new Callback([
'callback' => static function ($selected, ExecutionContextInterface $context) {
'callback' => function($selected, ExecutionContextInterface $context) {
if (count($selected) === 0) {
$context->buildViolation('You must select at least one element')
->atPath('fields')
->addViolation();
}
},
])],
}
])]
]);
}
public function getAllowedFormattersTypes()
@@ -97,72 +83,69 @@ class ListActivity implements ListInterface, GroupedExportInterface
public function getDescription()
{
return 'List activities linked to a person description';
return "List activities";
}
public function getLabels($key, array $values, $data)
{
switch ($key) {
case 'date':
return static function ($value) {
if ('_header' === $value) {
switch ($key)
{
case 'date' :
return static function($value) {
if ($value === '_header') {
return 'date';
}
$date = DateTime::createFromFormat('Y-m-d H:i:s', $value);
$date = \DateTime::createFromFormat('Y-m-d H:i:s', $value);
return $date->format('d-m-Y');
};
case 'attendee':
return static function ($value) {
if ('_header' === $value) {
return static function($value) {
if ($value === '_header') {
return 'attendee';
}
return $value ? 1 : 0;
};
case 'list_reasons':
case 'list_reasons' :
$activityRepository = $this->activityRepository;
return function ($value) use ($activityRepository): string {
if ('_header' === $value) {
return function($value) use ($activityRepository): string {
if ($value === '_header') {
return 'activity reasons';
}
$activity = $activityRepository->find($value);
return implode(', ', array_map(function (ActivityReason $r) {
return '"' .
return implode(", ", array_map(function(ActivityReason $r) {
return '"'.
$this->translatableStringHelper->localize($r->getCategory()->getName())
. ' > ' .
.' > '.
$this->translatableStringHelper->localize($r->getName())
. '"';
.'"';
}, $activity->getReasons()->toArray()));
};
case 'circle_name':
return function ($value) {
if ('_header' === $value) {
case 'circle_name' :
return function($value) {
if ($value === '_header') {
return 'circle';
}
return $this->translatableStringHelper->localize(json_decode($value, true));
};
case 'type_name':
return function ($value) {
if ('_header' === $value) {
case 'type_name' :
return function($value) {
if ($value === '_header') {
return 'activity type';
}
return $this->translatableStringHelper->localize(json_decode($value, true));
};
default:
return static function ($value) use ($key) {
if ('_header' === $value) {
return static function($value) use ($key) {
if ($value === '_header') {
return $key;
}
@@ -183,87 +166,69 @@ class ListActivity implements ListInterface, GroupedExportInterface
public function getTitle()
{
return 'List activity linked to a person';
return 'List activities';
}
public function getType(): string
public function getType()
{
return Declarations::ACTIVITY;
return 'activity';
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(static function ($el) {
return $el['center'];
}, $acl);
$centers = array_map(function($el) { return $el['center']; }, $acl);
// throw an error if any fields are present
if (!array_key_exists('fields', $data)) {
if (!\array_key_exists('fields', $data)) {
throw new InvalidArgumentException('Any fields have been checked.');
}
$qb = $this->entityManager->createQueryBuilder();
$qb
->from('ChillActivityBundle:Activity', 'activity')
->join('activity.person', 'person')
->join('person.center', 'center')
->andWhere('center IN (:authorized_centers)')
->setParameter('authorized_centers', $centers);
->from('ChillActivityBundle:Activity', 'activity')
->join('activity.person', 'person')
->join('person.center', 'center')
->andWhere('center IN (:authorized_centers)')
->setParameter('authorized_centers', $centers);
foreach ($this->fields as $f) {
if (in_array($f, $data['fields'], true)) {
if (in_array($f, $data['fields'])) {
switch ($f) {
case 'id':
$qb->addSelect('activity.id AS id');
break;
case 'person_firstname':
$qb->addSelect('person.firstName AS person_firstname');
break;
case 'person_lastname':
$qb->addSelect('person.lastName AS person_lastname');
break;
case 'person_id':
$qb->addSelect('person.id AS person_id');
break;
case 'user_username':
$qb->join('activity.user', 'user');
$qb->addSelect('user.username AS user_username');
break;
case 'circle_name':
$qb->join('activity.scope', 'circle');
$qb->addSelect('circle.name AS circle_name');
break;
case 'type_name':
$qb->join('activity.type', 'type');
$qb->addSelect('type.name AS type_name');
break;
case 'list_reasons':
// this is a trick... The reasons is filled with the
// activity id which will be used to load reasons
$qb->addSelect('activity.id AS list_reasons');
break;
default:
$qb->addSelect(sprintf('activity.%s as %s', $f, $f));
break;
}
}
}
@@ -277,15 +242,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
public function supportsModifiers()
{
return [
Declarations::ACTIVITY,
Declarations::ACTIVITY_PERSON,
//PersonDeclarations::PERSON_TYPE,
];
return ['activity', 'person'];
}
public function getGroup(): string
{
return 'Exports of activities linked to a person';
}
}

View File

@@ -1,36 +1,26 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Export\LinkedToPerson;
namespace Chill\ActivityBundle\Export\Export;
use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
use Chill\ActivityBundle\Export\Declarations;
use Doctrine\ORM\Query;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
use Doctrine\ORM\Query;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
/**
* This export allow to compute stats on activity duration.
*
* The desired stat must be given in constructor.
*/
class StatActivityDuration implements ExportInterface, GroupedExportInterface
class StatActivityDuration implements ExportInterface
{
private ActivityRepository $activityRepository;
public const SUM = 'sum';
/**
@@ -38,8 +28,6 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
*/
protected string $action;
private ActivityRepository $activityRepository;
/**
* @param string $action the stat to perform
*/
@@ -53,6 +41,59 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
public function buildForm(FormBuilderInterface $builder)
{
}
public function getDescription()
{
if ($this->action === self::SUM) {
return 'Sum activities duration by various parameters.';
}
}
public function getTitle()
{
if ($this->action === self::SUM) {
return 'Sum activity duration';
}
}
public function getType()
{
return 'activity';
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(
static fn(array $el): string => $el['center'],
$acl
);
$qb = $this->activityRepository->createQueryBuilder('activity');
$select = null;
if ($this->action === self::SUM) {
$select = 'SUM(activity.durationTime) AS export_stat_activity';
}
return $qb->select($select)
->join('activity.person', 'person')
->join('person.center', 'center')
->where($qb->expr()->in('center', ':centers'))
->setParameter(':centers', $centers);
}
public function supportsModifiers()
{
return ['person', 'activity'];
}
public function requiredRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function getAllowedFormattersTypes()
@@ -60,22 +101,15 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
return [FormatterInterface::TYPE_TABULAR];
}
public function getDescription()
{
if (self::SUM === $this->action) {
return 'Sum activities linked to a person duration by various parameters.';
}
}
public function getLabels($key, array $values, $data)
{
if ('export_stat_activity' !== $key) {
throw new LogicException(sprintf('The key %s is not used by this export', $key));
if ($key !== 'export_stat_activity') {
throw new \LogicException(sprintf('The key %s is not used by this export', $key));
}
$header = self::SUM === $this->action ? 'Sum activities linked to a person duration' : false;
$header = $this->action === self::SUM ? 'Sum of activities duration' : false;
return static fn (string $value) => '_header' === $value ? $header : $value;
return static fn(string $value) => $value === '_header' ? $header : $value;
}
public function getQueryKeys($data)
@@ -88,56 +122,4 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getTitle()
{
if (self::SUM === $this->action) {
return 'Sum activity linked to a person duration';
}
}
public function getType(): string
{
return Declarations::ACTIVITY;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(
static fn (array $el): Center => $el['center'],
$acl
);
$qb = $this->activityRepository->createQueryBuilder('activity');
$select = null;
if (self::SUM === $this->action) {
$select = 'SUM(activity.durationTime) AS export_stat_activity';
}
return $qb->select($select)
->join('activity.person', 'person')
->join('person.center', 'center')
->where($qb->expr()->in('center', ':centers'))
->setParameter(':centers', $centers);
}
public function requiredRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function supportsModifiers()
{
return [
Declarations::ACTIVITY,
Declarations::ACTIVITY_PERSON,
//PersonDeclarations::PERSON_TYPE,
];
}
public function getGroup(): string
{
return 'Exports of activities linked to a person';
}
}

View File

@@ -1,85 +0,0 @@
<?php
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
use Chill\MainBundle\Export\FilterInterface;
use Chill\ActivityBundle\Export\Declarations;
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
use Doctrine\ORM\Query\Expr\Andx;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
class BySocialActionFilter implements FilterInterface
{
private SocialActionRender $actionRender;
public function __construct(SocialActionRender $actionRender)
{
$this->actionRender = $actionRender;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('accepted_socialactions', EntityType::class, [
'class' => SocialAction::class,
'choice_label' => function (SocialAction $sa) {
return $this->actionRender->renderString($sa, []);
},
'multiple' => true,
'expanded' => true,
]);
}
public function getTitle(): string
{
return 'Filter activity by linked socialaction';
}
public function describeAction($data, $format = 'string'): array
{
$actions = [];
foreach ($data['accepted_socialactions'] as $sa) {
$actions[] = $this->actionRender->renderString($sa, []);
}
return ['Filtered activity by linked socialaction: only %actions%', [
'%actions%' => implode(", ou ", $actions)
]];
}
public function addRole()
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
if (!in_array('socialaction', $qb->getAllAliases())) {
$qb->join('activity.socialActions', 'socialaction');
}
$clause = $qb->expr()->in('socialaction.id', ':socialactions');
if ($where instanceof Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->add('where', $where);
$qb->setParameter('socialactions', $data['accepted_socialactions']);
}
public function applyOn(): string
{
return Declarations::ACTIVITY_ACP;
}
}

View File

@@ -1,85 +0,0 @@
<?php
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
use Chill\MainBundle\Export\FilterInterface;
use Chill\ActivityBundle\Export\Declarations;
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
use Doctrine\ORM\Query\Expr\Andx;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
class BySocialIssueFilter implements FilterInterface
{
private SocialIssueRender $issueRender;
public function __construct(SocialIssueRender $issueRender)
{
$this->issueRender = $issueRender;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('accepted_socialissues', EntityType::class, [
'class' => SocialIssue::class,
'choice_label' => function(SocialIssue $si) {
return $this->issueRender->renderString($si, []);
},
'multiple' => true,
'expanded' => true,
]);
}
public function getTitle(): string
{
return 'Filter activity by linked socialissue';
}
public function describeAction($data, $format = 'string'): array
{
$issues = [];
foreach ($data['accepted_socialissues'] as $si) {
$issues[] = $this->issueRender->renderString($si, []);
}
return ['Filtered activity by linked socialissue: only %issues%', [
'%issues%' => implode(", ou ", $issues)
]];
}
public function addRole()
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
if (!in_array('socialissue', $qb->getAllAliases())) {
$qb->join('activity.socialIssues', 'socialissue');
}
$clause = $qb->expr()->in('socialissue.id', ':socialissues');
if ($where instanceof Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->add('where', $where);
$qb->setParameter('socialissues', $data['accepted_socialissues']);
}
public function applyOn(): string
{
return Declarations::ACTIVITY_ACP;
}
}

View File

@@ -1,84 +0,0 @@
<?php
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Export\FilterInterface;
use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Templating\Entity\UserRender;
use Doctrine\ORM\Query\Expr\Andx;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
class ByUserFilter implements FilterInterface
{
private UserRender $userRender;
public function __construct(UserRender $userRender)
{
$this->userRender = $userRender;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('accepted_users', EntityType::class, [
'class' => User::class,
'choice_label' => function (User $u) {
return $this->userRender->renderString($u, []);
},
'multiple' => true,
'expanded' => true,
]);
}
public function getTitle(): string
{
return 'Filter activity by linked users';
}
public function describeAction($data, $format = 'string'): array
{
$users = [];
foreach ($data['accepted_users'] as $u) {
$users[] = $this->userRender->renderString($u, []);
}
return ['Filtered activity by linked users: only %users%', [
'%users%' => implode(", ou ", $users)
]];
}
public function addRole()
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
if (!in_array('user', $qb->getAllAliases())) {
$qb->join('activity.users', 'user');
}
$clause = $qb->expr()->in('user.id', ':users');
if ($where instanceof Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->add('where', $where);
$qb->setParameter('users', $data['accepted_users']);
}
public function applyOn(): string
{
return Declarations::ACTIVITY_ACP;
}
}

View File

@@ -1,86 +0,0 @@
<?php
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
use Chill\MainBundle\Export\FilterInterface;
use Chill\ActivityBundle\Export\Declarations;
use Doctrine\ORM\Query\Expr\Andx;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class EmergencyFilter implements FilterInterface
{
private const CHOICES = [
'activity is emergency' => true,
'activity is not emergency' => false,
];
private CONST DEFAULT_CHOICE = false;
private TranslatorInterface $translator;
public function __construct(TranslatorInterface $translator)
{
$this->translator = $translator;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('accepted_emergency', ChoiceType::class, [
'choices' => self::CHOICES,
'multiple' => false,
'expanded' => true,
'empty_data' => self::DEFAULT_CHOICE,
'data' => self::DEFAULT_CHOICE,
]);
}
public function getTitle(): string
{
return 'Filter activity by emergency';
}
public function describeAction($data, $format = 'string'): array
{
foreach (self::CHOICES as $k => $v) {
if ($v === $data['accepted_emergency']) {
$choice = $k;
}
}
return ['Filtered activity by emergency: only %emergency%', [
'%emergency%' => $this->translator->trans($choice)
]];
}
public function addRole()
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
$clause = $qb->expr()->eq('activity.emergency', ':emergency');
if ($where instanceof Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->add('where', $where);
$qb->setParameter('emergency', $data['accepted_emergency']);
}
public function applyOn(): string
{
return Declarations::ACTIVITY_ACP;
}
}

View File

@@ -1,85 +0,0 @@
<?php
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
use Chill\MainBundle\Entity\LocationType;
use Chill\MainBundle\Export\FilterInterface;
use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\Query\Expr\Andx;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
class LocationTypeFilter implements FilterInterface
{
private TranslatableStringHelper $translatableStringHelper;
public function __construct(TranslatableStringHelper $translatableStringHelper)
{
$this->translatableStringHelper = $translatableStringHelper;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('accepted_locationtype', EntityType::class, [
'class' => LocationType::class,
'choice_label' => function(LocationType $type) {
return $this->translatableStringHelper->localize($type->getTitle());
},
'multiple' => true,
'expanded' => true,
]);
}
public function getTitle(): string
{
return 'Filter activity by locationtype';
}
public function describeAction($data, $format = 'string'): array
{
$types = [];
foreach ($data['accepted_locationtype'] as $type) {
$types[] = $this->translatableStringHelper->localize(
$type->getTitle()
);
}
return ['Filtered activity by locationtype: only %types%', [
'%types%' => implode(", ou ", $types)
]];
}
public function addRole()
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
if (!in_array('location', $qb->getAllAliases())) {
$qb->join('activity.location', 'location');
}
$where = $qb->getDQLPart('where');
$clause = $qb->expr()->in('location.locationType', ':locationtype');
if ($where instanceof Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->add('where', $where);
$qb->setParameter('locationtype', $data['accepted_locationtype']);
}
public function applyOn(): string
{
return Declarations::ACTIVITY_ACP;
}
}

View File

@@ -1,82 +0,0 @@
<?php
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\Export\FilterInterface;
use Chill\ActivityBundle\Export\Declarations;
use Doctrine\ORM\Query\Expr\Andx;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class SentReceivedFilter implements FilterInterface
{
private const CHOICES = [
'is sent' => Activity::SENTRECEIVED_SENT,
'is received' => Activity::SENTRECEIVED_RECEIVED,
];
private CONST DEFAULT_CHOICE = Activity::SENTRECEIVED_SENT;
private TranslatorInterface $translator;
public function __construct(TranslatorInterface $translator)
{
$this->translator = $translator;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('accepted_sentreceived', ChoiceType::class, [
'choices' => self::CHOICES,
'multiple' => false,
'expanded' => true,
'empty_data' => self::DEFAULT_CHOICE,
'data' => self::DEFAULT_CHOICE,
]);
}
public function getTitle(): string
{
return 'Filter activity by sentreceived';
}
public function describeAction($data, $format = 'string'): array
{
$sentreceived = array_flip(self::CHOICES)[$data['accepted_sentreceived']];
return ['Filtered activity by sentreceived: only %sentreceived%', [
'%sentreceived%' => $this->translator->trans($sentreceived)
]];
}
public function addRole()
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
$clause = $qb->expr()->eq('activity.sentReceived', ':sentreceived');
if ($where instanceof Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->add('where', $where);
$qb->setParameter('sentreceived', $data['accepted_sentreceived']);
}
public function applyOn(): string
{
return Declarations::ACTIVITY_ACP;
}
}

View File

@@ -1,82 +0,0 @@
<?php
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Export\FilterInterface;
use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Templating\Entity\UserRender;
use Doctrine\ORM\Query\Expr\Andx;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
class UserFilter implements FilterInterface
{
private UserRender $userRender;
public function __construct(UserRender $userRender)
{
$this->userRender = $userRender;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('accepted_users', EntityType::class, [
'class' => User::class,
'choice_label' => function (User $u) {
return $this->userRender->renderString($u, []);
},
'multiple' => true,
'expanded' => true,
'label' => 'Creators'
]);
}
public function getTitle(): string
{
return 'Filter activity by user';
}
public function describeAction($data, $format = 'string'): array
{
$users = [];
foreach ($data['accepted_users'] as $u) {
$users[] = $this->userRender->renderString($u, []);
}
return ['Filtered activity by user: only %users%', [
'%users%' => implode(", ou ", $users)
]];
}
public function addRole()
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
$clause = $qb->expr()->in('activity.user', ':users');
if ($where instanceof Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->add('where', $where);
$qb->setParameter('users', $data['accepted_users']);
}
public function applyOn(): string
{
return Declarations::ACTIVITY_ACP;
}
}

View File

@@ -1,89 +0,0 @@
<?php
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Export\FilterInterface;
use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\Query\Expr\Andx;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
class UserScopeFilter implements FilterInterface
{
private TranslatableStringHelper $translatableStringHelper;
public function __construct(TranslatableStringHelper $translatableStringHelper)
{
$this->translatableStringHelper = $translatableStringHelper;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('accepted_userscope', EntityType::class, [
'class' => Scope::class,
'choice_label' => function (Scope $s) {
return $this->translatableStringHelper->localize(
$s->getName()
);
},
'multiple' => true,
'expanded' => true
]);
}
public function getTitle(): string
{
return 'Filter activity by userscope';
}
public function describeAction($data, $format = 'string'): array
{
$scopes = [];
foreach ($data['accepted_userscope'] as $s) {
$scopes[] = $this->translatableStringHelper->localize(
$s->getName()
);
}
return ['Filtered activity by userscope: only %scopes%', [
'%scopes%' => implode(", ou ", $scopes)
]];
}
public function addRole()
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
if (!in_array('user', $qb->getAllAliases())) {
$qb->join('activity.user', 'user');
}
$where = $qb->getDQLPart('where');
$clause = $qb->expr()->in('user.mainScope', ':userscope');
if ($where instanceof Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->add('where', $where);
$qb->setParameter('userscope', $data['accepted_userscope']);
}
public function applyOn(): string
{
return Declarations::ACTIVITY_ACP;
}
}

View File

@@ -1,34 +1,25 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Form\Type\Export\FilterType;
use DateTime;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormError;
use Chill\MainBundle\Form\Type\Export\FilterType;
use Doctrine\ORM\Query\Expr;
use Symfony\Component\Translation\TranslatorInterface;
class ActivityDateFilter implements FilterInterface
{
protected TranslatorInterface $translator;
public function __construct(TranslatorInterface $translator)
function __construct(TranslatorInterface $translator)
{
$this->translator = $translator;
}
@@ -41,11 +32,8 @@ class ActivityDateFilter implements FilterInterface
public function alterQuery(QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
$clause = $qb->expr()->between(
'activity.date',
':date_from',
':date_to'
);
$clause = $qb->expr()->between('activity.date', ':date_from',
':date_to');
if ($where instanceof Expr\Andx) {
$where->add($clause);
@@ -58,60 +46,70 @@ class ActivityDateFilter implements FilterInterface
$qb->setParameter('date_to', $data['date_to']);
}
public function applyOn(): string
public function applyOn()
{
return Declarations::ACTIVITY;
return 'activity';
}
public function buildForm(FormBuilderInterface $builder)
{
$builder
->add('date_from', ChillDateType::class, [
$builder->add(
'date_from',
DateType::class,
[
'label' => 'Activities after this date',
'data' => new DateTime(),
])
->add('date_to', ChillDateType::class, [
'label' => 'Activities before this date',
'data' => new DateTime(),
])
;
'data' => new \DateTime(),
'attr' => ['class' => 'datepicker'],
'widget'=> 'single_text',
'format' => 'dd-MM-yyyy',
]
);
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
/** @var \Symfony\Component\Form\FormInterface $filterForm */
$builder->add(
'date_to',
DateType::class,
[
'label' => 'Activities before this date',
'data' => new \DateTime(),
'attr' => ['class' => 'datepicker'],
'widget'=> 'single_text',
'format' => 'dd-MM-yyyy',
]
);
$builder->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
/* @var $filterForm \Symfony\Component\Form\FormInterface */
$filterForm = $event->getForm()->getParent();
$enabled = $filterForm->get(FilterType::ENABLED_FIELD)->getData();
if (true === $enabled) {
if ($enabled === true) {
// if the filter is enabled, add some validation
$form = $event->getForm();
$form = $event->getForm();
$date_from = $form->get('date_from')->getData();
$date_to = $form->get('date_to')->getData();
$date_to = $form->get('date_to')->getData();
// check that fields are not empty
if (null === $date_from) {
if ($date_from === null) {
$form->get('date_from')->addError(new FormError(
$this->translator->trans('This field '
. 'should not be empty')
));
. 'should not be empty')));
}
if (null === $date_to) {
if ($date_to === null) {
$form->get('date_to')->addError(new FormError(
$this->translator->trans('This field '
. 'should not be empty')
));
. 'should not be empty')));
}
// check that date_from is before date_to
if (
(null !== $date_from && null !== $date_to)
&& $date_from >= $date_to
($date_from !== null && $date_to !== null)
&&
$date_from >= $date_to
) {
$form->get('date_to')->addError(new FormError(
$this->translator->trans('This date should be after '
. 'the date given in "Implied in an activity after '
. 'this date" field')
));
. 'this date" field')));
}
}
});
@@ -123,8 +121,8 @@ class ActivityDateFilter implements FilterInterface
'Filtered by date of activity: only between %date_from% and %date_to%',
[
'%date_from%' => $data['date_from']->format('d-m-Y'),
'%date_to%' => $data['date_to']->format('d-m-Y'),
],
'%date_to%' => $data['date_to']->format('d-m-Y')
]
];
}
@@ -132,4 +130,5 @@ class ActivityDateFilter implements FilterInterface
{
return 'Filtered by date activity';
}
}

View File

@@ -1,41 +1,30 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter\PersonFilters;
namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\Query\Expr;
use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Doctrine\ORM\Query\Expr\Join;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use function array_key_exists;
use function count;
class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInterface
class ActivityReasonFilter implements FilterInterface, ExportElementValidatedInterface
{
protected ActivityReasonRepository $activityReasonRepository;
protected TranslatableStringHelperInterface $translatableStringHelper;
protected ActivityReasonRepository $activityReasonRepository;
public function __construct(
TranslatableStringHelper $helper,
ActivityReasonRepository $activityReasonRepository
@@ -44,30 +33,26 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
$this->activityReasonRepository = $activityReasonRepository;
}
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function alterQuery(QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
$join = $qb->getDQLPart('join');
$join = $qb->getDQLPart('join');
$clause = $qb->expr()->in('reasons', ':selected_activity_reasons');
//dump($join);
// add a join to reasons only if needed
if (
(
array_key_exists('activity', $join)
&& !$this->checkJoinAlreadyDefined($join['activity'], 'reasons')
(array_key_exists('activity', $join)
&&
!$this->checkJoinAlreadyDefined($join['activity'], 'reasons')
)
|| (!array_key_exists('activity', $join))
||
(! array_key_exists('activity', $join))
) {
$qb->add(
'join',
['activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons')],
true
);
'join',
array('activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons')),
true
);
}
if ($where instanceof Expr\Andx) {
@@ -80,57 +65,11 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
$qb->setParameter('selected_activity_reasons', $data['reasons']);
}
public function applyOn(): string
{
return Declarations::ACTIVITY_PERSON;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('reasons', EntityType::class, [
'class' => ActivityReason::class,
'choice_label' => fn (ActivityReason $reason) => $this->translatableStringHelper->localize($reason->getName()),
'group_by' => fn (ActivityReason $reason) => $this->translatableStringHelper->localize($reason->getCategory()->getName()),
'multiple' => true,
'expanded' => false,
]);
}
public function describeAction($data, $format = 'string')
{
// collect all the reasons'name used in this filter in one array
$reasonsNames = array_map(
fn (ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"',
$this->activityReasonRepository->findBy(['id' => $data['reasons']->toArray()])
);
return [
'Filtered by reasons: only %list%',
[
'%list%' => implode(', ', $reasonsNames),
],
];
}
public function getTitle()
{
return 'Filter by reason';
}
public function validateForm($data, ExecutionContextInterface $context)
{
if (null === $data['reasons'] || count($data['reasons']) === 0) {
$context
->buildViolation('At least one reason must be chosen')
->addViolation();
}
}
/**
* Check if a join between Activity and Reason is already defined.
* Check if a join between Activity and Reason is already defined
*
* @param Join[] $joins
* @param mixed $alias
* @return boolean
*/
private function checkJoinAlreadyDefined(array $joins, $alias): bool
{
@@ -142,4 +81,55 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
return false;
}
public function applyOn()
{
return 'activity';
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('reasons', EntityType::class, [
'class' => ActivityReason::class,
'choice_label' => fn(ActivityReason $reason) => $this->translatableStringHelper->localize($reason->getName()),
'group_by' => fn(ActivityReason $reason) => $this->translatableStringHelper->localize($reason->getCategory()->getName()),
'multiple' => true,
'expanded' => false
]);
}
public function validateForm($data, ExecutionContextInterface $context)
{
if ($data['reasons'] === null || count($data['reasons']) === 0) {
$context
->buildViolation('At least one reason must be chosen')
->addViolation();
}
}
public function getTitle()
{
return 'Filter by reason';
}
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function describeAction($data, $format = 'string')
{
// collect all the reasons'name used in this filter in one array
$reasonsNames = array_map(
fn(ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"',
$this->activityReasonRepository->findBy(array('id' => $data['reasons']->toArray()))
);
return [
'Filtered by reasons: only %list%',
[
'%list%' => implode(", ", $reasonsNames),
]
];
}
}

View File

@@ -1,39 +1,29 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Entity\ActivityType;
use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\Query\Expr;
use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Doctrine\ORM\Query\Expr\Join;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\ActivityBundle\Entity\ActivityType;
use function count;
class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInterface
class ActivityTypeFilter implements FilterInterface, ExportElementValidatedInterface
{
protected ActivityTypeRepository $activityTypeRepository;
protected TranslatableStringHelperInterface $translatableStringHelper;
protected ActivityTypeRepository $activityTypeRepository;
public function __construct(
TranslatableStringHelperInterface $translatableStringHelper,
ActivityTypeRepository $activityTypeRepository
@@ -42,15 +32,10 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
$this->activityTypeRepository = $activityTypeRepository;
}
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function alterQuery(QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
$clause = $qb->expr()->in('activity.activityType', ':selected_activity_types');
$clause = $qb->expr()->in('activity.type', ':selected_activity_types');
if ($where instanceof Expr\Andx) {
$where->add($clause);
@@ -62,56 +47,11 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
$qb->setParameter('selected_activity_types', $data['types']);
}
public function applyOn(): string
{
return Declarations::ACTIVITY;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('types', EntityType::class, [
'class' => ActivityType::class,
'choice_label' => fn (ActivityType $type) => $this->translatableStringHelper->localize($type->getName()),
'group_by' => fn (ActivityType $type) => $this->translatableStringHelper->localize($type->getCategory()->getName()),
'multiple' => true,
'expanded' => false,
]);
}
public function describeAction($data, $format = 'string')
{
// collect all the reasons'name used in this filter in one array
$reasonsNames = array_map(
fn (ActivityType $t): string => $this->translatableStringHelper->localize($t->getName()),
$this->activityTypeRepository->findBy(['id' => $data['types']->toArray()])
);
return ['Filtered by activity type: only %list%', [
'%list%' => implode(', ou ', $reasonsNames),
]];
}
public function getTitle()
{
return 'Filter by activity type';
}
public function validateForm($data, ExecutionContextInterface $context)
{
if (null === $data['types'] || count($data['types']) === 0) {
$context
->buildViolation('At least one type must be chosen')
->addViolation();
}
}
/**
* Check if a join between Activity and Reason is already defined.
* Check if a join between Activity and Reason is already defined
*
* @param Join[] $joins
* @param mixed $alias
*
* @return bool
* @return boolean
*/
private function checkJoinAlreadyDefined(array $joins, $alias)
{
@@ -123,4 +63,58 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
return false;
}
public function applyOn()
{
return 'activity';
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add(
'types',
EntityType::class,
[
'class' => ActivityType::class,
'choice_label' => fn(ActivityType $type) => $this->translatableStringHelper->localize($type->getName()),
'multiple' => true,
'expanded' => false
]
);
}
public function validateForm($data, ExecutionContextInterface $context)
{
if ($data['types'] === null || count($data['types']) === 0) {
$context
->buildViolation('At least one type must be chosen')
->addViolation();
}
}
public function getTitle()
{
return 'Filter by activity type';
}
public function addRole()
{
return new Role(ActivityStatsVoter::STATS);
}
public function describeAction($data, $format = 'string')
{
// collect all the reasons'name used in this filter in one array
$reasonsNames = array_map(
fn(ActivityType $t): string => '"' . $this->translatableStringHelper->localize($t->getName()) . '"',
$this->activityTypeRepository->findBy(['id' => $data['types']->toArray()])
);
return [
'Filtered by activity type: only %list%',
[
'%list%' => implode(", ", $reasonsNames),
]
];
}
}

View File

@@ -1,45 +1,35 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Filter\PersonFilters;
namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\Export\FilterType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Export\Declarations;
use DateTime;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormError;
use Chill\MainBundle\Form\Type\Export\FilterType;
use Doctrine\ORM\Query\Expr;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\PersonBundle\Export\Declarations;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use function count;
class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInterface, FilterInterface
class PersonHavingActivityBetweenDateFilter implements FilterInterface, ExportElementValidatedInterface
{
protected ActivityReasonRepository $activityReasonRepository;
protected TranslatableStringHelperInterface $translatableStringHelper;
protected ActivityReasonRepository $activityReasonRepository;
protected TranslatorInterface $translator;
public function __construct(
@@ -76,8 +66,7 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
$sqb->andWhere(
$sqb->expr()->in(
'reasons_person_having_activity',
':person_having_activity_reasons'
'reasons_person_having_activity', ':person_having_activity_reasons'
)
);
@@ -91,18 +80,14 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
}
$qb->add('where', $where);
$qb->setParameter(
'person_having_activity_between_date_from',
$data['date_from']
);
$qb->setParameter(
'person_having_activity_between_date_to',
$data['date_to']
);
$qb->setParameter('person_having_activity_between_date_from',
$data['date_from']);
$qb->setParameter('person_having_activity_between_date_to',
$data['date_to']);
$qb->setParameter('person_having_activity_reasons', $data['reasons']);
}
public function applyOn(): string
public function applyOn()
{
return Declarations::PERSON_IMPLIED_IN;
}
@@ -111,71 +96,76 @@ 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',
'data' => new \DateTime(),
'attr' => ['class' => 'datepicker'],
'widget'=> 'single_text',
'format' => 'dd-MM-yyyy',
]);
$builder->add('date_to', DateType::class, [
'label' => 'Implied in an activity before this date',
'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'data' => new \DateTime(),
'attr' => ['class' => 'datepicker'],
'widget'=> 'single_text',
'format' => 'dd-MM-yyyy',
]);
$builder->add('reasons', EntityType::class, [
'class' => ActivityReason::class,
'choice_label' => fn (ActivityReason $reason): ?string => $this->translatableStringHelper->localize($reason->getName()),
'group_by' => fn (ActivityReason $reason): ?string => $this->translatableStringHelper->localize($reason->getCategory()->getName()),
'group_by' => fn(ActivityReason $reason): ?string => $this->translatableStringHelper->localize($reason->getCategory()->getName()),
'data' => $this->activityReasonRepository->findAll(),
'multiple' => true,
'expanded' => false,
'label' => 'Activity reasons for those activities',
'label' => 'Activity reasons for those activities'
]);
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
/** @var FormInterface $filterForm */
$builder->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
/* @var FormInterface $filterForm */
$filterForm = $event->getForm()->getParent();
$enabled = $filterForm->get(FilterType::ENABLED_FIELD)->getData();
if (true === $enabled) {
if ($enabled === true) {
// if the filter is enabled, add some validation
$form = $event->getForm();
$form = $event->getForm();
$date_from = $form->get('date_from')->getData();
$date_to = $form->get('date_to')->getData();
$date_to = $form->get('date_to')->getData();
// check that fields are not empty
if (null === $date_from) {
if ($date_from === null) {
$form->get('date_from')->addError(new FormError(
$this->translator->trans('This field '
. 'should not be empty')
));
. 'should not be empty')));
}
if (null === $date_to) {
if ($date_to === null) {
$form->get('date_to')->addError(new FormError(
$this->translator->trans('This field '
. 'should not be empty')
));
. 'should not be empty')));
}
// check that date_from is before date_to
if (
(null !== $date_from && null !== $date_to)
&& $date_from >= $date_to
($date_from !== null && $date_to !== null)
&&
$date_from >= $date_to
) {
$form->get('date_to')->addError(new FormError(
$this->translator->trans('This date '
. 'should be after the date given in "Implied in an '
. 'activity after this date" field')
));
. 'activity after this date" field')));
}
}
});
}
public function validateForm($data, ExecutionContextInterface $context)
{
if ($data['reasons'] === null || count($data['reasons']) === 0) {
$context->buildViolation('At least one reason must be chosen')
->addViolation();
}
}
public function describeAction($data, $format = 'string')
{
return [
@@ -183,15 +173,15 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
. '%date_to% with reasons %reasons_name%',
[
'%date_from%' => $data['date_from']->format('d-m-Y'),
'%date_to%' => $data['date_to']->format('d-m-Y'),
'%reasons_name%' => implode(
', ',
'%date_to%' => $data['date_to']->format('d-m-Y'),
'%reasons_name%' => implode(
", ",
array_map(
fn (ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"',
fn(ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"',
$data['reasons']
)
),
],
)
]
];
}
@@ -200,11 +190,4 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
return 'Filtered by person having an activity in a period';
}
public function validateForm($data, ExecutionContextInterface $context)
{
if (null === $data['reasons'] || count($data['reasons']) === 0) {
$context->buildViolation('At least one reason must be chosen')
->addViolation();
}
}
}

View File

@@ -1,22 +1,13 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Entity\ActivityPresence;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
class ActivityPresenceType extends AbstractType
{
@@ -24,19 +15,19 @@ class ActivityPresenceType extends AbstractType
{
$builder
->add('name', TranslatableStringFormType::class)
->add('active', ChoiceType::class, [
'choices' => [
->add('active', ChoiceType::class, array(
'choices' => array(
'Yes' => true,
'No' => false,
],
'expanded' => true,
]);
'No' => false
),
'expanded' => true
));
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => ActivityPresence::class,
]);
$resolver->setDefaults(array(
'data_class' => ActivityPresence::class
));
}
}

View File

@@ -1,29 +1,25 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Form;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
class ActivityReasonCategoryType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TranslatableStringFormType::class)
->add('active', CheckboxType::class, ['required' => false]);
->add('active', CheckboxType::class, array('required' => false))
;
}
/**
@@ -31,9 +27,9 @@ class ActivityReasonCategoryType extends AbstractType
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'Chill\ActivityBundle\Entity\ActivityReasonCategory',
]);
$resolver->setDefaults(array(
'data_class' => 'Chill\ActivityBundle\Entity\ActivityReasonCategory'
));
}
/**

View File

@@ -1,38 +1,37 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Form\Type\TranslatableActivityReasonCategory;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
use Chill\ActivityBundle\Form\Type\TranslatableActivityReasonCategory;
class ActivityReasonType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TranslatableStringFormType::class)
->add('active', CheckboxType::class, ['required' => false])
->add('category', TranslatableActivityReasonCategory::class);
->add('active', CheckboxType::class, array('required' => false))
->add('category', TranslatableActivityReasonCategory::class)
;
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'Chill\ActivityBundle\Entity\ActivityReason',
]);
$resolver->setDefaults(array(
'data_class' => 'Chill\ActivityBundle\Entity\ActivityReason'
));
}
/**

View File

@@ -1,78 +1,60 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Entity\ActivityPresence;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Chill\DocStoreBundle\Form\StoredObjectType;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\Location;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Form\Type\ChillCollectionType;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Form\Type\CommentType;
use Chill\MainBundle\Form\Type\PickUserDynamicType;
use Chill\MainBundle\Form\Type\PrivateCommentType;
use Chill\MainBundle\Form\Type\ScopePickerType;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
use Chill\ThirdPartyBundle\Entity\ThirdParty;
use DateInterval;
use DateTime;
use DateTimeZone;
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ObjectManager;
use RuntimeException;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Doctrine\Persistence\ObjectManager;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Chill\MainBundle\Entity\User;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Role\Role;
use function in_array;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\MainBundle\Form\Type\UserPickerType;
use Chill\MainBundle\Form\Type\ScopePickerType;
use Chill\MainBundle\Form\Type\ChillDateType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\CallbackTransformer;
use Chill\PersonBundle\Form\DataTransformer\PersonToIdTransformer;
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
class ActivityType extends AbstractType
{
protected User $user;
protected AuthorizationHelper $authorizationHelper;
protected ObjectManager $om;
protected SocialActionRender $socialActionRender;
protected TranslatableStringHelper $translatableStringHelper;
protected SocialIssueRender $socialIssueRender;
protected SocialActionRender $socialActionRender;
protected array $timeChoices;
protected TranslatableStringHelper $translatableStringHelper;
protected User $user;
public function __construct(
public function __construct (
TokenStorageInterface $tokenStorage,
AuthorizationHelper $authorizationHelper,
ObjectManager $om,
@@ -82,7 +64,7 @@ class ActivityType extends AbstractType
SocialActionRender $socialActionRender
) {
if (!$tokenStorage->getToken()->getUser() instanceof User) {
throw new RuntimeException('you should have a valid user');
throw new \RuntimeException("you should have a valid user");
}
$this->user = $tokenStorage->getToken()->getUser();
@@ -113,75 +95,67 @@ class ActivityType extends AbstractType
$activityType = $options['activityType'];
// TODO revoir la gestion des center au niveau du form des activité.
if ($options['center'] instanceof Center && null !== $options['data']->getPerson()) {
if ($options['center']) {
$builder->add('scope', ScopePickerType::class, [
'center' => $options['center'],
'role' => ActivityVoter::CREATE === (string) $options['role'] ? ActivityVoter::CREATE_PERSON : (string) $options['role'],
'required' => true,
'role' => $options['role'],
// TODO make required again once scope and rights are fixed
'required' => false
]);
}
/** @var ? \Chill\PersonBundle\Entity\AccompanyingPeriod $accompanyingPeriod */
$accompanyingPeriod = null;
if ($options['accompanyingPeriod'] instanceof AccompanyingPeriod) {
$accompanyingPeriod = NULL;
if ($options['accompanyingPeriod']) {
$accompanyingPeriod = $options['accompanyingPeriod'];
}
if ($activityType->isVisible('socialIssues') && $accompanyingPeriod) {
$builder->add('socialIssues', HiddenType::class, [
'required' => $activityType->getSocialIssuesVisible() === 2,
]);
$builder->add('socialIssues', HiddenType::class);
$builder->get('socialIssues')
->addModelTransformer(new CallbackTransformer(
static function (iterable $socialIssuesAsIterable): string {
$socialIssueIds = [];
foreach ($socialIssuesAsIterable as $value) {
$socialIssueIds[] = $value->getId();
}
return implode(',', $socialIssueIds);
},
function (?string $socialIssuesAsString): array {
if (null === $socialIssuesAsString) {
return [];
}
return array_map(
fn (string $id): ?SocialIssue => $this->om->getRepository(SocialIssue::class)->findOneBy(['id' => (int) $id]),
explode(',', $socialIssuesAsString)
);
}
));
->addModelTransformer(new CallbackTransformer(
function (iterable $socialIssuesAsIterable): string {
$socialIssueIds = [];
foreach ($socialIssuesAsIterable as $value) {
$socialIssueIds[] = $value->getId();
}
return implode(',', $socialIssueIds);
},
function (?string $socialIssuesAsString): array {
if (null === $socialIssuesAsString) {
return [];
}
return array_map(
fn(string $id): ?SocialIssue => $this->om->getRepository(SocialIssue::class)->findOneBy(['id' => (int) $id]),
explode(',', $socialIssuesAsString)
);
}
))
;
}
if ($activityType->isVisible('socialActions') && $accompanyingPeriod) {
$builder->add('socialActions', HiddenType::class, [
'required' => $activityType->getSocialActionsVisible() === 2,
]);
$builder->add('socialActions', HiddenType::class);
$builder->get('socialActions')
->addModelTransformer(new CallbackTransformer(
static function (iterable $socialActionsAsIterable): string {
$socialActionIds = [];
foreach ($socialActionsAsIterable as $value) {
$socialActionIds[] = $value->getId();
}
return implode(',', $socialActionIds);
},
function (?string $socialActionsAsString): array {
if (null === $socialActionsAsString) {
return [];
}
return array_map(
fn (string $id): ?SocialAction => $this->om->getRepository(SocialAction::class)->findOneBy(['id' => (int) $id]),
explode(',', $socialActionsAsString)
);
}
));
->addModelTransformer(new CallbackTransformer(
function (iterable $socialActionsAsIterable): string {
$socialActionIds = [];
foreach ($socialActionsAsIterable as $value) {
$socialActionIds[] = $value->getId();
}
return implode(',', $socialActionIds);
},
function (?string $socialActionsAsString): array {
if (null === $socialActionsAsString) {
return [];
}
return array_map(
fn(string $id): ?SocialAction => $this->om->getRepository(SocialAction::class)->findOneBy(['id' => (int) $id]),
explode(',', $socialActionsAsString)
);
}
))
;
}
if ($activityType->isVisible('date')) {
@@ -214,17 +188,19 @@ class ActivityType extends AbstractType
'choice_label' => function (ActivityPresence $activityPresence) {
return $this->translatableStringHelper->localize($activityPresence->getName());
},
'query_builder' => static function (EntityRepository $er) {
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('a')
->where('a.active = true');
},
]);
}
if ($activityType->isVisible('user') && $options['center'] instanceof Center) {
$builder->add('user', PickUserDynamicType::class, [
if ($activityType->isVisible('user') && $options['center']) {
$builder->add('user', UserPickerType::class, [
'label' => $activityType->getLabel('user'),
'required' => $activityType->isRequired('user'),
'center' => $options['center'],
'role' => $options['role']
]);
}
@@ -237,8 +213,8 @@ class ActivityType extends AbstractType
'choice_label' => function (ActivityReason $activityReason) {
return $this->translatableStringHelper->localize($activityReason->getName());
},
'attr' => ['class' => 'select2 '],
'query_builder' => static function (EntityRepository $er) {
'attr' => array('class' => 'select2 '),
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('a')
->where('a.active = true');
},
@@ -253,63 +229,46 @@ class ActivityType extends AbstractType
]);
}
if ($activityType->isVisible('privateComment')) {
$builder->add('privateComment', PrivateCommentType::class, [
'label' => '' === $activityType->getLabel('privateComment') ? 'private comment' : $activityType->getPrivateCommentLabel(),
'required' => false,
]);
}
if ($activityType->isVisible('persons')) {
$builder->add('persons', HiddenType::class);
$builder->get('persons')
->addModelTransformer(new CallbackTransformer(
static function (iterable $personsAsIterable): string {
$personIds = [];
foreach ($personsAsIterable as $value) {
$personIds[] = $value->getId();
}
return implode(',', $personIds);
},
function (?string $personsAsString): array {
if (null === $personsAsString) {
return [];
}
return array_map(
fn (string $id): ?Person => $this->om->getRepository(Person::class)->findOneBy(['id' => (int) $id]),
explode(',', $personsAsString)
);
}
));
->addModelTransformer(new CallbackTransformer(
function (iterable $personsAsIterable): string {
$personIds = [];
foreach ($personsAsIterable as $value) {
$personIds[] = $value->getId();
}
return implode(',', $personIds);
},
function (?string $personsAsString): array {
return array_map(
fn(string $id): ?Person => $this->om->getRepository(Person::class)->findOneBy(['id' => (int) $id]),
explode(',', $personsAsString)
);
}
))
;
}
if ($activityType->isVisible('thirdParties')) {
$builder->add('thirdParties', HiddenType::class);
$builder->get('thirdParties')
->addModelTransformer(new CallbackTransformer(
static function (iterable $thirdpartyAsIterable): string {
$thirdpartyIds = [];
foreach ($thirdpartyAsIterable as $value) {
$thirdpartyIds[] = $value->getId();
}
return implode(',', $thirdpartyIds);
},
function (?string $thirdpartyAsString): array {
if (null === $thirdpartyAsString) {
return [];
}
return array_map(
fn (string $id): ?ThirdParty => $this->om->getRepository(ThirdParty::class)->findOneBy(['id' => (int) $id]),
explode(',', $thirdpartyAsString)
);
}
));
->addModelTransformer(new CallbackTransformer(
function (iterable $thirdpartyAsIterable): string {
$thirdpartyIds = [];
foreach ($thirdpartyAsIterable as $value) {
$thirdpartyIds[] = $value->getId();
}
return implode(',', $thirdpartyIds);
},
function (?string $thirdpartyAsString): array {
return array_map(
fn(string $id): ?ThirdParty => $this->om->getRepository(ThirdParty::class)->findOneBy(['id' => (int) $id]),
explode(',', $thirdpartyAsString)
);
}
))
;
}
if ($activityType->isVisible('documents')) {
@@ -318,57 +277,47 @@ class ActivityType extends AbstractType
'label' => $activityType->getLabel('documents'),
'required' => $activityType->isRequired('documents'),
'allow_add' => true,
'allow_delete' => true,
'button_add_label' => 'activity.Insert a document',
'button_remove_label' => 'activity.Remove a document',
'empty_collection_explain' => 'No documents',
'entry_options' => ['has_title' => true],
'button_remove_label' => 'activity.Remove a document'
]);
}
if ($activityType->isVisible('users')) {
$builder->add('users', HiddenType::class);
$builder->get('users')
->addModelTransformer(new CallbackTransformer(
static function (iterable $usersAsIterable): string {
$userIds = [];
foreach ($usersAsIterable as $value) {
$userIds[] = $value->getId();
}
return implode(',', $userIds);
},
function (?string $usersAsString): array {
if (null === $usersAsString) {
return [];
}
return array_map(
fn (string $id): ?User => $this->om->getRepository(User::class)->findOneBy(['id' => (int) $id]),
explode(',', $usersAsString)
);
}
));
->addModelTransformer(new CallbackTransformer(
function (iterable $usersAsIterable): string {
$userIds = [];
foreach ($usersAsIterable as $value) {
$userIds[] = $value->getId();
}
return implode(',', $userIds);
},
function (?string $usersAsString): array {
return array_map(
fn(string $id): ?User => $this->om->getRepository(User::class)->findOneBy(['id' => (int) $id]),
explode(',', $usersAsString)
);
}
))
;
}
if ($activityType->isVisible('location')) {
$builder->add('location', HiddenType::class, [
'required' => $activityType->getLocationVisible() === 2,
])
$builder->add('location', HiddenType::class)
->get('location')
->addModelTransformer(new CallbackTransformer(
static function (?Location $location): string {
function (?Location $location): string {
if (null === $location) {
return '';
}
return (string) $location->getId();
return $location->getId();
},
function (?string $id): ?Location {
return $this->om->getRepository(Location::class)->findOneBy(['id' => (int) $id]);
}
));
))
;
}
if ($activityType->isVisible('emergency')) {
@@ -383,8 +332,8 @@ class ActivityType extends AbstractType
'label' => $activityType->getLabel('sentReceived'),
'required' => $activityType->isRequired('sentReceived'),
'choices' => [
'Received' => Activity::SENTRECEIVED_RECEIVED,
'Sent' => Activity::SENTRECEIVED_SENT,
'Received' => Activity::SENTRECEIVED_RECEIVED,
],
]);
}
@@ -398,7 +347,7 @@ class ActivityType extends AbstractType
->addModelTransformer($durationTimeTransformer);
$builder->get($fieldName)
->addEventListener(FormEvents::PRE_SET_DATA, static function (FormEvent $formEvent) use (
->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $formEvent) use (
$timeChoices,
$builder,
$durationTimeTransformer,
@@ -407,25 +356,24 @@ class ActivityType extends AbstractType
) {
// set the timezone to GMT, and fix the difference between current and GMT
// the datetimetransformer will then handle timezone as GMT
$timezoneUTC = new DateTimeZone('GMT');
/** @var DateTime $data */
$data = $formEvent->getData() === null ?
DateTime::createFromFormat('U', '300') :
$timezoneUTC = new \DateTimeZone('GMT');
/* @var $data \DateTime */
$data = $formEvent->getData() === NULL ?
\DateTime::createFromFormat('U', 300) :
$formEvent->getData();
$seconds = $data->getTimezone()->getOffset($data);
$data->setTimeZone($timezoneUTC);
$data->add(new DateInterval('PT' . $seconds . 'S'));
$data->add(new \DateInterval('PT'.$seconds.'S'));
// test if the timestamp is in the choices.
// If not, recreate the field with the new timestamp
if (!in_array($data->getTimestamp(), $timeChoices, true)) {
if (!in_array($data->getTimestamp(), $timeChoices)) {
// the data are not in the possible values. add them
$timeChoices[$data->format('H:i')] = $data->getTimestamp();
$form = $builder->create($fieldName, ChoiceType::class, array_merge(
$durationTimeOptions,
[
$durationTimeOptions, [
'choices' => $timeChoices,
'auto_initialize' => false,
'auto_initialize' => false
]
));
$form->addModelTransformer($durationTimeTransformer);
@@ -435,18 +383,21 @@ class ActivityType extends AbstractType
}
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Activity::class,
'data_class' => Activity::class
]);
$resolver
->setRequired(['center', 'role', 'activityType', 'accompanyingPeriod'])
->setAllowedTypes('center', ['null', Center::class])
->setAllowedTypes('role', [Role::class, 'string'])
->setAllowedTypes('center', ['null', 'Chill\MainBundle\Entity\Center'])
->setAllowedTypes('role', 'Symfony\Component\Security\Core\Role\Role')
->setAllowedTypes('activityType', \Chill\ActivityBundle\Entity\ActivityType::class)
->setAllowedTypes('accompanyingPeriod', [\Chill\PersonBundle\Entity\AccompanyingPeriod::class, 'null']);
->setAllowedTypes('accompanyingPeriod', [\Chill\PersonBundle\Entity\AccompanyingPeriod::class, 'null'])
;
}
public function getBlockPrefix(): string

View File

@@ -1,23 +1,14 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Entity\ActivityTypeCategory;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
class ActivityTypeCategoryType extends AbstractType
{
@@ -25,23 +16,24 @@ class ActivityTypeCategoryType extends AbstractType
{
$builder
->add('name', TranslatableStringFormType::class)
->add('active', ChoiceType::class, [
'choices' => [
->add('active', ChoiceType::class, array(
'choices' => array(
'Yes' => true,
'No' => false,
],
'expanded' => true,
])
'No' => false
),
'expanded' => true
))
->add('ordering', NumberType::class, [
'required' => true,
'scale' => 5,
]);
'scale' => 5
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => ActivityTypeCategory::class,
]);
$resolver->setDefaults(array(
'data_class' => ActivityTypeCategory::class
));
}
}

View File

@@ -1,27 +1,18 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Entity\ActivityTypeCategory;
use Chill\ActivityBundle\Form\Type\ActivityFieldPresence;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
class ActivityTypeType extends AbstractType
{
@@ -39,9 +30,9 @@ class ActivityTypeType extends AbstractType
->add('active', ChoiceType::class, [
'choices' => [
'Yes' => true,
'No' => false,
'No' => false
],
'expanded' => true,
'expanded' => true
])
->add('category', EntityType::class, [
'class' => ActivityTypeCategory::class,
@@ -51,33 +42,30 @@ class ActivityTypeType extends AbstractType
])
->add('ordering', NumberType::class, [
'required' => true,
'scale' => 5,
]);
'scale' => 5
])
;
$fields = [
'persons', 'user', 'date', 'location', 'persons',
'persons', 'user', 'date', 'place', 'persons',
'thirdParties', 'durationTime', 'travelTime', 'attendee',
'reasons', 'comment', 'privateComment', 'sentReceived', 'documents',
'emergency', 'socialIssues', 'socialActions', 'users',
'reasons', 'comment', 'sentReceived', 'documents',
'emergency', 'accompanyingPeriod', 'socialData', 'users'
];
foreach ($fields as $field) {
$builder
->add($field . 'Visible', ActivityFieldPresence::class)
->add($field . 'Label', TextType::class, [
->add($field.'Visible', ActivityFieldPresence::class)
->add($field.'Label', TextType::class, [
'required' => false,
'empty_data' => '',
]);
}
$builder
->add('commentVisible', ActivityFieldPresence::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => \Chill\ActivityBundle\Entity\ActivityType::class,
]);
$resolver->setDefaults(array(
'data_class' => \Chill\ActivityBundle\Entity\ActivityType::class
));
}
}

View File

@@ -1,14 +1,5 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Form\Type;
use Chill\ActivityBundle\Entity\ActivityType;
@@ -18,21 +9,21 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
class ActivityFieldPresence extends AbstractType
{
public function getParent()
{
return ChoiceType::class;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
array(
'choices' => [
'Invisible' => ActivityType::FIELD_INVISIBLE,
'Optional' => ActivityType::FIELD_OPTIONAL,
'Required' => ActivityType::FIELD_REQUIRED,
],
]
)
);
}
public function getParent()
{
return ChoiceType::class;
}
}

View File

@@ -1,38 +1,53 @@
<?php
/**
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
* Copyright (C) 2014-2020, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Form\Type;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Templating\Entity\ActivityReasonRender;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\EntityRepository;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Templating\Entity\ActivityReasonRender;
/**
* FormType to choose amongst activity reasons.
* FormType to choose amongst activity reasons
*
*/
class TranslatableActivityReason extends AbstractType
{
/**
* @var ActivityReasonRender
*/
protected $reasonRender;
/**
*
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
/**
*
* @var ActivityReasonRender
*/
protected $reasonRender;
public function __construct(
TranslatableStringHelper $translatableStringHelper,
@@ -42,30 +57,6 @@ class TranslatableActivityReason extends AbstractType
$this->reasonRender = $reasonRender;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'class' => 'ChillActivityBundle:ActivityReason',
'choice_label' => function (ActivityReason $choice) {
return $this->reasonRender->renderString($choice, []);
},
'group_by' => function (ActivityReason $choice): ?string {
if (null !== $category = $choice->getCategory()) {
return $this->translatableStringHelper->localize($category->getName());
}
return null;
},
'query_builder' => static function (EntityRepository $er) {
return $er->createQueryBuilder('r')
->where('r.active = true');
},
'attr' => ['class' => ' select2 '],
]
);
}
public function getBlockPrefix()
{
return 'translatable_activity_reason';
@@ -75,4 +66,28 @@ class TranslatableActivityReason extends AbstractType
{
return EntityType::class;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
array(
'class' => 'ChillActivityBundle:ActivityReason',
'choice_label' => function(ActivityReason $choice) {
return $this->reasonRender->renderString($choice, []);
},
'group_by' => function(ActivityReason $choice): ?string {
if (null !== $category = $choice->getCategory()) {
return $this->translatableStringHelper->localize($category->getName());
}
return null;
},
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('r')
->where('r.active = true');
},
'attr' => [ 'class' => ' select2 ']
)
);
}
}

View File

@@ -1,25 +1,40 @@
<?php
/**
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Form\Type;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
/**
* Description of TranslatableActivityReasonCategory.
* Description of TranslatableActivityReasonCategory
*
* @author Champs-Libres Coop
*/
class TranslatableActivityReasonCategory extends AbstractType
{
/**
@@ -32,21 +47,6 @@ class TranslatableActivityReasonCategory extends AbstractType
$this->requestStack = $requestStack;
}
public function configureOptions(OptionsResolver $resolver)
{
$locale = $this->requestStack->getCurrentRequest()->getLocale();
$resolver->setDefaults(
[
'class' => 'ChillActivityBundle:ActivityReasonCategory',
'choice_label' => 'name[' . $locale . ']',
'query_builder' => static function (EntityRepository $er) {
return $er->createQueryBuilder('c')
->where('c.active = true');
},
]
);
}
public function getBlockPrefix()
{
return 'translatable_activity_reason_category';
@@ -56,4 +56,19 @@ class TranslatableActivityReasonCategory extends AbstractType
{
return EntityType::class;
}
public function configureOptions(OptionsResolver $resolver)
{
$locale = $this->requestStack->getCurrentRequest()->getLocale();
$resolver->setDefaults(
array(
'class' => 'ChillActivityBundle:ActivityReasonCategory',
'choice_label' => 'name['.$locale.']',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('c')
->where('c.active = true');
}
)
);
}
}

View File

@@ -1,32 +1,25 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\Form\Type;
use Chill\ActivityBundle\Entity\ActivityType;
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Chill\ActivityBundle\Entity\ActivityType;
class TranslatableActivityType extends AbstractType
{
protected ActivityTypeRepository $activityTypeRepository;
protected TranslatableStringHelperInterface $translatableStringHelper;
protected ActivityTypeRepository $activityTypeRepository;
public function __construct(
TranslatableStringHelperInterface $helper,
ActivityTypeRepository $activityTypeRepository
@@ -35,32 +28,6 @@ class TranslatableActivityType extends AbstractType
$this->activityTypeRepository = $activityTypeRepository;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
/** @var QueryBuilder $qb */
$qb = $options['query_builder'];
if (true === $options['active_only']) {
$qb->where($qb->expr()->eq('at.active', ':active'));
$qb->setParameter('active', true, Types::BOOLEAN);
}
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'class' => ActivityType::class,
'active_only' => true,
'query_builder' => $this->activityTypeRepository
->createQueryBuilder('at'),
'choice_label' => function (ActivityType $type) {
return $this->translatableStringHelper->localize($type->getName());
},
]
);
}
public function getBlockPrefix()
{
return 'translatable_activity_type';
@@ -70,4 +37,29 @@ class TranslatableActivityType extends AbstractType
{
return EntityType::class;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
/* @var QueryBuilder $qb */
$qb = $options['query_builder'];
if ($options['active_only'] === true) {
$qb->where($qb->expr()->eq('at.active', ':active'));
$qb->setParameter('active', true, Types::BOOLEAN);
}
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
array(
'class' => ActivityType::class,
'active_only' => true,
'query_builder' => $this->activityTypeRepository
->createQueryBuilder('at'),
'choice_label' => function (ActivityType $type) {
return $this->translatableStringHelper->localize($type->getName());
}
)
);
}
}

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