diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f76ec4b98..1037d8f86 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -60,7 +60,7 @@ code_style: - bin - tests/app/vendor/ -sa_tests: +phpstan_tests: stage: Tests image: registry.gitlab.com/chill-projet/chill-app/php-base-image:7.4 script: @@ -71,6 +71,17 @@ sa_tests: - 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 + 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 @@ -79,7 +90,7 @@ unit_tests: - 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=3G bin/phpunit --colors=never + - php -d memory_limit=4G bin/phpunit --colors=never artifacts: expire_in: 30 min paths: diff --git a/CHANGELOG.md b/CHANGELOG.md index ec27da83d..07c166301 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,11 +11,77 @@ and this project adheres to ## Unreleased -* [person search] fix bug when using birthdate after and birthdate before -* [person search] increase pertinence when lastname begins with search pattern +* 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) ## Test releases +### 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 @@ -23,6 +89,7 @@ and this project adheres to * [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) @@ -50,6 +117,9 @@ and this project adheres to * [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 + +## 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 @@ -164,7 +234,7 @@ and this project adheres to * fast creation buttons * add ordering for types -* [AccompanyingCourse Resume page] badge-title for AccompanyingCourseWork and for Activities; +* [AccompanyingCourse Resume page] dashboard for AccompanyingCourseWork and for Activities; * Improve badges behaviour with small screens; * [ThirdParty]: diff --git a/CONVENTIONS.md b/CONVENTIONS.md index 2543e54b7..5b9da225e 100644 --- a/CONVENTIONS.md +++ b/CONVENTIONS.md @@ -397,7 +397,6 @@ Créer une liste de suggestions à enlever (avec une croix rouge cliquable, l'an
  • item -
  • @@ -405,7 +404,8 @@ Créer une liste de suggestions à enlever (avec une croix rouge cliquable, l'an Créer un titre enlevable (avec une croix rouge cliquable, l'ancre a est vide) ```html
    - title - + title
    ``` +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. diff --git a/composer.json b/composer.json index 254486913..a6f059112 100644 --- a/composer.json +++ b/composer.json @@ -1,16 +1,17 @@ { "name": "chill-project/chill-bundles", - "type": "library", "description": "Most used bundles for chill-project", + "license": "AGPL-3.0-only", + "type": "library", "keywords": [ "chill", "social worker" ], - "license": "AGPL-3.0-only", "require": { - "champs-libres/async-uploader-bundle": "dev-sf4", - "champs-libres/wopi-bundle": "dev-master", - "composer/package-versions-deprecated": "^1.10", + "php": "^7.4", + "champs-libres/async-uploader-bundle": "dev-sf4#d57134aee8e504a83c902ff0cf9f8d36ac418290", + "champs-libres/wopi-bundle": "dev-master#59b468503b9413f8d588ef9e626e7675560db3d8", + "champs-libres/wopi-lib": "dev-master#0e1da19bb6de820080b8651867a7e475be590060", "doctrine/doctrine-bundle": "^2.1", "doctrine/doctrine-migrations-bundle": "^3.0", "doctrine/orm": "^2.7", @@ -21,34 +22,33 @@ "knplabs/knp-time-bundle": "^1.12", "league/csv": "^9.7.1", "nyholm/psr7": "^1.4", + "ocramius/package-versions": "^1.10", "phpoffice/phpspreadsheet": "^1.16", "ramsey/uuid-doctrine": "^1.7", "sensio/framework-extra-bundle": "^5.5", - "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", + "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/intl": "^4.4", + "symfony/mime": "^4.4", "symfony/monolog-bundle": "^3.5", - "symfony/security-bundle": "4.*", - "symfony/serializer": "^5.2", + "symfony/security-bundle": "^4.4", + "symfony/serializer": "^5.3", "symfony/swiftmailer-bundle": "^3.5", - "symfony/templating": "4.*", - "symfony/translation": "4.*", + "symfony/templating": "^4.4", + "symfony/translation": "^4.4", "symfony/twig-bundle": "^4.4", - "symfony/validator": "4.*", + "symfony/validator": "^4.4", "symfony/webpack-encore-bundle": "^1.11", - "symfony/workflow": "4.*", - "symfony/yaml": "4.*", - "twig/extra-bundle": "^2.12 || ^3.0", + "symfony/workflow": "^4.4", + "symfony/yaml": "^4.4", + "twig/extra-bundle": "^3.0", "twig/intl-extra": "^3.0", "twig/markdown-extra": "^3.3", - "twig/twig": "^2.12 || ^3.0" - }, - "conflict": { - "symfony/symfony": "*" + "twig/twig": "^3.0" }, "require-dev": { "doctrine/doctrine-fixtures-bundle": "^3.3", @@ -56,18 +56,17 @@ "fakerphp/faker": "^1.13", "nelmio/alice": "^3.8", "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^7.0", + "phpunit/phpunit": ">= 7.5", "symfony/debug-bundle": "^5.1", - "symfony/dotenv": "^5.1", + "symfony/dotenv": "^4.4", "symfony/maker-bundle": "^1.20", - "symfony/phpunit-bridge": "^5.2", - "symfony/stopwatch": "^5.1", - "symfony/var-dumper": "4.*", - "symfony/web-profiler-bundle": "^5.0" + "symfony/phpunit-bridge": "^4.4", + "symfony/stopwatch": "^4.4", + "symfony/var-dumper": "^4.4", + "symfony/web-profiler-bundle": "^4.4" }, - "config": { - "bin-dir": "bin", - "vendor-dir": "tests/app/vendor" + "conflict": { + "symfony/symfony": "*" }, "autoload": { "psr-4": { @@ -94,8 +93,19 @@ "Chill\\DocGeneratorBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests" } }, - "minimum-stability": "dev", - "prefer-stable": true, + "config": { + "allow-plugins": { + "composer/package-versions-deprecated": true, + "phpstan/extension-installer": true, + "ergebnis/composer-normalize": true, + "phpro/grumphp": true, + "ocramius/package-versions": true + }, + "bin-dir": "bin", + "optimize-autoloader": true, + "sort-packages": true, + "vendor-dir": "tests/app/vendor" + }, "scripts": { "auto-scripts": { "cache:clear": "symfony-cmd", diff --git a/docs/source/_static/code/exports/CountPerson.php b/docs/source/_static/code/exports/CountPerson.php index 98c4fcd00..dd95f3c88 100644 --- a/docs/source/_static/code/exports/CountPerson.php +++ b/docs/source/_static/code/exports/CountPerson.php @@ -91,7 +91,9 @@ class CountPerson implements ExportInterface public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) { // we gather all center the user choose. - $centers = array_map(static function ($el) { return $el['center']; }, $acl); + $centers = array_map(static function ($el) { + return $el['center']; + }, $acl); $qb = $this->entityManager->createQueryBuilder(); diff --git a/docs/source/development/user-interface/widgets/ChillMainConfiguration.php b/docs/source/development/user-interface/widgets/ChillMainConfiguration.php index 2786b3376..d11225245 100644 --- a/docs/source/development/user-interface/widgets/ChillMainConfiguration.php +++ b/docs/source/development/user-interface/widgets/ChillMainConfiguration.php @@ -11,53 +11,53 @@ declare(strict_types=1); namespace Chill\MainBundle\DependencyInjection; - use Chill\MainBundle\DependencyInjection\Widget\AddWidgetConfigurationTrait; - use Symfony\Component\Config\Definition\Builder\TreeBuilder; - use Symfony\Component\Config\Definition\ConfigurationInterface; - use Symfony\Component\DependencyInjection\ContainerBuilder; +use Chill\MainBundle\DependencyInjection\Widget\AddWidgetConfigurationTrait; +use Symfony\Component\Config\Definition\Builder\TreeBuilder; +use Symfony\Component\Config\Definition\ConfigurationInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; - /** - * Configure the main bundle. - */ - class ChillMainConfiguration implements ConfigurationInterface - { - use AddWidgetConfigurationTrait; +/** + * Configure the main bundle. + */ +class ChillMainConfiguration implements ConfigurationInterface +{ + use AddWidgetConfigurationTrait; - /** - * @var ContainerBuilder - */ - private $containerBuilder; + /** + * @var ContainerBuilder + */ + private $containerBuilder; - 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; - } + 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; + } - public function getConfigTreeBuilder() - { - $treeBuilder = new TreeBuilder(); - $rootNode = $treeBuilder->root('chill_main'); + public function getConfigTreeBuilder() + { + $treeBuilder = new TreeBuilder(); + $rootNode = $treeBuilder->root('chill_main'); - $rootNode - ->children() + $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 + // ... + ->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; - } - } + return $treeBuilder; + } +} diff --git a/grumphp.yml b/grumphp.yml index d25cc01ba..8efce6109 100644 --- a/grumphp.yml +++ b/grumphp.yml @@ -12,3 +12,28 @@ parameters: 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/" + + # Psalm + tasks.psalm.blocking: true + tasks.psalm.ignore_patterns: + - "/.github/" + - "/.idea/" + - "/build/" + - "/benchmarks/" + - "/node_modules/" + - "/resource/" + - "/spec/" + - "/var/" + - "/vendor/" diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index a3a2f6e04..d996ff3b8 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -10,16 +10,6 @@ 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 diff --git a/phpstan-deprecations.neon b/phpstan-deprecations.neon index 1e762ce9e..24deda05f 100644 --- a/phpstan-deprecations.neon +++ b/phpstan-deprecations.neon @@ -417,15 +417,6 @@ parameters: count: 1 path: src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.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/ChillDocStoreBundle/Controller/DocumentPersonController.php - - message: """ @@ -435,15 +426,6 @@ parameters: count: 1 path: src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.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/ChillDocStoreBundle/Form/PersonDocumentType.php - - message: """ @@ -525,24 +507,6 @@ parameters: 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: 2 - 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/ChillEventBundle/Timeline/TimelineEventProvider.php - - message: """ @@ -1311,16 +1275,6 @@ parameters: 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/Search/SimilarPersonMatcher.php - - - message: """ diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 80367c691..208c915ae 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -2,10 +2,11 @@ diff --git a/psalm-baseline.xml b/psalm-baseline.xml new file mode 100644 index 000000000..33107d40b --- /dev/null +++ b/psalm-baseline.xml @@ -0,0 +1,2006 @@ + + + + + 'ChillActivityBundle:ActivityReasonCategory' + 'ChillActivityBundle:ActivityReasonCategory' + 'ChillActivityBundle:ActivityReasonCategory' + 'ChillActivityBundle:ActivityReasonCategory' + + + + + 'ChillActivityBundle:ActivityReason' + 'ChillActivityBundle:ActivityReason' + 'ChillActivityBundle:ActivityReason' + 'ChillActivityBundle:ActivityReason' + + + + + $socialIssue + + + + + $qb + + + + + $qb + + + + + OptionsResolverInterface + + + + + $person + + + + + Activity[]|array + Activity[]|array + + + + + require __DIR__ . '/../../../../../vendor/autoload.php' + + + + + return trigger_error($e, E_USER_ERROR); + + + $baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, rtrim(dirname($baseUrl),'/'.DIRECTORY_SEPARATOR).'/') + + + $files + $files + + + + + addProvider + addProvider + new \Chill\CustomFieldsBundle\Form\CustomFieldType($this->get('chill.custom_field.provider')) + new \Chill\CustomFieldsBundle\Templating\Twig\CustomFieldRenderingTwig() + new \Chill\MainBundle\Form\Type\Select2CountryType($this->get('request_stack'), $this->get('doctrine.orm.default_entity_manager')) + new \Chill\MainBundle\Form\Type\Select2LanguageType($this->get('request_stack'), $this->get('doctrine.orm.default_entity_manager')) + new \Chill\MainBundle\Routing\MenuComposer() + new \Chill\MainBundle\Security\Authorization\AuthorizationHelper($this->get('security.role_hierarchy')) + new \Chill\MainBundle\Templating\TranslatableStringHelper($this->get('request_stack'), $this->get('translator.default')) + new \Chill\MainBundle\Templating\TranslatableStringTwig() + new \Chill\PersonBundle\Search\PersonSearch($this->get('doctrine.orm.default_entity_manager'), $this->get('security.token_storage'), $this->get('chill.main.security.authorization.helper')) + new \Chill\PersonBundle\Timeline\TimelineAccompanyingPeriodClosing($this->get('doctrine.orm.default_entity_manager')) + new \Chill\PersonBundle\Timeline\TimelineAccompanyingPeriodOpening($this->get('doctrine.orm.default_entity_manager')) + + + InactiveScopeException + InactiveScopeException + \Assetic\Cache\ConfigCache + \Assetic\Extension\Twig\TwigFormulaLoader + \Assetic\Factory\LazyAssetManager + \Assetic\Factory\Loader\CachedFormulaLoader + \Assetic\Filter\CssRewriteFilter + \Chill\MainBundle\Form\Type\CenterType + \Chill\PersonBundle\Form\Type\ClosingMotiveType + \Doctrine\Common\Cache\ArrayCache + \Doctrine\Common\Cache\ArrayCache + \Doctrine\Common\Cache\ArrayCache + \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain + \SensioLabs\Security\Command\SecurityCheckerCommand + \SensioLabs\Security\SecurityChecker + \Sensio\Bundle\DistributionBundle\Configurator\Configurator + \Sensio\Bundle\DistributionBundle\Configurator\Step\DoctrineStep + \Sensio\Bundle\DistributionBundle\Configurator\Step\SecretStep + \Symfony\Bridge\Monolog\Handler\DebugHandler + \Symfony\Bundle\AsseticBundle\CacheWarmer\AssetManagerCacheWarmer + \Symfony\Bundle\AsseticBundle\DefaultValueSupplier + \Symfony\Bundle\AsseticBundle\Factory\AssetFactory + \Symfony\Bundle\AsseticBundle\Factory\Resource\CoalescingDirectoryResource + \Symfony\Bundle\AsseticBundle\Factory\Resource\CoalescingDirectoryResource + \Symfony\Bundle\AsseticBundle\Factory\Resource\DirectoryResource + \Symfony\Bundle\AsseticBundle\Factory\Resource\DirectoryResource + \Symfony\Bundle\AsseticBundle\Factory\Resource\DirectoryResource + \Symfony\Bundle\AsseticBundle\Factory\Resource\DirectoryResource + \Symfony\Bundle\AsseticBundle\Factory\Resource\DirectoryResource + \Symfony\Bundle\AsseticBundle\FilterManager + \Symfony\Bundle\AsseticBundle\Twig\AsseticExtension + \Symfony\Bundle\FrameworkBundle\DataCollector\AjaxDataCollector + \Symfony\Bundle\FrameworkBundle\EventListener\SessionListener + \Symfony\Bundle\FrameworkBundle\EventListener\TestSessionListener + \Symfony\Bundle\FrameworkBundle\Translation\PhpExtractor + \Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader + \Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory + \Symfony\Bundle\TwigBundle\Extension\ActionsExtension + \Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher + \Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfTokenManagerAdapter + \Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel + \Symfony\Component\Security\Core\SecurityContext + \Symfony\Component\Security\Core\Util\SecureRandom + \Twig_Environment + \Twig_Extension_Debug + \Twig_Extensions_Extension_Intl + \Twig_Profiler_Profile + + + InactiveScopeException + InactiveScopeException + \Assetic\Factory\LazyAssetManager + \Assetic\Filter\CssRewriteFilter + \Chill\MainBundle\Form\Type\CenterType + \Chill\PersonBundle\Form\Type\ClosingMotiveType + \Doctrine\Common\Cache\ArrayCache + \Doctrine\Common\Cache\ArrayCache + \Doctrine\Common\Cache\ArrayCache + \SensioLabs\Security\Command\SecurityCheckerCommand + \SensioLabs\Security\SecurityChecker + \Sensio\Bundle\DistributionBundle\Configurator\Configurator + \Symfony\Bridge\Monolog\Handler\DebugHandler + \Symfony\Bundle\AsseticBundle\Factory\AssetFactory + \Symfony\Bundle\AsseticBundle\FilterManager + \Symfony\Bundle\FrameworkBundle\EventListener\SessionListener + \Symfony\Bundle\FrameworkBundle\EventListener\TestSessionListener + \Symfony\Bundle\FrameworkBundle\Translation\PhpExtractor + \Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader + \Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfTokenManagerAdapter + \Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel + \Symfony\Component\Security\Core\SecurityContext + \Symfony\Component\Security\Core\Util\SecureRandom + \Twig_Environment + \Twig_Extensions_Extension_Intl + \Twig_Profiler_Profile + + + + + type + type + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + \Chill\PersonBundle\Export\Filter\PersonHavingActivityBetweenDateFilter + + + + + public function setUp() + + + + + public function setUp() + + + + Prophecy\Prophet + + + + + public function setUp() + + + + + public function setUp() + + + type + + + + + $activity + + + + + $createdAt + $createdBy + $updatedAt + $updatedBy + + + + + $asideActivityCategory + $asideActivityCategory + $asideActivityCategory + + + + + public function setUp() + + + + + $calculator::getAlias() + $calculator::getAlias() + $calculator::getAlias() + + + + + decimal + + + + + AbstractMigration + + + + + $qb + + + + + 'ChillCalendarBundle:Calendar' + 'ChillCalendarBundle:Calendar' + 'ChillCalendarBundle:Calendar' + + + + + public function setUp() + + + + + 'ChillCustomFieldsBundle:CustomFieldsGroup' + + + + + 'ChillCustomFieldsBundle:CustomField' + + + + + 'ChillCustomFieldsBundle:CustomFieldsDefaultGroup' + 'ChillCustomFieldsBundle:CustomFieldsGroup' + 'ChillCustomFieldsBundle:CustomFieldsGroup' + 'ChillCustomFieldsBundle:CustomFieldsGroup' + 'ChillCustomFieldsBundle:CustomFieldsGroup' + 'ChillCustomFieldsBundle:CustomFieldsGroup' + 'ChillCustomFieldsBundle:CustomFieldsGroup' + + + + + $date + + + + + \Chill\CustomFieldsBundle\CustomField\CustomField + \Chill\CustomFieldsBundle\CustomField\CustomField + \Chill\CustomFieldsBundle\CustomField\CustomField + \Chill\CustomFieldsBundle\CustomField\CustomField + \Chill\CustomFieldsBundle\CustomField\FormBuilderInterface + \Chill\CustomFieldsBundle\CustomField\FormBuilderInterface + + + + + OptionsResolverInterface + + + + + $customFieldsGroup + $id + + + + + $customFieldsArray + $customFieldsJSON + + + + + $this->customFieldCompiler + CustomFieldCompiler + + + + + AppKernel + + + + + require __DIR__ . '/../../../../../vendor/autoload.php' + + + + + require_once __DIR__ . '/../app/bootstrap.php.cache' + + + + + Container + CustomFieldInterface + type + type + + + + + $customFieldType + $customFieldType + $customFieldType + The + + + + + CustomFieldsGroud + + + + + type + + + type + + + + + public function setUp() + public function tearDown() + + + type + type + type + type + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + protected function setUp() + + + + + protected function setUp() + + + + + protected function setUp() + + + + + 'ChillDocStoreBundle:AccompanyingCourseDocument' + + + + + 'ChillDocStoreBundle:DocumentCategory' + 'ChillDocStoreBundle:DocumentCategory' + 'ChillDocStoreBundle:DocumentCategory' + + + + + 'ChillDocStoreBundle:PersonDocument' + + + + + \Chill\PersonBundle\Entity\user + + + + + $this->getPerson() + \Chill\MainBundle\Entity\Person + + + + + 'ChillEventBundle:Event' + 'ChillEventBundle:Event' + 'ChillEventBundle:Event' + 'ChillEventBundle:Participation' + 'ChillEventBundle:Participation' + 'ChillPersonBundle:Person' + + + + + 'ChillEventBundle:EventType' + 'ChillEventBundle:EventType' + 'ChillEventBundle:EventType' + 'ChillEventBundle:EventType' + 'ChillEventBundle:EventType' + + + + + 'ChillEventBundle:Event' + 'ChillEventBundle:Event' + 'ChillEventBundle:Event' + 'ChillEventBundle:Participation' + 'ChillPersonBundle:Person' + + + $participation + $participation + $participation + $participation + $participations[0] + Participation|Participations[] + + + + + 'ChillEventBundle:Role' + 'ChillEventBundle:Role' + 'ChillEventBundle:Role' + 'ChillEventBundle:Role' + 'ChillEventBundle:Role' + + + + + 'ChillEventBundle:Status' + 'ChillEventBundle:Status' + 'ChillEventBundle:Status' + 'ChillEventBundle:Status' + 'ChillEventBundle:Status' + + + + + 'ChillMainBundle:Center' + 'ChillPersonBundle:Person' + + + + + OptionsResolverInterface + + + + + OptionsResolverInterface + + + + + OptionsResolverInterface + + + + + AppKernel + + + + + type + + + public function setUp() + + + 'ChillEventBundle:Event' + 'ChillEventBundle:Event' + 'ChillEventBundle:Event' + 'ChillEventBundle:Event' + 'ChillMainBundle:Center' + 'ChillMainBundle:Center' + 'ChillMainBundle:Scope' + 'ChillPersonBundle:Person' + + + type + + + + + public function setUp() + public function tearDown() + + + 'ChillMainBundle:Scope' + + + $dateTo + $dateTo + + + + + date_immutable|null + date_immutable|null + + + + + AbstractMigration + + + + + $this->buildQueryEntities($action, $request) + $this->buildQueryEntities($action, $request) + QueryBuilder + \Symfony\Component\Security\Core\Exception\AccessDeniedHttpException + + + + + ?Scope + + + $query + \Symfony\Component\Security\Core\Exception\AccessDeniedHttpException + type + type + type + + + + + + + + 'ChillMainBundle:Language' + + + + + 'ChillMainBundle:Country' + + + + + 'ChillMainBundle:User' + + + + + $qb + + + + + 'ChillMainBundle:Center' + 'ChillMainBundle:Center' + 'ChillMainBundle:Center' + 'ChillMainBundle:Center' + + + + + Response + type + + + + + 'ChillMainBundle:PermissionsGroup' + 'ChillMainBundle:PermissionsGroup' + 'ChillMainBundle:PermissionsGroup' + 'ChillMainBundle:PermissionsGroup' + 'ChillMainBundle:PermissionsGroup' + 'ChillMainBundle:PermissionsGroup' + 'ChillMainBundle:RoleScope' + 'ChillMainBundle:RoleScope' + + + Respon + redirection + type + + + + + $qb + + + + + 'ChillMainBundle:Scope' + 'ChillMainBundle:Scope' + 'ChillMainBundle:Scope' + 'ChillMainBundle:Scope' + + + + + $search + $search + $search + $searchProvider + $searchProvider + + + + + 'ChillMainBundle:GroupCenter' + 'ChillMainBundle:GroupCenter' + 'ChillMainBundle:User' + 'ChillMainBundle:User' + + + + + + + + $class::getMenuIds() + + + + + unknown + + + + + WidgetFactoryInterface[] + WidgetFactoryInterface[] + type + type + type + type + + + + + type + type + type + + + + + \Chill\MainBundle\DependencyInjection\Widget\WidgetFactoryInterface + + + + + $fieldDeclaration + + + + + the + + + + + interger + + + + + PermissionGroup + + + + + $createdAt + $createdBy + $updatedAt + $updatedBy + + + + + Agent + Report + + + + + array + protected array $label = []; + + + + + $this->authorizationChecker + AuthorizationChecker + type + type + type + type + + + + + type + + + + + type + + + + + $this->aggregatorsData + $this->aggregatorsData + + + $this->formatterData + type + type + type + + + + + type + + + + + + + + OptionsResolverInterface + + + + + $address + $address + + + + + $data + $data + + + + + OptionsResolverInterface + + + + + OptionsResolverInterface + + + + + OptionsResolverInterface + + + + + $center + $id + + + + + $array + $array + + + + + $id + $object + + + + + $id + $scope + + + + + OptionsResolverInterface + + + + + \Symfony\Component\Mailer\Exception\TransportExceptionInterface + + + + + $current + + + + + $itemPerPage + + + type + + + + + $query->buildParameters() + + + + + $query->buildParameters() + + + + + $onlyEnabled + + + + + AppKernel + + + + + require __DIR__ . '/../../../../../vendor/autoload.php' + + + + + type + + + + + $args + $args + $args + $params + $this->buildSelectParams($countOnly) + $this->fromClauseParams + $this->fromClauseParams + $this->jsonbMetadataParams + $this->pertinenceParams + $this->selectKeyParams + $this->selectParams + $this->whereClausesParams + $this->whereClausesParams + + + + + number + number + + + HasAdvancedSearchForm + HasAdvancedSearchForm[] + number + number + private $hasAdvancedFormSearchServices = []; + type + + + + + $subject + + + + + type + type + + + + + resolveScope + + + Center|Center[]|null + + + + + $address + + + + + $center + + + + + $collection + + + + + $date + + + + + $user + + + + + The + + + + + $addr + $addr + + + + + type + type + + + + + The + + + + + $widget + $widget + + + + + type + + + + + getClient + + + Query + + + + + public function setUp() + + + type + + + + + public function setUp() + + + + + public function setUp() + + + + + protected function tearDown() + public function setUp() + + + + + public function setUp() + public function tearDown() + + + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + $this->prophet + Prophecy\Prophet + + + + + CenterType + + + CenterType + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + unknown + + + + + public function setUp() + + + + + public function setUp() + + + + + protected function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + protected function setUp() + + + + + public function setUp() + + + + + protected function setUp() + + + + + unknown + + + + + type + type + + + + + type + + + + + type + + + + + \Chill\MainBundle\CRUD\Controller\string|string + + + Symfony\Component\HttpKernel\Exception\NotFoundHttpException + \Chill\PersonBundle\CRUD\Controller\QueryBuilder + \Chill\PersonBundle\CRUD\Controller\QueryBuilder + + + + + $sqls + + + + + $cfProvider->getCustomFieldByType($customField->getType()) + type + type + + + + + $participation + + + + + 'ChillPersonBundle:Person' + + + + + \Chill\MainBundle\CRUD\Controller\string|string + + + + + $person + + + + + $p + + + + + $qb + + + + + 'ChillPersonBundle:Person' + 'ChillPersonBundle:Person' + 'ChillPersonBundle:Person' + 'ChillPersonBundle:Person' + 'ChillPersonBundle:Person' + + + Chill\PersonBundle\Entity\Person + + + + + 'ChillCustomFieldsBundle:CustomFieldsDefaultGroup' + + + + + $sqls + InvalidArgumentException + InvalidArgumentException + + + + + \Chill\PersonBundle\DependencyInjection\containerBuilder + + + + + $a + + + + + $createdBy + + + Collection|SocialAction[] + Collection|SocialIssues[] + + + + + $createdAt + $createdBy + + + + + $createdAt + $createdBy + $updatedAt + $updatedBy + + + + + DateTimeImmutable|null + + + + + $createdAt + $updatedAt + $updatedBy + + + + + Person[] + + + + + $createdBy + + + Chill\MainBundle\Entity\Country + Chill\MainBundle\Entity\Country + Chill\MainBundle\Entity\Country + Report + type + + + + + $createdAt + $updatedAt + $updatedBy + + + + + $qb + + + + + 'ChillMainBundle:Country' + + + + $choiceSlug + + + + + EntityRepository + + + + + FormInterface[] + + + + + $id + $issue + + + 'ChillPersonBundle:Person' + + + + + OptionsResolverInterface + + + + + $qb + $qb + $qb + QueryBuilder + SocialAction + SocialAction + + + $action + $orderBy + + + + + AppKernel + + + + + require __DIR__ . '/../../../../../vendor/autoload.php' + + + + + require_once __DIR__ . '/../app/bootstrap.php.cache' + + + + + $period + + + + + $origin + + + + + $participation + + + + + ·\is_array('concerned') + + + + + $person + + + + + $person + + + + + $relation + + + + + $socialAction + + + + + $socialIssue + + + + + $person + $person + + + + + $socialAction + $socialAction + + + + + $socialIssue + $socialIssue + + + + + public function setUp() + public static function setUpBeforeClass() + + + AccompanyingPeriodRepository + stdClass + + + + + public function setUp() + public static function setUpBeforeClass() + + + + + public function setUp() + + + + + + public function setUp() + public function tearDown() + public static function setUpBeforeClass() + + + 'ChillMainBundle:Center' + 'ChillPersonBundle:AccompanyingPeriod\ClosingMotive' + LogicalException + + + Chill\PersonBundle\Entity\AccompanyingPeriod + Chill\PersonBundle\Entity\AccompanyingPeriod + + + + + protected function tearDown() + + + User + + + + + protected function setUp() + + + + + $this + + + public function setUp() + public static function setUpBeforeClass() + + + 'ChillPersonBundle:Person' + + + + + public static function tearDownAfterClass() + + + + + public function setUp() + public function tearDown() + + + 'ChillMainBundle:Country' + 'ChillPersonBundle:Person' + + + $person->getCountryOfBirth() + + + + + public function setUp() + public function tearDown() + + + 'ChillMainBundle:Country' + 'ChillPersonBundle:Person' + + + + + public function setUp() + public function tearDown() + + + 'ChillPersonBundle:Person' + + + + + public function setUp() + public function tearDown() + + + 'ChillPersonBundle:Person' + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + $participationL + + + getEndDate + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + public function setUp() + + + + + protected function setUp() + + + + + public function setUp() + + + + + protected function setUp() + + + + + protected function setUp() + + + + + protected function setUp() + + + + + protected function setUp() + + + + + protected function setUp() + + + + + protected function setUp() + + + + + 'ChillPersonBundle:AccompanyingPeriod' + + + + + $period + + + + + $period + + + + + $participations + + + + + $resources + + + + + $person + + + + + $household + + + + + $person + + + + + 'ChillCustomFieldsBundle:CustomField' + + + + + 'ChillCustomFieldsBundle:CustomFieldsGroup' + 'ChillCustomFieldsBundle:CustomFieldsGroup' + 'ChillCustomFieldsBundle:CustomFieldsGroup' + 'ChillCustomFieldsBundle:CustomFieldsGroup' + 'ChillCustomFieldsBundle:CustomFieldsGroup' + 'ChillPersonBundle:Person' + 'ChillPersonBundle:Person' + 'ChillPersonBundle:Person' + 'ChillPersonBundle:Person' + 'ChillPersonBundle:Person' + 'ChillPersonBundle:Person' + 'ChillReportBundle:Report' + 'ChillReportBundle:Report' + 'ChillReportBundle:Report' + 'ChillReportBundle:Report' + + + A + Response + Response + Response + Response + Response + Response + Response + Response + + + + + the + + + + + 'ChillMainBundle:Country' + + + + $choiceSlug + + + + + AppKernel + + + + + require __DIR__ . '/../../../../../vendor/autoload.php' + + + + + public function setUp() + + + + + type + + + public function setUp() + public static function setUpBeforeClass() + + + $client + $client + $client + $client + $client + $client + $client + $client + $client + $client + $client + $client + $client + $client + $client + $client + $client + $client + $client + $client + $client + $client + $this->getAuthenticatedClient('center a_administrative') + Client + \Chill\ReportBundle\Tests\Controller\Person + \SClientymfony\Component\BrowserKit\ + type + type + type + + + + + Exception + + + + + public function setUp() + public static function setUpBeforeClass() + + + type + type + type + + + + + public function setUp() + public function tearDown() + + + 'ChillCustomFieldsBundle:CustomFieldsGroup' + + + + + 'ChillReportBundle:Report' + + + + + $defaultScopeId + + + + + \Chill\TaskBundle\Controller\AbstractTask + + + $type + + + + + $definition->getClass()::getAssociatedWorkflowName() + $definition->getClass()::getAssociatedWorkflowName() + $definition->getClass()::getAssociatedWorkflowName() + + + + + json + private $currentStates = []; + + + + + dateinterval + dateinterval + dateinterval + dateinterval + dateinterval + dateinterval + + + + + datetime_immutable + datetime_immutable + datetime_immutable + + + + + type + type + + + + + \Chill\PersonBundle\Entity\Person|Chill\TaskBundle\Entity\AbstractTask|null + + + + + $this->cachePool + $this->cachePool + $this->cachePool + $this->cachePool + CacheItempPoolInterface + + + + + protected function setUp() + + + + + $taggedService->getClass()::getKey() + + + + + $createdAt + $updatedAt + $updatedBy + + + + + type + + + type + + + + + $thirdParty + + + + + protected function setUp() + + + + + $object + $object + $object + $object->url + $object->url + $object->url + + + diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 000000000..be17d1d86 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/src/Bundle/ChillActivityBundle/Controller/ActivityController.php b/src/Bundle/ChillActivityBundle/Controller/ActivityController.php index 863190a9f..6db1f6945 100644 --- a/src/Bundle/ChillActivityBundle/Controller/ActivityController.php +++ b/src/Bundle/ChillActivityBundle/Controller/ActivityController.php @@ -39,6 +39,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Serializer\SerializerInterface; + use function array_key_exists; final class ActivityController extends AbstractController @@ -307,8 +308,10 @@ final class ActivityController extends AbstractController $activityData = $request->query->get('activityData'); } - if (!$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType - || !$activityType->isActive()) { + if ( + !$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType + || !$activityType->isActive() + ) { $params = $this->buildParamsToUrl($person, $accompanyingPeriod); if (null !== $activityData) { diff --git a/src/Bundle/ChillActivityBundle/Controller/ActivityReasonCategoryController.php b/src/Bundle/ChillActivityBundle/Controller/ActivityReasonCategoryController.php index 7da49a823..3d5591b77 100644 --- a/src/Bundle/ChillActivityBundle/Controller/ActivityReasonCategoryController.php +++ b/src/Bundle/ChillActivityBundle/Controller/ActivityReasonCategoryController.php @@ -14,7 +14,6 @@ namespace Chill\ActivityBundle\Controller; 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; diff --git a/src/Bundle/ChillActivityBundle/Controller/ActivityReasonController.php b/src/Bundle/ChillActivityBundle/Controller/ActivityReasonController.php index c656fe7a7..d69347ae9 100644 --- a/src/Bundle/ChillActivityBundle/Controller/ActivityReasonController.php +++ b/src/Bundle/ChillActivityBundle/Controller/ActivityReasonController.php @@ -14,7 +14,6 @@ namespace Chill\ActivityBundle\Controller; 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; diff --git a/src/Bundle/ChillActivityBundle/DataFixtures/ORM/LoadActivitytACL.php b/src/Bundle/ChillActivityBundle/DataFixtures/ORM/LoadActivitytACL.php index cb2d46d49..f61e15f1c 100644 --- a/src/Bundle/ChillActivityBundle/DataFixtures/ORM/LoadActivitytACL.php +++ b/src/Bundle/ChillActivityBundle/DataFixtures/ORM/LoadActivitytACL.php @@ -19,6 +19,7 @@ use Chill\MainBundle\Entity\RoleScope; use Doctrine\Common\DataFixtures\AbstractFixture; use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Persistence\ObjectManager; + use function in_array; /** diff --git a/src/Bundle/ChillActivityBundle/DependencyInjection/ChillActivityExtension.php b/src/Bundle/ChillActivityBundle/DependencyInjection/ChillActivityExtension.php index e1c657947..39c7eab36 100644 --- a/src/Bundle/ChillActivityBundle/DependencyInjection/ChillActivityExtension.php +++ b/src/Bundle/ChillActivityBundle/DependencyInjection/ChillActivityExtension.php @@ -41,6 +41,7 @@ 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) diff --git a/src/Bundle/ChillActivityBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillActivityBundle/DependencyInjection/Configuration.php index f4b9d177c..4e4e6f3c6 100644 --- a/src/Bundle/ChillActivityBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillActivityBundle/DependencyInjection/Configuration.php @@ -13,6 +13,7 @@ namespace Chill\ActivityBundle\DependencyInjection; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; + use function is_int; /** diff --git a/src/Bundle/ChillActivityBundle/Entity/Activity.php b/src/Bundle/ChillActivityBundle/Entity/Activity.php index 183b56225..77f650ce4 100644 --- a/src/Bundle/ChillActivityBundle/Entity/Activity.php +++ b/src/Bundle/ChillActivityBundle/Entity/Activity.php @@ -47,7 +47,8 @@ use Symfony\Component\Serializer\Annotation\SerializedName; * }) * @ActivityValidator\ActivityValidity * - * @UserCircleConsistency( + * TODO see if necessary + * UserCircleConsistency( * "CHILL_ACTIVITY_SEE_DETAILS", * getUserFunction="getUser", * path="scope") diff --git a/src/Bundle/ChillActivityBundle/Entity/ActivityType.php b/src/Bundle/ChillActivityBundle/Entity/ActivityType.php index f0e412a8c..5ad692bf4 100644 --- a/src/Bundle/ChillActivityBundle/Entity/ActivityType.php +++ b/src/Bundle/ChillActivityBundle/Entity/ActivityType.php @@ -163,16 +163,6 @@ class ActivityType */ private int $personVisible = self::FIELD_REQUIRED; - /** - * @ORM\Column(type="string", nullable=false, options={"default": ""}) - */ - private string $placeLabel = ''; - - /** - * @ORM\Column(type="smallint", nullable=false, options={"default": 1}) - */ - private int $placeVisible = self::FIELD_OPTIONAL; - /** * @ORM\Column(type="string", nullable=false, options={"default": ""}) */ @@ -406,16 +396,6 @@ class ActivityType return $this->personVisible; } - public function getPlaceLabel(): string - { - return $this->placeLabel; - } - - public function getPlaceVisible(): int - { - return $this->placeVisible; - } - public function getReasonsLabel(): string { return $this->reasonsLabel; @@ -688,20 +668,6 @@ class ActivityType return $this; } - public function setPlaceLabel(string $placeLabel): self - { - $this->placeLabel = $placeLabel; - - return $this; - } - - public function setPlaceVisible(int $placeVisible): self - { - $this->placeVisible = $placeVisible; - - return $this; - } - public function setReasonsLabel(string $reasonsLabel): self { $this->reasonsLabel = $reasonsLabel; diff --git a/src/Bundle/ChillActivityBundle/EntityListener/ActivityEntityListener.php b/src/Bundle/ChillActivityBundle/EntityListener/ActivityEntityListener.php new file mode 100644 index 000000000..ab370e89e --- /dev/null +++ b/src/Bundle/ChillActivityBundle/EntityListener/ActivityEntityListener.php @@ -0,0 +1,77 @@ +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); + } + + foreach ($associatedThirdparties as $thirdparty) { + $newAction->setHandlingThierparty($thirdparty); + } + $this->em->persist($newAction); + $this->em->flush(); + } + } + } +} diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityReasonAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityReasonAggregator.php index 56306d90a..19811f584 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityReasonAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityReasonAggregator.php @@ -25,6 +25,7 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Validator\Context\ExecutionContextInterface; + use function array_key_exists; use function count; diff --git a/src/Bundle/ChillActivityBundle/Export/Export/ListActivity.php b/src/Bundle/ChillActivityBundle/Export/Export/ListActivity.php index 8fcb6ec6f..07153fc2c 100644 --- a/src/Bundle/ChillActivityBundle/Export/Export/ListActivity.php +++ b/src/Bundle/ChillActivityBundle/Export/Export/ListActivity.php @@ -27,6 +27,7 @@ use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Context\ExecutionContextInterface; + use function array_key_exists; use function count; use function in_array; @@ -189,7 +190,9 @@ class ListActivity implements ListInterface public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) { - $centers = array_map(static function ($el) { return $el['center']; }, $acl); + $centers = array_map(static function ($el) { + return $el['center']; + }, $acl); // throw an error if any fields are present if (!array_key_exists('fields', $data)) { diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ActivityReasonFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ActivityReasonFilter.php index ff0767116..467471a8d 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/ActivityReasonFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ActivityReasonFilter.php @@ -25,6 +25,7 @@ use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Validator\Context\ExecutionContextInterface; + use function array_key_exists; use function count; diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ActivityTypeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ActivityTypeFilter.php index 0b283632a..d3f35a746 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/ActivityTypeFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ActivityTypeFilter.php @@ -24,6 +24,7 @@ use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Validator\Context\ExecutionContextInterface; + use function count; class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInterface diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/PersonHavingActivityBetweenDateFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/PersonHavingActivityBetweenDateFilter.php index 55b1337bf..f162ed2ef 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/PersonHavingActivityBetweenDateFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/PersonHavingActivityBetweenDateFilter.php @@ -31,6 +31,7 @@ use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormInterface; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface; + use function count; class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInterface, FilterInterface diff --git a/src/Bundle/ChillActivityBundle/Form/ActivityType.php b/src/Bundle/ChillActivityBundle/Form/ActivityType.php index d332acdcb..7c5e0e410 100644 --- a/src/Bundle/ChillActivityBundle/Form/ActivityType.php +++ b/src/Bundle/ChillActivityBundle/Form/ActivityType.php @@ -48,6 +48,7 @@ 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 function in_array; class ActivityType extends AbstractType @@ -260,6 +261,10 @@ class ActivityType extends AbstractType 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) @@ -282,6 +287,10 @@ class ActivityType extends AbstractType 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) @@ -315,6 +324,10 @@ class ActivityType extends AbstractType 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) @@ -332,7 +345,7 @@ class ActivityType extends AbstractType return ''; } - return $location->getId(); + return (string) $location->getId(); }, function (?string $id): ?Location { return $this->om->getRepository(Location::class)->findOneBy(['id' => (int) $id]); @@ -379,7 +392,7 @@ class ActivityType extends AbstractType $timezoneUTC = new DateTimeZone('GMT'); /** @var DateTime $data */ $data = $formEvent->getData() === null ? - DateTime::createFromFormat('U', 300) : + DateTime::createFromFormat('U', '300') : $formEvent->getData(); $seconds = $data->getTimezone()->getOffset($data); $data->setTimeZone($timezoneUTC); diff --git a/src/Bundle/ChillActivityBundle/Form/ActivityTypeType.php b/src/Bundle/ChillActivityBundle/Form/ActivityTypeType.php index 26148c340..28947d72b 100644 --- a/src/Bundle/ChillActivityBundle/Form/ActivityTypeType.php +++ b/src/Bundle/ChillActivityBundle/Form/ActivityTypeType.php @@ -55,7 +55,7 @@ class ActivityTypeType extends AbstractType ]); $fields = [ - 'persons', 'user', 'date', 'place', 'persons', + 'persons', 'user', 'date', 'location', 'persons', 'thirdParties', 'durationTime', 'travelTime', 'attendee', 'reasons', 'comment', 'sentReceived', 'documents', 'emergency', 'socialIssues', 'socialActions', 'users', diff --git a/src/Bundle/ChillActivityBundle/Menu/AccompanyingCourseMenuBuilder.php b/src/Bundle/ChillActivityBundle/Menu/AccompanyingCourseMenuBuilder.php index b0e91a3a5..636d03488 100644 --- a/src/Bundle/ChillActivityBundle/Menu/AccompanyingCourseMenuBuilder.php +++ b/src/Bundle/ChillActivityBundle/Menu/AccompanyingCourseMenuBuilder.php @@ -36,8 +36,10 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface { $period = $parameters['accompanyingCourse']; - if (AccompanyingPeriod::STEP_DRAFT !== $period->getStep() - && $this->security->isGranted(ActivityVoter::SEE, $period)) { + if ( + AccompanyingPeriod::STEP_DRAFT !== $period->getStep() + && $this->security->isGranted(ActivityVoter::SEE, $period) + ) { $menu->addChild($this->translator->trans('Activity'), [ 'route' => 'chill_activity_activity_list', 'routeParameters' => [ diff --git a/src/Bundle/ChillActivityBundle/Menu/AdminMenuBuilder.php b/src/Bundle/ChillActivityBundle/Menu/AdminMenuBuilder.php index 58b0825dc..13c3b3e6a 100644 --- a/src/Bundle/ChillActivityBundle/Menu/AdminMenuBuilder.php +++ b/src/Bundle/ChillActivityBundle/Menu/AdminMenuBuilder.php @@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Menu; use Chill\MainBundle\Routing\LocalMenuBuilderInterface; use Knp\Menu\MenuItem; use Symfony\Component\Security\Core\Security; + use function in_array; final class AdminMenuBuilder implements LocalMenuBuilderInterface diff --git a/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php b/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php index e80dc5522..48f750c26 100644 --- a/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php +++ b/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php @@ -22,6 +22,7 @@ use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Security; + use function count; use function in_array; @@ -167,7 +168,9 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte $reachableScopes = $this->authorizationHelper->getReachableScopes($this->tokenStorage->getToken()->getUser(), $role, $center); // we get the ids for those scopes $reachablesScopesId = array_map( - static function (Scope $scope) { return $scope->getId(); }, + static function (Scope $scope) { + return $scope->getId(); + }, $reachableScopes ); diff --git a/src/Bundle/ChillActivityBundle/Repository/ActivityRepository.php b/src/Bundle/ChillActivityBundle/Repository/ActivityRepository.php index 1493a45ae..312d601ad 100644 --- a/src/Bundle/ChillActivityBundle/Repository/ActivityRepository.php +++ b/src/Bundle/ChillActivityBundle/Repository/ActivityRepository.php @@ -31,6 +31,8 @@ class ActivityRepository extends ServiceEntityRepository } /** + * @deprecated use @see{ActivityACLAwareRepositoryInterface::findByAccompanyingPeriod} + * * @return Activity[] */ public function findByAccompanyingPeriod(AccompanyingPeriod $period, array $scopes, ?bool $allowNullScope = false, ?int $limit = 100, ?int $offset = 0, array $orderBy = ['date' => 'desc']): array diff --git a/src/Bundle/ChillActivityBundle/Resources/public/chill/chillactivity.scss b/src/Bundle/ChillActivityBundle/Resources/public/chill/chillactivity.scss index 28c02e23e..275f67950 100644 --- a/src/Bundle/ChillActivityBundle/Resources/public/chill/chillactivity.scss +++ b/src/Bundle/ChillActivityBundle/Resources/public/chill/chillactivity.scss @@ -24,14 +24,16 @@ div.new-activity-select-type { } //// ACTIVITY LIST PAGE -// precise badge-title specific details +// precise dashboard specific details +p.date-label { + display: inline-block; + margin: 0 0.5em 0 0; + font-weight: 700; + font-size: 18pt; +} +div.dashboard, h2.badge-title { - div.duration { - font-size: smaller; - padding-left: 1em; - margin-top: 1em; - } ul.list-content { font-size: 70%; list-style-type: none; @@ -39,16 +41,13 @@ h2.badge-title { margin: 0; li { margin-bottom: 0.2em; - // exception: change bg color for action badges above badge-title + // exception: change bg color for action badges above dashboard .bg-light { background-color: $chill-light-gray !important; } } } } -div.main { - padding: 1em; -} //// ACTIVITY SHOW AND FORM PAGES // Exceptions for flex-bloc in concerned-groups diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/api.js b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/api.js index 8d4bcac3b..edc0a616c 100644 --- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/api.js +++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/api.js @@ -17,6 +17,14 @@ const getLocations = () => fetchResults('/api/1.0/main/location.json'); const getLocationTypes = () => fetchResults('/api/1.0/main/location-type.json'); +const getUserCurrentLocation = + () => fetch('/api/1.0/main/user-current-location.json') + .then(response => { + if (response.ok) { return response.json(); } + throw Error('Error with request resource response'); + }); + + /* * Load Location Type by defaultFor * @param {string} entity - can be "person" or "thirdparty" @@ -48,5 +56,6 @@ export { getLocations, getLocationTypes, getLocationTypeByDefaultFor, - postLocation + postLocation, + getUserCurrentLocation }; diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/ConcernedGroups.vue b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/ConcernedGroups.vue index 853b43eb0..49b53c8cb 100644 --- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/ConcernedGroups.vue +++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/ConcernedGroups.vue @@ -11,7 +11,7 @@
    -
      +
      • {{ p.text }}
      • diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/ConcernedGroups/PersonBadge.vue b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/ConcernedGroups/PersonBadge.vue index a13e672c2..de78c9b85 100644 --- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/ConcernedGroups/PersonBadge.vue +++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/ConcernedGroups/PersonBadge.vue @@ -1,8 +1,7 @@ diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location.vue b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location.vue index 9a4b78334..50eb14799 100644 --- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location.vue +++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location.vue @@ -15,7 +15,7 @@ :searchable="true" :placeholder="$t('activity.choose_location')" :custom-label="customLabel" - :options="locations" + :options="availableLocations" group-values="locations" group-label="locationGroup" v-model="location" @@ -32,7 +32,7 @@ import { mapState, mapGetters } from "vuex"; import VueMultiselect from "vue-multiselect"; import NewLocation from "./Location/NewLocation.vue"; -import { getLocations, getLocationTypeByDefaultFor } from "../api.js"; +import { getLocations, getLocationTypeByDefaultFor, getUserCurrentLocation } from "../api.js"; export default { name: "Location", @@ -40,13 +40,8 @@ export default { NewLocation, VueMultiselect, }, - data() { - return { - locations: [], - }; - }, computed: { - ...mapState(["activity"]), + ...mapState(["activity", "availableLocations"]), ...mapGetters(["suggestedEntities"]), location: { get() { @@ -57,53 +52,6 @@ export default { }, }, }, - mounted() { - getLocations().then( - (results) => { - getLocationTypeByDefaultFor('person').then( - (personLocationType) => { - if (personLocationType) { - const personLocation = this.makeAccompanyingPeriodLocation(personLocationType); - const concernedPersonsLocation = - this.makeConcernedPersonsLocation(personLocationType); - getLocationTypeByDefaultFor('thirdparty').then( - thirdpartyLocationType => { - const concernedThirdPartiesLocation = - this.makeConcernedThirdPartiesLocation(thirdpartyLocationType); - this.locations = [ - { - locationGroup: 'Localisation du parcours', - locations: [personLocation] - }, - { - locationGroup: 'Parties concernées', - locations: [...concernedPersonsLocation, ...concernedThirdPartiesLocation] - }, - { - locationGroup: 'Autres localisations', - locations: results - } - ]; - } - ) - } else { - this.locations = [ - { - locationGroup: 'Localisations', - locations: response.results - } - ]; - } - if (window.default_location_id) { - let location = this.locations.filter( - (l) => l.id === window.default_location_id - ); - this.$store.dispatch("updateLocation", location); - } - } - ) - }) - }, methods: { labelAccompanyingCourseLocation(value) { return `${value.address.text} (${value.locationType.title.fr})` @@ -117,58 +65,6 @@ export default { : value.locationType.title.fr : ''; }, - makeConcernedPersonsLocation(locationType) { - let locations = []; - this.suggestedEntities.forEach( - (e) => { - if (e.type === 'person' && e.current_household_address !== null){ - locations.push({ - type: 'location', - id: -this.suggestedEntities.indexOf(e)*10, - onthefly: true, - name: e.text, - address: { - id: e.current_household_address.address_id, - }, - locationType: locationType - }); - } - } - ) - return locations; - }, - makeConcernedThirdPartiesLocation(locationType) { - let locations = []; - this.suggestedEntities.forEach( - (e) => { - if (e.type === 'thirdparty' && e.address !== null){ - locations.push({ - type: 'location', - id: -this.suggestedEntities.indexOf(e)*10, - onthefly: true, - name: e.text, - address: { id: e.address.address_id }, - locationType: locationType - }); - } - } - ) - return locations; - }, - makeAccompanyingPeriodLocation(locationType) { - const accPeriodLocation = this.activity.accompanyingPeriod.location; - return { - type: 'location', - id: -1, - onthefly: true, - name: '__AccompanyingCourseLocation__', - address: { - id: accPeriodLocation.address_id, - text: `${accPeriodLocation.text} - ${accPeriodLocation.postcode.code} ${accPeriodLocation.postcode.name}` - }, - locationType: locationType - } - } }, }; diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.js b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.js index 5b6297553..4bf70b006 100644 --- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.js +++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.js @@ -1,22 +1,23 @@ import 'es6-promise/auto'; import { createStore } from 'vuex'; import { postLocation } from './api'; +import prepareLocations from './store.locations.js'; const debug = process.env.NODE_ENV !== 'production'; //console.log('window.activity', window.activity); const addIdToValue = (string, id) => { - let array = string ? string.split(',') : []; - array.push(id.toString()); - let str = array.join(); - return str; + let array = string ? string.split(',') : []; + array.push(id.toString()); + let str = array.join(); + return str; }; const removeIdFromValue = (string, id) => { - let array = string.split(','); - array = array.filter(el => el !== id.toString()); - let str = array.join(); - return str; + let array = string.split(','); + array = array.filter(el => el !== id.toString()); + let str = array.join(); + return str; }; const store = createStore({ @@ -25,6 +26,7 @@ const store = createStore({ activity: window.activity, socialIssuesOther: [], socialActionsList: [], + availableLocations: [], }, getters: { suggestedEntities(state) { @@ -50,9 +52,9 @@ const store = createStore({ return state.activity.activityType.personsVisible === 0 ? [] : state.activity.accompanyingPeriod.participations - .filter((p) => p.endDate === null) - .map((p) => p.person) - .filter((p) => !existingPersonIds.includes(p.id)); + .filter((p) => p.endDate === null) + .map((p) => p.person) + .filter((p) => !existingPersonIds.includes(p.id)); }, suggestedRequestor(state) { if (state.activity.accompanyingPeriod.requestor === null) { @@ -78,8 +80,8 @@ const store = createStore({ return state.activity.activityType.usersVisible === 0 ? [] : [state.activity.accompanyingPeriod.user].filter( - (u) => u !== null && !existingUserIds.includes(u.id) - ); + (u) => u !== null && !existingUserIds.includes(u.id) + ); }, suggestedResources(state) { const resources = state.activity.accompanyingPeriod.resources; @@ -200,6 +202,9 @@ const store = createStore({ console.log("### mutation: updateLocation", value); state.activity.location = value; }, + addAvailableLocationGroup(state, group) { + state.availableLocations.push(group); + } }, actions: { addIssueSelected({ commit }, issue) { @@ -335,4 +340,6 @@ const store = createStore({ }, }); +prepareLocations(store); + export default store; diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.locations.js b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.locations.js new file mode 100644 index 000000000..311bdc219 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.locations.js @@ -0,0 +1,123 @@ +import {getLocations, getLocationTypeByDefaultFor, getUserCurrentLocation} from "./api"; + +const makeConcernedPersonsLocation = (locationType, store) => { + let locations = []; + store.getters.suggestedEntities.forEach( + (e) => { + if (e.type === 'person' && e.current_household_address !== null){ + locations.push({ + type: 'location', + id: -store.getters.suggestedEntities.indexOf(e)*10, + onthefly: true, + name: e.text, + address: { + id: e.current_household_address.address_id, + }, + locationType: locationType + }); + } + } + ) + return locations; +}; +const makeConcernedThirdPartiesLocation = (locationType, store) => { + let locations = []; + store.getters.suggestedEntities.forEach( + (e) => { + if (e.type === 'thirdparty' && e.address !== null){ + locations.push({ + type: 'location', + id: -store.getters.suggestedEntities.indexOf(e)*10, + onthefly: true, + name: e.text, + address: { id: e.address.address_id }, + locationType: locationType + }); + } + } + ) + return locations; +}; +const makeAccompanyingPeriodLocation = (locationType, store) => { + const accPeriodLocation = store.state.activity.accompanyingPeriod.location; + return { + type: 'location', + id: -1, + onthefly: true, + name: '__AccompanyingCourseLocation__', + address: { + id: accPeriodLocation.address_id, + text: `${accPeriodLocation.text} - ${accPeriodLocation.postcode.code} ${accPeriodLocation.postcode.name}` + }, + locationType: locationType + } +}; + +export default function prepareLocations(store) { + +// find the locations + let allLocations = getLocations().then( + (results) => { + store.commit('addAvailableLocationGroup', { + locationGroup: 'Autres localisations', + locations: results + }); + } + ); + + let currentLocation = getUserCurrentLocation().then( + userCurrentLocation => { + if (null !== userCurrentLocation) { + store.commit('addAvailableLocationGroup', { + locationGroup: 'Ma localisation', + locations: [userCurrentLocation] + }); + } + } + ); + + let partiesLocations = [], partyPromise; + ['person', 'thirdparty'].forEach(kind => { + partyPromise = getLocationTypeByDefaultFor(kind).then( + (kindLocationType) => { + if (kindLocationType) { + let concernedKindLocations; + if (kind === 'person') { + concernedKindLocations = makeConcernedPersonsLocation(kindLocationType, store); + // add location for the parcours into suggestions + const personLocation = makeAccompanyingPeriodLocation(kindLocationType, store); + store.commit('addAvailableLocationGroup', { + locationGroup: 'Localisation du parcours', + locations: [personLocation] + }); + } else { + concernedKindLocations = makeConcernedThirdPartiesLocation(kindLocationType, store); + } + + store.commit('addAvailableLocationGroup', { + locationGroup: kind === 'person' ? 'Usagers concernés' : 'Tiers concernés', + locations: concernedKindLocations, + }); + } + } + ); + partiesLocations.push(partyPromise); + }); + +// when all location are loaded + Promise.all([allLocations, currentLocation, ...partiesLocations]).then(() => { + console.log('current location in activity', store.state.activity.location); + console.log('default loation id', window.default_location_id); + if (window.default_location_id) { + for (let group of store.state.availableLocations) { + console.log(group); + let location = group.locations.find((l) => l.id === window.default_location_id); + console.log(location); + if (location !== undefined) { + store.dispatch('updateLocation', location); + break; + } + } + } + }); +} diff --git a/src/Bundle/ChillActivityBundle/Resources/test/Fixtures/App/web/app_dev.php b/src/Bundle/ChillActivityBundle/Resources/test/Fixtures/App/web/app_dev.php index 914d09ffd..e171c8521 100644 --- a/src/Bundle/ChillActivityBundle/Resources/test/Fixtures/App/web/app_dev.php +++ b/src/Bundle/ChillActivityBundle/Resources/test/Fixtures/App/web/app_dev.php @@ -18,7 +18,8 @@ use Symfony\Component\HttpFoundation\Request; // This check prevents access to debug front controllers that are deployed by accident to production servers. // Feel free to remove this, extend it, or make something more sophisticated. -if (isset($_SERVER['HTTP_CLIENT_IP']) +if ( + isset($_SERVER['HTTP_CLIENT_IP']) || isset($_SERVER['HTTP_X_FORWARDED_FOR']) || !(in_array($_SERVER['REMOTE_ADDR'], ['127.0.0.1', 'fe80::1', '::1'], true) || \PHP_SAPI === 'cli-server') ) { diff --git a/src/Bundle/ChillActivityBundle/Resources/views/Activity/activity-badge-title.html.twig b/src/Bundle/ChillActivityBundle/Resources/views/Activity/activity-badge-title.html.twig deleted file mode 100644 index f51854163..000000000 --- a/src/Bundle/ChillActivityBundle/Resources/views/Activity/activity-badge-title.html.twig +++ /dev/null @@ -1,110 +0,0 @@ -

        - - - {% if activity.date %} -

        {{ activity.date|format_date('short') }}

        - {% endif %} - -
        - {% if activity.durationTime and t.durationTimeVisible %} -

        - - {{ activity.durationTime|date('H:i') }} -

        - {% endif %} - - {% if activity.travelTime and t.travelTimeVisible %} -

        - - {{ activity.travelTime|date('H:i') }} -

        - {% endif %} -
        - -
        - - - {{ activity.type.name | localize_translatable_string }} - - {% if activity.emergency %} - {{ 'Emergency'|trans|upper }} - {% endif %} - -
          - - {% if activity.sentReceived is not empty and t.sentReceivedVisible %} -
        • - {{ 'Sent received'|trans ~ ' : ' }} - {{ activity.sentReceived|capitalize|trans }} -
        • - {% endif %} - - {% if activity.location and t.locationVisible %} -
        • - {{ 'location'|trans ~ ': ' }} - - {{ activity.location.locationType.title|localize_translatable_string }} - {{ activity.location.name }} - -
        • - {% endif %} - - {% if activity.user and t.userVisible %} -
        • - {{ 'Referrer'|trans ~ ': ' }} - {{ activity.user.usernameCanonical }} -
        • - {% endif %} - -
        • - {{ 'Participants'|trans ~ ' : ' }} - {% for p in activity.personsAssociated %} - {{ p|chill_entity_render_box }} - {% endfor %} -
        • -
        - -
          - {%- if t.reasonsVisible -%} - {%- if activity.reasons is not empty -%} -
        • - {% for r in activity.reasons %} - {{ r|chill_entity_render_box }} - {% endfor %} -
        • - {%- endif -%} - {% endif %} - {%- if t.socialIssuesVisible %} - {%- if activity.socialIssues is not empty -%} - - {%- endif -%} - {% endif %} - {%- if t.socialActionsVisible -%} - {%- if activity.socialActions is not empty -%} - - {%- endif -%} - {% endif %} -
        -
        -

        - -{% if context == 'person' and activity.accompanyingPeriod is not empty %} -
        - - -
        -{% endif %} - diff --git a/src/Bundle/ChillActivityBundle/Resources/views/Activity/concernedGroups.html.twig b/src/Bundle/ChillActivityBundle/Resources/views/Activity/concernedGroups.html.twig index f6b052265..d6d0ed43d 100644 --- a/src/Bundle/ChillActivityBundle/Resources/views/Activity/concernedGroups.html.twig +++ b/src/Bundle/ChillActivityBundle/Resources/views/Activity/concernedGroups.html.twig @@ -3,6 +3,14 @@ {{ path(pathname, parms) }} {% endmacro %} +{% macro insert_onthefly(type, entity) %} + {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { + action: 'show', displayBadge: true, + targetEntity: { name: type, id: entity.id }, + buttonText: entity|chill_entity_render_string + } %} +{% endmacro %} + {% macro computeWidth(nbBlocks) %} {{ 'flex-basis: ' ~ (100 / nbBlocks)|round(1) ~ '%;' }} {% endmacro %} @@ -13,6 +21,7 @@ {% set blocks = blocks|merge([{ 'title': 'Others persons'|trans, 'items': entity.persons, + 'type': 'person', 'path' : 'chill_person_view', 'key' : 'person_id' }]) %} @@ -20,11 +29,13 @@ {% set blocks = blocks|merge([{ 'title': 'Persons in accompanying course'|trans, 'items': entity.personsAssociated, + 'type': 'person', 'path' : 'chill_person_view', 'key' : 'person_id' },{ 'title': 'Third persons'|trans, 'items': entity.personsNotAssociated, + 'type': 'person', 'path' : 'chill_person_view', 'key' : 'person_id', }]) %} @@ -34,6 +45,7 @@ {% set blocks = blocks|merge([{ 'title': 'Third parties'|trans, 'items': entity.thirdParties, + 'type': 'thirdparty', 'path' : 'chill_crud_3party_3party_view', 'key' : 'id', }]) %} @@ -42,6 +54,7 @@ {% set blocks = blocks|merge([{ 'title': 'Users concerned'|trans, 'items': entity.users, + 'type': 'user', 'key' : 'id', }]) %} {% endif %} @@ -59,22 +72,12 @@
          {% for item in bloc.items %}
        • - {% if bloc.path is defined %} - - - {{ item|chill_entity_render_box({ - 'render': 'raw', - 'addAltNames': false - }) }} + {% if bloc.type == 'user' %} + + {{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false }) }} - {% else %} - - {{ item|chill_entity_render_box({ - 'render': 'raw', - 'addAltNames': false - }) }} - + {{ _self.insert_onthefly(bloc.type, item) }} {% endif %}
        • {% endfor %} @@ -96,20 +99,12 @@
            {% for item in bloc.items %}
          • - {% if bloc.path is defined %} - - - {{ item|chill_entity_render_box({ - 'render': 'raw', - 'addAltNames': false - }) }} + {% if bloc.type == 'user' %} + + {{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false }) }} - {% else %} - {{ item|chill_entity_render_box({ - 'render': 'raw', - 'addAltNames': false - }) }} + {{ _self.insert_onthefly(bloc.type, item) }} {% endif %}
          • {% endfor %} @@ -126,24 +121,18 @@
            {% if bloc.items|length > 0 %}
            -

            {{ bloc.title }}

            +

            {{ bloc.title }}

            {% for item in bloc.items %} - - {% if bloc.path is defined %} - - {{ item|chill_entity_render_box({ - 'render': 'raw', - 'addAltNames': false - }) }} - + + {% if bloc.type == 'user' %} + + {{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false }) }} + {% else %} - {{ item|chill_entity_render_box({ - 'render': 'raw', - 'addAltNames': false - }) }} + {{ _self.insert_onthefly(bloc.type, item) }} {% endif %} diff --git a/src/Bundle/ChillActivityBundle/Resources/views/Activity/edit.html.twig b/src/Bundle/ChillActivityBundle/Resources/views/Activity/edit.html.twig index b3da40e96..235a5b7f2 100644 --- a/src/Bundle/ChillActivityBundle/Resources/views/Activity/edit.html.twig +++ b/src/Bundle/ChillActivityBundle/Resources/views/Activity/edit.html.twig @@ -1,5 +1,12 @@ -

            {{ "Update activity"|trans }}

            -

            {{ entity.type.name|localize_translatable_string }}

            +

            + {{ "Update activity"|trans }} +

            +

            + + + {{ entity.type.name | localize_translatable_string }} + +

            {{ form_start(edit_form) }} {{ form_errors(edit_form) }} @@ -37,7 +44,7 @@ {% endif %} {%- if edit_form.persons is defined or edit_form.thirdParties is defined or edit_form.users is defined -%} -

            {{ 'Concerned groups'|trans }}

            +

            {{ 'Concerned groups'|trans }}

            {%- if edit_form.persons is defined -%} {{ form_widget(edit_form.persons) }} @@ -53,7 +60,7 @@ {% endif %} -

            {{ 'Activity data'|trans }}

            +

            {{ 'Activity data'|trans }}

            {%- if edit_form.date is defined -%} {{ form_row(edit_form.date) }} @@ -73,7 +80,6 @@ {% endif %} {%- if edit_form.comment is defined -%} - {# TODO .. public and private #} {{ form_row(edit_form.comment) }} {% endif %} @@ -97,16 +103,16 @@ {% set accompanying_course_id = accompanyingCourse.id %} {% endif %} - -{{ form_end(edit_form) }} + +{{ form_end(edit_form) }} {# {{ form(delete_form) }} #} diff --git a/src/Bundle/ChillActivityBundle/Resources/views/Activity/list.html.twig b/src/Bundle/ChillActivityBundle/Resources/views/Activity/list.html.twig index 7c75f5bf0..3f49e67cc 100644 --- a/src/Bundle/ChillActivityBundle/Resources/views/Activity/list.html.twig +++ b/src/Bundle/ChillActivityBundle/Resources/views/Activity/list.html.twig @@ -10,49 +10,196 @@ {% for activity in activities %} {% set t = activity.type %}
            +
            - {% include '@ChillActivity/Activity/activity-badge-title.html.twig' %} +
            +
            +
            + {% if activity.date %} +

            + {{ activity.date|format_date('short') }} +

            + {% endif %} +
            +
            +

            + + + {{ activity.type.name | localize_translatable_string }} + + {% if activity.emergency %} + {{ 'Emergency'|trans|upper }} + {% endif %} + +

            +
            +
            +
            - {% if activity.comment.comment is not empty - or activity.persons|length > 0 - or activity.thirdParties|length > 0 - or activity.users|length > 0 - %} -
            - {% if activity.comment.comment is not empty %} - {{ activity.comment|chill_entity_render_box({ - 'disable_markdown': false, - 'limit_lines': 3, - 'metadata': false, - }) }} - {% endif %} +
            +
            + {% if activity.location and t.locationVisible %} +
            +

            {{ 'location'|trans }}

            +
            +

            + {{ activity.location.locationType.title|localize_translatable_string }} + {{ activity.location.name }} +

            +
            +
            + {% endif %} + + {% if activity.sentReceived is not empty and t.sentReceivedVisible %} +
            +

            {{ 'Sent received'|trans }}

            +
            +

            + {{ activity.sentReceived|capitalize|trans }} +

            +
            +
            + {% endif %} + + {% if activity.user and t.userVisible %} +
            +

            {{ 'Referrer'|trans }}

            +
            +

            + {{ activity.user.usernameCanonical|chill_entity_render_string|capitalize }} +

            +
            +
            + {% endif %} +
            {% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with { 'context': context, - 'with_display': 'row', + 'with_display': 'wrap-list', 'entity': activity, 'badge_person': true } %} + +
            + {%- if activity.reasons is not empty and t.reasonsVisible -%} +
            +
            +

            {{ 'Reasons'|trans }}

            +
            +
            + {% for r in activity.reasons %} +

            + {{ r|chill_entity_render_box }} +

            + {% endfor %} +
            +
            + {% endif %} + + {%- if activity.socialIssues is not empty and t.socialIssuesVisible -%} +
            +
            +

            {{ 'Social issues'|trans }}

            +
            +
            + {% for r in activity.socialIssues %} + + {% endfor %} +
            +
            + {% endif %} + + {%- if activity.socialActions is not empty and t.socialActionsVisible -%} +
            +
            +

            {{ 'Social actions'|trans }}

            +
            +
            + {% for r in activity.socialActions %} + + {% endfor %} +
            +
            + {% endif %} + + {% if activity.comment.comment is not empty and is_granted('CHILL_ACTIVITY_SEE_DETAILS', activity) %} +
            +
            +

            {{ 'Comment'|trans }}

            +
            +
            + {{ activity.comment|chill_entity_render_box({ + 'disable_markdown': false, + 'limit_lines': 3, + 'metadata': false + }) }} +
            +
            + {% endif %} + + {# Only if ACL SEE_DETAILS AND/OR only on template SHOW ?? + durationTime + travelTime + comment + documents + attendee + #} +
            - {% endif %}
            -
              + {% if context == 'person' and activity.accompanyingPeriod is not empty %} + {# + Disable person_id in following links, for redirect to accompanyingCourse context + #} + {% set person_id = null %} + {% set accompanying_course_id = activity.accompanyingPeriod.id %} +
            • + + + {{ 'Period number %number%'|trans({'%number%': accompanying_course_id}) }} + +
            • + {% endif %}
            • - +
            • {% if no_action is not defined or no_action == false %} -
            • - -
            • -
            • - -
            • + {% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %} +
            • + +
            • + {% endif %} + {% if is_granted('CHILL_ACTIVITY_DELETE', activity) %} +
            • + +
            • + {% endif %} {% endif %}
            diff --git a/src/Bundle/ChillActivityBundle/Resources/views/Activity/listAccompanyingCourse.html.twig b/src/Bundle/ChillActivityBundle/Resources/views/Activity/listAccompanyingCourse.html.twig index c5de72308..431a06ba6 100644 --- a/src/Bundle/ChillActivityBundle/Resources/views/Activity/listAccompanyingCourse.html.twig +++ b/src/Bundle/ChillActivityBundle/Resources/views/Activity/listAccompanyingCourse.html.twig @@ -23,8 +23,8 @@ {% if is_granted('CHILL_ACTIVITY_CREATE', accompanyingCourse) %} diff --git a/src/Bundle/ChillActivityBundle/Resources/views/Activity/list_recent.html.twig b/src/Bundle/ChillActivityBundle/Resources/views/Activity/list_recent.html.twig index 2829d8153..0f426c5a9 100644 --- a/src/Bundle/ChillActivityBundle/Resources/views/Activity/list_recent.html.twig +++ b/src/Bundle/ChillActivityBundle/Resources/views/Activity/list_recent.html.twig @@ -3,10 +3,88 @@ {% set t = activity.type %} + class="dashboard-link" title="{{ 'Show the activity'|trans }}"> - {% include '@ChillActivity/Activity/activity-badge-title.html.twig' %} +
            + + + + {%- if activity.date -%} +

            {{ activity.date|format_date('short') }}

            + {%- endif -%} + + + + {% if activity.emergency %} + {{ 'Emergency'|trans|upper }} + {% endif %} + +
              + + {% if activity.sentReceived is not empty and t.sentReceivedVisible %} +
            • + {{ 'Sent received'|trans ~ ' : ' }} + {{ activity.sentReceived|capitalize|trans }} +
            • + {% endif %} + + {% if activity.location and t.locationVisible %} +
            • + {{ 'location'|trans ~ ': ' }} + + {{ activity.location.locationType.title|localize_translatable_string }} + {{ activity.location.name }} + +
            • + {% endif %} + + {% if activity.user and t.userVisible %} +
            • + {{ 'Referrer'|trans ~ ': ' }} + {{ activity.user.usernameCanonical }} +
            • + {% endif %} + +
            • + {{ 'Participants'|trans ~ ' : ' }} + {% for p in activity.personsAssociated %} + {{ p|chill_entity_render_box }} + {% endfor %} +
            • +
            + +
              + {%- if t.reasonsVisible -%} + {%- if activity.reasons is not empty -%} +
            • + {% for r in activity.reasons %} + {{ r|chill_entity_render_box }} + {% endfor %} +
            • + {%- endif -%} + {% endif %} + {%- if t.socialIssuesVisible %} + {%- if activity.socialIssues is not empty -%} + + {%- endif -%} + {% endif %} + {%- if t.socialActionsVisible -%} + {%- if activity.socialActions is not empty -%} + + {%- endif -%} + {% endif %} +
            + +
            +
            - {% endfor %}
            diff --git a/src/Bundle/ChillActivityBundle/Resources/views/Activity/new.html.twig b/src/Bundle/ChillActivityBundle/Resources/views/Activity/new.html.twig index 2fc8be3e6..a0668119c 100644 --- a/src/Bundle/ChillActivityBundle/Resources/views/Activity/new.html.twig +++ b/src/Bundle/ChillActivityBundle/Resources/views/Activity/new.html.twig @@ -1,10 +1,16 @@ -

            {{ "Activity creation"|trans ~ ' :' }}

            -

            {{ entity.type.name|localize_translatable_string }}

            +

            + {{ "Activity creation"|trans }} +

            +

            + + + {{ entity.type.name | localize_translatable_string }} + +

            {{ form_start(form) }} {{ form_errors(form) }} - {%- if form.emergency is defined -%} {{ form_row(form.emergency) }} {% endif %} @@ -39,7 +45,7 @@ {%- if form.persons is defined or form.thirdParties is defined or form.users is defined -%} -

            {{ 'Concerned groups'|trans }}

            +

            {{ 'Concerned groups'|trans }}

            {%- if form.persons is defined -%} {{ form_widget(form.persons) }} @@ -55,7 +61,7 @@ {% endif %} -

            {{ 'Activity data'|trans }}

            +

            {{ 'Activity data'|trans }}

            {%- if form.date is defined -%} {{ form_row(form.date) }} @@ -103,7 +109,7 @@
          • -
          • diff --git a/src/Bundle/ChillActivityBundle/Resources/views/Activity/show.html.twig b/src/Bundle/ChillActivityBundle/Resources/views/Activity/show.html.twig index a1fc44196..cb5b135b3 100644 --- a/src/Bundle/ChillActivityBundle/Resources/views/Activity/show.html.twig +++ b/src/Bundle/ChillActivityBundle/Resources/views/Activity/show.html.twig @@ -1,128 +1,185 @@ {%- set t = entity.type -%} {%- import "@ChillDocStore/Macro/macro.html.twig" as m -%} -

            - {{ "Activity"|trans }} - {%- if t.emergencyVisible and entity.emergency -%} - - {{- 'Emergency'|trans -}} - -{%- endif -%} -

            +

            {{ "Activity"|trans }}

            -
            +
            +
            -
            {{ 'by'|trans|capitalize }}
            -
            {{ entity.user }}
            +
            +
            +
            +
            + {% if entity.date %} +

            + {{ entity.date|format_date('short') }} +

            + {% endif %} +
            +
            +

            + + + {{ entity.type.name | localize_translatable_string }} + {% if entity.emergency %} + {{ 'Emergency'|trans|upper }} + {% endif %} + +

            +
            +
            +
            +
            -
            {{ 'Type'|trans }}
            -
            {{ entity.type.name | localize_translatable_string }}
            +
            +
            +
            {{ 'Referrer'|trans|capitalize }}
            +
            {{ entity.user }}
            - {%- if entity.scope -%} -
            {{ 'Scope'|trans }}
            -
            {{ entity.scope.name|localize_translatable_string }}
            - {% endif %} + {%- if entity.scope -%} +
            {{ 'Scope'|trans }}
            +
            + {{ entity.scope.name|localize_translatable_string }} +
            + {% endif %} - {% if t.socialIssuesVisible %} -
            {{ 'Social issues'|trans }}
            -
            - {% if entity.socialIssues|length == 0 %} -

            {{ 'No social issues associated'|trans }}

            - {% else %} - {% for si in entity.socialIssues %}{{ si|chill_entity_render_box }}{% endfor %} - {% endif %} -
            - {% endif %} + {% if t.socialIssuesVisible %} +
            {{ 'Social issues'|trans }}
            +
            + {% if entity.socialIssues|length == 0 %} +

            {{ 'No social issues associated'|trans }}

            + {% else %} + {% for si in entity.socialIssues %}{{ si|chill_entity_render_box }}{% endfor %} + {% endif %} +
            + {% endif %} - {% if t.socialActionsVisible %} -
            {{ 'Social actions'|trans }}
            -
            - {% if entity.socialActions|length == 0 %} -

            {{ 'No social actions associated'|trans }}

            - {% else %} - {% for sa in entity.socialActions %}{{ sa|chill_entity_render_box }}{% endfor %} - {% endif %} -
            - {% endif %} + {% if t.socialActionsVisible %} +
            {{ 'Social actions'|trans }}
            +
            + {% if entity.socialActions|length == 0 %} + {{ 'No social actions associated'|trans }} + {% else %} + {% for sa in entity.socialActions %}{{ sa|chill_entity_render_box }}{% endfor %} + {% endif %} +
            + {% endif %} - {% if t.reasonsVisible %} -
            {{ 'Reasons'|trans }}
            - {%- if entity.reasons is empty -%} -
            {{ 'No reason associated'|trans }}
            - {%- else -%} -
            {% for r in entity.reasons %}{{ r|chill_entity_render_box }} {% endfor %}
            - {%- endif -%} - {% endif %} + {% if t.reasonsVisible %} +
            {{ 'Reasons'|trans }}
            +
            + {%- if entity.reasons is empty -%} + {{ 'No reason associated'|trans }} + {%- else -%} + {% for r in entity.reasons %}{{ r|chill_entity_render_box }}{% endfor %} + {%- endif -%} +
            + {% endif %} +
            +
            -

            {{ 'Concerned groups'|trans }}

            -{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {'context': context, 'with_display': 'bloc', 'badge_person': 'true' } %} +
            +
            -

            {{ 'Activity data'|trans }}

            +

            {{ 'Concerned groups'|trans }}

            -
            {{ 'Date'|trans }}
            -
            {{ entity.date|format_date('long') }}
            +{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with { + 'context': context, + 'with_display': 'bloc', + 'badge_person': 'true' +} %} - {% if t.locationVisible %} -
            {{ 'Activity location'|trans }}
            -
            - {% if entity.location is not null %} -

            - {{ entity.location.name }} - ({{ entity.location.locationType.title|localize_translatable_string }}) -

            - {{ entity.location.address|chill_entity_render_box }} - {% else %} - {{ 'No address given'|trans }} +

            {{ 'Activity data'|trans }}

            + +
            +
            + +
            +
            {{ 'Date'|trans }}
            +
            {{ entity.date|format_date('long') }}
            + + {% if t.locationVisible %} +
            {{ 'Activity location'|trans }}
            +
            + {% if entity.location is not null %} +

            + {{ entity.location.locationType.title|localize_translatable_string }} + {{ entity.location.name }} +

            +
            {{ entity.location.address|chill_entity_render_box }}
            + {% else %} + {{ 'No address given'|trans }} + {% endif %} +
            {% endif %} -
            - {% endif %} - {% if t.durationTimeVisible %} -
            {{ 'Duration Time'|trans }}
            -
            {% if entity.durationTime is not null %} - {{ entity.durationTime|date('H:i') }} - {% else %} - {{ 'None'|trans|capitalize }} - {% endif %} -
            - {% endif %} + {% if t.durationTimeVisible and is_granted('CHILL_ACTIVITY_SEE_DETAILS', entity) %} +
            {{ 'Duration Time'|trans }}
            +
            + {% if entity.durationTime is not null %} + {{ entity.durationTime|date('H:i') }} + {% else %} + {{ 'None'|trans|capitalize }} + {% endif %} +
            + {% endif %} - {% if t.travelTimeVisible %} -
            {{ 'Travel time'|trans }}
            -
            {% if entity.travelTime is not null %} - {{ entity.travelTime|date('H:i') }} - {% else %} - {{ 'None'|trans|capitalize }} - {% endif %} -
            - {% endif %} + {% if t.travelTimeVisible and is_granted('CHILL_ACTIVITY_SEE_DETAILS', entity) %} +
            {{ 'Travel time'|trans }}
            +
            + {% if entity.travelTime is not null %} + {{ entity.travelTime|date('H:i') }} + {% else %} + {{ 'None'|trans|capitalize }} + {% endif %} +
            + {% endif %} - {% if t.commentVisible %} -
            {{ 'activity.comment'|trans }}
            - {%- if entity.comment.empty -%} -
            {{ 'No comment associated'|trans }}
            - {%- else -%} -
            {{ entity.comment|chill_entity_render_box }}
            - {%- endif -%} - {% endif %} + {% if t.commentVisible and is_granted('CHILL_ACTIVITY_SEE_DETAILS', entity) %} +
            {{ 'activity.comment'|trans }}
            +
            + {%- if entity.comment.empty -%} + {{ 'No comment associated'|trans }} + {%- else -%} + {{ entity.comment|chill_entity_render_box }} + {%- endif -%} +
            + {% endif %} - {% if t.documentsVisible and entity.documents|length > 0 %} -
            {{ 'Documents'|trans }}
            -
            -
              - {% for d in entity.documents %} -
            • {{ m.download_button(d) }}
            • - {% endfor %} -
            -
            - {% endif %} + {% if t.documentsVisible and is_granted('CHILL_ACTIVITY_SEE_DETAILS', entity) %} +
            {{ 'Documents'|trans }}
            +
            + {% if entity.documents|length > 0 %} +
              + {% for d in entity.documents %} +
            • {{ m.download_button(d) }}
            • + {% endfor %} +
            + {% else %} + {{ 'Any document found'|trans }} + {% endif %} +
            + {% endif %} - {% if t.attendeeVisible %} -
            {{ 'Attendee'|trans }}
            -
            {% if entity.attendee is not null %}{% if entity.attendee %}{{ 'present'|trans|capitalize }} {% else %} {{ 'not present'|trans|capitalize }}{% endif %}{% else %}{{ 'None'|trans|capitalize }}{% endif %}
            - {% endif %} + {% if t.attendeeVisible and is_granted('CHILL_ACTIVITY_SEE_DETAILS', entity) %} +
            {{ 'Attendee'|trans }}
            +
            + {% if entity.attendee is not null %} + {% if entity.attendee %} + {{ 'present'|trans|capitalize }} + {% else %} + {{ 'not present'|trans|capitalize }} + {% endif %} + {% else %} + {{ 'None'|trans|capitalize }} + {% endif %} +
            + {% endif %} -
            + + +
            +
            {% set person_id = null %} {% if person %} @@ -140,23 +197,24 @@ {{ 'Back to the list'|trans }} + {% if is_granted('CHILL_ACTIVITY_UPDATE', entity) %}
          • {{ 'Edit'|trans }}
          • - - {# TODO + {% endif %} {% if is_granted('CHILL_ACTIVITY_DELETE', entity) %} - #} -
          • {{ 'Delete'|trans }}
          • - - {# {% endif %} - #}
          + diff --git a/src/Bundle/ChillActivityBundle/Resources/views/Activity/showAccompanyingCourse.html.twig b/src/Bundle/ChillActivityBundle/Resources/views/Activity/showAccompanyingCourse.html.twig index ada3ebbd6..b74b315a3 100644 --- a/src/Bundle/ChillActivityBundle/Resources/views/Activity/showAccompanyingCourse.html.twig +++ b/src/Bundle/ChillActivityBundle/Resources/views/Activity/showAccompanyingCourse.html.twig @@ -8,8 +8,6 @@ {% block content -%}
          - {% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'accompanyingCourse'} %} -
          {% endblock content %} diff --git a/src/Bundle/ChillActivityBundle/Resources/views/Activity/showPerson.html.twig b/src/Bundle/ChillActivityBundle/Resources/views/Activity/showPerson.html.twig index 8462c4178..5e92f8fa2 100644 --- a/src/Bundle/ChillActivityBundle/Resources/views/Activity/showPerson.html.twig +++ b/src/Bundle/ChillActivityBundle/Resources/views/Activity/showPerson.html.twig @@ -8,8 +8,6 @@ {% block personcontent -%}
          - - {% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'person'} %} - + {% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'person'} %}
          {% endblock personcontent %} diff --git a/src/Bundle/ChillActivityBundle/Security/Authorization/ActivityStatsVoter.php b/src/Bundle/ChillActivityBundle/Security/Authorization/ActivityStatsVoter.php index 39b0deef9..789e634e5 100644 --- a/src/Bundle/ChillActivityBundle/Security/Authorization/ActivityStatsVoter.php +++ b/src/Bundle/ChillActivityBundle/Security/Authorization/ActivityStatsVoter.php @@ -15,6 +15,7 @@ use Chill\MainBundle\Entity\Center; use Chill\MainBundle\Security\Authorization\AbstractChillVoter; use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Chill\MainBundle\Security\ProvideRoleHierarchyInterface; + use function in_array; class ActivityStatsVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface @@ -64,8 +65,10 @@ class ActivityStatsVoter extends AbstractChillVoter implements ProvideRoleHierar protected function supports($attribute, $subject) { - if ($subject instanceof Center - && in_array($attribute, $this->getAttributes(), true)) { + if ( + $subject instanceof Center + && in_array($attribute, $this->getAttributes(), true) + ) { return true; } diff --git a/src/Bundle/ChillActivityBundle/Security/Authorization/ActivityVoter.php b/src/Bundle/ChillActivityBundle/Security/Authorization/ActivityVoter.php index 30e8f2c06..9911bf9fd 100644 --- a/src/Bundle/ChillActivityBundle/Security/Authorization/ActivityVoter.php +++ b/src/Bundle/ChillActivityBundle/Security/Authorization/ActivityVoter.php @@ -24,6 +24,7 @@ use Chill\PersonBundle\Security\Authorization\PersonVoter; use RuntimeException; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Security; + use function in_array; class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface @@ -92,6 +93,8 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn public function getRoles(): array { return [ + self::SEE, + self::SEE_DETAILS, self::CREATE_PERSON, self::CREATE_ACCOMPANYING_COURSE, self::UPDATE, diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityReasonAggregatorTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityReasonAggregatorTest.php index cded1edeb..fb98f0a8e 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityReasonAggregatorTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityReasonAggregatorTest.php @@ -26,7 +26,7 @@ final class ActivityReasonAggregatorTest extends AbstractAggregatorTest */ private $aggregator; - public function setUp() + protected function setUp(): void { self::bootKernel(); diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityTypeAggregatorTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityTypeAggregatorTest.php index 0b0c6500a..7959825a7 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityTypeAggregatorTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityTypeAggregatorTest.php @@ -26,7 +26,7 @@ final class ActivityTypeAggregatorTest extends AbstractAggregatorTest */ private $aggregator; - public function setUp() + protected function setUp(): void { self::bootKernel(); diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityUserAggregatorTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityUserAggregatorTest.php index 426de911d..056ba6049 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityUserAggregatorTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ActivityUserAggregatorTest.php @@ -26,7 +26,7 @@ final class ActivityUserAggregatorTest extends AbstractAggregatorTest */ private $aggregator; - public function setUp() + protected function setUp(): void { self::bootKernel(); diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Export/CountActivityTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Export/CountActivityTest.php index 3981c1948..cbf562dfa 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Export/CountActivityTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Export/CountActivityTest.php @@ -24,7 +24,7 @@ final class CountActivityTest extends AbstractExportTest */ private $export; - public function setUp() + protected function setUp(): void { self::bootKernel(); diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Export/ListActivityTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Export/ListActivityTest.php index df1e64fd7..46d23b023 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Export/ListActivityTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Export/ListActivityTest.php @@ -24,7 +24,7 @@ final class ListActivityTest extends AbstractExportTest */ private $export; - public function setUp() + protected function setUp(): void { self::bootKernel(); diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Export/StatActivityDurationSumTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Export/StatActivityDurationSumTest.php index 12587e5a3..c69a31b5a 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Export/StatActivityDurationSumTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Export/StatActivityDurationSumTest.php @@ -26,7 +26,7 @@ final class StatActivityDurationSumTest extends AbstractExportTest */ private $export; - public function setUp() + protected function setUp(): void { self::bootKernel(); diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ActivityReasonFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ActivityReasonFilterTest.php index 46c1e0ef6..cbac6febd 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ActivityReasonFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/ActivityReasonFilterTest.php @@ -25,7 +25,7 @@ final class ActivityReasonFilterTest extends AbstractFilterTest */ private $filter; - public function setUp() + protected function setUp(): void { self::bootKernel(); diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/PersonHavingActivityBetweenDateFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/PersonHavingActivityBetweenDateFilterTest.php index b69e4d8b2..f444c368b 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/PersonHavingActivityBetweenDateFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/PersonHavingActivityBetweenDateFilterTest.php @@ -26,7 +26,7 @@ final class PersonHavingActivityBetweenDateFilterTest extends AbstractFilterTest */ private $filter; - public function setUp() + protected function setUp(): void { self::bootKernel(); diff --git a/src/Bundle/ChillActivityBundle/Tests/Form/ActivityTypeTest.php b/src/Bundle/ChillActivityBundle/Tests/Form/ActivityTypeTest.php index 3ba204d9a..15842e729 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Form/ActivityTypeTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Form/ActivityTypeTest.php @@ -45,7 +45,7 @@ final class ActivityTypeTest extends KernelTestCase */ protected $user; - public function setUp() + protected function setUp(): void { self::bootKernel(); diff --git a/src/Bundle/ChillActivityBundle/Tests/Form/Type/TranslatableActivityReasonTest.php b/src/Bundle/ChillActivityBundle/Tests/Form/Type/TranslatableActivityReasonTest.php index 7d186192e..76e8e438c 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Form/Type/TranslatableActivityReasonTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Form/Type/TranslatableActivityReasonTest.php @@ -29,7 +29,7 @@ final class TranslatableActivityReasonTest extends TypeTestCase */ private static $prophet; - public function setUp() + protected function setUp(): void { parent::setUp(); } diff --git a/src/Bundle/ChillActivityBundle/Tests/Form/Type/TranslatableActivityTypeTest.php b/src/Bundle/ChillActivityBundle/Tests/Form/Type/TranslatableActivityTypeTest.php index 5c1dcd958..68f206da2 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Form/Type/TranslatableActivityTypeTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Form/Type/TranslatableActivityTypeTest.php @@ -31,7 +31,7 @@ final class TranslatableActivityTypeTest extends KernelTestCase */ protected $container; - public function setUp() + protected function setUp(): void { self::bootKernel(); diff --git a/src/Bundle/ChillActivityBundle/Tests/Security/Authorization/ActivityVoterTest.php b/src/Bundle/ChillActivityBundle/Tests/Security/Authorization/ActivityVoterTest.php index 46351a052..b3d8472c6 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Security/Authorization/ActivityVoterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Security/Authorization/ActivityVoterTest.php @@ -44,7 +44,7 @@ final class ActivityVoterTest extends KernelTestCase */ protected $voter; - public function setUp() + protected function setUp(): void { self::bootKernel(); $this->voter = self::$kernel->getContainer() diff --git a/src/Bundle/ChillActivityBundle/Timeline/TimelineActivityProvider.php b/src/Bundle/ChillActivityBundle/Timeline/TimelineActivityProvider.php index 072ba39d9..74e98e9dc 100644 --- a/src/Bundle/ChillActivityBundle/Timeline/TimelineActivityProvider.php +++ b/src/Bundle/ChillActivityBundle/Timeline/TimelineActivityProvider.php @@ -24,6 +24,7 @@ use RuntimeException; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\User\UserInterface; + use function implode; use function in_array; use function strtr; diff --git a/src/Bundle/ChillActivityBundle/Validator/Constraints/ActivityValidityValidator.php b/src/Bundle/ChillActivityBundle/Validator/Constraints/ActivityValidityValidator.php index d429d4e4d..b1d0f13e7 100644 --- a/src/Bundle/ChillActivityBundle/Validator/Constraints/ActivityValidityValidator.php +++ b/src/Bundle/ChillActivityBundle/Validator/Constraints/ActivityValidityValidator.php @@ -17,6 +17,7 @@ use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; use Symfony\Component\Validator\Exception\UnexpectedValueException; + use function array_merge; use function count; diff --git a/src/Bundle/ChillActivityBundle/config/services/doctrine.entitylistener.yaml b/src/Bundle/ChillActivityBundle/config/services/doctrine.entitylistener.yaml new file mode 100644 index 000000000..3c439153b --- /dev/null +++ b/src/Bundle/ChillActivityBundle/config/services/doctrine.entitylistener.yaml @@ -0,0 +1,15 @@ +services: + Chill\ActivityBundle\EntityListener\ActivityEntityListener: + autowire: true + autoconfigure: true + tags: + - + name: 'doctrine.orm.entity_listener' + event: 'postPersist' + entity: 'Chill\ActivityBundle\Entity\Activity' + method: 'persistActionToCourse' + - + name: 'doctrine.orm.entity_listener' + event: 'postUpdate' + entity: 'Chill\ActivityBundle\Entity\Activity' + method: 'persistActionToCourse' diff --git a/src/Bundle/ChillActivityBundle/migrations/Version20210422073711.php b/src/Bundle/ChillActivityBundle/migrations/Version20210422073711.php index 8501767b2..b24bb9ea7 100644 --- a/src/Bundle/ChillActivityBundle/migrations/Version20210422073711.php +++ b/src/Bundle/ChillActivityBundle/migrations/Version20210422073711.php @@ -13,6 +13,7 @@ namespace Chill\Migrations\Activity; use Doctrine\DBAL\Schema\Schema; use Doctrine\Migrations\AbstractMigration; + use function count; /** diff --git a/src/Bundle/ChillActivityBundle/migrations/Version20211207152023.php b/src/Bundle/ChillActivityBundle/migrations/Version20211207152023.php new file mode 100644 index 000000000..034fee71a --- /dev/null +++ b/src/Bundle/ChillActivityBundle/migrations/Version20211207152023.php @@ -0,0 +1,34 @@ +throwIrreversibleMigrationException('placevisible and placelabel could not be created'); + } + + public function getDescription(): string + { + return 'DROP place visible and place label, which are replaced by location'; + } + + public function up(Schema $schema): void + { + $this->addSql('ALTER TABLE activitytype DROP placevisible'); + $this->addSql('ALTER TABLE activitytype DROP placelabel'); + } +} diff --git a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml index 098a6f6df..00715d283 100644 --- a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml @@ -146,8 +146,8 @@ User visible: Visibilité du champ Utilisateur User label: Libellé du champ Utilisateur Date visible: Visibilité du champ Date Date label: Libellé du champ Date -Place visible: Visibilité du champ Lieu -Place label: Libellé du champ Lieu +Location visible: Visibilité du champ Lieu +Location label: Libellé du champ Lieu Third parties visible: Visibilité du champ Tiers Third parties label: Libellé du champ Tiers Duration time visible: Visibilité du champ Durée @@ -222,3 +222,5 @@ Aggregate by activity type: Aggréger par type d'activité Aggregate by activity reason: Aggréger par sujet de l'activité Last activities: Les dernières activités + +See activity in accompanying course context: Voir l'activité dans le contexte du parcours d'accompagnement diff --git a/src/Bundle/ChillAsideActivityBundle/src/DataFixtures/ORM/LoadAsideActivity.php b/src/Bundle/ChillAsideActivityBundle/src/DataFixtures/ORM/LoadAsideActivity.php index e6fdbb5fe..ae84ac472 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/DataFixtures/ORM/LoadAsideActivity.php +++ b/src/Bundle/ChillAsideActivityBundle/src/DataFixtures/ORM/LoadAsideActivity.php @@ -19,6 +19,7 @@ use DateTimeImmutable; use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Common\DataFixtures\DependentFixtureInterface; use Doctrine\Persistence\ObjectManager; + use function random_int; class LoadAsideActivity extends Fixture implements DependentFixtureInterface diff --git a/src/Bundle/ChillAsideActivityBundle/src/DataFixtures/ORM/LoadAsideActivityCategory.php b/src/Bundle/ChillAsideActivityBundle/src/DataFixtures/ORM/LoadAsideActivityCategory.php index da5cb721b..5c897e8ec 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/DataFixtures/ORM/LoadAsideActivityCategory.php +++ b/src/Bundle/ChillAsideActivityBundle/src/DataFixtures/ORM/LoadAsideActivityCategory.php @@ -18,10 +18,12 @@ class LoadAsideActivityCategory extends \Doctrine\Bundle\FixturesBundle\Fixture { public function load(ObjectManager $manager) { - foreach ([ - 'Appel téléphonique', - 'Formation', - ] as $key => $label) { + foreach ( + [ + 'Appel téléphonique', + 'Formation', + ] as $key => $label + ) { $category = new AsideActivityCategory(); $category->setTitle(['fr' => $label]); $manager->persist($category); diff --git a/src/Bundle/ChillAsideActivityBundle/src/DependencyInjection/Configuration.php b/src/Bundle/ChillAsideActivityBundle/src/DependencyInjection/Configuration.php index 3032e1b2c..a077ce902 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillAsideActivityBundle/src/DependencyInjection/Configuration.php @@ -13,6 +13,7 @@ namespace Chill\AsideActivityBundle\DependencyInjection; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; + use function is_int; class Configuration implements ConfigurationInterface diff --git a/src/Bundle/ChillAsideActivityBundle/src/Entity/AsideActivityCategory.php b/src/Bundle/ChillAsideActivityBundle/src/Entity/AsideActivityCategory.php index 8ef9664c7..6418a7990 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Entity/AsideActivityCategory.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Entity/AsideActivityCategory.php @@ -162,8 +162,12 @@ class AsideActivityCategory public function setParent(?self $parent): self { // cache the old result for changing it during validaiton - $this->oldParent = $this->parent; + if ($this->parent) { + $this->oldParent = $this->parent; + } + $this->parent = $parent; + dump($this); return $this; } diff --git a/src/Bundle/ChillAsideActivityBundle/src/Form/AsideActivityFormType.php b/src/Bundle/ChillAsideActivityBundle/src/Form/AsideActivityFormType.php index 73f937ff1..5a4eec9e0 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Form/AsideActivityFormType.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Form/AsideActivityFormType.php @@ -32,6 +32,7 @@ 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 function in_array; final class AsideActivityFormType extends AbstractType @@ -137,7 +138,7 @@ final class AsideActivityFormType extends AbstractType $timezoneUTC = new DateTimeZone('GMT'); /** @var DateTimeImmutable $data */ $data = $formEvent->getData() === null ? - DateTime::createFromFormat('U', 300) : + DateTime::createFromFormat('U', '300') : $formEvent->getData(); $seconds = $data->getTimezone()->getOffset($data); $data->setTimeZone($timezoneUTC); diff --git a/src/Bundle/ChillAsideActivityBundle/src/Menu/AdminMenuBuilder.php b/src/Bundle/ChillAsideActivityBundle/src/Menu/AdminMenuBuilder.php index 2d5968e48..4fa2c2c96 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Menu/AdminMenuBuilder.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Menu/AdminMenuBuilder.php @@ -13,6 +13,7 @@ namespace Chill\AsideActivityBundle\Menu; use Knp\Menu\MenuItem; use Symfony\Component\Security\Core\Security; + use function in_array; final class AdminMenuBuilder implements \Chill\MainBundle\Routing\LocalMenuBuilderInterface diff --git a/src/Bundle/ChillAsideActivityBundle/src/Tests/Controller/AsideActivityControllerTest.php b/src/Bundle/ChillAsideActivityBundle/src/Tests/Controller/AsideActivityControllerTest.php index 3f8a514d2..1dea9bc0c 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Tests/Controller/AsideActivityControllerTest.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Tests/Controller/AsideActivityControllerTest.php @@ -26,7 +26,7 @@ final class AsideActivityControllerTest extends WebTestCase { use PrepareClientTrait; - public function setUp() + protected function setUp(): void { parent::setUp(); self::bootKernel(); diff --git a/src/Bundle/ChillBudgetBundle/Calculator/CalculatorManager.php b/src/Bundle/ChillBudgetBundle/Calculator/CalculatorManager.php index 2a9a89b13..0916b703c 100644 --- a/src/Bundle/ChillBudgetBundle/Calculator/CalculatorManager.php +++ b/src/Bundle/ChillBudgetBundle/Calculator/CalculatorManager.php @@ -13,6 +13,7 @@ namespace Chill\AMLI\BudgetBundle\Calculator; use Chill\AMLI\BudgetBundle\Entity\AbstractElement; use OutOfBoundsException; + use function array_key_exists; use function array_keys; use function implode; diff --git a/src/Bundle/ChillBudgetBundle/Controller/AbstractElementController.php b/src/Bundle/ChillBudgetBundle/Controller/AbstractElementController.php index fd596cc3a..01315e889 100644 --- a/src/Bundle/ChillBudgetBundle/Controller/AbstractElementController.php +++ b/src/Bundle/ChillBudgetBundle/Controller/AbstractElementController.php @@ -21,6 +21,7 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Translation\TranslatorInterface; + use function get_class; abstract class AbstractElementController extends Controller diff --git a/src/Bundle/ChillBudgetBundle/Controller/ElementController.php b/src/Bundle/ChillBudgetBundle/Controller/ElementController.php index b0c01732b..df1e83081 100644 --- a/src/Bundle/ChillBudgetBundle/Controller/ElementController.php +++ b/src/Bundle/ChillBudgetBundle/Controller/ElementController.php @@ -22,6 +22,7 @@ use Psr\Log\LoggerInterface; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\Translation\TranslatorInterface; + use function array_merge; use function count; diff --git a/src/Bundle/ChillBudgetBundle/Form/ChargeType.php b/src/Bundle/ChillBudgetBundle/Form/ChargeType.php index f64283b5a..96aea3ea4 100644 --- a/src/Bundle/ChillBudgetBundle/Form/ChargeType.php +++ b/src/Bundle/ChillBudgetBundle/Form/ChargeType.php @@ -21,6 +21,7 @@ use Symfony\Component\Form\Extension\Core\Type\MoneyType; use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; + use function array_flip; use function asort; diff --git a/src/Bundle/ChillBudgetBundle/Form/ResourceType.php b/src/Bundle/ChillBudgetBundle/Form/ResourceType.php index ddb4dd777..9f772648d 100644 --- a/src/Bundle/ChillBudgetBundle/Form/ResourceType.php +++ b/src/Bundle/ChillBudgetBundle/Form/ResourceType.php @@ -21,6 +21,7 @@ use Symfony\Component\Form\Extension\Core\Type\MoneyType; use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; + use function array_flip; class ResourceType extends AbstractType diff --git a/src/Bundle/ChillBudgetBundle/Security/Authorization/BudgetElementVoter.php b/src/Bundle/ChillBudgetBundle/Security/Authorization/BudgetElementVoter.php index 71a5f2523..e0d9e9266 100644 --- a/src/Bundle/ChillBudgetBundle/Security/Authorization/BudgetElementVoter.php +++ b/src/Bundle/ChillBudgetBundle/Security/Authorization/BudgetElementVoter.php @@ -18,6 +18,7 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Chill\MainBundle\Security\ProvideRoleHierarchyInterface; use Chill\PersonBundle\Entity\Person; use Symfony\Component\Security\Core\Role\Role; + use function in_array; class BudgetElementVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface diff --git a/src/Bundle/ChillCalendarBundle/Controller/CalendarRangeAPIController.php b/src/Bundle/ChillCalendarBundle/Controller/CalendarRangeAPIController.php index f62323a29..018d23426 100644 --- a/src/Bundle/ChillCalendarBundle/Controller/CalendarRangeAPIController.php +++ b/src/Bundle/ChillCalendarBundle/Controller/CalendarRangeAPIController.php @@ -16,6 +16,7 @@ use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; + use function count; class CalendarRangeAPIController extends ApiController diff --git a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php index d026b399c..11104cc6a 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php +++ b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php @@ -28,6 +28,7 @@ use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Mapping\ClassMetadata; + use function in_array; /** diff --git a/src/Bundle/ChillCalendarBundle/Event/ListenToActivityCreate.php b/src/Bundle/ChillCalendarBundle/Event/ListenToActivityCreate.php index c79cccbf5..ec902bd64 100644 --- a/src/Bundle/ChillCalendarBundle/Event/ListenToActivityCreate.php +++ b/src/Bundle/ChillCalendarBundle/Event/ListenToActivityCreate.php @@ -14,6 +14,7 @@ namespace Chill\CalendarBundle\Event; use Chill\ActivityBundle\Entity\Activity; use Doctrine\Persistence\Event\LifecycleEventArgs; use Symfony\Component\HttpFoundation\RequestStack; + use function array_key_exists; class ListenToActivityCreate diff --git a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php index f36c7f07b..acaeccf34 100644 --- a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php +++ b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php @@ -20,7 +20,6 @@ use Chill\MainBundle\Entity\User; use Chill\MainBundle\Form\Type\CommentType; use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\PersonBundle\Entity\Person; - use Chill\ThirdPartyBundle\Entity\ThirdParty; use DateTimeImmutable; use Doctrine\Persistence\ObjectManager; diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js index edfb7f236..db2950bd4 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js @@ -1,6 +1,10 @@ import 'es6-promise/auto'; import { createStore } from 'vuex'; import { postLocation } from 'ChillActivityAssets/vuejs/Activity/api'; +import { + getLocations, getLocationTypeByDefaultFor, + getUserCurrentLocation +} from "../../../../../ChillActivityBundle/Resources/public/vuejs/Activity/api"; const debug = process.env.NODE_ENV !== 'production'; @@ -82,7 +86,7 @@ const store = createStore({ } }, mutations: { - + // ConcernedGroups addPersonsInvolved(state, payload) { //console.log('### mutation addPersonsInvolved', payload.result.type); @@ -94,7 +98,7 @@ const store = createStore({ state.activity.thirdParties.push(payload.result); break; case 'user': - state.activity.users.push(payload.result); + state.activity.users.push(payload.result); break; }; }, @@ -108,7 +112,7 @@ const store = createStore({ state.activity.thirdParties = state.activity.thirdParties.filter(thirdparty => thirdparty !== payload); break; case 'user': - state.activity.users = state.activity.users.filter(user => user !== payload); + state.activity.users = state.activity.users.filter(user => user !== payload); break; }; }, @@ -217,9 +221,7 @@ const store = createStore({ hiddenLocation.value = value.id; } commit("updateLocation", value); - } - } }); diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/listByAccompanyingCourse.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/listByAccompanyingCourse.html.twig index 07aed8686..215b7bb55 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/listByAccompanyingCourse.html.twig +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/listByAccompanyingCourse.html.twig @@ -92,8 +92,11 @@ %}
          - - {% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {'context': accompanyingCourse, 'with_display': 'row', 'entity': calendar } %} + {% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with { + 'context': accompanyingCourse, + 'with_display': 'row', + 'entity': calendar + } %}
          {% if calendar.comment.comment is not empty %} @@ -123,4 +126,4 @@
        -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/src/Bundle/ChillCalendarBundle/Tests/Controller/CalendarControllerTest.php b/src/Bundle/ChillCalendarBundle/Tests/Controller/CalendarControllerTest.php index 06e0cd5a9..813bb87bd 100644 --- a/src/Bundle/ChillCalendarBundle/Tests/Controller/CalendarControllerTest.php +++ b/src/Bundle/ChillCalendarBundle/Tests/Controller/CalendarControllerTest.php @@ -26,7 +26,7 @@ final class CalendarControllerTest extends WebTestCase /** * Setup before each test method (see phpunit doc). */ - public function setUp() + protected function setUp(): void { self::bootKernel(); $this->client = self::createClient([], [ diff --git a/src/Bundle/ChillCustomFieldsBundle/Command/CreateFieldsOnGroupCommand.php b/src/Bundle/ChillCustomFieldsBundle/Command/CreateFieldsOnGroupCommand.php index 633f70f05..a20157ce0 100644 --- a/src/Bundle/ChillCustomFieldsBundle/Command/CreateFieldsOnGroupCommand.php +++ b/src/Bundle/ChillCustomFieldsBundle/Command/CreateFieldsOnGroupCommand.php @@ -25,6 +25,7 @@ use Symfony\Component\Console\Question\Question; use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Parser; + use function count; /** diff --git a/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldChoice.php b/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldChoice.php index 718f5dbb7..b57fdf4db 100644 --- a/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldChoice.php +++ b/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldChoice.php @@ -23,6 +23,7 @@ use Symfony\Bridge\Twig\TwigEngine; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Contracts\Translation\TranslatorInterface; + use function array_key_exists; use function count; use function in_array; diff --git a/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldDate.php b/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldDate.php index 1afa9982a..38a31491d 100644 --- a/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldDate.php +++ b/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldDate.php @@ -135,7 +135,7 @@ class CustomFieldDate extends AbstractCustomField return null; } - return $date->format('Y-m-d'); + return $date->format('Y-m-d'); default: $template = 'ChillCustomFieldsBundle:CustomFieldsRendering:date.' diff --git a/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldLongChoice.php b/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldLongChoice.php index 311df8fad..20b1a9ec7 100644 --- a/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldLongChoice.php +++ b/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldLongChoice.php @@ -21,6 +21,7 @@ use LogicException; use Symfony\Bridge\Twig\TwigEngine; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormBuilderInterface; + use function get_class; use function gettype; use function is_object; diff --git a/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldNumber.php b/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldNumber.php index c7ec62ba2..cd42ca751 100644 --- a/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldNumber.php +++ b/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldNumber.php @@ -18,7 +18,6 @@ use Symfony\Component\Form\Extension\Core\Type\IntegerType; use Symfony\Component\Form\Extension\Core\Type\NumberType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; - use Symfony\Component\Validator\Constraints\GreaterThanOrEqual; use Symfony\Component\Validator\Constraints\LessThanOrEqual; diff --git a/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldText.php b/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldText.php index 62325b797..849f851fd 100644 --- a/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldText.php +++ b/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldText.php @@ -20,6 +20,7 @@ use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\HttpFoundation\RequestStack; + use function array_key_exists; class CustomFieldText extends AbstractCustomField @@ -65,8 +66,10 @@ class CustomFieldText extends AbstractCustomField $attrArray = []; - if (array_key_exists(self::MULTIPLE_CF_INLINE, $options) - && $options[self::MULTIPLE_CF_INLINE]) { + if ( + array_key_exists(self::MULTIPLE_CF_INLINE, $options) + && $options[self::MULTIPLE_CF_INLINE] + ) { $attrArray['class'] = 'multiple-cf-inline'; } diff --git a/src/Bundle/ChillCustomFieldsBundle/Form/CustomFieldsGroupType.php b/src/Bundle/ChillCustomFieldsBundle/Form/CustomFieldsGroupType.php index f9d773f72..7dff8e119 100644 --- a/src/Bundle/ChillCustomFieldsBundle/Form/CustomFieldsGroupType.php +++ b/src/Bundle/ChillCustomFieldsBundle/Form/CustomFieldsGroupType.php @@ -20,6 +20,7 @@ use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Translation\TranslatorInterface; + use function count; class CustomFieldsGroupType extends AbstractType diff --git a/src/Bundle/ChillCustomFieldsBundle/Form/DataTransformer/CustomFieldsGroupToIdTransformer.php b/src/Bundle/ChillCustomFieldsBundle/Form/DataTransformer/CustomFieldsGroupToIdTransformer.php index 937aaaa9b..fc6dfd75f 100644 --- a/src/Bundle/ChillCustomFieldsBundle/Form/DataTransformer/CustomFieldsGroupToIdTransformer.php +++ b/src/Bundle/ChillCustomFieldsBundle/Form/DataTransformer/CustomFieldsGroupToIdTransformer.php @@ -15,6 +15,7 @@ use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup; use Doctrine\Persistence\ObjectManager; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; + use function gettype; class CustomFieldsGroupToIdTransformer implements DataTransformerInterface diff --git a/src/Bundle/ChillCustomFieldsBundle/Form/DataTransformer/JsonCustomFieldToArrayTransformer.php b/src/Bundle/ChillCustomFieldsBundle/Form/DataTransformer/JsonCustomFieldToArrayTransformer.php index 095c6f463..250418581 100644 --- a/src/Bundle/ChillCustomFieldsBundle/Form/DataTransformer/JsonCustomFieldToArrayTransformer.php +++ b/src/Bundle/ChillCustomFieldsBundle/Form/DataTransformer/JsonCustomFieldToArrayTransformer.php @@ -14,7 +14,9 @@ namespace Chill\CustomFieldsBundle\Form\DataTransformer; use Chill\CustomFieldsBundle\Entity\CustomField; use Doctrine\Persistence\ObjectManager; use Symfony\Component\Form\DataTransformerInterface; + use function array_key_exists; + use const JSON_THROW_ON_ERROR; class JsonCustomFieldToArrayTransformer implements DataTransformerInterface @@ -33,7 +35,9 @@ class JsonCustomFieldToArrayTransformer implements DataTransformerInterface // @TODO: in the array_map callback, CustomField::getLabel() does not exist. What do we do here? $customFieldsLablels = array_map( - static function ($e) { return $e->getLabel(); }, + static function ($e) { + return $e->getLabel(); + }, $customFields ); diff --git a/src/Bundle/ChillCustomFieldsBundle/Form/Extension/PostTextExtension.php b/src/Bundle/ChillCustomFieldsBundle/Form/Extension/PostTextExtension.php index 6c35097e5..42428c21b 100644 --- a/src/Bundle/ChillCustomFieldsBundle/Form/Extension/PostTextExtension.php +++ b/src/Bundle/ChillCustomFieldsBundle/Form/Extension/PostTextExtension.php @@ -15,6 +15,7 @@ use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolver; + use function array_key_exists; /** diff --git a/src/Bundle/ChillCustomFieldsBundle/Form/Type/ChoicesListType.php b/src/Bundle/ChillCustomFieldsBundle/Form/Type/ChoicesListType.php index b2d50b422..77a479728 100644 --- a/src/Bundle/ChillCustomFieldsBundle/Form/Type/ChoicesListType.php +++ b/src/Bundle/ChillCustomFieldsBundle/Form/Type/ChoicesListType.php @@ -17,7 +17,6 @@ use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormEvent; - use Symfony\Component\Form\FormEvents; class ChoicesListType extends AbstractType diff --git a/src/Bundle/ChillCustomFieldsBundle/Resources/test/Fixtures/App/web/app_dev.php b/src/Bundle/ChillCustomFieldsBundle/Resources/test/Fixtures/App/web/app_dev.php index 914d09ffd..e171c8521 100644 --- a/src/Bundle/ChillCustomFieldsBundle/Resources/test/Fixtures/App/web/app_dev.php +++ b/src/Bundle/ChillCustomFieldsBundle/Resources/test/Fixtures/App/web/app_dev.php @@ -18,7 +18,8 @@ use Symfony\Component\HttpFoundation\Request; // This check prevents access to debug front controllers that are deployed by accident to production servers. // Feel free to remove this, extend it, or make something more sophisticated. -if (isset($_SERVER['HTTP_CLIENT_IP']) +if ( + isset($_SERVER['HTTP_CLIENT_IP']) || isset($_SERVER['HTTP_X_FORWARDED_FOR']) || !(in_array($_SERVER['REMOTE_ADDR'], ['127.0.0.1', 'fe80::1', '::1'], true) || \PHP_SAPI === 'cli-server') ) { diff --git a/src/Bundle/ChillCustomFieldsBundle/Tests/CustomFields/CustomFieldsChoiceTest.php b/src/Bundle/ChillCustomFieldsBundle/Tests/CustomFields/CustomFieldsChoiceTest.php index 58b15f0c3..db27ec921 100644 --- a/src/Bundle/ChillCustomFieldsBundle/Tests/CustomFields/CustomFieldsChoiceTest.php +++ b/src/Bundle/ChillCustomFieldsBundle/Tests/CustomFields/CustomFieldsChoiceTest.php @@ -37,7 +37,7 @@ final class CustomFieldsChoiceTest extends KernelTestCase */ private $cfProvider; - public function setUp() + protected function setUp(): void { self::bootKernel(); @@ -46,7 +46,7 @@ final class CustomFieldsChoiceTest extends KernelTestCase $this->cfChoice = $this->cfProvider->getCustomFieldByType('choice'); } - public function tearDown() + protected function tearDown(): void { parent::tearDown(); } diff --git a/src/Bundle/ChillCustomFieldsBundle/Tests/CustomFields/CustomFieldsNumberTest.php b/src/Bundle/ChillCustomFieldsBundle/Tests/CustomFields/CustomFieldsNumberTest.php index d65577d91..60381f567 100644 --- a/src/Bundle/ChillCustomFieldsBundle/Tests/CustomFields/CustomFieldsNumberTest.php +++ b/src/Bundle/ChillCustomFieldsBundle/Tests/CustomFields/CustomFieldsNumberTest.php @@ -34,7 +34,7 @@ final class CustomFieldsNumberTest extends \Symfony\Bundle\FrameworkBundle\Test\ */ private $formBuilder; - public function setUp() + protected function setUp(): void { self::bootKernel(); diff --git a/src/Bundle/ChillCustomFieldsBundle/Tests/CustomFields/CustomFieldsTextTest.php b/src/Bundle/ChillCustomFieldsBundle/Tests/CustomFields/CustomFieldsTextTest.php index 8d84f072e..50bf689d4 100644 --- a/src/Bundle/ChillCustomFieldsBundle/Tests/CustomFields/CustomFieldsTextTest.php +++ b/src/Bundle/ChillCustomFieldsBundle/Tests/CustomFields/CustomFieldsTextTest.php @@ -28,7 +28,7 @@ final class CustomFieldsTextTest extends WebTestCase */ private $customFieldProvider; - public function setUp() + protected function setUp(): void { self::bootKernel(); $this->customFieldProvider = self::$kernel->getContainer() diff --git a/src/Bundle/ChillCustomFieldsBundle/Tests/Form/Extension/PostTextIntegerExtensionTest.php b/src/Bundle/ChillCustomFieldsBundle/Tests/Form/Extension/PostTextIntegerExtensionTest.php index 8ce7b0cef..1c8b8e143 100644 --- a/src/Bundle/ChillCustomFieldsBundle/Tests/Form/Extension/PostTextIntegerExtensionTest.php +++ b/src/Bundle/ChillCustomFieldsBundle/Tests/Form/Extension/PostTextIntegerExtensionTest.php @@ -27,7 +27,7 @@ final class PostTextIntegerExtensionTest extends KernelTestCase */ private $formBuilder; - public function setUp() + protected function setUp(): void { self::bootKernel(); diff --git a/src/Bundle/ChillCustomFieldsBundle/Tests/Form/Extension/PostTextNumberExtensionTest.php b/src/Bundle/ChillCustomFieldsBundle/Tests/Form/Extension/PostTextNumberExtensionTest.php index a16980be0..8469b6210 100644 --- a/src/Bundle/ChillCustomFieldsBundle/Tests/Form/Extension/PostTextNumberExtensionTest.php +++ b/src/Bundle/ChillCustomFieldsBundle/Tests/Form/Extension/PostTextNumberExtensionTest.php @@ -27,7 +27,7 @@ final class PostTextNumberExtensionTest extends KernelTestCase */ private $formBuilder; - public function setUp() + protected function setUp(): void { self::bootKernel(); diff --git a/src/Bundle/ChillCustomFieldsBundle/Tests/Service/CustomFieldsHelperTest.php b/src/Bundle/ChillCustomFieldsBundle/Tests/Service/CustomFieldsHelperTest.php index 594e55e34..b08ca05c0 100644 --- a/src/Bundle/ChillCustomFieldsBundle/Tests/Service/CustomFieldsHelperTest.php +++ b/src/Bundle/ChillCustomFieldsBundle/Tests/Service/CustomFieldsHelperTest.php @@ -33,7 +33,7 @@ final class CustomFieldsHelperTest extends KernelTestCase */ private $randomCFText; - public function setUp() + protected function setUp(): void { self::bootKernel(); diff --git a/src/Bundle/ChillCustomFieldsBundle/Tests/Templating/Twig/CustomFieldRenderingTwigTest.php b/src/Bundle/ChillCustomFieldsBundle/Tests/Templating/Twig/CustomFieldRenderingTwigTest.php index 425e79537..ab43936eb 100644 --- a/src/Bundle/ChillCustomFieldsBundle/Tests/Templating/Twig/CustomFieldRenderingTwigTest.php +++ b/src/Bundle/ChillCustomFieldsBundle/Tests/Templating/Twig/CustomFieldRenderingTwigTest.php @@ -34,7 +34,7 @@ final class CustomFieldRenderingTwigTest extends KernelTestCase */ private $cfRendering; - public function setUp() + protected function setUp(): void { self::bootKernel(); $this->cfRendering = self::$kernel->getContainer() diff --git a/src/Bundle/ChillCustomFieldsBundle/Tests/Templating/Twig/CustomFieldsGroupRenderingTwigTest.php b/src/Bundle/ChillCustomFieldsBundle/Tests/Templating/Twig/CustomFieldsGroupRenderingTwigTest.php index aa52e3efd..b950d562e 100644 --- a/src/Bundle/ChillCustomFieldsBundle/Tests/Templating/Twig/CustomFieldsGroupRenderingTwigTest.php +++ b/src/Bundle/ChillCustomFieldsBundle/Tests/Templating/Twig/CustomFieldsGroupRenderingTwigTest.php @@ -36,7 +36,7 @@ final class CustomFieldsGroupRenderingTwigTest extends KernelTestCase */ private $cfRendering; - public function setUp() + protected function setUp(): void { self::bootKernel(); $this->cfRendering = self::$kernel->getContainer() diff --git a/src/Bundle/ChillDocGeneratorBundle/ChillDocGeneratorBundle.php b/src/Bundle/ChillDocGeneratorBundle/ChillDocGeneratorBundle.php index d52f0f4b1..aa02a6101 100644 --- a/src/Bundle/ChillDocGeneratorBundle/ChillDocGeneratorBundle.php +++ b/src/Bundle/ChillDocGeneratorBundle/ChillDocGeneratorBundle.php @@ -11,8 +11,17 @@ declare(strict_types=1); namespace Chill\DocGeneratorBundle; +use Chill\DocGeneratorBundle\Context\DocGeneratorContextInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; class ChillDocGeneratorBundle extends Bundle { + public function build(ContainerBuilder $container) + { + parent::build($container); + + $container->registerForAutoconfiguration(DocGeneratorContextInterface::class) + ->addTag('chill_docgen.context'); + } } diff --git a/src/Bundle/ChillDocGeneratorBundle/Context/ContextManager.php b/src/Bundle/ChillDocGeneratorBundle/Context/ContextManager.php new file mode 100644 index 000000000..8dfecb730 --- /dev/null +++ b/src/Bundle/ChillDocGeneratorBundle/Context/ContextManager.php @@ -0,0 +1,58 @@ +contexts = $contexts; + } + + /** + * @throw ContextNotFoundException when the context is not found + */ + public function getContextByDocGeneratorTemplate(DocGeneratorTemplate $docGeneratorTemplate): DocGeneratorContextInterface + { + foreach ($this->contexts as $key => $context) { + if ($docGeneratorTemplate->getContext() === $key) { + return $context; + } + } + + throw new ContextNotFoundException($docGeneratorTemplate->getContext()); + } + + public function getContextByKey(string $searchedKey): DocGeneratorContextInterface + { + foreach ($this->contexts as $key => $context) { + if ($searchedKey === $key) { + return $context; + } + } + + throw new ContextNotFoundException($searchedKey); + } + + public function getContexts(): array + { + return iterator_to_array($this->contexts); + } +} diff --git a/src/Bundle/ChillDocGeneratorBundle/Context/DocGeneratorContextInterface.php b/src/Bundle/ChillDocGeneratorBundle/Context/DocGeneratorContextInterface.php index 7493f7000..df148f6e1 100644 --- a/src/Bundle/ChillDocGeneratorBundle/Context/DocGeneratorContextInterface.php +++ b/src/Bundle/ChillDocGeneratorBundle/Context/DocGeneratorContextInterface.php @@ -11,8 +11,11 @@ declare(strict_types=1); namespace Chill\DocGeneratorBundle\Context; +use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate; +use Chill\DocStoreBundle\Entity\StoredObject; + /** - * Interface for context for for document generation. + * Interface for context for document generation. */ interface DocGeneratorContextInterface { @@ -21,22 +24,15 @@ interface DocGeneratorContextInterface * * @param mixed $entity */ - public function getData($entity): array; + public function getData(DocGeneratorTemplate $template, $entity, array $contextGenerationData = []): array; - /** - * Generate the form that display. - * - * @param mixed $entity - */ - public function getForm($entity); + public function getDescription(): string; - /** - * has form. - */ - public function hasForm(): bool; + public function getEntityClass(): string; - /** - * True of false which entity supports. - */ - public function supports(string $entityClass): bool; + public static function getKey(): string; + + public function getName(): string; + + public function storeGenerated(DocGeneratorTemplate $template, StoredObject $storedObject, object $entity, array $contextGenerationData): void; } diff --git a/src/Bundle/ChillDocGeneratorBundle/Context/DocGeneratorContextWithAdminFormInterface.php b/src/Bundle/ChillDocGeneratorBundle/Context/DocGeneratorContextWithAdminFormInterface.php new file mode 100644 index 000000000..3b606ccb5 --- /dev/null +++ b/src/Bundle/ChillDocGeneratorBundle/Context/DocGeneratorContextWithAdminFormInterface.php @@ -0,0 +1,25 @@ + [], - 'cloneRowAndSetValues' => [], - ]; - - $persons = $entity->getAccompanyingPeriodWork()->getPersons(); - - if (count($persons) > 0) { - $firstPerson = $persons[0]; - - $datas['setValues'][] = [ - 'firstPersonFirstName' => $firstPerson->getFirstName(), - 'firstPersonLastName' => $firstPerson->getLastName(), ]; - } - - if (get_class($entity) === AccompanyingPeriodWorkEvaluation::class) { - $values = []; - - foreach ($entity->getAccompanyingPeriodWork()->getPersons() as $person) { - $i = 1; - $values[] = [ - 'personRowId' => $i, - 'personFirstName' => $person->getFirstName(), - 'personLastName' => $person->getLastName(), - ]; - } - - $datas['cloneRowAndSetValues'][] = [ - 'personRowId', $values, ]; - } - - return $datas; - } - - /** - * Generate the form that display. - * - * @param mixed $entity - */ - public function getForm($entity) - { - throw new Exception('No implemented yet', 1); - $choices = []; - - if (get_class($entity) === AccompanyingPeriodWorkEvaluation::class) { - foreach ($entity->getAccompanyingPeriodWork()->getPersons() as $person) { - $choices[$person->getId()] = $person->getName(); - } - } - - $builder->add('members', ChoiceType::class, [ - 'choices' => $choices, - 'placeholder' => 'Choose a person', - 'label' => 'Person to add', - ]); - - return $builder; - } - - /** - * has form. - */ - public function hasForm(): bool - { - return true; - } - - /** - * True of false which entity supports. - */ - public function supports(string $entityClass): bool - { - return - (AccompanyingPeriod::class === $entityClass) - || (SocialAction::class === $entityClass); - } -} diff --git a/src/Bundle/ChillDocGeneratorBundle/Controller/AdminDocGeneratorTemplateController.php b/src/Bundle/ChillDocGeneratorBundle/Controller/AdminDocGeneratorTemplateController.php index a7d24f127..c92aff527 100644 --- a/src/Bundle/ChillDocGeneratorBundle/Controller/AdminDocGeneratorTemplateController.php +++ b/src/Bundle/ChillDocGeneratorBundle/Controller/AdminDocGeneratorTemplateController.php @@ -11,8 +11,77 @@ declare(strict_types=1); namespace Chill\DocGeneratorBundle\Controller; +use Chill\DocGeneratorBundle\Context\ContextManager; +use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate; use Chill\MainBundle\CRUD\Controller\CRUDController; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Annotation\Route; class AdminDocGeneratorTemplateController extends CRUDController { + private ContextManager $contextManager; + + public function __construct(ContextManager $contextManager) + { + $this->contextManager = $contextManager; + } + + public function generateTemplateParameter(string $action, $entity, Request $request, array $defaultTemplateParameters = []) + { + switch ($action) { + case 'new': + $context = $this->contextManager->getContextByKey($request->get('context')); + // no break + case 'edit': + $context = $this->contextManager->getContextByDocGeneratorTemplate($entity); + + return array_merge( + $defaultTemplateParameters, + ['context' => $context] + ); + + case 'index': + return array_merge( + $defaultTemplateParameters, + ['contextManager' => $this->contextManager] + ); + + default: + return parent::generateTemplateParameter($action, $entity, $request, $defaultTemplateParameters); // TODO: Change the autogenerated stub + } + } + + public function new(Request $request): Response + { + if (!$request->query->has('context')) { + return $this->redirectToRoute('chill_docgen_admin_template_pick-context'); + } + + return parent::new($request); + } + + /** + * @Route("{_locale}/admin/docgen/template/pick-context", name="chill_docgen_admin_template_pick-context") + */ + public function pickContext(Request $request): Response + { + $this->denyAccessUnlessGranted('ROLE_ADMIN'); + + return $this->render('ChillDocGeneratorBundle:Admin/DocGeneratorTemplate:pick-context.html.twig', [ + 'contexts' => $this->contextManager->getContexts(), + ]); + } + + protected function createEntity(string $action, Request $request): object + { + /** @var DocGeneratorTemplate $entity */ + $entity = parent::createEntity($action, $request); + $key = $request->query->get('context'); + $context = $this->contextManager->getContextByKey($key); + + $entity->setContext($key)->setEntity($context->getEntityClass()); + + return $entity; + } } diff --git a/src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorController.php b/src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorController.php deleted file mode 100644 index 50201f6b0..000000000 --- a/src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorController.php +++ /dev/null @@ -1,76 +0,0 @@ -generate( - 'GET', - 'FORMULAIRE_AEB.docx', - $request->query->has('expires_delay') ? $request->query->getInt('expires_delay', 0) : null - ); - - $tmpfname = tempnam(sys_get_temp_dir(), 'DOC_TEMPLATE'); - file_put_contents($tmpfname, file_get_contents($p->url)); - - $templateProcessor = new TemplateProcessor($tmpfname); - $templateProcessor->setValues(['firstname' => 'John', 'lastname' => 'Doe']); - - $tmpfname2 = tempnam(sys_get_temp_dir(), 'DOC_GENERATED'); - $templateProcessor->saveAs($tmpfname2); - - unlink($tmpfname); - - $fileContent = fopen($tmpfname2, 'rb'); // the generated file content - $response = new Response(fread($fileContent, filesize($tmpfname2))); - - $disposition = HeaderUtils::makeDisposition( - HeaderUtils::DISPOSITION_ATTACHMENT, - 'foo.docx' - ); - - $response->headers->set('Content-Disposition', $disposition); - unlink($tmpfname2); - - return $response; - } - - /** - * @Route( - * "{_locale}/doc/gen/test", - * name="chill_docgenerator_test" - * ) - */ - public function testAction(): Response - { - return (new Response())->setContent('Test'); - } -} diff --git a/src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorTemplateController.php b/src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorTemplateController.php index f517a7cc6..66d475d89 100644 --- a/src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorTemplateController.php +++ b/src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorTemplateController.php @@ -11,28 +11,97 @@ declare(strict_types=1); namespace Chill\DocGeneratorBundle\Controller; +use Base64Url\Base64Url; use ChampsLibres\AsyncUploaderBundle\TempUrl\TempUrlGeneratorInterface; -use Chill\DocGeneratorBundle\Context\HouseholdMemberSelectionContext; +use Chill\DocGeneratorBundle\Context\ContextManager; +use Chill\DocGeneratorBundle\Context\DocGeneratorContextWithPublicFormInterface; +use Chill\DocGeneratorBundle\Context\Exception\ContextNotFoundException; use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate; +use Chill\DocGeneratorBundle\GeneratorDriver\DriverInterface; +use Chill\DocGeneratorBundle\GeneratorDriver\Exception\TemplateException; use Chill\DocGeneratorBundle\Repository\DocGeneratorTemplateRepository; use Chill\DocStoreBundle\Entity\StoredObject; -use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation; -use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument; -use Chill\PersonBundle\Entity\SocialWork\Evaluation; +use Chill\MainBundle\Pagination\PaginatorFactory; +use Chill\MainBundle\Serializer\Model\Collection; use Exception; use GuzzleHttp\Client; use GuzzleHttp\Exception\TransferException; -use PhpOffice\PhpWord\TemplateProcessor; +use Psr\Log\LoggerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; -use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\Form\Extension\Core\Type\FileType; +use Symfony\Component\HttpFoundation\File\File; +use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; - // TODO à mettre dans services use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\StreamedResponse; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; +use Symfony\Component\HttpKernel\Exception\HttpException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; +use Symfony\Contracts\HttpClient\HttpClientInterface; -class DocGeneratorTemplateController extends AbstractController +final class DocGeneratorTemplateController extends AbstractController { + private HttpClientInterface $client; + + private ContextManager $contextManager; + + private DocGeneratorTemplateRepository $docGeneratorTemplateRepository; + + private DriverInterface $driver; + + private KernelInterface $kernel; + + private LoggerInterface $logger; + + private PaginatorFactory $paginatorFactory; + + private TempUrlGeneratorInterface $tempUrlGenerator; + + public function __construct( + ContextManager $contextManager, + DocGeneratorTemplateRepository $docGeneratorTemplateRepository, + DriverInterface $driver, + LoggerInterface $logger, + PaginatorFactory $paginatorFactory, + TempUrlGeneratorInterface $tempUrlGenerator, + KernelInterface $kernel, + HttpClientInterface $client + ) { + $this->contextManager = $contextManager; + $this->docGeneratorTemplateRepository = $docGeneratorTemplateRepository; + $this->driver = $driver; + $this->logger = $logger; + $this->paginatorFactory = $paginatorFactory; + $this->tempUrlGenerator = $tempUrlGenerator; + $this->kernel = $kernel; + $this->client = $client; + } + + /** + * @Route( + * "{_locale}/admin/doc/gen/generate/test/from/{template}/for/{entityClassName}/{entityId}", + * name="chill_docgenerator_test_generate_from_template" + * ) + */ + public function adminTestGenerateDocFromTemplateAction( + DocGeneratorTemplate $template, + string $entityClassName, + int $entityId, + Request $request + ): Response { + return $this->generateDocFromTemplate( + $template, + $entityClassName, + $entityId, + $request, + true + ); + } + /** * @Route( * "{_locale}/doc/gen/generate/from/{template}/for/{entityClassName}/{entityId}", @@ -40,80 +109,237 @@ class DocGeneratorTemplateController extends AbstractController * ) */ public function generateDocFromTemplateAction( - TempUrlGeneratorInterface $tempUrlGenerator, DocGeneratorTemplate $template, string $entityClassName, int $entityId, Request $request ): Response { - $getUrlGen = $tempUrlGenerator->generate( - 'GET', - $template->getFile() + return $this->generateDocFromTemplate( + $template, + $entityClassName, + $entityId, + $request, + false + ); + } + + /** + * @Route( + * "/api/1.0/docgen/templates/by-entity/{entityClassName}", + * name="chill_docgenerator_templates_for_entity_api" + * ) + */ + public function listTemplateApiAction(string $entityClassName): Response + { + $nb = $this->docGeneratorTemplateRepository->countByEntity($entityClassName); + $paginator = $this->paginatorFactory->create($nb); + $entities = $this->docGeneratorTemplateRepository->findByEntity( + $entityClassName, + $paginator->getCurrentPageFirstItemNumber(), + $paginator->getItemsPerPage() ); - $tmpfname = tempnam(sys_get_temp_dir(), 'DOC_TEMPLATE'); - file_put_contents($tmpfname, file_get_contents($getUrlGen->url)); + return $this->json( + new Collection($entities, $paginator), + Response::HTTP_OK, + [], + [AbstractNormalizer::GROUPS => ['read']] + ); + } - $entity = $this->getDoctrine()->getRepository($entityClassName)->find($entityId); + /** + * @Route( + * "{_locale}/admin/doc/gen/generate/test/redirect", + * name="chill_docgenerator_test_generate_redirect" + * ) + * + * @return void + */ + public function redirectToTestGenerate(Request $request): RedirectResponse + { + $template = $request->query->getInt('template'); - if ($template->getContext() === HouseholdMemberSelectionContext::class) { - $context = new HouseholdMemberSelectionContext(); - $datas = $context->getData($entity); + if (null === $template) { + throw new BadRequestHttpException('template parameter is missing'); + } + + $entityClassName = $request->query->get('entityClassName'); + + if (null === $entityClassName) { + throw new BadRequestHttpException('entityClassName is missing'); + } + + $entityId = $request->query->get('entityId'); + + if (null === $entityId) { + throw new BadRequestHttpException('entityId is missing'); + } + + return $this->redirectToRoute( + 'chill_docgenerator_test_generate_from_template', + ['template' => $template, 'entityClassName' => $entityClassName, 'entityId' => $entityId, + 'returnPath' => $request->query->get('returnPath', '/'), ] + ); + } + + private function generateDocFromTemplate( + DocGeneratorTemplate $template, + string $entityClassName, + int $entityId, + Request $request, + bool $isTest + ): Response { + try { + $context = $this->contextManager->getContextByDocGeneratorTemplate($template); + } catch (ContextNotFoundException $e) { + throw new NotFoundHttpException($e->getMessage(), $e); + } + + $entity = $this->getDoctrine()->getRepository($context->getEntityClass())->find($entityId); + + if (null === $entity) { + throw new NotFoundHttpException("Entity with classname {$entityClassName} and id {$entityId} is not found"); + } + + $contextGenerationData = []; + + if ( + $context instanceof DocGeneratorContextWithPublicFormInterface + && $context->hasPublicForm($template, $entity) || $isTest + ) { + if ($context instanceof DocGeneratorContextWithPublicFormInterface) { + $builder = $this->createFormBuilder( + array_merge( + $context->getFormData($template, $entity), + $isTest ? ['test_file' => null] : [] + ) + ); + } else { + $builder = $this->createFormBuilder( + ['test_file' => null] + ); + } + + $context->buildPublicForm($builder, $template, $entity); + + if ($isTest) { + $builder->add('test_file', FileType::class, [ + 'label' => 'Template file', + 'required' => false, + ]); + } + + $form = $builder->getForm()->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $contextGenerationData = $form->getData(); + } elseif (!$form->isSubmitted() || ($form->isSubmitted() && !$form->isValid())) { + $templatePath = '@ChillDocGenerator/Generator/basic_form.html.twig'; + $templateOptions = ['entity' => $entity, 'form' => $form->createView(), + 'template' => $template, 'context' => $context, ]; + + return $this->render($templatePath, $templateOptions); + } + } + + if ($isTest && null !== $contextGenerationData['test_file']) { + /** @var File $file */ + $file = $contextGenerationData['test_file']; + $templateResource = fopen($file->getPathname(), 'rb'); } else { - throw new Exception('Not implemented', 1); + $getUrlGen = $this->tempUrlGenerator->generate( + 'GET', + $template->getFile()->getFilename() + ); + + $data = $this->client->request('GET', $getUrlGen->url); + + $iv = $template->getFile()->getIv(); // iv as an Array + $ivGoodFormat = pack('C*', ...$iv); // iv as a String (ok for openssl_decrypt) + + $method = 'AES-256-CBC'; + + $key = $template->getFile()->getKeyInfos()['k']; + $keyGoodFormat = Base64Url::decode($key); + + $dataDecrypted = openssl_decrypt($data->getContent(), $method, $keyGoodFormat, 1, $ivGoodFormat); + + if (false === $dataDecrypted) { + throw new Exception('Error during Decrypt ', 1); + } + + if (false === $templateResource = fopen('php://memory', 'r+b')) { + $this->logger->error('Could not write data to memory'); + + throw new HttpException(500); + } + fwrite($templateResource, $dataDecrypted); + rewind($templateResource); } - $templateProcessor = new TemplateProcessor($tmpfname); + $datas = $context->getData($template, $entity, $contextGenerationData); - foreach ($datas['setValues'] as $setValuesConf) { - $templateProcessor->setValues($setValuesConf); + try { + $generatedResource = $this->driver->generateFromResource($templateResource, $template->getFile()->getType(), $datas, $template->getFile()->getFilename()); + } catch (TemplateException $e) { + $msg = implode("\n", $e->getErrors()); + + return new Response($msg, 400, [ + 'Content-Type' => 'text/plain', + ]); } - foreach ($datas['cloneRowAndSetValues'] as $cloneRowAndSetValues) { - $templateProcessor->cloneRowAndSetValues($cloneRowAndSetValues[0], $cloneRowAndSetValues[1]); + fclose($templateResource); + + if ($isTest) { + return new StreamedResponse( + static function () use ($generatedResource) { + fpassthru($generatedResource); + fclose($generatedResource); + }, + Response::HTTP_OK, + [ + 'Content-Transfer-Encoding', 'binary', + 'Content-Type' => 'application/vnd.oasis.opendocument.text', + 'Content-Disposition' => sprintf('attachment; filename="%s.odt"', 'generated'), + 'Content-Length' => fstat($generatedResource)['size'], + ], + ); } - $tmpfname2 = tempnam(sys_get_temp_dir(), 'DOC_GENERATED'); - $templateProcessor->saveAs($tmpfname2); + $genDocName = 'doc_' . sprintf('%010d', mt_rand()) . 'odt'; - unlink($tmpfname); - - $fileContent = fopen($tmpfname2, 'rb'); // the generated file content - - $genDocName = 'doc_' . sprintf('%010d', mt_rand()) . '.docx'; - - $getUrlGen = $tempUrlGenerator->generate( + $getUrlGen = $this->tempUrlGenerator->generate( 'PUT', $genDocName ); - unlink($tmpfname2); - $client = new Client(); try { $putResponse = $client->request('PUT', $getUrlGen->url, [ - 'body' => $fileContent, + 'body' => $generatedResource, ]); if ($putResponse->getStatusCode() === 201) { $em = $this->getDoctrine()->getManager(); $storedObject = new StoredObject(); $storedObject - // currently, only docx is supported - ->setType('application/vnd.openxmlformats-officedocument.wordprocessingml.document') + ->setType($template->getFile()->getType()) ->setFilename($genDocName); $em->persist($storedObject); - // Only for evaluation - if ($entity instanceof AccompanyingPeriodWorkEvaluation) { - $doc = new AccompanyingPeriodWorkEvaluationDocument(); - $doc - ->setStoredObject($storedObject) - ->setTemplate($template); - $entity->addDocument($doc); - $em->persist($doc); + try { + $context->storeGenerated($template, $storedObject, $entity, $contextGenerationData); + } catch (Exception $e) { + $this->logger->error('Could not store the associated document to entity', [ + 'entityClassName' => $entityClassName, + 'entityId' => $entityId, + 'contextKey' => $context->getName(), + ]); + + throw $e; } $em->flush(); @@ -129,29 +355,4 @@ class DocGeneratorTemplateController extends AbstractController throw new Exception('Unable to generate document.'); } - - /** - * @Route( - * "{_locale}/doc/gen/templates/for/{entityClassName}", - * name="chill_docgenerator_templates_for_entity_api" - * ) - */ - public function listTemplateApiAction( - string $entityClassName, - DocGeneratorTemplateRepository $templateRepository - ): Response { - $entities = $templateRepository->findByEntity($entityClassName); - - $ret = []; - - foreach ($entities as $entity) { - $ret[] = [ - 'id' => $entity->getId(), - 'name' => $entity->getName(), - 'description' => $entity->getDescription(), - ]; - } - - return new JsonResponse(['results' => $ret]); - } } diff --git a/src/Bundle/ChillDocGeneratorBundle/DataFixtures/ORM/LoadDocGeneratorTemplate.php b/src/Bundle/ChillDocGeneratorBundle/DataFixtures/ORM/LoadDocGeneratorTemplate.php index 082605fd7..86cedfb3e 100644 --- a/src/Bundle/ChillDocGeneratorBundle/DataFixtures/ORM/LoadDocGeneratorTemplate.php +++ b/src/Bundle/ChillDocGeneratorBundle/DataFixtures/ORM/LoadDocGeneratorTemplate.php @@ -12,9 +12,11 @@ declare(strict_types=1); namespace Chill\DocGeneratorBundle\DataFixtures\ORM; use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate; -use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation; +use Chill\DocStoreBundle\Entity\StoredObject; +use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Chill\PersonBundle\Service\DocGenerator\AccompanyingPeriodContext; +use DateTime; use Doctrine\Common\DataFixtures\AbstractFixture; - use Doctrine\Persistence\ObjectManager; /** @@ -28,31 +30,52 @@ class LoadDocGeneratorTemplate extends AbstractFixture [ 'name' => ['fr' => 'FORMULAIRE AEB'], 'desc' => 'stocké sur openstack comedienbe', - 'file' => 'FORMULAIRE_AEB_WITH_DATA_INJ.docx', - 'context' => 'Chill\DocGeneratorBundle\Context\HouseholdMemberSelectionContext', - 'entities' => [AccompanyingPeriodWorkEvaluation::class], + 'file' => [ + 'filename' => 'pKNlhCrQDCRsAuC8vYHDKa', + 'key' => '{"alg":"A256CBC","ext":true,"k":"_VihnD41-VDHlpS-ouwtbMPnu-OXVdtA7ENQWWtAQYM","key_ops":["encrypt","decrypt"],"kty":"oct"}', + 'iv' => '[86,231,83,148,117,107,149,173,130,19,105,194,224,145,8,48]', + 'type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + ], + 'context' => AccompanyingPeriodContext::class, + 'entity' => AccompanyingPeriod::class, + 'options' => ['mainPerson' => false, 'person1' => false, 'person2' => false], ], [ 'name' => ['fr' => 'AIDE ALIMENTAIRE'], 'desc' => 'stocké sur openstack comedienbe', - 'file' => 'AIDE_ALIMENTAIRE.docx', - 'context' => 'Chill\DocGeneratorBundle\Context\HouseholdMemberSelectionContext', - 'entities' => ['Chill\PersonBundle\Entity\AccompanyingPeriod', 'Chill\PersonBundle\Entity\SocialWork\SocialAction', AccompanyingPeriodWorkEvaluation::class], + 'file' => [ + 'filename' => 'pKNlhCrQDCRsAuC8vYHDKa', + 'key' => '{"alg":"A256CBC","ext":true,"k":"_VihnD41-VDHlpS-ouwtbMPnu-OXVdtA7ENQWWtAQYM","key_ops":["encrypt","decrypt"],"kty":"oct"}', + 'iv' => '[86,231,83,148,117,107,149,173,130,19,105,194,224,145,8,48]', + 'type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + ], + 'context' => AccompanyingPeriodContext::class, + 'entity' => AccompanyingPeriod::class, + 'options' => ['mainPerson' => false, 'person1' => false, 'person2' => false], ], ]; foreach ($templates as $template) { echo 'Adding doc generator templates ' . $template['file'] . ")\n"; + $newStoredObj = (new StoredObject()) + ->setFilename($template['file']['filename']) + ->setKeyInfos(json_decode($template['file']['key'], true)) + ->setIv(json_decode($template['file']['iv'], true)) + ->setCreationDate(new DateTime('today')) + ->setType($template['file']['type']); + + $manager->persist($newStoredObj); + $newTemplate = (new DocGeneratorTemplate()) ->setName($template['name']) ->setDescription($template['desc']) - ->setFile($template['file']) + ->setFile($newStoredObj) ->setContext($template['context']) - ->setEntities($template['entities']); + ->setEntity($template['entity']) + ->setOptions($template['options']); $manager->persist($newTemplate); - - $manager->flush(); } + $manager->flush(); } } diff --git a/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/ChillDocGeneratorExtension.php b/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/ChillDocGeneratorExtension.php index 15fd49140..9712ffac8 100644 --- a/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/ChillDocGeneratorExtension.php +++ b/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/ChillDocGeneratorExtension.php @@ -26,6 +26,10 @@ class ChillDocGeneratorExtension extends Extension implements PrependExtensionIn { public function load(array $configs, ContainerBuilder $container) { + $configuration = new Configuration(); + $config = $this->processConfiguration($configuration, $configs); + $container->setParameter('chill_doc_generator', $config); + $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../config')); $loader->load('services.yaml'); $loader->load('services/controller.yaml'); @@ -37,6 +41,7 @@ class ChillDocGeneratorExtension extends Extension implements PrependExtensionIn { $this->preprendRoutes($container); $this->prependCruds($container); + $this->prependClientConfig($container); } protected function prependCruds(ContainerBuilder $container) @@ -78,4 +83,23 @@ class ChillDocGeneratorExtension extends Extension implements PrependExtensionIn ], ]); } + + private function prependClientConfig(ContainerBuilder $container) + { + $configs = $container->getExtensionConfig($this->getAlias()); + $resolvingBag = $container->getParameterBag(); + $configs = $resolvingBag->resolveValue($configs); + + $config = $this->processConfiguration(new Configuration(), $configs); + + $container->prependExtensionConfig('framework', [ + 'http_client' => [ + 'scoped_clients' => [ + 'relatorio.client' => [ + 'scope' => $config['driver']['relatorio']['url'], + ], + ], + ], + ]); + } } diff --git a/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/Configuration.php index 161886d87..1117a5fc0 100644 --- a/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/Configuration.php @@ -14,21 +14,35 @@ namespace Chill\DocGeneratorBundle\DependencyInjection; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; -/** - * 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/configuration.html} - */ class Configuration implements ConfigurationInterface { public function getConfigTreeBuilder() { - $treeBuilder = new TreeBuilder('chill_calendar'); - $rootNode = $treeBuilder->getRootNode('chill_calendar'); + $treeBuilder = new TreeBuilder('chill_doc_generator'); + $rootNode = $treeBuilder->getRootNode(); - // Here you should define the parameters that are allowed to - // configure your bundle. See the documentation linked above for - // more information on that topic. + $rootNode + ->children() + ->arrayNode('driver') + ->addDefaultsIfNotSet() + ->children() + ->enumNode('type') + ->isRequired() + ->values(['relatorio']) + ->defaultValue('relatorio') + ->end() + ->arrayNode('relatorio') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('url') + ->isRequired() + ->defaultValue('http://relatorio:8888/') + ->end() + ->end() + ->end() + ->end() + ->end() + ->end(); return $treeBuilder; } diff --git a/src/Bundle/ChillDocGeneratorBundle/Entity/DocGeneratorTemplate.php b/src/Bundle/ChillDocGeneratorBundle/Entity/DocGeneratorTemplate.php index 75edbcbdf..ee93f74fb 100644 --- a/src/Bundle/ChillDocGeneratorBundle/Entity/DocGeneratorTemplate.php +++ b/src/Bundle/ChillDocGeneratorBundle/Entity/DocGeneratorTemplate.php @@ -11,44 +11,51 @@ declare(strict_types=1); namespace Chill\DocGeneratorBundle\Entity; +use Chill\DocStoreBundle\Entity\StoredObject; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; /** * @ORM\Entity * @ORM\Table(name="chill_docgen_template") + * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ + * "docgen_template": DocGeneratorTemplate::class + * }) */ class DocGeneratorTemplate { /** - * @ORM\Column(type="string", length=255) - * - * Class name of the context to use + * @ORM\Column(type="boolean", options={"default": true}) + */ + private bool $active = true; + + /** + * Class name of the context to use. * * so if $context = '' * this template will use '' as context + * + * @ORM\Column(type="string", length=255) */ private string $context; /** * @ORM\Column(type="text", nullable=true) + * @Serializer\Groups({"read"}) */ - private string $description; + private ?string $description = null; /** - * @ORM\Column(type="simple_array") + * Class name of the entity for which this template can be used. * - * Class name of the entities for which this template can be used - * - * so if $entities = ['Chill\PersonBundle\Entity\AccompanyingPeriod', 'Chill\PersonBundle\Entity\SocialWork\SocialAction'] - * this template can be selected for an AccompanyingPeriod or a SocialAction + * @ORM\Column(type="string", options={"default": ""}) */ - private array $entities = []; + private string $entity = ''; /** - * @ORM\Column(type="string", length=255) + * @ORM\ManyToOne(targetEntity=StoredObject::class, cascade={"persist"})) */ - private string $file; + private ?StoredObject $file = null; /** * @ORM\Id @@ -64,6 +71,13 @@ class DocGeneratorTemplate */ private array $name = []; + /** + * Options for the template. + * + * @ORM\Column(type="json", name="template_options", options={"default":"[]"}) + */ + private array $options = []; + public function getContext(): ?string { return $this->context; @@ -74,12 +88,12 @@ class DocGeneratorTemplate return $this->description; } - public function getEntities(): ?array + public function getEntity(): string { - return $this->entities; + return $this->entity; } - public function getFile(): ?string + public function getFile(): ?StoredObject { return $this->file; } @@ -94,6 +108,23 @@ class DocGeneratorTemplate return $this->name; } + public function getOptions(): array + { + return $this->options; + } + + public function isActive(): bool + { + return $this->active; + } + + public function setActive(bool $active): DocGeneratorTemplate + { + $this->active = $active; + + return $this; + } + public function setContext(string $context): self { $this->context = $context; @@ -108,14 +139,14 @@ class DocGeneratorTemplate return $this; } - public function setEntities(array $entities): self + public function setEntity(string $entity): self { - $this->entities = $entities; + $this->entity = $entity; return $this; } - public function setFile(string $file): self + public function setFile(StoredObject $file): self { $this->file = $file; @@ -128,4 +159,11 @@ class DocGeneratorTemplate return $this; } + + public function setOptions(array $options): self + { + $this->options = $options; + + return $this; + } } diff --git a/src/Bundle/ChillDocGeneratorBundle/Form/DocGeneratorTemplateType.php b/src/Bundle/ChillDocGeneratorBundle/Form/DocGeneratorTemplateType.php index 75d33d0e5..ff516d3de 100644 --- a/src/Bundle/ChillDocGeneratorBundle/Form/DocGeneratorTemplateType.php +++ b/src/Bundle/ChillDocGeneratorBundle/Form/DocGeneratorTemplateType.php @@ -11,22 +11,66 @@ declare(strict_types=1); namespace Chill\DocGeneratorBundle\Form; +use Chill\DocGeneratorBundle\Context\ContextManager; +use Chill\DocGeneratorBundle\Context\DocGeneratorContextWithAdminFormInterface; use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate; +use Chill\DocStoreBundle\Form\StoredObjectType; use Chill\MainBundle\Form\Type\TranslatableStringFormType; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\CallbackTransformer; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; class DocGeneratorTemplateType extends AbstractType { + private ContextManager $contextManager; + + public function __construct(ContextManager $contextManager) + { + $this->contextManager = $contextManager; + } + public function buildForm(FormBuilderInterface $builder, array $options) { + /** @var DocGeneratorTemplate $template */ + $template = $options['data']; + $context = $this->contextManager->getContextByKey($template->getContext()); + $builder ->add('name', TranslatableStringFormType::class, [ 'label' => 'Nom', ]) ->add('description') - ->add('file'); + ->add('file', StoredObjectType::class, [ + 'error_bubbling' => true, + ]) + ->add('active', ChoiceType::class, [ + 'label' => 'Active', + 'choices' => [ + 'Yes' => true, + 'No' => false, + ], + 'required' => true, + ]); + + if ( + $context instanceof DocGeneratorContextWithAdminFormInterface + && $context->hasAdminForm() + ) { + $sub = $builder + ->create('options', null, ['compound' => true]) + ->addModelTransformer(new CallbackTransformer( + static function (array $data) use ($context) { + return $context->adminFormTransform($data); + }, + static function (array $data) use ($context) { + return $context->adminFormReverseTransform($data); + } + )); + $context->buildAdminForm($sub); + $builder->add($sub); + } } public function configureOptions(OptionsResolver $resolver) diff --git a/src/Bundle/ChillDocGeneratorBundle/GeneratorDriver/DriverInterface.php b/src/Bundle/ChillDocGeneratorBundle/GeneratorDriver/DriverInterface.php new file mode 100644 index 000000000..2572484e1 --- /dev/null +++ b/src/Bundle/ChillDocGeneratorBundle/GeneratorDriver/DriverInterface.php @@ -0,0 +1,22 @@ +errors = $errors; + } + + public function getErrors(): array + { + return $this->errors; + } +} diff --git a/src/Bundle/ChillDocGeneratorBundle/GeneratorDriver/RelatorioDriver.php b/src/Bundle/ChillDocGeneratorBundle/GeneratorDriver/RelatorioDriver.php new file mode 100644 index 000000000..7101e562d --- /dev/null +++ b/src/Bundle/ChillDocGeneratorBundle/GeneratorDriver/RelatorioDriver.php @@ -0,0 +1,93 @@ +relatorioClient = $relatorioClient; + $this->logger = $logger; + $this->url = $parameterBag->get('chill_doc_generator')['driver']['relatorio']['url']; + } + + public function generateFromResource($template, string $resourceType, array $data, ?string $templateName = null) + { + $formFields = [ + 'variables' => json_encode($data), + 'template' => new DataPart($template, $templateName ?? uniqid('template_'), $resourceType), + ]; + $form = new FormDataPart($formFields); + dump(json_encode($data)); + + try { + $response = $this->relatorioClient->request('POST', $this->url, [ + 'headers' => $form->getPreparedHeaders()->toArray(), + 'body' => $form->bodyToIterable(), + ]); + + return $response->toStream(); + } catch (HttpExceptionInterface $e) { + $content = $e->getResponse()->getContent(false); + + if (400 === $e->getResponse()->getStatusCode()) { + $content = json_decode($content, true); + $this->logger->error('relatorio: template error', [ + 'error' => $content['message'] ?? '_not defined', + ]); + + throw new TemplateException([$content['message']]); + } + + $this->logger->error('relatorio: error while generating document', [ + 'msg' => $e->getMessage(), + 'response' => $e->getResponse()->getStatusCode(), + 'content' => $content, + ]); + + throw $e; + } catch (TransportExceptionInterface $e) { + $this->logger->error('relatorio: transport exception', [ + 'msg' => $e->getMessage(), + 'e' => $e->getTraceAsString(), + ]); + + throw $e; + } catch (DecodingExceptionInterface $e) { + $this->logger->error('relatorio: could not decode response', [ + 'msg' => $e->getMessage(), + 'e' => $e->getTraceAsString(), + ]); + + throw $e; + } + } +} diff --git a/src/Bundle/ChillDocGeneratorBundle/Menu/AdminMenuBuilder.php b/src/Bundle/ChillDocGeneratorBundle/Menu/AdminMenuBuilder.php new file mode 100644 index 000000000..d88f0c122 --- /dev/null +++ b/src/Bundle/ChillDocGeneratorBundle/Menu/AdminMenuBuilder.php @@ -0,0 +1,51 @@ +translator = $translator; + $this->security = $security; + } + + public function buildMenu($menuId, MenuItem $menu, array $parameters) + { + if ($this->security->isGranted('ROLE_ADMIN')) { + if (in_array($menuId, ['admin_index', 'admin_section'], true)) { + $menu->addChild($this->translator->trans('docgen.Document generation'), [ + 'route' => 'chill_crud_docgen_template_index', + ])->setExtras([ + 'order' => 350, + 'explain' => 'docgen.Manage templates and document generation', + ]); + } + } + } + + public static function getMenuIds(): array + { + return ['admin_index', 'admin_section', 'docgen_admin']; + } +} diff --git a/src/Bundle/ChillDocGeneratorBundle/Repository/DocGeneratorTemplateRepository.php b/src/Bundle/ChillDocGeneratorBundle/Repository/DocGeneratorTemplateRepository.php index df0e0bd3d..5d99efa94 100644 --- a/src/Bundle/ChillDocGeneratorBundle/Repository/DocGeneratorTemplateRepository.php +++ b/src/Bundle/ChillDocGeneratorBundle/Repository/DocGeneratorTemplateRepository.php @@ -25,6 +25,18 @@ final class DocGeneratorTemplateRepository implements ObjectRepository $this->repository = $entityManager->getRepository(DocGeneratorTemplate::class); } + public function countByEntity(string $entity): int + { + $builder = $this->repository->createQueryBuilder('t'); + + $builder + ->select('count(t)') + ->where('t.entity LIKE :entity') + ->setParameter('entity', addslashes($entity)); + + return $builder->getQuery()->getSingleScalarResult(); + } + public function find($id, $lockMode = null, $lockVersion = null): ?DocGeneratorTemplate { return $this->repository->find($id, $lockMode, $lockVersion); @@ -49,15 +61,22 @@ final class DocGeneratorTemplateRepository implements ObjectRepository return $this->repository->findBy($criteria, $orderBy, $limit, $offset); } - public function findByEntity($entity) + /** + * @return array|DocGeneratorTemplate[] + */ + public function findByEntity(string $entity, ?int $start = 0, ?int $limit = 50): array { $builder = $this->repository->createQueryBuilder('t'); $builder - ->where('t.entities LIKE :entity') - ->setParameter('entity', '%' . addslashes($entity) . '%'); + ->where('t.entity LIKE :entity') + ->setParameter('entity', addslashes($entity)); - return $builder->getQuery()->execute(); + return $builder + ->getQuery() + ->setFirstResult($start) + ->setMaxResults($limit) + ->getResult(); } public function findOneBy(array $criteria, ?array $orderBy = null): ?DocGeneratorTemplate diff --git a/src/Bundle/ChillDocGeneratorBundle/Resources/public/api/pickTemplate.js b/src/Bundle/ChillDocGeneratorBundle/Resources/public/api/pickTemplate.js new file mode 100644 index 000000000..a668fe29d --- /dev/null +++ b/src/Bundle/ChillDocGeneratorBundle/Resources/public/api/pickTemplate.js @@ -0,0 +1,10 @@ +import { fetchResults } from "ChillMainAssets/lib/api/apiMethods.js"; + +const fetchTemplates = (entityClass) => { + let fqdnEntityClass = encodeURI(entityClass); + return fetchResults(`/api/1.0/docgen/templates/by-entity/${fqdnEntityClass}`); +} + +export { + fetchTemplates +}; diff --git a/src/Bundle/ChillDocGeneratorBundle/Resources/public/module/PickTemplate/index.js b/src/Bundle/ChillDocGeneratorBundle/Resources/public/module/PickTemplate/index.js new file mode 100644 index 000000000..9d26d1009 --- /dev/null +++ b/src/Bundle/ChillDocGeneratorBundle/Resources/public/module/PickTemplate/index.js @@ -0,0 +1,27 @@ +import {createApp} from 'vue'; +import PickTemplate from 'ChillDocGeneratorAssets/vuejs/_components/PickTemplate.vue'; +import {fetchTemplates} from 'ChillDocGeneratorAssets/api/pickTemplate.js'; +import {_createI18n} from 'ChillMainAssets/vuejs/_js/i18n'; + +const i18n = _createI18n({}); + +document.querySelectorAll('div[data-docgen-template-picker]').forEach(el => { + fetchTemplates(el.dataset.entityClass).then(templates => { + let + picker = { + template: '', + components: { + PickTemplate, + }, + data() { + return { + templates: templates, + entityId: el.dataset.entityId, + } + }, + } + ; + createApp(picker).use(i18n).mount(el); + }) + +}); diff --git a/src/Bundle/ChillDocGeneratorBundle/Resources/public/vuejs/_components/PickTemplate.vue b/src/Bundle/ChillDocGeneratorBundle/Resources/public/vuejs/_components/PickTemplate.vue new file mode 100644 index 000000000..f1fb6c84b --- /dev/null +++ b/src/Bundle/ChillDocGeneratorBundle/Resources/public/vuejs/_components/PickTemplate.vue @@ -0,0 +1,141 @@ + + + + + diff --git a/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/DocGeneratorTemplate/edit.html.twig b/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/DocGeneratorTemplate/edit.html.twig index 040dea1c0..93b08f688 100644 --- a/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/DocGeneratorTemplate/edit.html.twig +++ b/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/DocGeneratorTemplate/edit.html.twig @@ -1,12 +1,25 @@ -{% extends '@ChillPerson/Admin/layout.html.twig' %} +{% extends '@ChillDocGenerator/Admin/layout.html.twig' %} -{% block title %} - {% include('@ChillMain/CRUD/_edit_title.html.twig') %} -{% endblock %} +{% block title 'docgen.Edit template'|trans %} {% block layout_wvm_content %} {% embed '@ChillMain/CRUD/_edit_content.html.twig' %} + + {% block crud_content_header %} +

        {{ 'docgen.Edit template'|trans }}

        +

        {{ 'docgen.With context %name%'|trans({'%name%': context.name|trans }) }}

        + {% endblock crud_content_header %} + {% block content_form_actions_view %}{% endblock %} {% block content_form_actions_save_and_show %}{% endblock %} {% endembed %} {% endblock %} + +{% block js %} + {{ parent() }} + {{ encore_entry_script_tags('mod_async_upload') }} +{% endblock %} + +{% block css %} + {{ encore_entry_link_tags('mod_async_upload') }} +{% endblock %} diff --git a/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/DocGeneratorTemplate/index.html.twig b/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/DocGeneratorTemplate/index.html.twig index c601b8836..29050ce02 100644 --- a/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/DocGeneratorTemplate/index.html.twig +++ b/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/DocGeneratorTemplate/index.html.twig @@ -1,19 +1,40 @@ -{% extends '@ChillPerson/Admin/layout.html.twig' %} +{% extends '@ChillDocGenerator/Admin/layout.html.twig' %} {% block layout_wvm_content %} {% embed '@ChillMain/CRUD/_index.html.twig' %} {% block table_entities_thead_tr %} {{ 'Title'|trans }} - {{ 'File'|trans }} + {{ 'docgen.Context'|trans }} + {{ 'docgen.test generate'|trans }} + {{ 'Edit'|trans }} {% endblock %} {% block table_entities_tbody %} {% for entity in entities %} {{ entity.id }} - {{ entity.name | localize_translatable_string }} - {{ entity.file }} + {{ entity.name|localize_translatable_string}} + {{ contextManager.getContextByKey(entity.context).name|trans }} + +
        + + + + + +
          +
        • + +
        • +
        +
        + + + + {{ 'Edit'|trans }} + + {% endfor %} {% endblock %} diff --git a/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/DocGeneratorTemplate/new.html.twig b/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/DocGeneratorTemplate/new.html.twig index f31ac39c9..fe4991ffa 100644 --- a/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/DocGeneratorTemplate/new.html.twig +++ b/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/DocGeneratorTemplate/new.html.twig @@ -1,11 +1,25 @@ -{% extends '@ChillPerson/Admin/layout.html.twig' %} +{% extends '@ChillDocGenerator/Admin/layout.html.twig' %} -{% block title %} - {% include('@ChillMain/CRUD/_new_title.html.twig') %} -{% endblock %} +{% block title 'docgen.New template'|trans %} {% block layout_wvm_content %} {% embed '@ChillMain/CRUD/_new_content.html.twig' %} + + {% block crud_content_header %} +

        {{ 'docgen.New template'|trans }}

        +

        {{ 'docgen.With context %name%'|trans({'%name%': context.name|trans }) }}

        + {% endblock crud_content_header %} + {% block content_form_actions_save_and_show %}{% endblock %} + {% endembed %} {% endblock %} + +{% block js %} + {{ parent() }} + {{ encore_entry_script_tags('mod_async_upload') }} +{% endblock %} + +{% block css %} + {{ encore_entry_link_tags('mod_async_upload') }} +{% endblock %} diff --git a/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/DocGeneratorTemplate/pick-context.html.twig b/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/DocGeneratorTemplate/pick-context.html.twig new file mode 100644 index 000000000..5e3ff2049 --- /dev/null +++ b/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/DocGeneratorTemplate/pick-context.html.twig @@ -0,0 +1,27 @@ +{% extends '@ChillDocGenerator/Admin/layout.html.twig' %} + +{% block title 'docgen.Pick template context'|trans %} + +{% block layout_wvm_content %} +
        + +

        {{ block('title') }}

        +
        + {% for key, context in contexts %} +
        + +
        + {{ context.description|trans|nl2br }} +
        +
        + {% endfor %} +
        +
        + +{% endblock %} diff --git a/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/layout.html.twig b/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/layout.html.twig new file mode 100644 index 000000000..6e7c9387c --- /dev/null +++ b/src/Bundle/ChillDocGeneratorBundle/Resources/views/Admin/layout.html.twig @@ -0,0 +1,4 @@ +{% extends '@ChillPerson/Admin/layout.html.twig' %} + +{% block vertical_menu_content %} +{% endblock %} diff --git a/src/Bundle/ChillDocGeneratorBundle/Resources/views/Generator/basic_form.html.twig b/src/Bundle/ChillDocGeneratorBundle/Resources/views/Generator/basic_form.html.twig new file mode 100644 index 000000000..7b24eae0d --- /dev/null +++ b/src/Bundle/ChillDocGeneratorBundle/Resources/views/Generator/basic_form.html.twig @@ -0,0 +1,22 @@ +{% extends 'ChillMainBundle::layout.html.twig' %} + +{% block title 'docgen.Generate a document'|trans %} + +{% block content %} +
        +

        {{ block('title') }}

        +

        {{ template.name|localize_translatable_string }}

        + + {{ form_start(form, { 'attr': { 'id': 'generate_doc_form' }}) }} + {{ form(form) }} + {{ form_end(form) }} + +
          +
        • + +
        • +
        +
        +{% endblock %} diff --git a/src/Bundle/ChillDocGeneratorBundle/Serializer/Encoder/DocGenEncoder.php b/src/Bundle/ChillDocGeneratorBundle/Serializer/Encoder/DocGenEncoder.php index 2de46228a..b8fca5119 100644 --- a/src/Bundle/ChillDocGeneratorBundle/Serializer/Encoder/DocGenEncoder.php +++ b/src/Bundle/ChillDocGeneratorBundle/Serializer/Encoder/DocGenEncoder.php @@ -11,13 +11,15 @@ declare(strict_types=1); namespace Chill\DocGeneratorBundle\Serializer\Encoder; +use Symfony\Component\Serializer\Encoder\EncoderInterface; + use Symfony\Component\Serializer\Exception\UnexpectedValueException; use function array_keys; use function is_array; -class DocGenEncoder implements \Symfony\Component\Serializer\Encoder\EncoderInterface +class DocGenEncoder implements EncoderInterface { - public function encode($data, string $format, array $context = []) + public function encode($data, $format, array $context = []) { if (!$this->isAssociative($data)) { throw new UnexpectedValueException('Only associative arrays are allowed; lists are not allowed'); @@ -29,7 +31,7 @@ class DocGenEncoder implements \Symfony\Component\Serializer\Encoder\EncoderInte return $result; } - public function supportsEncoding(string $format) + public function supportsEncoding($format) { return 'docgen' === $format; } diff --git a/src/Bundle/ChillDocGeneratorBundle/Serializer/Helper/NormalizeNullValueHelper.php b/src/Bundle/ChillDocGeneratorBundle/Serializer/Helper/NormalizeNullValueHelper.php index 594ae8376..91e8e6170 100644 --- a/src/Bundle/ChillDocGeneratorBundle/Serializer/Helper/NormalizeNullValueHelper.php +++ b/src/Bundle/ChillDocGeneratorBundle/Serializer/Helper/NormalizeNullValueHelper.php @@ -12,20 +12,32 @@ declare(strict_types=1); namespace Chill\DocGeneratorBundle\Serializer\Helper; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; + use function array_merge; class NormalizeNullValueHelper { + private ?string $discriminatorType = null; + + private ?string $discriminatorValue = null; + private NormalizerInterface $normalizer; - public function __construct(NormalizerInterface $normalizer) + public function __construct(NormalizerInterface $normalizer, $discriminatorType = null, $discriminatorValue = null) { $this->normalizer = $normalizer; + $this->discriminatorType = $discriminatorType; + $this->discriminatorValue = $discriminatorValue; } public function normalize(array $attributes, string $format = 'docgen', ?array $context = []) { $data = []; + $data['isNull'] = true; + + if (null !== $this->discriminatorType) { + $data[$this->discriminatorType] = $this->discriminatorValue; + } foreach ($attributes as $key => $class) { if (is_numeric($key)) { diff --git a/src/Bundle/ChillDocGeneratorBundle/Serializer/Normalizer/CollectionDocGenNormalizer.php b/src/Bundle/ChillDocGeneratorBundle/Serializer/Normalizer/CollectionDocGenNormalizer.php new file mode 100644 index 000000000..55774dd83 --- /dev/null +++ b/src/Bundle/ChillDocGeneratorBundle/Serializer/Normalizer/CollectionDocGenNormalizer.php @@ -0,0 +1,57 @@ +count()) { + return $data; + } + + foreach ($object->getIterator() as $item) { + $data[] = $this->normalizer->normalize($item, $format, $context); + } + + return $data; + } + + public function supportsNormalization($data, $format = null, array $context = []) + { + if ('docgen' !== $format) { + return false; + } + + return $data instanceof Collection + || (null === $data && Collection::class === ($context['docgen:expects'] ?? null)); + } +} diff --git a/src/Bundle/ChillDocGeneratorBundle/Serializer/Normalizer/DocGenObjectNormalizer.php b/src/Bundle/ChillDocGeneratorBundle/Serializer/Normalizer/DocGenObjectNormalizer.php index 040738571..fc4b4beb9 100644 --- a/src/Bundle/ChillDocGeneratorBundle/Serializer/Normalizer/DocGenObjectNormalizer.php +++ b/src/Bundle/ChillDocGeneratorBundle/Serializer/Normalizer/DocGenObjectNormalizer.php @@ -12,7 +12,9 @@ declare(strict_types=1); namespace Chill\DocGeneratorBundle\Serializer\Normalizer; use Chill\DocGeneratorBundle\Serializer\Helper\NormalizeNullValueHelper; +use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use ReflectionClass; +use RuntimeException; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessor; use Symfony\Component\Serializer\Exception\ExceptionInterface; @@ -24,6 +26,7 @@ use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; + use function array_filter; use function array_key_exists; use function array_merge; @@ -41,18 +44,32 @@ class DocGenObjectNormalizer implements NormalizerAwareInterface, NormalizerInte private PropertyAccessor $propertyAccess; - public function __construct(ClassMetadataFactoryInterface $classMetadataFactory) - { + private TranslatableStringHelperInterface $translatableStringHelper; + + public function __construct( + ClassMetadataFactoryInterface $classMetadataFactory, + TranslatableStringHelperInterface $translatableStringHelper + ) { $this->classMetadataFactory = $classMetadataFactory; $this->propertyAccess = PropertyAccess::createPropertyAccessor(); + $this->translatableStringHelper = $translatableStringHelper; } - public function normalize($object, ?string $format = null, array $context = []) + public function normalize($object, $format = null, array $context = []) { - $classMetadataKey = $object ?? $context['docgen:expects']; + $classMetadataKey = $object ?? $context['docgen:expects'] ?? null; + + if (null === $classMetadataKey) { + throw new RuntimeException('Could not determine the metadata for this object. Either provide a non-null object, or a "docgen:expects" key in the context'); + } if (!$this->classMetadataFactory->hasMetadataFor($classMetadataKey)) { - throw new LogicException(sprintf('This object does not have metadata: %s. Add groups on this entity to allow to serialize with the format %s and groups %s', is_object($object) ? get_class($object) : $context['docgen:expects'], $format, implode(', ', $context['groups']))); + throw new LogicException(sprintf( + 'This object does not have metadata: %s. Add groups on this entity to allow to serialize with the format %s and groups %s', + is_object($object) ? get_class($object) : '(todo' /*$context['docgen:expects'],*/, + $format, + implode(', ', ($context['groups'] ?? [])) + )); } $metadata = $this->classMetadataFactory->getMetadataFor($classMetadataKey); @@ -79,26 +96,63 @@ class DocGenObjectNormalizer implements NormalizerAwareInterface, NormalizerInte return $this->normalizeObject($object, $format, $context, $expectedGroups, $metadata, $attributes); } - public function supportsNormalization($data, ?string $format = null): bool + public function supportsNormalization($data, $format = null): bool { return 'docgen' === $format && (is_object($data) || null === $data); } private function getExpectedType(AttributeMetadata $attribute, ReflectionClass $reflection): string { - // we have to get the expected content - if ($reflection->hasProperty($attribute->getName())) { - $type = $reflection->getProperty($attribute->getName())->getType(); - } elseif ($reflection->hasMethod($attribute->getName())) { - $type = $reflection->getMethod($attribute->getName())->getReturnType(); - } else { - throw new \LogicException(sprintf( - 'Could not determine how the content is determined for the attribute %s. Add attribute property only on property or method', - $attribute->getName() - )); - } + $type = null; - if (null === $type) { + do { + // we have to get the expected content + if ($reflection->hasProperty($attribute->getName())) { + if (!$reflection->getProperty($attribute->getName())->hasType()) { + throw new \LogicException(sprintf( + 'Could not determine how the content is determined for the attribute %s on class %s. Add a type on this property', + $attribute->getName(), + $reflection->getName() + )); + } + + $type = $reflection->getProperty($attribute->getName())->getType(); + } elseif ($reflection->hasMethod($method = 'get' . ucfirst($attribute->getName()))) { + if (!$reflection->getMethod($method)->hasReturnType()) { + throw new \LogicException(sprintf( + 'Could not determine how the content is determined for the attribute %s on class %s. Add a return type on the method', + $attribute->getName(), + $reflection->getName() + )); + } + + $type = $reflection->getMethod($method)->getReturnType(); + } elseif ($reflection->hasMethod($method = 'is' . ucfirst($attribute->getName()))) { + if (!$reflection->getMethod($method)->hasReturnType()) { + throw new \LogicException(sprintf( + 'Could not determine how the content is determined for the attribute %s on class %s. Add a return type on the method', + $attribute->getName(), + $reflection->getName() + )); + } + + $type = $reflection->getMethod($method)->getReturnType(); + } elseif ($reflection->hasMethod($attribute->getName())) { + if (!$reflection->getMethod($attribute->getName())->hasReturnType()) { + throw new \LogicException(sprintf( + 'Could not determine how the content is determined for the attribute %s on class %s. Add a return type on the method', + $attribute->getName(), + $reflection->getName() + )); + } + + $type = $reflection->getMethod($attribute->getName())->getReturnType(); + } else { + $reflection = $reflection->getParentClass(); + } + } while (null === $type && $reflection instanceof ReflectionClass); + + if (null === $type ?? null) { throw new \LogicException(sprintf( 'Could not determine the type for this attribute: %s. Add a return type to the method or property declaration', $attribute->getName() @@ -115,12 +169,32 @@ class DocGenObjectNormalizer implements NormalizerAwareInterface, NormalizerInte { $keys = []; + // add a discriminator + if (null !== $discriminator = $metadata->getClassDiscriminatorMapping()) { + $typeKey = $discriminator->getTypeProperty(); + $typeValue = null; + + foreach ($discriminator->getTypesMapping() as $type => $typeClass) { + if ($typeClass === $context['docgen:expects']) { + $typeValue = $type; + + break; + } + } + + if (null === $typeValue) { + $typeKey = null; + } + } else { + $typeKey = $typeValue = null; + } + foreach ($attributes as $attribute) { $key = $attribute->getSerializedName() ?? $attribute->getName(); $keys[$key] = $this->getExpectedType($attribute, $metadata->getReflectionClass()); } - $normalizer = new NormalizeNullValueHelper($this->normalizer); + $normalizer = new NormalizeNullValueHelper($this->normalizer, $typeKey, $typeValue); return $normalizer->normalize($keys, $format, $context); } @@ -134,11 +208,19 @@ class DocGenObjectNormalizer implements NormalizerAwareInterface, NormalizerInte switch ($type) { case 'array': + if (in_array('is-translatable', $attribute->getNormalizationContextForGroups(['docgen:read']), true)) { + return ''; + } + + return []; + case 'bool': case 'double': case 'float': case 'int': case 'resource': + return null; + case 'string': return ''; @@ -166,14 +248,37 @@ class DocGenObjectNormalizer implements NormalizerAwareInterface, NormalizerInte private function normalizeObject($object, $format, array $context, array $expectedGroups, ClassMetadata $metadata, array $attributes) { $data = []; + $data['isNull'] = false; $reflection = $metadata->getReflectionClass(); + // add a discriminator + if (null !== $discriminator = $metadata->getClassDiscriminatorMapping()) { + $data[$discriminator->getTypeProperty()] = $discriminator->getMappedObjectType($object); + } + foreach ($attributes as $attribute) { /** @var AttributeMetadata $attribute */ $value = $this->propertyAccess->getValue($object, $attribute->getName()); $key = $attribute->getSerializedName() ?? $attribute->getName(); + $isTranslatable = $attribute->getNormalizationContextForGroups( + is_array($context['groups']) ? $context['groups'] : [$context['groups']] + )['is-translatable'] ?? false; - if (is_object($value)) { + if ($isTranslatable) { + $data[$key] = $this->translatableStringHelper + ->localize($value); + } elseif (is_iterable($value)) { + $arr = []; + + foreach ($value as $k => $v) { + $arr[$k] = + $this->normalizer->normalize($v, $format, array_merge( + $context, + $attribute->getNormalizationContextForGroups($expectedGroups) + )); + } + $data[$key] = $arr; + } elseif (is_object($value)) { $data[$key] = $this->normalizer->normalize($value, $format, array_merge( $context, @@ -182,7 +287,7 @@ class DocGenObjectNormalizer implements NormalizerAwareInterface, NormalizerInte } elseif (null === $value) { $data[$key] = $this->normalizeNullOutputValue($format, $context, $attribute, $reflection); } else { - $data[$key] = (string) $value; + $data[$key] = $value; } } diff --git a/src/Bundle/ChillDocGeneratorBundle/Service/Context/BaseContextData.php b/src/Bundle/ChillDocGeneratorBundle/Service/Context/BaseContextData.php new file mode 100644 index 000000000..0e2da164f --- /dev/null +++ b/src/Bundle/ChillDocGeneratorBundle/Service/Context/BaseContextData.php @@ -0,0 +1,53 @@ +security = $security; + $this->normalizer = $normalizer; + } + + public function getData(): array + { + $data = []; + $user = $this->security->getUser(); + + $data['creator'] = $this->normalizer->normalize( + $user instanceof User ? $user : null, + 'docgen', + ['docgen:expects' => User::class, 'groups' => ['docgen:read']] + ); + $data['createdAt'] = $this->normalizer->normalize(new DateTimeImmutable(), 'docgen', [ + 'docgen:expects' => DateTimeImmutable::class, 'groups' => ['docgen:read'], + ]); + $data['location'] = $this->normalizer->normalize( + $user instanceof User ? $user->getCurrentLocation() : null, + 'docgen', + ['docgen:expects' => Location::class, 'groups' => ['docgen:read']] + ); + + return $data; + } +} diff --git a/src/Bundle/ChillDocGeneratorBundle/chill.webpack.config.js b/src/Bundle/ChillDocGeneratorBundle/chill.webpack.config.js index d894be9b0..9017c7e08 100644 --- a/src/Bundle/ChillDocGeneratorBundle/chill.webpack.config.js +++ b/src/Bundle/ChillDocGeneratorBundle/chill.webpack.config.js @@ -3,4 +3,6 @@ module.exports = function(encore, entries) { encore.addAliases({ ChillDocGeneratorAssets: __dirname + '/Resources/public' }); + + encore.addEntry('mod_docgen_picktemplate', __dirname + '/Resources/public/module/PickTemplate/index.js'); }; diff --git a/src/Bundle/ChillDocGeneratorBundle/config/services.yaml b/src/Bundle/ChillDocGeneratorBundle/config/services.yaml index 6d87dbd25..5bdfe2a11 100644 --- a/src/Bundle/ChillDocGeneratorBundle/config/services.yaml +++ b/src/Bundle/ChillDocGeneratorBundle/config/services.yaml @@ -9,9 +9,43 @@ services: autoconfigure: true resource: '../Repository/' + Chill\DocGeneratorBundle\Menu\: + autoconfigure: true + autowire: true + resource: '../Menu/' + Chill\DocGeneratorBundle\Serializer\Normalizer\: autowire: true autoconfigure: true resource: '../Serializer/Normalizer/' tags: - { name: 'serializer.normalizer', priority: -152 } + Chill\DocGeneratorBundle\Serializer\Normalizer\CollectionDocGenNormalizer: + tags: + - { name: 'serializer.normalizer', priority: -126 } + + Chill\DocGeneratorBundle\Controller\: + resource: "../Controller" + autowire: true + autoconfigure: true + + Chill\DocGeneratorBundle\Form\: + resource: "../Form/" + autowire: true + autoconfigure: true + + Chill\DocGeneratorBundle\Service\Context\: + resource: "../Service/Context/" + autowire: true + autoconfigure: true + + Chill\DocGeneratorBundle\GeneratorDriver\: + resource: "../GeneratorDriver/" + autowire: true + autoconfigure: true + + Chill\DocGeneratorBundle\Driver\RelatorioDriver: '@Chill\DocGeneratorBundle\Driver\DriverInterface' + + Chill\DocGeneratorBundle\Context\ContextManager: + arguments: + $contexts: !tagged_iterator { tag: chill_docgen.context, default_index_method: getKey } diff --git a/src/Bundle/ChillDocGeneratorBundle/migrations/Version20211103111010.php b/src/Bundle/ChillDocGeneratorBundle/migrations/Version20211103111010.php new file mode 100644 index 000000000..1530fd065 --- /dev/null +++ b/src/Bundle/ChillDocGeneratorBundle/migrations/Version20211103111010.php @@ -0,0 +1,46 @@ +addSql('ALTER TABLE chill_docgen_template DROP CONSTRAINT FK_49A347E893CB796C'); + $this->addSql('DROP INDEX IDX_49A347E893CB796C'); + $this->addSql('ALTER TABLE chill_docgen_template ADD file VARCHAR(255) NOT NULL'); + $this->addSql('ALTER TABLE chill_docgen_template DROP file_id'); + $this->addSql('ALTER TABLE chill_docgen_template ALTER entities DROP NOT NULL'); + $this->addSql('ALTER TABLE chill_docgen_template ALTER context DROP NOT NULL'); + } + + public function getDescription(): string + { + return 'Using DocStore objects inside the DocGenTemplate'; + } + + public function up(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_docgen_template ADD file_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_docgen_template DROP file'); + $this->addSql('ALTER TABLE chill_docgen_template ALTER entities SET NOT NULL'); + $this->addSql('ALTER TABLE chill_docgen_template ALTER context SET NOT NULL'); + $this->addSql('ALTER TABLE chill_docgen_template ADD CONSTRAINT FK_49A347E893CB796C FOREIGN KEY (file_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('CREATE INDEX IDX_49A347E893CB796C ON chill_docgen_template (file_id)'); + } +} diff --git a/src/Bundle/ChillDocGeneratorBundle/migrations/Version20211201191757.php b/src/Bundle/ChillDocGeneratorBundle/migrations/Version20211201191757.php new file mode 100644 index 000000000..814974d7b --- /dev/null +++ b/src/Bundle/ChillDocGeneratorBundle/migrations/Version20211201191757.php @@ -0,0 +1,41 @@ +addSql('ALTER TABLE chill_docgen_template DROP active'); + $this->addSql('ALTER TABLE chill_docgen_template DROP entity'); + $this->addSql('ALTER TABLE chill_docgen_template DROP template_options'); + $this->addSql('ALTER TABLE chill_docgen_template ADD entities TEXT'); + $this->addSql('COMMENT ON COLUMN chill_docgen_template.entities IS \'(DC2Type:simple_array)\''); + } + + public function getDescription(): string + { + return 'Add options, active and link to entity in docgen_template'; + } + + public function up(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_docgen_template ADD active BOOLEAN DEFAULT true NOT NULL'); + $this->addSql('ALTER TABLE chill_docgen_template ADD entity VARCHAR(255) NOT NULL DEFAULT \'\''); + $this->addSql('ALTER TABLE chill_docgen_template ADD template_options JSONB NOT NULL DEFAULT \'[]\'::jsonb '); + $this->addSql('COMMENT ON COLUMN chill_docgen_template.template_options IS \'(DC2Type:json)\''); + $this->addSql('ALTER TABLE chill_docgen_template DROP entities'); + } +} diff --git a/src/Bundle/ChillDocGeneratorBundle/tests/Serializer/Encoder/DocGenEncoderTest.php b/src/Bundle/ChillDocGeneratorBundle/tests/Serializer/Encoder/DocGenEncoderTest.php index 35768a28c..1e529712f 100644 --- a/src/Bundle/ChillDocGeneratorBundle/tests/Serializer/Encoder/DocGenEncoderTest.php +++ b/src/Bundle/ChillDocGeneratorBundle/tests/Serializer/Encoder/DocGenEncoderTest.php @@ -23,7 +23,7 @@ final class DocGenEncoderTest extends TestCase { private DocGenEncoder $encoder; - protected function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/src/Bundle/ChillDocGeneratorBundle/tests/Serializer/Normalizer/DocGenObjectNormalizerTest.php b/src/Bundle/ChillDocGeneratorBundle/tests/Serializer/Normalizer/DocGenObjectNormalizerTest.php index 04a241d26..ef7055048 100644 --- a/src/Bundle/ChillDocGeneratorBundle/tests/Serializer/Normalizer/DocGenObjectNormalizerTest.php +++ b/src/Bundle/ChillDocGeneratorBundle/tests/Serializer/Normalizer/DocGenObjectNormalizerTest.php @@ -11,7 +11,7 @@ declare(strict_types=1); namespace Chill\DocGeneratorBundle\tests\Serializer\Normalizer; -use Chill\MainBundle\Entity\Center; +use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\User; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; @@ -25,7 +25,7 @@ final class DocGenObjectNormalizerTest extends KernelTestCase { private NormalizerInterface $normalizer; - protected function setUp() + protected function setUp(): void { parent::setUp(); self::bootKernel(); @@ -35,25 +35,36 @@ final class DocGenObjectNormalizerTest extends KernelTestCase public function testNormalizationBasic() { - $user = new User(); - $user->setUsername('User Test'); - $user->setMainCenter($center = new Center()); - $center->setName('test'); + $scope = new Scope(); + $scope->setName(['fr' => 'scope']); - $normalized = $this->normalizer->normalize($user, 'docgen', [AbstractNormalizer::GROUPS => ['docgen:read']]); + $normalized = $this->normalizer->normalize($scope, 'docgen', [AbstractNormalizer::GROUPS => ['docgen:read'], 'docgen:expects' => Scope::class]); $expected = [ - 'label' => 'User Test', - 'email' => '', - 'mainCenter' => [ - 'name' => 'test', - ], + 'id' => null, + 'name' => 'scope', + 'type' => 'scope', + 'isNull' => false, ]; - $this->assertEquals($expected, $normalized, 'test normalization fo an user'); + $this->assertEquals($expected, $normalized, 'test normalization fo a scope'); + } + + public function testNormalizeNull() + { + $actual = $this->normalizer->normalize(null, 'docgen', [AbstractNormalizer::GROUPS => ['docgen:read'], 'docgen:expects' => Scope::class]); + $expected = [ + 'id' => '', + 'name' => '', + 'type' => 'scope', + 'isNull' => true, + ]; + + $this->assertEquals($expected, $actual, 'test normalization for a null scope'); } public function testNormalizeNullObjectWithObjectEmbedded() { + $this->markTestIncomplete('test to implement'); $normalized = $this->normalizer->normalize(null, 'docgen', [ AbstractNormalizer::GROUPS => ['docgen:read'], 'docgen:expects' => User::class, @@ -62,7 +73,7 @@ final class DocGenObjectNormalizerTest extends KernelTestCase $expected = [ 'label' => '', 'email' => '', - 'mainCenter' => [ + 'main_center' => [ 'name' => '', ], ]; @@ -72,10 +83,11 @@ final class DocGenObjectNormalizerTest extends KernelTestCase public function testNormalizeWithNullValueEmbedded() { + $this->markTestIncomplete('test to write'); $user = new User(); $user->setUsername('User Test'); - $normalized = $this->normalizer->normalize($user, 'docgen', [AbstractNormalizer::GROUPS => ['docgen:read']]); + $normalized = $this->normalizer->normalize($user, 'docgen', [AbstractNormalizer::GROUPS => ['docgen:read'], 'docgen:expects' => User::class]); $expected = [ 'label' => 'User Test', 'email' => '', diff --git a/src/Bundle/ChillDocGeneratorBundle/tests/Service/Context/BaseContextDataTest.php b/src/Bundle/ChillDocGeneratorBundle/tests/Service/Context/BaseContextDataTest.php new file mode 100644 index 000000000..e5a1c6d5f --- /dev/null +++ b/src/Bundle/ChillDocGeneratorBundle/tests/Service/Context/BaseContextDataTest.php @@ -0,0 +1,68 @@ +buildBaseContext(); + + $actual = $context->getData(); + + $this->assertIsArray($actual); + $this->assertArrayHasKey('creator', $actual); + $this->assertArrayHasKey('createdAt', $actual); + $this->assertArrayHasKey('location', $actual); + } + + public function testGenerateWithUser() + { + $security = $this->prophesize(Security::class); + $security->getUser()->willReturn(new User()); + + $context = $this->buildBaseContext($security->reveal()); + + $actual = $context->getData(); + + $this->assertIsArray($actual); + $this->assertArrayHasKey('creator', $actual); + $this->assertArrayHasKey('createdAt', $actual); + $this->assertArrayHasKey('location', $actual); + } + + private function buildBaseContext( + ?Security $security = null, + ?NormalizerInterface $normalizer = null + ): BaseContextData { + return new BaseContextData( + $security ?? self::$container->get(Security::class), + $normalizer ?? self::$container->get(NormalizerInterface::class) + ); + } +} diff --git a/src/Bundle/ChillDocGeneratorBundle/translations/messages.fr.yml b/src/Bundle/ChillDocGeneratorBundle/translations/messages.fr.yml index e69de29bb..af08cf1c8 100644 --- a/src/Bundle/ChillDocGeneratorBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillDocGeneratorBundle/translations/messages.fr.yml @@ -0,0 +1,19 @@ +docgen: + Generate a document: Génerer un document + Generate: Génerer + Document generation: Génération de documents + Manage templates and document generation: Gestion des documents générés et de leurs gabarits + Pick template context: Choisir un contexte + Context: Contexte + New template: Nouveau gabarit + Edit template: Modifier gabarit + With context: 'Avec le contexte :' + + +crud: + docgen_template: + index: + title: Génération de documents + add_new: Créer + + diff --git a/src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php b/src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php index 25ac9f1bd..5028757bd 100644 --- a/src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php +++ b/src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php @@ -24,7 +24,6 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; -use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Translation\TranslatorInterface; /** @@ -100,7 +99,7 @@ class DocumentPersonController extends AbstractController $document, [ 'center' => $document->getCenter(), - 'role' => new Role('CHILL_PERSON_DOCUMENT_UPDATE'), + 'role' => 'CHILL_PERSON_DOCUMENT_UPDATE', ] ); $form->handleRequest($request); @@ -160,7 +159,7 @@ class DocumentPersonController extends AbstractController $reachableScopes = $this->authorizationHelper ->getReachableScopes( $this->getUser(), - new Role(PersonDocumentVoter::SEE), + PersonDocumentVoter::SEE, $person->getCenter() ); @@ -204,7 +203,7 @@ class DocumentPersonController extends AbstractController $form = $this->createForm(PersonDocumentType::class, $document, [ 'center' => $document->getCenter(), - 'role' => new Role('CHILL_PERSON_DOCUMENT_CREATE'), + 'role' => 'CHILL_PERSON_DOCUMENT_CREATE', ]); $form->handleRequest($request); diff --git a/src/Bundle/ChillDocStoreBundle/DataFixtures/ORM/LoadDocumentACL.php b/src/Bundle/ChillDocStoreBundle/DataFixtures/ORM/LoadDocumentACL.php index 28a35dfb4..cab5895a9 100644 --- a/src/Bundle/ChillDocStoreBundle/DataFixtures/ORM/LoadDocumentACL.php +++ b/src/Bundle/ChillDocStoreBundle/DataFixtures/ORM/LoadDocumentACL.php @@ -18,6 +18,7 @@ use Chill\MainBundle\Entity\RoleScope; use Doctrine\Common\DataFixtures\AbstractFixture; use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Persistence\ObjectManager; + use function in_array; /** diff --git a/src/Bundle/ChillDocStoreBundle/Entity/DocumentCategory.php b/src/Bundle/ChillDocStoreBundle/Entity/DocumentCategory.php index 1ded5ccb2..55850b157 100644 --- a/src/Bundle/ChillDocStoreBundle/Entity/DocumentCategory.php +++ b/src/Bundle/ChillDocStoreBundle/Entity/DocumentCategory.php @@ -15,7 +15,7 @@ use Doctrine\ORM\Mapping as ORM; /** * @ORM\Table("chill_doc.document_category") - * @ORM\Entity(repositoryClass="Chill\DocStoreBundle\EntityRepository\DocumentCategoryRepository") + * @ORM\Entity */ class DocumentCategory { diff --git a/src/Bundle/ChillDocStoreBundle/EntityRepository/DocumentCategoryRepository.php b/src/Bundle/ChillDocStoreBundle/EntityRepository/DocumentCategoryRepository.php deleted file mode 100644 index fbf4acb15..000000000 --- a/src/Bundle/ChillDocStoreBundle/EntityRepository/DocumentCategoryRepository.php +++ /dev/null @@ -1,31 +0,0 @@ -getEntityManager() - ->createQuery( - 'SELECT MAX(c.idInsideBundle) + 1 FROM ChillDocStoreBundle:DocumentCategory c' - ) - ->getSingleResult(); - - return reset($array_res); - } -} diff --git a/src/Bundle/ChillDocStoreBundle/Form/AccompanyingCourseDocumentType.php b/src/Bundle/ChillDocStoreBundle/Form/AccompanyingCourseDocumentType.php index 12797da79..64a81e9c7 100644 --- a/src/Bundle/ChillDocStoreBundle/Form/AccompanyingCourseDocumentType.php +++ b/src/Bundle/ChillDocStoreBundle/Form/AccompanyingCourseDocumentType.php @@ -11,8 +11,9 @@ declare(strict_types=1); namespace Chill\DocStoreBundle\Form; +use Chill\DocStoreBundle\Entity\AccompanyingCourseDocument; use Chill\DocStoreBundle\Entity\Document; -use Chill\DocStoreBundle\Entity\PersonDocument; +use Chill\DocStoreBundle\Entity\DocumentCategory; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Form\Type\ChillDateType; use Chill\MainBundle\Form\Type\ChillTextareaType; @@ -70,11 +71,11 @@ class AccompanyingCourseDocumentType extends AbstractType //TODO : adapt to using AccompanyingCourseDocument categories. Currently there are none... ->add('category', EntityType::class, [ 'placeholder' => 'Choose a document category', - 'class' => 'ChillDocStoreBundle:DocumentCategory', + 'class' => DocumentCategory::class, 'query_builder' => static function (EntityRepository $er) { return $er->createQueryBuilder('c') ->where('c.documentClass = :docClass') - ->setParameter('docClass', PersonDocument::class); + ->setParameter('docClass', AccompanyingCourseDocument::class); }, 'choice_label' => function ($entity = null) { return $entity ? $this->translatableStringHelper->localize($entity->getName()) : ''; diff --git a/src/Bundle/ChillDocStoreBundle/Form/PersonDocumentType.php b/src/Bundle/ChillDocStoreBundle/Form/PersonDocumentType.php index 474d9d132..86e8d350a 100644 --- a/src/Bundle/ChillDocStoreBundle/Form/PersonDocumentType.php +++ b/src/Bundle/ChillDocStoreBundle/Form/PersonDocumentType.php @@ -93,7 +93,7 @@ class PersonDocumentType extends AbstractType ]); $resolver->setRequired(['role', 'center']) - ->setAllowedTypes('role', [\Symfony\Component\Security\Core\Role\Role::class]) + ->setAllowedTypes('role', ['string']) ->setAllowedTypes('center', [\Chill\MainBundle\Entity\Center::class]); } } diff --git a/src/Bundle/ChillDocStoreBundle/Form/StoredObjectType.php b/src/Bundle/ChillDocStoreBundle/Form/StoredObjectType.php index 4de5cf48c..f9cb645f7 100644 --- a/src/Bundle/ChillDocStoreBundle/Form/StoredObjectType.php +++ b/src/Bundle/ChillDocStoreBundle/Form/StoredObjectType.php @@ -19,6 +19,7 @@ use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; + use function json_decode; use function json_encode; diff --git a/src/Bundle/ChillDocStoreBundle/Repository/DocumentCategoryRepository.php b/src/Bundle/ChillDocStoreBundle/Repository/DocumentCategoryRepository.php new file mode 100644 index 000000000..f930e8ece --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Repository/DocumentCategoryRepository.php @@ -0,0 +1,75 @@ +em = $em; + $this->repository = $em->getRepository(DocumentCategory::class); + } + + /** + * @param mixed $id + */ + public function find($id): ?DocumentCategory + { + return $this->repository->find($id); + } + + /** + * @return array|DocumentCategory[] + */ + public function findAll(): array + { + return $this->repository->findAll(); + } + + public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null) + { + return $this->repository->findBy($criteria, $orderBy, $limit, $offset); + } + + public function findOneBy(array $criteria): ?DocumentCategory + { + return $this->findOneBy($criteria); + } + + public function getClassName() + { + return DocumentCategory::class; + } + + public function nextIdInsideBundle() + { + $array_res = $this->em + ->createQuery( + 'SELECT MAX(c.idInsideBundle) + 1 FROM ChillDocStoreBundle:DocumentCategory c' + ) + ->getSingleResult(); + + return reset($array_res); + } +} diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/module/async_upload/downloader.js b/src/Bundle/ChillDocStoreBundle/Resources/public/module/async_upload/downloader.js index deeb2828f..4c82a8e4b 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/public/module/async_upload/downloader.js +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/module/async_upload/downloader.js @@ -5,7 +5,7 @@ var algo = 'AES-CBC'; var initializeButtons = (root) => { var buttons = root.querySelectorAll('a[data-download-button]'); - + for (let i = 0; i < buttons.length; i ++) { initialize(buttons[i]); } @@ -33,9 +33,9 @@ var download = (button) => { fetchError = "Error while fetching file", key, url ; - + button.textContent = labelPreparing; - + window.fetch(urlGenerator) .then((r) => { if (r.ok) { @@ -45,44 +45,26 @@ var download = (button) => { } }) .then(data => { - url = data.url; - - return window.crypto.subtle.importKey('jwk', keyData, { name: algo, iv: iv}, false, ['decrypt']); + return window.fetch(data.url); }) - .catch(e => { - console.error("error while importing key"); - console.error(e); - button.appendChild(document.createTextNode(decryptError)); - }) - .then(nKey => { - key = nKey; - - return window.fetch(url); - }) - .catch(e => { - console.error("error while fetching data"); - console.error(e); - button.textContent = ""; - button.appendChild(document.createTextNode(fetchError)); - }) - .then(r => { - if (r.ok) { - return r.arrayBuffer(); - } else { - throw new Error(r.status + r.statusText); + .then(response => { + if (response.ok) { + return response.arrayBuffer(); } + throw new Error(response.status + response.statusText); }) .then(buffer => { - return window.crypto.subtle.decrypt({ name: algo, iv: iv }, key, buffer); - }) - .catch(e => { - console.error("error while importing key"); - console.error(e); - button.textContent = ""; - button.appendChild(document.createTextNode(decryptError)); + if (keyData.alg !== undefined) { + return window.crypto.subtle + .importKey('jwk', keyData, { name: algo, iv: iv}, false, ['decrypt']) + .then(key => { + return window.crypto.subtle.decrypt({ name: algo, iv: iv }, key, buffer); + }); + } + return Promise.resolve(buffer); }) .then(decrypted => { - var + var blob = new Blob([decrypted], { type: mimeType }), url = window.URL.createObjectURL(blob) ; @@ -100,7 +82,6 @@ var download = (button) => { button.click(); }) .catch(error => { - console.log(error); button.textContent = ""; button.appendChild(document.createTextNode("error while handling decrypted file")); }) diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/edit.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/edit.html.twig index 088a351f3..e28611701 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/edit.html.twig +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/edit.html.twig @@ -41,5 +41,6 @@ {% endblock %} {% block css %} + {{ parent() }} {{ encore_entry_link_tags('mod_async_upload') }} {% endblock %} diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/index.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/index.html.twig index dd0c9cc62..893f504bc 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/index.html.twig +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/index.html.twig @@ -11,6 +11,13 @@ {% block js %} {{ parent() }} {{ encore_entry_script_tags('mod_async_upload') }} + {{ encore_entry_script_tags('mod_docgen_picktemplate') }} +{% endblock %} + +{% block css %} + {{ parent() }} + {{ encore_entry_link_tags('mod_async_upload') }} + {{ encore_entry_link_tags('mod_docgen_picktemplate') }} {% endblock %} {% block content %} @@ -29,7 +36,7 @@ {% for document in documents %} {{ document.title }} - {{ document.category.name|localize_translatable_string }} + {% if document.category %}{{ document.category.name|localize_translatable_string }}{% endif %}
          {% if is_granted('CHILL_ACCOMPANYING_COURSE_DOCUMENT_SEE_DETAILS', document) %} @@ -58,6 +65,8 @@ +
          + {% if is_granted('CHILL_ACCOMPANYING_COURSE_DOCUMENT_CREATE', accompanyingCourse) %}
          • diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/new.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/new.html.twig index 713654739..d76e5a745 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/new.html.twig +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/new.html.twig @@ -42,5 +42,6 @@ {% endblock %} {% block css %} + {{ parent() }} {{ encore_entry_link_tags('mod_async_upload') }} {% endblock %} diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/show.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/show.html.twig index 3bf9cac43..97299675a 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/show.html.twig +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/show.html.twig @@ -14,6 +14,11 @@ {{ encore_entry_script_tags('mod_async_upload') }} {% endblock %} +{% block css %} + {{ parent() }} + {{ encore_entry_link_tags('mod_async_upload') }} +{% endblock %} + {% block content %}

            {{ 'Document %title%' | trans({ '%title%': document.title }) }}

            @@ -22,8 +27,10 @@
            {{ 'Title'|trans }}
            {{ document.title }}
            -
            {{ 'Category'|trans }}
            -
            {{ document.category.name|localize_translatable_string }}
            + {% if document.category is not null %} +
            {{ 'Category'|trans }}
            +
            {{ document.category.name|localize_translatable_string }}
            + {% endif %}
            {{ 'Description' | trans }}
            diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/new.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/new.html.twig index 73d8cddf5..ad4fcfc81 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/new.html.twig +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/new.html.twig @@ -32,7 +32,11 @@ {{ form_row(form.title) }} {{ form_row(form.date) }} {{ form_row(form.category) }} - {{ form_row(form.scope) }} + + {% if form.scope is defined %} + {{ form_row(form.scope) }} + {% endif %} + {{ form_row(form.description) }} {{ form_row(form.object, { 'label': 'Document', 'existing': document.object }) }} diff --git a/src/Bundle/ChillDocStoreBundle/Security/Authorization/AccompanyingCourseDocumentVoter.php b/src/Bundle/ChillDocStoreBundle/Security/Authorization/AccompanyingCourseDocumentVoter.php index 18377211c..88e701fcf 100644 --- a/src/Bundle/ChillDocStoreBundle/Security/Authorization/AccompanyingCourseDocumentVoter.php +++ b/src/Bundle/ChillDocStoreBundle/Security/Authorization/AccompanyingCourseDocumentVoter.php @@ -22,6 +22,7 @@ use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter; use Psr\Log\LoggerInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Security; + use function in_array; class AccompanyingCourseDocumentVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface @@ -101,8 +102,10 @@ class AccompanyingCourseDocumentVoter extends AbstractChillVoter implements Prov return false; } - if (AccompanyingPeriod::STEP_CLOSED === $subject->getCourse()->getStep() - && in_array($attribute, [self::CREATE, self::DELETE, self::UPDATE], true)) { + if ( + AccompanyingPeriod::STEP_CLOSED === $subject->getCourse()->getStep() + && in_array($attribute, [self::CREATE, self::DELETE, self::UPDATE], true) + ) { return false; } } diff --git a/src/Bundle/ChillDocStoreBundle/Security/Authorization/PersonDocumentVoter.php b/src/Bundle/ChillDocStoreBundle/Security/Authorization/PersonDocumentVoter.php index 43d17e420..dbaa474a3 100644 --- a/src/Bundle/ChillDocStoreBundle/Security/Authorization/PersonDocumentVoter.php +++ b/src/Bundle/ChillDocStoreBundle/Security/Authorization/PersonDocumentVoter.php @@ -95,8 +95,10 @@ class PersonDocumentVoter extends AbstractChillVoter implements ProvideRoleHiera return false; } - if ($subject instanceof PersonDocument - && !$this->security->isGranted(PersonVoter::SEE, $subject->getPerson())) { + if ( + $subject instanceof PersonDocument + && !$this->security->isGranted(PersonVoter::SEE, $subject->getPerson()) + ) { return false; } diff --git a/src/Bundle/ChillEventBundle/Controller/EventController.php b/src/Bundle/ChillEventBundle/Controller/EventController.php index c7d98baaa..d87afac09 100644 --- a/src/Bundle/ChillEventBundle/Controller/EventController.php +++ b/src/Bundle/ChillEventBundle/Controller/EventController.php @@ -39,6 +39,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Translation\TranslatorInterface; + use function count; /** diff --git a/src/Bundle/ChillEventBundle/Controller/EventTypeController.php b/src/Bundle/ChillEventBundle/Controller/EventTypeController.php index b4e19efc7..f1ced71a5 100644 --- a/src/Bundle/ChillEventBundle/Controller/EventTypeController.php +++ b/src/Bundle/ChillEventBundle/Controller/EventTypeController.php @@ -14,7 +14,6 @@ namespace Chill\EventBundle\Controller; use Chill\EventBundle\Entity\EventType; use Chill\EventBundle\Form\EventTypeType; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; - use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\HttpFoundation\Request; diff --git a/src/Bundle/ChillEventBundle/Controller/ParticipationController.php b/src/Bundle/ChillEventBundle/Controller/ParticipationController.php index b3294cfc6..63f40df32 100644 --- a/src/Bundle/ChillEventBundle/Controller/ParticipationController.php +++ b/src/Bundle/ChillEventBundle/Controller/ParticipationController.php @@ -25,6 +25,7 @@ use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; + use function count; /** @@ -112,7 +113,9 @@ class ParticipationController extends AbstractController [ 'event_id' => current($participations)->getEvent()->getId(), 'persons_ids' => implode(',', array_map( - static function (Participation $p) { return $p->getPerson()->getId(); }, + static function (Participation $p) { + return $p->getPerson()->getId(); + }, $participations )), ] @@ -648,7 +651,9 @@ class ParticipationController extends AbstractController /** @var \Doctrine\Common\Collections\ArrayCollection $peopleParticipating */ $peopleParticipating = $peopleParticipating ?? $participation->getEvent()->getParticipations()->map( - static function (Participation $p) { return $p->getPerson()->getId(); } + static function (Participation $p) { + return $p->getPerson()->getId(); + } ); // check that the user is not already in the event if ($peopleParticipating->contains($participation->getPerson()->getId())) { diff --git a/src/Bundle/ChillEventBundle/Controller/StatusController.php b/src/Bundle/ChillEventBundle/Controller/StatusController.php index 7da8b989f..72e80b27b 100644 --- a/src/Bundle/ChillEventBundle/Controller/StatusController.php +++ b/src/Bundle/ChillEventBundle/Controller/StatusController.php @@ -14,7 +14,6 @@ namespace Chill\EventBundle\Controller; use Chill\EventBundle\Entity\Status; use Chill\EventBundle\Form\StatusType; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; - use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\HttpFoundation\Request; diff --git a/src/Bundle/ChillEventBundle/DataFixtures/ORM/LoadRolesACL.php b/src/Bundle/ChillEventBundle/DataFixtures/ORM/LoadRolesACL.php index ddcef3422..8bd1a3513 100644 --- a/src/Bundle/ChillEventBundle/DataFixtures/ORM/LoadRolesACL.php +++ b/src/Bundle/ChillEventBundle/DataFixtures/ORM/LoadRolesACL.php @@ -17,6 +17,7 @@ use Chill\MainBundle\Entity\RoleScope; use Doctrine\Common\DataFixtures\AbstractFixture; use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Persistence\ObjectManager; + use function in_array; /** diff --git a/src/Bundle/ChillEventBundle/Entity/Participation.php b/src/Bundle/ChillEventBundle/Entity/Participation.php index 9ba34d398..d52618bcd 100644 --- a/src/Bundle/ChillEventBundle/Entity/Participation.php +++ b/src/Bundle/ChillEventBundle/Entity/Participation.php @@ -21,6 +21,7 @@ use DateTime; use Doctrine\ORM\Mapping as ORM; use RuntimeException; use Symfony\Component\Validator\Context\ExecutionContextInterface; + use function in_array; /** @@ -172,15 +173,19 @@ class Participation implements ArrayAccess, HasCenterInterface, HasScopeInterfac return; } - if ($this->getRole()->getType()->getId() !== - $this->getEvent()->getType()->getId()) { + if ( + $this->getRole()->getType()->getId() !== + $this->getEvent()->getType()->getId() + ) { $context->buildViolation('The role is not allowed with this event type') ->atPath('role') ->addViolation(); } - if ($this->getStatus()->getType()->getId() !== - $this->getEvent()->getType()->getId()) { + if ( + $this->getStatus()->getType()->getId() !== + $this->getEvent()->getType()->getId() + ) { $context->buildViolation('The status is not allowed with this event type') ->atPath('status') ->addViolation(); diff --git a/src/Bundle/ChillEventBundle/Form/ChoiceLoader/EventChoiceLoader.php b/src/Bundle/ChillEventBundle/Form/ChoiceLoader/EventChoiceLoader.php index 953f1cc82..faac75668 100644 --- a/src/Bundle/ChillEventBundle/Form/ChoiceLoader/EventChoiceLoader.php +++ b/src/Bundle/ChillEventBundle/Form/ChoiceLoader/EventChoiceLoader.php @@ -16,6 +16,7 @@ use Doctrine\ORM\EntityRepository; use RuntimeException; use Symfony\Component\Form\ChoiceList\ChoiceListInterface; use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; + use function call_user_func; use function count; use function in_array; @@ -83,8 +84,10 @@ class EventChoiceLoader implements ChoiceLoaderInterface $event = $this->eventRepository->find($value); - if ($this->hasCenterFilter() - && !in_array($event->getCenter(), $this->centers, true)) { + if ( + $this->hasCenterFilter() + && !in_array($event->getCenter(), $this->centers, true) + ) { throw new RuntimeException('chosen an event not in correct center'); } diff --git a/src/Bundle/ChillEventBundle/Form/Type/PickEventType.php b/src/Bundle/ChillEventBundle/Form/Type/PickEventType.php index bb12e272c..881a9645b 100644 --- a/src/Bundle/ChillEventBundle/Form/Type/PickEventType.php +++ b/src/Bundle/ChillEventBundle/Form/Type/PickEventType.php @@ -29,6 +29,7 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Translation\TranslatorInterface; + use function in_array; use function is_array; @@ -170,10 +171,14 @@ class PickEventType extends AbstractType . 'option must be an instance of ' . Center::class); } - if (!in_array($c->getId(), array_map( - static function (Center $c) { return $c->getId(); }, - $centers - ), true)) { + if ( + !in_array($c->getId(), array_map( + static function (Center $c) { + return $c->getId(); + }, + $centers + ), true) + ) { throw new AccessDeniedException('The given center is not reachable'); } $selectedCenters[] = $c; diff --git a/src/Bundle/ChillEventBundle/Search/EventSearch.php b/src/Bundle/ChillEventBundle/Search/EventSearch.php index b3594c274..9b2052305 100644 --- a/src/Bundle/ChillEventBundle/Search/EventSearch.php +++ b/src/Bundle/ChillEventBundle/Search/EventSearch.php @@ -19,8 +19,8 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; -use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Templating\EngineInterface as TemplatingEngine; + use function count; /** @@ -145,7 +145,7 @@ class EventSearch extends AbstractSearch { // add security clauses $reachableCenters = $this->helper - ->getReachableCenters($this->user, new Role('CHILL_EVENT_SEE')); + ->getReachableCenters($this->user, 'CHILL_EVENT_SEE'); if (count($reachableCenters) === 0) { // add a clause to block all events @@ -158,7 +158,7 @@ class EventSearch extends AbstractSearch foreach ($reachableCenters as $center) { $circles = $this->helper->getReachableScopes( $this->user, - new Role('CHILL_EVENT_SEE'), + 'CHILL_EVENT_SEE', $center ); $where = $qb->expr()->andX( @@ -175,7 +175,8 @@ class EventSearch extends AbstractSearch if ( (isset($terms['name']) || isset($terms['_default'])) - && (!empty($terms['name']) || !empty($terms['_default']))) { + && (!empty($terms['name']) || !empty($terms['_default'])) + ) { // the form with name:"xyz" has precedence $name = $terms['name'] ?? $terms['_default']; diff --git a/src/Bundle/ChillEventBundle/Security/Authorization/EventVoter.php b/src/Bundle/ChillEventBundle/Security/Authorization/EventVoter.php index b2c201e01..9d7c88500 100644 --- a/src/Bundle/ChillEventBundle/Security/Authorization/EventVoter.php +++ b/src/Bundle/ChillEventBundle/Security/Authorization/EventVoter.php @@ -22,6 +22,7 @@ use Psr\Log\LoggerInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Core\Role\Role; + use function count; use function in_array; diff --git a/src/Bundle/ChillEventBundle/Security/Authorization/ParticipationVoter.php b/src/Bundle/ChillEventBundle/Security/Authorization/ParticipationVoter.php index 3438f71c3..8d7a76c62 100644 --- a/src/Bundle/ChillEventBundle/Security/Authorization/ParticipationVoter.php +++ b/src/Bundle/ChillEventBundle/Security/Authorization/ParticipationVoter.php @@ -22,6 +22,7 @@ use Psr\Log\LoggerInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Core\Role\Role; + use function count; use function in_array; diff --git a/src/Bundle/ChillEventBundle/Tests/Controller/ParticipationControllerTest.php b/src/Bundle/ChillEventBundle/Tests/Controller/ParticipationControllerTest.php index 201cfb183..9cd9243b3 100644 --- a/src/Bundle/ChillEventBundle/Tests/Controller/ParticipationControllerTest.php +++ b/src/Bundle/ChillEventBundle/Tests/Controller/ParticipationControllerTest.php @@ -44,7 +44,7 @@ final class ParticipationControllerTest extends WebTestCase */ private $personsIdsCache = []; - public function setUp() + protected function setUp(): void { self::bootKernel(); diff --git a/src/Bundle/ChillEventBundle/Tests/Search/EventSearchTest.php b/src/Bundle/ChillEventBundle/Tests/Search/EventSearchTest.php index 3e93c0dbf..30479b1a4 100644 --- a/src/Bundle/ChillEventBundle/Tests/Search/EventSearchTest.php +++ b/src/Bundle/ChillEventBundle/Tests/Search/EventSearchTest.php @@ -68,7 +68,7 @@ final class EventSearchTest extends WebTestCase */ protected $prophet; - public function setUp() + protected function setUp(): void { self::bootKernel(); /** @var \Symfony\Component\HttpKernel\KernelInterface $kernel */ @@ -96,7 +96,7 @@ final class EventSearchTest extends WebTestCase $this->createEvents(); } - public function tearDown() + protected function tearDown(): void { foreach ($this->events as $event) { $this->entityManager->createQuery('DELETE FROM ChillEventBundle:Event e WHERE e.id = :event_id') diff --git a/src/Bundle/ChillEventBundle/Timeline/TimelineEventProvider.php b/src/Bundle/ChillEventBundle/Timeline/TimelineEventProvider.php index 92629fd21..132a74144 100644 --- a/src/Bundle/ChillEventBundle/Timeline/TimelineEventProvider.php +++ b/src/Bundle/ChillEventBundle/Timeline/TimelineEventProvider.php @@ -23,7 +23,7 @@ use Doctrine\ORM\Mapping\ClassMetadata; use LogicException; use RuntimeException; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; -use Symfony\Component\Security\Core\Role\Role; + use function count; /** @@ -188,7 +188,7 @@ class TimelineEventProvider implements TimelineProviderInterface ClassMetadata $metadataPerson, Person $person ) { - $role = new Role('CHILL_EVENT_SEE'); + $role = 'CHILL_EVENT_SEE'; $reachableCenters = $this->helper->getReachableCenters($this->user, $role); $associationMapping = $metadataParticipation->getAssociationMapping('person'); @@ -208,7 +208,9 @@ class TimelineEventProvider implements TimelineProviderInterface foreach ($reachableCenters as $center) { $reachableCircleId = array_map( - static function (Scope $scope) { return $scope->getId(); }, + static function (Scope $scope) { + return $scope->getId(); + }, $this->helper->getReachableCircles($this->user, $role, $person->getCenter()) ); $centerAndScopeLines[] = sprintf( diff --git a/src/Bundle/ChillFamilyMembersBundle/Security/Voter/FamilyMemberVoter.php b/src/Bundle/ChillFamilyMembersBundle/Security/Voter/FamilyMemberVoter.php index 73c320720..2340ba7b9 100644 --- a/src/Bundle/ChillFamilyMembersBundle/Security/Voter/FamilyMemberVoter.php +++ b/src/Bundle/ChillFamilyMembersBundle/Security/Voter/FamilyMemberVoter.php @@ -18,6 +18,7 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Chill\MainBundle\Security\ProvideRoleHierarchyInterface; use Chill\PersonBundle\Entity\Person; use Symfony\Component\Security\Core\Role\Role; + use function in_array; class FamilyMemberVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface diff --git a/src/Bundle/ChillMainBundle/CRUD/Controller/AbstractCRUDController.php b/src/Bundle/ChillMainBundle/CRUD/Controller/AbstractCRUDController.php index cd458e222..b1ee4894e 100644 --- a/src/Bundle/ChillMainBundle/CRUD/Controller/AbstractCRUDController.php +++ b/src/Bundle/ChillMainBundle/CRUD/Controller/AbstractCRUDController.php @@ -22,6 +22,7 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; + use function array_merge; abstract class AbstractCRUDController extends AbstractController diff --git a/src/Bundle/ChillMainBundle/CRUD/Controller/ApiController.php b/src/Bundle/ChillMainBundle/CRUD/Controller/ApiController.php index 15d8dbcc3..cfbe811fa 100644 --- a/src/Bundle/ChillMainBundle/CRUD/Controller/ApiController.php +++ b/src/Bundle/ChillMainBundle/CRUD/Controller/ApiController.php @@ -23,6 +23,7 @@ use Symfony\Component\Serializer\Exception\NotEncodableValueException; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Validator\ConstraintViolationListInterface; + use function array_merge; use function ucfirst; diff --git a/src/Bundle/ChillMainBundle/CRUD/Controller/CRUDController.php b/src/Bundle/ChillMainBundle/CRUD/Controller/CRUDController.php index 0e2881b54..d6e0450e3 100644 --- a/src/Bundle/ChillMainBundle/CRUD/Controller/CRUDController.php +++ b/src/Bundle/ChillMainBundle/CRUD/Controller/CRUDController.php @@ -28,6 +28,7 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Translation\TranslatorInterface; + use function array_key_exists; use function array_merge; diff --git a/src/Bundle/ChillMainBundle/CRUD/Resolver/Resolver.php b/src/Bundle/ChillMainBundle/CRUD/Resolver/Resolver.php index 11b84e586..d11c5fb98 100644 --- a/src/Bundle/ChillMainBundle/CRUD/Resolver/Resolver.php +++ b/src/Bundle/ChillMainBundle/CRUD/Resolver/Resolver.php @@ -13,6 +13,7 @@ namespace Chill\MainBundle\CRUD\Resolver; use Doctrine\ORM\EntityManagerInterface; use LogicException; + use function array_key_exists; use function strtoupper; diff --git a/src/Bundle/ChillMainBundle/CRUD/Routing/CRUDRoutesLoader.php b/src/Bundle/ChillMainBundle/CRUD/Routing/CRUDRoutesLoader.php index 33cce8a2f..322218202 100644 --- a/src/Bundle/ChillMainBundle/CRUD/Routing/CRUDRoutesLoader.php +++ b/src/Bundle/ChillMainBundle/CRUD/Routing/CRUDRoutesLoader.php @@ -16,11 +16,13 @@ use Symfony\Component\Config\Loader\Loader; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; + use function array_filter; use function array_keys; use function array_search; use function count; use function in_array; + use const ARRAY_FILTER_USE_BOTH; class CRUDRoutesLoader extends Loader @@ -139,7 +141,9 @@ class CRUDRoutesLoader extends Loader $methods = array_keys(array_filter( $action['methods'], - static function ($value, $key) { return $value; }, + static function ($value, $key) { + return $value; + }, ARRAY_FILTER_USE_BOTH )); diff --git a/src/Bundle/ChillMainBundle/Command/ChillImportUsersCommand.php b/src/Bundle/ChillMainBundle/Command/ChillImportUsersCommand.php index 1f07af303..383fd501d 100644 --- a/src/Bundle/ChillMainBundle/Command/ChillImportUsersCommand.php +++ b/src/Bundle/ChillMainBundle/Command/ChillImportUsersCommand.php @@ -32,6 +32,7 @@ use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; use Symfony\Component\Validator\ConstraintViolationListInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; + use function array_key_exists; use function array_keys; use function array_merge; @@ -308,8 +309,10 @@ class ChillImportUsersCommand extends Command $permissionGroupsByName = []; - foreach ($this->em->getRepository(PermissionsGroup::class) - ->findAll() as $permissionGroup) { + foreach ( + $this->em->getRepository(PermissionsGroup::class) + ->findAll() as $permissionGroup + ) { $permissionGroupsByName[$permissionGroup->getName()] = $permissionGroup; } @@ -338,11 +341,13 @@ class ChillImportUsersCommand extends Command $this->tempOutput->writeln('You have chosen ' . implode(', ', $keys)); - if ($helper->ask( - $this->tempInput, - $this->tempOutput, - new ConfirmationQuestion('Are you sure ?', true) - )) { + if ( + $helper->ask( + $this->tempInput, + $this->tempOutput, + new ConfirmationQuestion('Are you sure ?', true) + ) + ) { foreach ($keys as $key) { $this->permissionGroups[$alias][] = $permissionGroupsByName[$key]; } diff --git a/src/Bundle/ChillMainBundle/Command/ChillUserSendRenewPasswordCodeCommand.php b/src/Bundle/ChillMainBundle/Command/ChillUserSendRenewPasswordCodeCommand.php index c94ea35c2..c119907b4 100644 --- a/src/Bundle/ChillMainBundle/Command/ChillUserSendRenewPasswordCodeCommand.php +++ b/src/Bundle/ChillMainBundle/Command/ChillUserSendRenewPasswordCodeCommand.php @@ -26,6 +26,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; + use function array_key_exists; use function array_merge; use function in_array; @@ -141,8 +142,10 @@ class ChillUserSendRenewPasswordCodeCommand extends Command $headers = $reader->getHeader(); - if (false === in_array('username', $headers, true) - && false === in_array('email', $headers, true)) { + if ( + false === in_array('username', $headers, true) + && false === in_array('email', $headers, true) + ) { throw new InvalidArgumentException('The csv file does not have an ' . 'username or email header'); } diff --git a/src/Bundle/ChillMainBundle/Command/LoadAndUpdateLanguagesCommand.php b/src/Bundle/ChillMainBundle/Command/LoadAndUpdateLanguagesCommand.php index dfb912eb9..dd751db01 100644 --- a/src/Bundle/ChillMainBundle/Command/LoadAndUpdateLanguagesCommand.php +++ b/src/Bundle/ChillMainBundle/Command/LoadAndUpdateLanguagesCommand.php @@ -17,6 +17,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Intl\Intl; + use function in_array; /* diff --git a/src/Bundle/ChillMainBundle/Command/LoadPostalCodesCommand.php b/src/Bundle/ChillMainBundle/Command/LoadPostalCodesCommand.php index a5f3c8611..a3b1c1a26 100644 --- a/src/Bundle/ChillMainBundle/Command/LoadPostalCodesCommand.php +++ b/src/Bundle/ChillMainBundle/Command/LoadPostalCodesCommand.php @@ -24,6 +24,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Validator\Validator\ValidatorInterface; + use function count; class LoadPostalCodesCommand extends Command @@ -88,13 +89,15 @@ class LoadPostalCodesCommand extends Command $num = 0; $line = 0; - while (false !== ($row = fgetcsv( - $csv, - 0, - $input->getOption('delimiter'), - $input->getOption('enclosure'), - $input->getOption('escape') - ))) { + while ( + false !== ($row = fgetcsv( + $csv, + 0, + $input->getOption('delimiter'), + $input->getOption('enclosure'), + $input->getOption('escape') + )) + ) { try { $this->addPostalCode($row, $output); ++$num; diff --git a/src/Bundle/ChillMainBundle/Controller/AddressReferenceAPIController.php b/src/Bundle/ChillMainBundle/Controller/AddressReferenceAPIController.php index 1230cd0f6..1a7d8956a 100644 --- a/src/Bundle/ChillMainBundle/Controller/AddressReferenceAPIController.php +++ b/src/Bundle/ChillMainBundle/Controller/AddressReferenceAPIController.php @@ -12,14 +12,67 @@ declare(strict_types=1); namespace Chill\MainBundle\Controller; use Chill\MainBundle\CRUD\Controller\ApiController; +use Chill\MainBundle\Entity\PostalCode; +use Chill\MainBundle\Pagination\PaginatorFactory; use Chill\MainBundle\Pagination\PaginatorInterface; +use Chill\MainBundle\Repository\AddressReferenceRepository; +use Chill\MainBundle\Serializer\Model\Collection; +use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; +use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; -/** - * Class AddressReferenceAPIController. - */ -class AddressReferenceAPIController extends ApiController +use function trim; + +final class AddressReferenceAPIController extends ApiController { + private AddressReferenceRepository $addressReferenceRepository; + + private PaginatorFactory $paginatorFactory; + + public function __construct(AddressReferenceRepository $addressReferenceRepository, PaginatorFactory $paginatorFactory) + { + $this->addressReferenceRepository = $addressReferenceRepository; + $this->paginatorFactory = $paginatorFactory; + } + + /** + * @Route("/api/1.0/main/address-reference/by-postal-code/{id}/search.json") + */ + public function search(PostalCode $postalCode, Request $request): JsonResponse + { + $this->denyAccessUnlessGranted('ROLE_USER'); + + if (!$request->query->has('q')) { + throw new BadRequestHttpException('You must supply a "q" parameter'); + } + + $pattern = $request->query->get('q'); + + if ('' === trim($pattern)) { + throw new BadRequestHttpException('the search pattern is empty'); + } + + $nb = $this->addressReferenceRepository->countByPostalCodePattern($postalCode, $pattern); + $paginator = $this->paginatorFactory->create($nb); + $addresses = $this->addressReferenceRepository->findByPostalCodePattern( + $postalCode, + $pattern, + false, + $paginator->getCurrentPageFirstItemNumber(), + $paginator->getItemsPerPage() + ); + + return $this->json( + new Collection($addresses, $paginator), + Response::HTTP_OK, + [], + [AbstractNormalizer::GROUPS => ['read']] + ); + } + protected function customizeQuery(string $action, Request $request, $qb): void { if ($request->query->has('postal_code')) { diff --git a/src/Bundle/ChillMainBundle/Controller/AdminController.php b/src/Bundle/ChillMainBundle/Controller/AdminController.php index 96ba627e4..efde1ae20 100644 --- a/src/Bundle/ChillMainBundle/Controller/AdminController.php +++ b/src/Bundle/ChillMainBundle/Controller/AdminController.php @@ -12,7 +12,6 @@ declare(strict_types=1); namespace Chill\MainBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; - use Symfony\Component\Routing\Annotation\Route; class AdminController extends AbstractController diff --git a/src/Bundle/ChillMainBundle/Controller/CenterController.php b/src/Bundle/ChillMainBundle/Controller/CenterController.php index 02ea19e20..fbdca566b 100644 --- a/src/Bundle/ChillMainBundle/Controller/CenterController.php +++ b/src/Bundle/ChillMainBundle/Controller/CenterController.php @@ -14,7 +14,6 @@ namespace Chill\MainBundle\Controller; use Chill\MainBundle\Entity\Center; use Chill\MainBundle\Form\CenterType; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; - use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\HttpFoundation\Request; diff --git a/src/Bundle/ChillMainBundle/Controller/ExportController.php b/src/Bundle/ChillMainBundle/Controller/ExportController.php index 809d0502d..6921dd284 100644 --- a/src/Bundle/ChillMainBundle/Controller/ExportController.php +++ b/src/Bundle/ChillMainBundle/Controller/ExportController.php @@ -25,6 +25,7 @@ use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\Translation\TranslatorInterface; + use function count; use function serialize; use function unserialize; @@ -484,11 +485,13 @@ class ExportController extends AbstractController $data = $form->getData(); // check ACL - if ($exportManager->isGrantedForElement( - $export, - null, - $exportManager->getPickedCenters($data['centers']) - ) === false) { + if ( + $exportManager->isGrantedForElement( + $export, + null, + $exportManager->getPickedCenters($data['centers']) + ) === false + ) { throw $this->createAccessDeniedException('you do not have ' . 'access to this export for those centers'); } diff --git a/src/Bundle/ChillMainBundle/Controller/LocationApiController.php b/src/Bundle/ChillMainBundle/Controller/LocationApiController.php index 525475e3c..250d92980 100644 --- a/src/Bundle/ChillMainBundle/Controller/LocationApiController.php +++ b/src/Bundle/ChillMainBundle/Controller/LocationApiController.php @@ -21,11 +21,14 @@ class LocationApiController extends ApiController { public function customizeQuery(string $action, Request $request, $query): void { - $query->andWhere( - $query->expr()->andX( - $query->expr()->eq('e.availableForUsers', "'TRUE'"), - $query->expr()->eq('e.active', "'TRUE'"), - ) - ); + $query + ->leftJoin('e.locationType', 'lt') + ->andWhere( + $query->expr()->andX( + $query->expr()->eq('e.availableForUsers', "'TRUE'"), + $query->expr()->eq('lt.availableForUsers', "'TRUE'"), + $query->expr()->eq('e.active', "'TRUE'"), + ) + ); } } diff --git a/src/Bundle/ChillMainBundle/Controller/PasswordController.php b/src/Bundle/ChillMainBundle/Controller/PasswordController.php index 853cb85d6..2dd700a89 100644 --- a/src/Bundle/ChillMainBundle/Controller/PasswordController.php +++ b/src/Bundle/ChillMainBundle/Controller/PasswordController.php @@ -108,7 +108,7 @@ class PasswordController extends AbstractController $username = $query->get(TokenManager::USERNAME_CANONICAL); $hash = $query->getAlnum(TokenManager::HASH); $token = $query->getAlnum(TokenManager::TOKEN); - $timestamp = $query->getInt(TokenManager::TIMESTAMP); + $timestamp = $query->getAlnum(TokenManager::TIMESTAMP); $user = $this->getDoctrine()->getRepository(User::class) ->findOneByUsernameCanonical($username); diff --git a/src/Bundle/ChillMainBundle/Controller/PermissionApiController.php b/src/Bundle/ChillMainBundle/Controller/PermissionApiController.php index 6a2afccb2..5293ddc70 100644 --- a/src/Bundle/ChillMainBundle/Controller/PermissionApiController.php +++ b/src/Bundle/ChillMainBundle/Controller/PermissionApiController.php @@ -18,6 +18,7 @@ use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Core\Security; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; + use function array_key_exists; use function json_decode; diff --git a/src/Bundle/ChillMainBundle/Controller/PermissionsGroupController.php b/src/Bundle/ChillMainBundle/Controller/PermissionsGroupController.php index 8cffd02b3..59b97a57c 100644 --- a/src/Bundle/ChillMainBundle/Controller/PermissionsGroupController.php +++ b/src/Bundle/ChillMainBundle/Controller/PermissionsGroupController.php @@ -26,6 +26,7 @@ use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\RoleHierarchy; use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Contracts\Translation\TranslatorInterface; + use function array_key_exists; /** diff --git a/src/Bundle/ChillMainBundle/Controller/PostalCodeAPIController.php b/src/Bundle/ChillMainBundle/Controller/PostalCodeAPIController.php index fb926733b..fa1a29296 100644 --- a/src/Bundle/ChillMainBundle/Controller/PostalCodeAPIController.php +++ b/src/Bundle/ChillMainBundle/Controller/PostalCodeAPIController.php @@ -12,13 +12,80 @@ declare(strict_types=1); namespace Chill\MainBundle\Controller; use Chill\MainBundle\CRUD\Controller\ApiController; +use Chill\MainBundle\Pagination\PaginatorFactory; +use Chill\MainBundle\Repository\CountryRepository; +use Chill\MainBundle\Repository\PostalCodeRepository; +use Chill\MainBundle\Serializer\Model\Collection; +use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; -/** - * Class PostalCodeAPIController. - */ -class PostalCodeAPIController extends ApiController +final class PostalCodeAPIController extends ApiController { + private CountryRepository $countryRepository; + + private PaginatorFactory $paginatorFactory; + + private PostalCodeRepository $postalCodeRepository; + + public function __construct( + CountryRepository $countryRepository, + PostalCodeRepository $postalCodeRepository, + PaginatorFactory $paginatorFactory + ) { + $this->countryRepository = $countryRepository; + $this->postalCodeRepository = $postalCodeRepository; + $this->paginatorFactory = $paginatorFactory; + } + + /** + * @Route("/api/1.0/main/postal-code/search.json") + */ + public function search(Request $request): JsonResponse + { + $this->denyAccessUnlessGranted('ROLE_USER'); + + if (!$request->query->has('q')) { + throw new BadRequestHttpException('You must supply a "q" parameter'); + } + + $pattern = $request->query->get('q'); + + if ('' === trim($pattern)) { + throw new BadRequestHttpException('the search pattern is empty'); + } + + if ($request->query->has('country')) { + $country = $this->countryRepository->find($request->query->getInt('country')); + + if (null === $country) { + throw new NotFoundHttpException('country not found'); + } + } else { + $country = null; + } + + $nb = $this->postalCodeRepository->countByPattern($pattern, $country); + $paginator = $this->paginatorFactory->create($nb); + $codes = $this->postalCodeRepository->findByPattern( + $pattern, + $country, + $paginator->getCurrentPageFirstItemNumber(), + $paginator->getItemsPerPage() + ); + + return $this->json( + new Collection($codes, $paginator), + Response::HTTP_OK, + [], + [AbstractNormalizer::GROUPS => ['read']] + ); + } + protected function customizeQuery(string $action, Request $request, $qb): void { if ($request->query->has('country')) { diff --git a/src/Bundle/ChillMainBundle/Controller/PostalCodeController.php b/src/Bundle/ChillMainBundle/Controller/PostalCodeController.php index 0280be61f..f38e0004b 100644 --- a/src/Bundle/ChillMainBundle/Controller/PostalCodeController.php +++ b/src/Bundle/ChillMainBundle/Controller/PostalCodeController.php @@ -18,6 +18,7 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; + use function array_map; /** @@ -54,12 +55,12 @@ class PostalCodeController extends AbstractController ->createQuery( sprintf( 'SELECT p.id AS id, p.name AS name, p.code AS code, ' - . 'country.name AS country_name, ' - . 'country.countryCode AS country_code ' - . 'FROM %s p ' - . 'JOIN p.country country ' - . 'WHERE LOWER(p.name) LIKE LOWER(:pattern) OR LOWER(p.code) LIKE LOWER(:pattern) ' - . 'ORDER BY code', + . 'country.name AS country_name, ' + . 'country.countryCode AS country_code ' + . 'FROM %s p ' + . 'JOIN p.country country ' + . 'WHERE LOWER(p.name) LIKE LOWER(:pattern) OR LOWER(p.code) LIKE LOWER(:pattern) ' + . 'ORDER BY code', PostalCode::class ) ) diff --git a/src/Bundle/ChillMainBundle/Controller/SearchController.php b/src/Bundle/ChillMainBundle/Controller/SearchController.php index c231bf162..b9f5d19d8 100644 --- a/src/Bundle/ChillMainBundle/Controller/SearchController.php +++ b/src/Bundle/ChillMainBundle/Controller/SearchController.php @@ -27,6 +27,7 @@ use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Contracts\Translation\TranslatorInterface; + use function count; use function key; use function reset; diff --git a/src/Bundle/ChillMainBundle/Controller/TimelineCenterController.php b/src/Bundle/ChillMainBundle/Controller/TimelineCenterController.php index 8cf5f8782..5d50f246c 100644 --- a/src/Bundle/ChillMainBundle/Controller/TimelineCenterController.php +++ b/src/Bundle/ChillMainBundle/Controller/TimelineCenterController.php @@ -17,6 +17,7 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Core\Security; + use function count; class TimelineCenterController extends AbstractController diff --git a/src/Bundle/ChillMainBundle/Controller/UserApiController.php b/src/Bundle/ChillMainBundle/Controller/UserApiController.php index 75e566048..d1fd4d5bb 100644 --- a/src/Bundle/ChillMainBundle/Controller/UserApiController.php +++ b/src/Bundle/ChillMainBundle/Controller/UserApiController.php @@ -17,6 +17,27 @@ use Symfony\Component\Routing\Annotation\Route; class UserApiController extends ApiController { + /** + * @Route( + * "/api/1.0/main/user-current-location.{_format}", + * name="chill_main_user_current_location", + * requirements={ + * "_format": "json" + * } + * ) + * + * @param mixed $_format + */ + public function currentLocation($_format): JsonResponse + { + return $this->json( + $this->getUser()->getCurrentLocation(), + JsonResponse::HTTP_OK, + [], + ['groups' => ['read']] + ); + } + /** * @Route( * "/api/1.0/main/whoami.{_format}", diff --git a/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadCivility.php b/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadCivility.php index 856ef6a46..07cf976eb 100644 --- a/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadCivility.php +++ b/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadCivility.php @@ -26,8 +26,8 @@ class LoadCivility extends Fixture implements FixtureGroupInterface public function load(ObjectManager $manager): void { $civilities = [ - ['name' => ['fr' => 'Monsieur'], 'abbrev' => ['fr' => 'M.']], ['name' => ['fr' => 'Madame'], 'abbrev' => ['fr' => 'Mme']], + ['name' => ['fr' => 'Monsieur'], 'abbrev' => ['fr' => 'M.']], ['name' => ['fr' => 'Docteur'], 'abbrev' => ['fr' => 'Dr']], ['name' => ['fr' => 'Professeur'], 'abbrev' => ['fr' => 'Pr']], ['name' => ['fr' => 'Madame la Directrice'], 'abbrev' => ['fr' => 'Mme']], diff --git a/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadLanguages.php b/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadLanguages.php index 47d63efdf..0b6e6a833 100644 --- a/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadLanguages.php +++ b/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadLanguages.php @@ -18,6 +18,7 @@ use Doctrine\Persistence\ObjectManager; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Intl\Intl; + use function in_array; /** @@ -51,7 +52,7 @@ class LoadLanguages extends AbstractFixture implements ContainerAwareInterface, if ( !in_array($code, $this->regionalVersionToInclude, true) && !in_array($code, $this->ancientToExclude, true) - ) { + ) { $lang = (new Language()) ->setId($code) ->setName($this->prepareName($code)); diff --git a/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadPostalCodes.php b/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadPostalCodes.php index ecf839450..3da6e86da 100644 --- a/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadPostalCodes.php +++ b/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadPostalCodes.php @@ -17,6 +17,7 @@ use Chill\MainBundle\Entity\PostalCode; use Doctrine\Common\DataFixtures\AbstractFixture; use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Persistence\ObjectManager; + use function strtolower; use function ucwords; diff --git a/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadUsers.php b/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadUsers.php index b7d7cb941..6a518bada 100644 --- a/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadUsers.php +++ b/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadUsers.php @@ -20,6 +20,7 @@ use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Security\Core\Encoder\EncoderFactory; use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder; + use function str_replace; /** diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php index 012643aad..772f4d8ee 100644 --- a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php +++ b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php @@ -38,12 +38,14 @@ use Chill\MainBundle\Form\LocationTypeType; use Chill\MainBundle\Form\UserJobType; use Chill\MainBundle\Form\UserType; use Exception; +use Ramsey\Uuid\Doctrine\UuidType; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; use Symfony\Component\DependencyInjection\Loader; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\DependencyInjection\Extension; + use function count; /** @@ -228,12 +230,9 @@ class ChillMainExtension extends Extension implements 'geometry' => 'string', ], 'types' => [ - 'dateinterval' => [ - 'class' => NativeDateIntervalType::class, - ], - 'point' => [ - 'class' => PointType::class, - ], + 'dateinterval' => NativeDateIntervalType::class, + 'point' => PointType::class, + 'uuid' => UuidType::class, ], ], ] diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/ConfigConsistencyCompilerPass.php b/src/Bundle/ChillMainBundle/DependencyInjection/ConfigConsistencyCompilerPass.php index 5a803e9de..15943b775 100644 --- a/src/Bundle/ChillMainBundle/DependencyInjection/ConfigConsistencyCompilerPass.php +++ b/src/Bundle/ChillMainBundle/DependencyInjection/ConfigConsistencyCompilerPass.php @@ -15,6 +15,7 @@ use LogicException; use RuntimeException; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; + use function count; /** diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/Widget/AbstractWidgetsCompilerPass.php b/src/Bundle/ChillMainBundle/DependencyInjection/Widget/AbstractWidgetsCompilerPass.php index e352470e7..0b055b682 100644 --- a/src/Bundle/ChillMainBundle/DependencyInjection/Widget/AbstractWidgetsCompilerPass.php +++ b/src/Bundle/ChillMainBundle/DependencyInjection/Widget/AbstractWidgetsCompilerPass.php @@ -21,6 +21,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use UnexpectedValueException; + use function array_key_exists; use function count; use function get_class; @@ -373,8 +374,10 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface private function isPlaceAllowedForWidget($place, $widgetAlias, ContainerBuilder $container) { if ($this->widgetServices[$widgetAlias] instanceof WidgetFactoryInterface) { - if (in_array($place, $this->widgetServices[$widgetAlias] - ->getAllowedPlaces(), true)) { + if ( + in_array($place, $this->widgetServices[$widgetAlias] + ->getAllowedPlaces(), true) + ) { return true; } } else { diff --git a/src/Bundle/ChillMainBundle/Doctrine/Event/TrackCreateUpdateSubscriber.php b/src/Bundle/ChillMainBundle/Doctrine/Event/TrackCreateUpdateSubscriber.php index 3aabe46fc..ad355544f 100644 --- a/src/Bundle/ChillMainBundle/Doctrine/Event/TrackCreateUpdateSubscriber.php +++ b/src/Bundle/ChillMainBundle/Doctrine/Event/TrackCreateUpdateSubscriber.php @@ -41,8 +41,10 @@ class TrackCreateUpdateSubscriber implements EventSubscriber { $object = $args->getObject(); - if ($object instanceof TrackCreationInterface - && $this->security->getUser() instanceof User) { + if ( + $object instanceof TrackCreationInterface + && $this->security->getUser() instanceof User + ) { $object->setCreatedBy($this->security->getUser()); $object->setCreatedAt(new DateTimeImmutable('now')); } @@ -59,8 +61,10 @@ class TrackCreateUpdateSubscriber implements EventSubscriber protected function onUpdate(object $object): void { - if ($object instanceof TrackUpdateInterface - && $this->security->getUser() instanceof User) { + if ( + $object instanceof TrackUpdateInterface + && $this->security->getUser() instanceof User + ) { $object->setUpdatedBy($this->security->getUser()); $object->setUpdatedAt(new DateTimeImmutable('now')); } diff --git a/src/Bundle/ChillMainBundle/Doctrine/Model/Point.php b/src/Bundle/ChillMainBundle/Doctrine/Model/Point.php index f63101b33..31983d969 100644 --- a/src/Bundle/ChillMainBundle/Doctrine/Model/Point.php +++ b/src/Bundle/ChillMainBundle/Doctrine/Model/Point.php @@ -13,6 +13,7 @@ namespace Chill\MainBundle\Doctrine\Model; use Exception; use JsonSerializable; + use function json_encode; class Point implements JsonSerializable diff --git a/src/Bundle/ChillMainBundle/Doctrine/Type/NativeDateIntervalType.php b/src/Bundle/ChillMainBundle/Doctrine/Type/NativeDateIntervalType.php index a1ec0c955..8f8d63aef 100644 --- a/src/Bundle/ChillMainBundle/Doctrine/Type/NativeDateIntervalType.php +++ b/src/Bundle/ChillMainBundle/Doctrine/Type/NativeDateIntervalType.php @@ -16,6 +16,7 @@ use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\ConversionException; use Doctrine\DBAL\Types\DateIntervalType; use Exception; + use function count; use function current; use function preg_match; diff --git a/src/Bundle/ChillMainBundle/Entity/AddressReference.php b/src/Bundle/ChillMainBundle/Entity/AddressReference.php index e793167f6..a9d421fcb 100644 --- a/src/Bundle/ChillMainBundle/Entity/AddressReference.php +++ b/src/Bundle/ChillMainBundle/Entity/AddressReference.php @@ -17,11 +17,22 @@ use Symfony\Component\Serializer\Annotation\Groups; /** * @ORM\Entity - * @ORM\Table(name="chill_main_address_reference") + * @ORM\Table(name="chill_main_address_reference", indexes={ + * @ORM\Index(name="address_refid", columns={"refId"}, options={"where": "refid != ''"}) + * }) * @ORM\HasLifecycleCallbacks */ class AddressReference { + /** + * This is an internal column which is populated by database. + * + * This column will ease the search operations + * + * @ORM\Column(type="text", options={"default": ""}) + */ + private string $addressCanonical = ''; + /** * @ORM\Id * @ORM\GeneratedValue diff --git a/src/Bundle/ChillMainBundle/Entity/Center.php b/src/Bundle/ChillMainBundle/Entity/Center.php index 10584bea9..5b25ee119 100644 --- a/src/Bundle/ChillMainBundle/Entity/Center.php +++ b/src/Bundle/ChillMainBundle/Entity/Center.php @@ -38,8 +38,9 @@ class Center implements HasCenterInterface * @ORM\Id * @ORM\Column(name="id", type="integer") * @ORM\GeneratedValue(strategy="AUTO") + * @Serializer\Groups({"docgen:read"}) */ - private $id; + private ?int $id = null; /** * @ORM\Column(type="string", length=255) diff --git a/src/Bundle/ChillMainBundle/Entity/Civility.php b/src/Bundle/ChillMainBundle/Entity/Civility.php index 4fcad0db8..c91016a63 100644 --- a/src/Bundle/ChillMainBundle/Entity/Civility.php +++ b/src/Bundle/ChillMainBundle/Entity/Civility.php @@ -22,7 +22,8 @@ class Civility { /** * @ORM\Column(type="json") - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) + * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) */ private array $abbreviation = []; @@ -35,16 +36,22 @@ class Civility * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ - private $id; + private ?int $id = null; /** * @ORM\Column(type="json") - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) + * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) */ private array $name = []; + /** + * @ORM\Column(type="float", name="ordering", nullable=true, options={"default": 0.0}) + */ + private float $order = 0; + public function getAbbreviation(): array { return $this->abbreviation; @@ -65,6 +72,11 @@ class Civility return $this->name; } + public function getOrder(): ?float + { + return $this->order; + } + /** * @return Civility */ @@ -88,4 +100,11 @@ class Civility return $this; } + + public function setOrder(float $order): self + { + $this->order = $order; + + return $this; + } } diff --git a/src/Bundle/ChillMainBundle/Entity/Country.php b/src/Bundle/ChillMainBundle/Entity/Country.php index 1bd009689..f1fc18557 100644 --- a/src/Bundle/ChillMainBundle/Entity/Country.php +++ b/src/Bundle/ChillMainBundle/Entity/Country.php @@ -12,6 +12,7 @@ declare(strict_types=1); namespace Chill\MainBundle\Entity; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation\Context; use Symfony\Component\Serializer\Annotation\Groups; /** @@ -25,12 +26,11 @@ use Symfony\Component\Serializer\Annotation\Groups; class Country { /** - * @var string - * * @ORM\Column(type="string", length=3) - * @groups({"read"}) + * @groups({"read", "docgen:read"}) + * @Context({"is-translatable": true}, groups={"docgen:read"}) */ - private $countryCode; + private string $countryCode = ''; /** * @var int @@ -38,15 +38,16 @@ class Country * @ORM\Id * @ORM\Column(name="id", type="integer") * @ORM\GeneratedValue(strategy="AUTO") - * @groups({"read"}) + * @groups({"read", "docgen:read"}) */ - private $id; + private ?int $id = null; /** * @var string * * @ORM\Column(type="json") - * @groups({"read"}) + * @groups({"read", "docgen:read"}) + * @Context({"is-translatable": true}, groups={"docgen:read"}) */ private $name; diff --git a/src/Bundle/ChillMainBundle/Entity/Language.php b/src/Bundle/ChillMainBundle/Entity/Language.php index ad47eae1b..b4929b662 100644 --- a/src/Bundle/ChillMainBundle/Entity/Language.php +++ b/src/Bundle/ChillMainBundle/Entity/Language.php @@ -12,6 +12,7 @@ declare(strict_types=1); namespace Chill\MainBundle\Entity; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation as Serializer; /** * Language. @@ -28,15 +29,18 @@ class Language * * @ORM\Id * @ORM\Column(type="string") + * @Serializer\Groups({"docgen:read"}) */ - private $id; + private ?string $id = null; /** * @var string array * * @ORM\Column(type="json") + * @Serializer\Groups({"docgen:read"}) + * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) */ - private $name; + private array $name = []; /** * Get id. diff --git a/src/Bundle/ChillMainBundle/Entity/Location.php b/src/Bundle/ChillMainBundle/Entity/Location.php index ba1ad8fb0..8496374d8 100644 --- a/src/Bundle/ChillMainBundle/Entity/Location.php +++ b/src/Bundle/ChillMainBundle/Entity/Location.php @@ -40,7 +40,7 @@ class Location implements TrackCreationInterface, TrackUpdateInterface /** * @ORM\ManyToOne(targetEntity=Address::class, cascade={"persist"}) * @ORM\JoinColumn(nullable=true) - * @Serializer\Groups({"read", "write"}) + * @Serializer\Groups({"read", "write", "docgen:read"}) */ private ?Address $address = null; @@ -72,26 +72,26 @@ class Location implements TrackCreationInterface, TrackUpdateInterface * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ private ?int $id = null; /** * @ORM\ManyToOne(targetEntity=LocationType::class) * @ORM\JoinColumn(nullable=false) - * @Serializer\Groups({"read", "write"}) + * @Serializer\Groups({"read", "write", "docgen:read"}) */ private ?LocationType $locationType = null; /** * @ORM\Column(type="string", length=255, nullable=true) - * @Serializer\Groups({"read", "write"}) + * @Serializer\Groups({"read", "write", "docgen:read"}) */ private ?string $name = null; /** * @ORM\Column(type="string", length=64, nullable=true) - * @Serializer\Groups({"read", "write"}) + * @Serializer\Groups({"read", "write", "docgen:read"}) * @Assert\Regex(pattern="/^([\+{1}])([0-9\s*]{4,20})$/") * @PhonenumberConstraint(type="any") */ @@ -99,7 +99,7 @@ class Location implements TrackCreationInterface, TrackUpdateInterface /** * @ORM\Column(type="string", length=64, nullable=true) - * @Serializer\Groups({"read", "write"}) + * @Serializer\Groups({"read", "write", "docgen:read"}) * @Assert\Regex(pattern="/^([\+{1}])([0-9\s*]{4,20})$/") * @PhonenumberConstraint(type="any") */ diff --git a/src/Bundle/ChillMainBundle/Entity/LocationType.php b/src/Bundle/ChillMainBundle/Entity/LocationType.php index cda7e073f..9081304c8 100644 --- a/src/Bundle/ChillMainBundle/Entity/LocationType.php +++ b/src/Bundle/ChillMainBundle/Entity/LocationType.php @@ -71,13 +71,14 @@ class LocationType * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ private ?int $id = null; /** * @ORM\Column(type="json") - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) + * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) */ private array $title = []; diff --git a/src/Bundle/ChillMainBundle/Entity/PostalCode.php b/src/Bundle/ChillMainBundle/Entity/PostalCode.php index 866ad04db..484a9e322 100644 --- a/src/Bundle/ChillMainBundle/Entity/PostalCode.php +++ b/src/Bundle/ChillMainBundle/Entity/PostalCode.php @@ -29,6 +29,15 @@ use Symfony\Component\Serializer\Annotation\Groups; */ class PostalCode { + /** + * This is an internal column which is populated by database. + * + * This column will ease the search operations + * + * @ORM\Column(type="text", options={"default": ""}) + */ + private string $canonical = ''; + /** * @var Point * diff --git a/src/Bundle/ChillMainBundle/Entity/Scope.php b/src/Bundle/ChillMainBundle/Entity/Scope.php index 3a6cbd953..72ac0ad01 100644 --- a/src/Bundle/ChillMainBundle/Entity/Scope.php +++ b/src/Bundle/ChillMainBundle/Entity/Scope.php @@ -14,6 +14,7 @@ namespace Chill\MainBundle\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation\Context; use Symfony\Component\Serializer\Annotation\DiscriminatorMap; use Symfony\Component\Serializer\Annotation\Groups; @@ -28,24 +29,21 @@ use Symfony\Component\Serializer\Annotation\Groups; class Scope { /** - * @var int - * * @ORM\Id * @ORM\Column(name="id", type="integer") * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"read"}) + * @Groups({"read", "docgen:read"}) */ - private $id; + private ?int $id = null; /** * translatable names. * - * @var array - * * @ORM\Column(type="json") - * @Groups({"read"}) + * @Groups({"read", "docgen:read"}) + * @Context({"is-translatable": true}, groups={"docgen:read"}) */ - private $name = []; + private array $name = []; /** * @var Collection @@ -65,31 +63,27 @@ class Scope $this->roleScopes = new ArrayCollection(); } - public function addRoleScope(RoleScope $roleScope) + public function addRoleScope(RoleScope $roleScope): self { $this->roleScopes->add($roleScope); + + return $this; } /** * @return int */ - public function getId() + public function getId(): ?int { return $this->id; } - /** - * @return array - */ - public function getName() + public function getName(): array { return $this->name; } - /** - * @return Collection - */ - public function getRoleScopes() + public function getRoleScopes(): Collection { return $this->roleScopes; } @@ -99,7 +93,7 @@ class Scope * * @return $this */ - public function setName($name) + public function setName(array $name): self { $this->name = $name; diff --git a/src/Bundle/ChillMainBundle/Entity/User.php b/src/Bundle/ChillMainBundle/Entity/User.php index 73fc45bbe..0c3194fba 100644 --- a/src/Bundle/ChillMainBundle/Entity/User.php +++ b/src/Bundle/ChillMainBundle/Entity/User.php @@ -18,6 +18,7 @@ use RuntimeException; use Symfony\Component\Security\Core\User\AdvancedUserInterface; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Context\ExecutionContextInterface; + use function in_array; /** @@ -33,22 +34,18 @@ use function in_array; class User implements AdvancedUserInterface { /** - * @var int - * * @ORM\Id * @ORM\Column(name="id", type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ - protected $id; + protected ?int $id = null; /** * Array where SAML attributes's data are stored. * - * @var array - * * @ORM\Column(type="json", nullable=true) */ - private $attributes; + private array $attributes; /** * @ORM\ManyToOne(targetEntity=Location::class) @@ -59,55 +56,44 @@ class User implements AdvancedUserInterface * @var string * * @ORM\Column(type="string", length=150, nullable=true) - * @Serializer\Groups({"docgen:read"}) */ private ?string $email = null; /** - * @var string - * * @ORM\Column( * type="string", * length=150, * nullable=true, * unique=true) */ - private $emailCanonical; + private ?string $emailCanonical = null; /** - * @var bool - * * @ORM\Column(type="boolean") */ - private $enabled = true; + private bool $enabled = true; /** - * @var Collection - * * @ORM\ManyToMany( * targetEntity="Chill\MainBundle\Entity\GroupCenter", * inversedBy="users") * @ORM\Cache(usage="NONSTRICT_READ_WRITE") */ - private $groupCenters; + private Collection $groupCenters; /** * @ORM\Column(type="string", length=200) - * @Serializer\Groups({"docgen:read"}) */ private string $label = ''; /** - * @var bool - * * @ORM\Column(type="boolean") * sf4 check: in yml was false by default !? */ - private $locked = true; + private bool $locked = true; /** * @ORM\ManyToOne(targetEntity=Center::class) - * @Serializer\Groups({"docgen:read"}) */ private ?Center $mainCenter = null; @@ -117,20 +103,16 @@ class User implements AdvancedUserInterface private ?Scope $mainScope = null; /** - * @var string - * * @ORM\Column(type="string", length=255) */ - private $password; + private string $password = ''; /** - * @var string - * * @internal must be set to null if we use bcrypt * * @ORM\Column(type="string", length=255, nullable=true) */ - private $salt; + private ?string $salt = null; /** * @ORM\ManyToOne(targetEntity=UserJob::class) @@ -138,22 +120,18 @@ class User implements AdvancedUserInterface private ?UserJob $userJob = null; /** - * @var string - * * @ORM\Column(type="string", length=80) */ - private $username; + private string $username = ''; /** - * @var string - * * @ORM\Column( * type="string", * length=80, * unique=true, * nullable=true) */ - private $usernameCanonical; + private ?string $usernameCanonical = null; /** * User constructor. @@ -209,7 +187,7 @@ class User implements AdvancedUserInterface /** * @return string */ - public function getEmail() + public function getEmail(): ?string { return $this->email; } @@ -406,10 +384,7 @@ class User implements AdvancedUserInterface return $this; } - /** - * @param bool $enabled - */ - public function setEnabled($enabled) + public function setEnabled(bool $enabled) { $this->enabled = $enabled; diff --git a/src/Bundle/ChillMainBundle/Entity/UserJob.php b/src/Bundle/ChillMainBundle/Entity/UserJob.php index bccba10dd..5f0bea45d 100644 --- a/src/Bundle/ChillMainBundle/Entity/UserJob.php +++ b/src/Bundle/ChillMainBundle/Entity/UserJob.php @@ -32,14 +32,14 @@ class UserJob * @ORM\Id * @ORM\Column(name="id", type="integer") * @ORM\GeneratedValue(strategy="AUTO") - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ protected ?int $id = null; /** * @var array|string[]A * @ORM\Column(name="label", type="json") - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ protected array $label = []; diff --git a/src/Bundle/ChillMainBundle/Export/ExportManager.php b/src/Bundle/ChillMainBundle/Export/ExportManager.php index 782a2fdd2..f9964ea3b 100644 --- a/src/Bundle/ChillMainBundle/Export/ExportManager.php +++ b/src/Bundle/ChillMainBundle/Export/ExportManager.php @@ -26,6 +26,7 @@ use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use UnexpectedValueException; + use function array_key_exists; use function count; use function get_class; @@ -122,8 +123,10 @@ class ExportManager public function &getFiltersApplyingOn(ExportInterface $export, ?array $centers = null) { foreach ($this->filters as $alias => $filter) { - if (in_array($filter->applyOn(), $export->supportsModifiers(), true) - && $this->isGrantedForElement($filter, $export, $centers)) { + if ( + in_array($filter->applyOn(), $export->supportsModifiers(), true) + && $this->isGrantedForElement($filter, $export, $centers) + ) { yield $alias => $filter; } } @@ -143,8 +146,10 @@ class ExportManager } foreach ($this->aggregators as $alias => $aggregator) { - if (in_array($aggregator->applyOn(), $export->supportsModifiers(), true) - && $this->isGrantedForElement($aggregator, $export, $centers)) { + if ( + in_array($aggregator->applyOn(), $export->supportsModifiers(), true) + && $this->isGrantedForElement($aggregator, $export, $centers) + ) { yield $alias => $aggregator; } } @@ -545,7 +550,7 @@ class ExportManager if (null === $centers) { $centers = $this->authorizationHelper->getReachableCenters( $this->user, - $role + $role->getRole(), ); } @@ -585,7 +590,7 @@ class ExportManager 'center' => $center, 'circles' => $this->authorizationHelper->getReachableScopes( $this->user, - $element->requiredRole(), + $element->requiredRole()->getRole(), $center ), ]; diff --git a/src/Bundle/ChillMainBundle/Export/Formatter/CSVFormatter.php b/src/Bundle/ChillMainBundle/Export/Formatter/CSVFormatter.php index 914fa15c3..7e5b71268 100644 --- a/src/Bundle/ChillMainBundle/Export/Formatter/CSVFormatter.php +++ b/src/Bundle/ChillMainBundle/Export/Formatter/CSVFormatter.php @@ -20,6 +20,7 @@ use Symfony\Component\Form\Extension\Core\Type\FormType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Contracts\Translation\TranslatorInterface; + use function array_key_exists; use function array_slice; use function call_user_func; diff --git a/src/Bundle/ChillMainBundle/Export/Formatter/CSVListFormatter.php b/src/Bundle/ChillMainBundle/Export/Formatter/CSVListFormatter.php index 94c8c5ee3..cb184e250 100644 --- a/src/Bundle/ChillMainBundle/Export/Formatter/CSVListFormatter.php +++ b/src/Bundle/ChillMainBundle/Export/Formatter/CSVListFormatter.php @@ -19,6 +19,7 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Translation\TranslatorInterface; + use function array_key_exists; use function array_keys; use function array_map; @@ -198,7 +199,9 @@ class CSVListFormatter implements FormatterInterface foreach ($keys as $key) { // get an array with all values for this key if possible - $values = array_map(static function ($v) use ($key) { return $v[$key]; }, $this->result); + $values = array_map(static function ($v) use ($key) { + return $v[$key]; + }, $this->result); // store the label in the labelsCache property $this->labelsCache[$key] = $export->getLabels($key, $values, $this->exportData); } diff --git a/src/Bundle/ChillMainBundle/Export/Formatter/CSVPivotedListFormatter.php b/src/Bundle/ChillMainBundle/Export/Formatter/CSVPivotedListFormatter.php index 7e3334340..790a8b540 100644 --- a/src/Bundle/ChillMainBundle/Export/Formatter/CSVPivotedListFormatter.php +++ b/src/Bundle/ChillMainBundle/Export/Formatter/CSVPivotedListFormatter.php @@ -18,6 +18,7 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Translation\TranslatorInterface; + use function array_map; use function count; @@ -186,7 +187,9 @@ class CSVPivotedListFormatter implements FormatterInterface foreach ($keys as $key) { // get an array with all values for this key if possible - $values = array_map(static function ($v) use ($key) { return $v[$key]; }, $this->result); + $values = array_map(static function ($v) use ($key) { + return $v[$key]; + }, $this->result); // store the label in the labelsCache property $this->labelsCache[$key] = $export->getLabels($key, $values, $this->exportData); } diff --git a/src/Bundle/ChillMainBundle/Export/Formatter/SpreadSheetFormatter.php b/src/Bundle/ChillMainBundle/Export/Formatter/SpreadSheetFormatter.php index 590e79a41..0c890f009 100644 --- a/src/Bundle/ChillMainBundle/Export/Formatter/SpreadSheetFormatter.php +++ b/src/Bundle/ChillMainBundle/Export/Formatter/SpreadSheetFormatter.php @@ -20,6 +20,7 @@ use Symfony\Component\Form\Extension\Core\Type\FormType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Translation\TranslatorInterface; + use function array_map; use function array_merge; use function array_multisort; diff --git a/src/Bundle/ChillMainBundle/Export/Formatter/SpreadsheetListFormatter.php b/src/Bundle/ChillMainBundle/Export/Formatter/SpreadsheetListFormatter.php index e31535602..aaebadd99 100644 --- a/src/Bundle/ChillMainBundle/Export/Formatter/SpreadsheetListFormatter.php +++ b/src/Bundle/ChillMainBundle/Export/Formatter/SpreadsheetListFormatter.php @@ -24,6 +24,7 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Translation\TranslatorInterface; + use function array_key_exists; use function array_keys; use function array_map; @@ -257,7 +258,9 @@ class SpreadsheetListFormatter implements FormatterInterface foreach ($keys as $key) { // get an array with all values for this key if possible - $values = array_map(static function ($v) use ($key) { return $v[$key]; }, $this->result); + $values = array_map(static function ($v) use ($key) { + return $v[$key]; + }, $this->result); // store the label in the labelsCache property $this->labelsCache[$key] = $export->getLabels($key, $values, $this->exportData); } diff --git a/src/Bundle/ChillMainBundle/Form/ChoiceLoader/PostalCodeChoiceLoader.php b/src/Bundle/ChillMainBundle/Form/ChoiceLoader/PostalCodeChoiceLoader.php index 7e0702de1..ed0426b8b 100644 --- a/src/Bundle/ChillMainBundle/Form/ChoiceLoader/PostalCodeChoiceLoader.php +++ b/src/Bundle/ChillMainBundle/Form/ChoiceLoader/PostalCodeChoiceLoader.php @@ -15,6 +15,7 @@ use Chill\MainBundle\Entity\PostalCode; use Chill\MainBundle\Repository\PostalCodeRepository; use Symfony\Component\Form\ChoiceList\ChoiceListInterface; use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; + use function call_user_func; /** diff --git a/src/Bundle/ChillMainBundle/Form/PermissionsGroupType.php b/src/Bundle/ChillMainBundle/Form/PermissionsGroupType.php index e798a262e..706ba4f08 100644 --- a/src/Bundle/ChillMainBundle/Form/PermissionsGroupType.php +++ b/src/Bundle/ChillMainBundle/Form/PermissionsGroupType.php @@ -17,6 +17,7 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; + use function array_combine; use function array_merge; use function count; diff --git a/src/Bundle/ChillMainBundle/Form/Type/ComposedGroupCenterType.php b/src/Bundle/ChillMainBundle/Form/Type/ComposedGroupCenterType.php index 1398a8ce2..11b079f4a 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/ComposedGroupCenterType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/ComposedGroupCenterType.php @@ -15,7 +15,6 @@ use Chill\MainBundle\Entity\Center; use Chill\MainBundle\Entity\PermissionsGroup; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractType; - use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; diff --git a/src/Bundle/ChillMainBundle/Form/Type/ComposedRoleScopeType.php b/src/Bundle/ChillMainBundle/Form/Type/ComposedRoleScopeType.php index bf5e2d4f8..2f3378ae8 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/ComposedRoleScopeType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/ComposedRoleScopeType.php @@ -16,10 +16,10 @@ use Chill\MainBundle\Security\RoleProvider; 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\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; + use function in_array; /** diff --git a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/CenterTransformer.php b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/CenterTransformer.php index a0f609d46..1bc02f9dd 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/CenterTransformer.php +++ b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/CenterTransformer.php @@ -18,6 +18,7 @@ use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Traversable; + use function count; class CenterTransformer implements DataTransformerInterface diff --git a/src/Bundle/ChillMainBundle/Form/Type/DateIntervalType.php b/src/Bundle/ChillMainBundle/Form/Type/DateIntervalType.php index 66ae4d846..a99ee6135 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/DateIntervalType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/DateIntervalType.php @@ -19,6 +19,7 @@ use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Validator\Constraints\GreaterThan; + use function array_diff; use function array_values; use function count; diff --git a/src/Bundle/ChillMainBundle/Form/Type/Export/PickCenterType.php b/src/Bundle/ChillMainBundle/Form/Type/Export/PickCenterType.php index daf33eb57..2fe5ff8f2 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/Export/PickCenterType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/Export/PickCenterType.php @@ -23,6 +23,7 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; + use function array_intersect; use function array_key_exists; use function array_merge; @@ -85,7 +86,9 @@ class PickCenterType extends AbstractType 'query_builder' => static function (EntityRepository $er) use ($centers) { $qb = $er->createQueryBuilder('c'); $ids = array_map( - static function (Center $el) { return $el->getId(); }, + static function (Center $el) { + return $el->getId(); + }, $centers ); @@ -93,7 +96,9 @@ class PickCenterType extends AbstractType }, 'multiple' => true, 'expanded' => true, - 'choice_label' => static function (Center $c) { return $c->getName(); }, + 'choice_label' => static function (Center $c) { + return $c->getName(); + }, 'data' => count($this->groupingCenters) > 0 ? null : $centers, ]); @@ -122,8 +127,12 @@ class PickCenterType extends AbstractType } $builder->addModelTransformer(new CallbackTransformer( - function ($data) use ($centers) { return $this->transform($data, $centers); }, - function ($data) use ($centers) { return $this->reverseTransform($data, $centers); } + function ($data) use ($centers) { + return $this->transform($data, $centers); + }, + function ($data) use ($centers) { + return $this->reverseTransform($data, $centers); + } )); } diff --git a/src/Bundle/ChillMainBundle/Form/Type/Export/PickFormatterType.php b/src/Bundle/ChillMainBundle/Form/Type/Export/PickFormatterType.php index 2b1c8e093..885be3c27 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/Export/PickFormatterType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/Export/PickFormatterType.php @@ -15,7 +15,6 @@ use Chill\MainBundle\Export\ExportManager; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormBuilderInterface; - use Symfony\Component\OptionsResolver\OptionsResolver; /** diff --git a/src/Bundle/ChillMainBundle/Form/Type/Listing/FilterOrderType.php b/src/Bundle/ChillMainBundle/Form/Type/Listing/FilterOrderType.php index 488246a50..2b6cdc21d 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/Listing/FilterOrderType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/Listing/FilterOrderType.php @@ -19,6 +19,7 @@ use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\HttpFoundation\RequestStack; + use function array_combine; use function array_map; use function count; diff --git a/src/Bundle/ChillMainBundle/Form/Type/PickAddressType.php b/src/Bundle/ChillMainBundle/Form/Type/PickAddressType.php index 647c45553..20933563a 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/PickAddressType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/PickAddressType.php @@ -20,6 +20,7 @@ use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Contracts\Translation\TranslatorInterface; + use function uniqid; /** diff --git a/src/Bundle/ChillMainBundle/Form/Type/PickCenterType.php b/src/Bundle/ChillMainBundle/Form/Type/PickCenterType.php index 5ccf217a0..053ee31e1 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/PickCenterType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/PickCenterType.php @@ -25,6 +25,7 @@ use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Security\Core\Security; + use function array_merge; use function array_values; use function count; @@ -151,8 +152,10 @@ class PickCenterType extends AbstractType $centers = []; foreach ($scopes as $scope) { - foreach ($this->authorizationHelper - ->getReachableCenters($this->security->getUser(), $role, $scope) as $center) { + foreach ( + $this->authorizationHelper + ->getReachableCenters($this->security->getUser(), $role, $scope) as $center + ) { $centers[spl_object_hash($center)] = $center; } } diff --git a/src/Bundle/ChillMainBundle/Form/Type/ScopePickerType.php b/src/Bundle/ChillMainBundle/Form/Type/ScopePickerType.php index 0b3642f7d..92a1b26c3 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/ScopePickerType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/ScopePickerType.php @@ -29,6 +29,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Security; + use function array_map; use function count; @@ -80,7 +81,7 @@ class ScopePickerType extends AbstractType { $items = $this->authorizationHelper->getReachableScopes( $this->security->getUser(), - $options['role'], + $options['role'] instanceof Role ? $options['role']->getRole() : $options['role'], $options['center'] ); diff --git a/src/Bundle/ChillMainBundle/Form/Type/Select2CountryType.php b/src/Bundle/ChillMainBundle/Form/Type/Select2CountryType.php index bed90ad18..d3374e9de 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/Select2CountryType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/Select2CountryType.php @@ -19,6 +19,7 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\OptionsResolver\OptionsResolver; + use const SORT_FLAG_CASE; use const SORT_STRING; diff --git a/src/Bundle/ChillMainBundle/Form/Type/Select2LanguageType.php b/src/Bundle/ChillMainBundle/Form/Type/Select2LanguageType.php index 9fad2bdb3..4c8e11a49 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/Select2LanguageType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/Select2LanguageType.php @@ -19,6 +19,7 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\OptionsResolver\OptionsResolver; + use const SORT_FLAG_CASE; use const SORT_STRING; diff --git a/src/Bundle/ChillMainBundle/Form/Type/TranslatableStringFormType.php b/src/Bundle/ChillMainBundle/Form/Type/TranslatableStringFormType.php index 3f44a4e97..822ff0101 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/TranslatableStringFormType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/TranslatableStringFormType.php @@ -19,6 +19,7 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Translation\Translator; + use function in_array; class TranslatableStringFormType extends AbstractType diff --git a/src/Bundle/ChillMainBundle/Form/Type/UserPickerType.php b/src/Bundle/ChillMainBundle/Form/Type/UserPickerType.php index 9c8829dd9..c9a644aa9 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/UserPickerType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/UserPickerType.php @@ -16,6 +16,7 @@ use Chill\MainBundle\Entity\User; use Chill\MainBundle\Repository\UserACLAwareRepositoryInterface; use Chill\MainBundle\Repository\UserRepository; use Chill\MainBundle\Security\Authorization\AuthorizationHelper; +use Chill\MainBundle\Templating\Entity\UserRender; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\Options; @@ -47,16 +48,20 @@ class UserPickerType extends AbstractType protected UserRepository $userRepository; + private UserRender $userRender; + public function __construct( AuthorizationHelper $authorizationHelper, TokenStorageInterface $tokenStorage, UserRepository $userRepository, - UserACLAwareRepositoryInterface $userACLAwareRepository + UserACLAwareRepositoryInterface $userACLAwareRepository, + UserRender $userRender ) { $this->authorizationHelper = $authorizationHelper; $this->tokenStorage = $tokenStorage; $this->userRepository = $userRepository; $this->userACLAwareRepository = $userACLAwareRepository; + $this->userRender = $userRender; } public function configureOptions(OptionsResolver $resolver) @@ -74,14 +79,19 @@ class UserPickerType extends AbstractType ->setAllowedTypes('having_permissions_group_flag', ['string', 'null']) ->setDefault('class', User::class) ->setDefault('placeholder', 'Choose an user') - ->setDefault('choice_label', static function (User $u) { - return $u->getUsername(); + ->setDefault('choice_label', function (User $u) { + return $this->userRender->renderString($u, []); }) ->setDefault('scope', null) ->setAllowedTypes('scope', [Scope::class, 'array', 'null']) ->setNormalizer('choices', function (Options $options) { + if ($options['role'] instanceof Role) { + $role = $options['role']->getRole(); + } else { + $role = $options['role']; + } $users = $this->userACLAwareRepository - ->findUsersByReachedACL($options['role'], $options['center'], $options['scope'], true); + ->findUsersByReachedACL($role, $options['center'], $options['scope'], true); if (null !== $options['having_permissions_group_flag']) { return $this->userRepository diff --git a/src/Bundle/ChillMainBundle/Notification/Mailer.php b/src/Bundle/ChillMainBundle/Notification/Mailer.php index 84382b4fb..479502060 100644 --- a/src/Bundle/ChillMainBundle/Notification/Mailer.php +++ b/src/Bundle/ChillMainBundle/Notification/Mailer.php @@ -18,6 +18,7 @@ use Swift_Message; use Symfony\Component\Routing\RouterInterface; use Symfony\Component\Translation\TranslatorInterface; use Twig\Environment; + use function call_user_func; /** diff --git a/src/Bundle/ChillMainBundle/Pagination/Paginator.php b/src/Bundle/ChillMainBundle/Pagination/Paginator.php index d6da55618..54fa36084 100644 --- a/src/Bundle/ChillMainBundle/Pagination/Paginator.php +++ b/src/Bundle/ChillMainBundle/Pagination/Paginator.php @@ -109,6 +109,10 @@ class Paginator implements PaginatorInterface return 1; } + if (0 === $this->totalItems) { + return 1; + } + $nb = floor($this->totalItems / $this->itemPerPage); if ($this->totalItems % $this->itemPerPage > 0) { @@ -211,6 +215,10 @@ class Paginator implements PaginatorInterface public function hasPage($number) { + if (0 === $this->totalItems) { + return 1 === $number; + } + return 0 < $number && $this->countPages() >= $number; } diff --git a/src/Bundle/ChillMainBundle/Pagination/PaginatorFactory.php b/src/Bundle/ChillMainBundle/Pagination/PaginatorFactory.php index e02729287..5b3684d3c 100644 --- a/src/Bundle/ChillMainBundle/Pagination/PaginatorFactory.php +++ b/src/Bundle/ChillMainBundle/Pagination/PaginatorFactory.php @@ -123,11 +123,11 @@ class PaginatorFactory { return array_merge( $this->router->getContext()->getParameters(), - // get the route parameters + // get the route parameters $this->requestStack ->getCurrentRequest() ->attributes->get('_route_params'), - // get the query parameters + // get the query parameters $this->requestStack ->getCurrentRequest()->query->all() ); diff --git a/src/Bundle/ChillMainBundle/Phonenumber/PhonenumberHelper.php b/src/Bundle/ChillMainBundle/Phonenumber/PhonenumberHelper.php index e807efebe..0eae018a8 100644 --- a/src/Bundle/ChillMainBundle/Phonenumber/PhonenumberHelper.php +++ b/src/Bundle/ChillMainBundle/Phonenumber/PhonenumberHelper.php @@ -17,6 +17,7 @@ use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Exception\ServerException; use Psr\Cache\CacheItemPoolInterface; use Psr\Log\LoggerInterface; + use function array_key_exists; use function in_array; use function json_decode; @@ -58,13 +59,14 @@ class PhonenumberHelper $this->logger = $logger; $this->cachePool = $cachePool; - if (array_key_exists('twilio_sid', $config) + if ( + array_key_exists('twilio_sid', $config) && !empty($config['twilio_sid']) && strlen($config['twilio_sid']) > 2 && array_key_exists('twilio_secret', $config) && !empty($config['twilio_secret']) && strlen($config['twilio_secret']) > 2 - ) { + ) { $this->twilioClient = new Client([ 'auth' => [$config['twilio_sid'], $config['twilio_secret']], ]); @@ -204,7 +206,7 @@ class PhonenumberHelper return null; } - $format = json_decode($response->getBody())->national_format; + $format = json_decode($response->getBody()->getContents())->national_format; $item ->set($format) @@ -260,7 +262,7 @@ class PhonenumberHelper return null; } - $validation = json_decode($response->getBody())->carrier->type; + $validation = json_decode($response->getBody()->getContents())->carrier->type; $item ->set($validation) diff --git a/src/Bundle/ChillMainBundle/Repository/AddressReferenceRepository.php b/src/Bundle/ChillMainBundle/Repository/AddressReferenceRepository.php index 4344964af..9cbad91c9 100644 --- a/src/Bundle/ChillMainBundle/Repository/AddressReferenceRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/AddressReferenceRepository.php @@ -12,17 +12,30 @@ declare(strict_types=1); namespace Chill\MainBundle\Repository; use Chill\MainBundle\Entity\AddressReference; +use Chill\MainBundle\Entity\PostalCode; +use Chill\MainBundle\Search\SearchApiQuery; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; +use Doctrine\ORM\Query\ResultSetMapping; +use Doctrine\ORM\Query\ResultSetMappingBuilder; use Doctrine\Persistence\ObjectRepository; +use RuntimeException; + +use function explode; +use function implode; +use function strtr; +use function trim; final class AddressReferenceRepository implements ObjectRepository { + private EntityManagerInterface $entityManager; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { $this->repository = $entityManager->getRepository(AddressReference::class); + $this->entityManager = $entityManager; } public function countAll(): int @@ -33,6 +46,18 @@ final class AddressReferenceRepository implements ObjectRepository return $qb->getQuery()->getSingleScalarResult(); } + public function countByPostalCodePattern(PostalCode $postalCode, string $pattern): int + { + $query = $this->buildQueryByPostalCodePattern($postalCode, $pattern); + $sql = $query->buildQuery(true); + $rsm = new ResultSetMapping(); + $rsm->addScalarResult('c', 'c'); + + $nq = $this->entityManager->createNativeQuery($sql, $rsm)->setParameters($query->buildParameters(true)); + + return (int) $nq->getSingleResult()['c']; + } + public function find($id, $lockMode = null, $lockVersion = null): ?AddressReference { return $this->repository->find($id, $lockMode, $lockVersion); @@ -57,6 +82,33 @@ final class AddressReferenceRepository implements ObjectRepository return $this->repository->findBy($criteria, $orderBy, $limit, $offset); } + /** + * @return AddressReference[]|array + */ + public function findByPostalCodePattern(PostalCode $postalCode, string $pattern, bool $simplify = false, int $start = 0, int $limit = 50): array + { + $query = $this->buildQueryByPostalCodePattern($postalCode, $pattern); + + if (!$simplify) { + $rsm = new ResultSetMappingBuilder($this->entityManager); + $rsm->addRootEntityFromClassMetadata(AddressReference::class, 'cma'); + $query->addSelectClause($rsm->generateSelectClause()); + } else { + throw new RuntimeException('not implemented'); + } + + $sql = strtr( + $query->buildQuery() . 'ORDER BY pertinence DESC, lpad(streetnumber, 10, \'0\') ASC OFFSET ? LIMIT ? ', + // little hack for adding sql method to point + ['cma.point AS point' => 'ST_AsGeojson(cma.point) AS point'] + ); + $parameters = [...$query->buildParameters(), $start, $limit]; + + return $this->entityManager->createNativeQuery($sql, $rsm) + ->setParameters($parameters) + ->getResult(); + } + public function findOneBy(array $criteria, ?array $orderBy = null): ?AddressReference { return $this->repository->findOneBy($criteria, $orderBy); @@ -66,4 +118,44 @@ final class AddressReferenceRepository implements ObjectRepository { return AddressReference::class; } + + private function buildQueryByPostalCodePattern(PostalCode $postalCode, string $pattern): SearchApiQuery + { + $pattern = trim($pattern); + + if ('' === $pattern) { + throw new RuntimeException('the search pattern must not be empty'); + } + $query = new SearchApiQuery(); + + $query + ->setFromClause('chill_main_address_reference cma') + ->andWhereClause('postcode_id = ?', [$postalCode->getId()]); + + $pertinenceClause = ['STRICT_WORD_SIMILARITY(addresscanonical, UNACCENT(?))']; + $pertinenceArgs = [$pattern]; + $orWhere = ['addresscanonical %>> UNACCENT(?)']; + $orWhereArgs = [$pattern]; + + foreach (explode(' ', $pattern) as $part) { + $part = trim($part); + + if ('' === $part) { + continue; + } + + $orWhere[] = "addresscanonical LIKE '%' || UNACCENT(LOWER(?)) || '%'"; + $orWhereArgs[] = $part; + $pertinenceClause[] = + "(EXISTS (SELECT 1 FROM unnest(string_to_array(addresscanonical, ' ')) AS t WHERE starts_with(t, UNACCENT(LOWER(?)))))::int"; + $pertinenceClause[] = + '(addresscanonical LIKE UNACCENT(LOWER(?)))::int'; + array_push($pertinenceArgs, $part, $part); + } + $query + ->setSelectPertinence(implode(' + ', $pertinenceClause), $pertinenceArgs) + ->andWhereClause(implode(' OR ', $orWhere), $orWhereArgs); + + return $query; + } } diff --git a/src/Bundle/ChillMainBundle/Repository/PostalCodeRepository.php b/src/Bundle/ChillMainBundle/Repository/PostalCodeRepository.php index 697c8f90d..02e63771b 100644 --- a/src/Bundle/ChillMainBundle/Repository/PostalCodeRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/PostalCodeRepository.php @@ -11,18 +11,39 @@ declare(strict_types=1); namespace Chill\MainBundle\Repository; +use Chill\MainBundle\Entity\Country; use Chill\MainBundle\Entity\PostalCode; +use Chill\MainBundle\Search\SearchApiQuery; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; +use Doctrine\ORM\Query\ResultSetMapping; +use Doctrine\ORM\Query\ResultSetMappingBuilder; use Doctrine\Persistence\ObjectRepository; +use RuntimeException; final class PostalCodeRepository implements ObjectRepository { + private EntityManagerInterface $entityManager; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { $this->repository = $entityManager->getRepository(PostalCode::class); + $this->entityManager = $entityManager; + } + + public function countByPattern(string $pattern, ?Country $country): int + { + $query = $this->buildQueryByPattern($pattern, $country); + $sql = $query->buildQuery(true); + $rsm = new ResultSetMapping(); + $rsm->addScalarResult('c', 'c'); + + $nq = $this->entityManager->createNativeQuery($sql, $rsm) + ->setParameters($query->buildParameters(true)); + + return (int) $nq->getSingleResult()['c']; } public function find($id, $lockMode = null, $lockVersion = null): ?PostalCode @@ -49,6 +70,26 @@ final class PostalCodeRepository implements ObjectRepository return $this->repository->findBy($criteria, $orderBy, $limit, $offset); } + public function findByPattern(string $pattern, ?Country $country, ?int $start = 0, ?int $limit = 50): array + { + $query = $this->buildQueryByPattern($pattern, $country); + + $rsm = new ResultSetMappingBuilder($this->entityManager); + $rsm->addRootEntityFromClassMetadata(PostalCode::class, 'cmpc'); + $query->addSelectClause($rsm->generateSelectClause()); + + $sql = strtr( + $query->buildQuery() . 'ORDER BY pertinence DESC, canonical ASC OFFSET ? LIMIT ? ', + // little hack for adding sql method to point + ['cmpc.center AS center' => 'ST_AsGeojson(cmpc.center) AS center'] + ); + $parameters = [...$query->buildParameters(), $start, $limit]; + + return $this->entityManager->createNativeQuery($sql, $rsm) + ->setParameters($parameters) + ->getResult(); + } + public function findOneBy(array $criteria, ?array $orderBy = null): ?PostalCode { return $this->repository->findOneBy($criteria, $orderBy); @@ -58,4 +99,48 @@ final class PostalCodeRepository implements ObjectRepository { return PostalCode::class; } + + private function buildQueryByPattern(string $pattern, ?Country $country): SearchApiQuery + { + $pattern = trim($pattern); + + if ('' === $pattern) { + throw new RuntimeException('the search pattern must not be empty'); + } + $query = new SearchApiQuery(); + + $query + ->setFromClause('chill_main_postal_code cmpc') + ->andWhereClause('cmpc.origin = 0'); + + if (null !== $country) { + $query->andWhereClause('cmpc.country_id = ?', [$country->getId()]); + } + + $pertinenceClause = ['STRICT_WORD_SIMILARITY(canonical, UNACCENT(?))']; + $pertinenceArgs = [$pattern]; + $orWhere = ['canonical %>> UNACCENT(?)']; + $orWhereArgs = [$pattern]; + + foreach (explode(' ', $pattern) as $part) { + $part = trim($part); + + if ('' === $part) { + continue; + } + + $orWhere[] = "canonical LIKE '%' || UNACCENT(LOWER(?)) || '%'"; + $orWhereArgs[] = $part; + $pertinenceClause[] = + "(EXISTS (SELECT 1 FROM unnest(string_to_array(canonical, ' ')) AS t WHERE starts_with(t, UNACCENT(LOWER(?)))))::int"; + $pertinenceClause[] = + '(canonical LIKE UNACCENT(LOWER(?)))::int'; + array_push($pertinenceArgs, $part, $part); + } + $query + ->setSelectPertinence(implode(' + ', $pertinenceClause), $pertinenceArgs) + ->andWhereClause(implode(' OR ', $orWhere), $orWhereArgs); + + return $query; + } } diff --git a/src/Bundle/ChillMainBundle/Repository/UserRepository.php b/src/Bundle/ChillMainBundle/Repository/UserRepository.php index 00556702e..fc3a6e187 100644 --- a/src/Bundle/ChillMainBundle/Repository/UserRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/UserRepository.php @@ -17,6 +17,7 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ObjectRepository; + use function count; final class UserRepository implements ObjectRepository diff --git a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/badge.scss b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/badge.scss index 5a7c084a8..4d213645e 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/badge.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/badge.scss @@ -8,6 +8,10 @@ content: "\f00d"; // fa-times color: var(--bs-danger); text-decoration: none; + position: absolute; + display: block; + top: calc(50% - 7px); + right: 10px; } } @@ -25,20 +29,47 @@ ul.list-suggest { text-align: start; margin-bottom: 3px; } + &.cols { + columns: 3; + } + &.inline { + li { + display: inline-block; + margin-right: 0.2em; + } + } &.add-items { li { - cursor: pointer; + position: relative; + span { + cursor: pointer; + padding-left: 2rem; + } & > span:before { font: normal normal normal 14px/1 ForkAwesome; margin-right: 0.5em; content: "\f067"; // fa-plus color: var(--bs-success); + position: absolute; + display: block; + top: 50%; + left: .75rem; + -webkit-transform: translateY(-50%); + -moz-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + } + & span:hover { + color: $chill-l-gray; } } } &.remove-items { li { - a { + position: relative; + span { + display: block; + padding-right: .75rem; @include remove_link; } } @@ -48,7 +79,14 @@ ul.list-suggest { /// manage remove link if it isn't a list but a title /// (cfr. in Vue AccompanyingCourseWorkEdit) div.item-title { - a { - @include remove_link; + span { + display: block; + position: relative; + padding: 0.5em 0.8em; + background-color: $chill-llight-gray; + border-radius: .25rem; + &.removable { + @include remove_link; + } } } diff --git a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/flex_table.scss b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/flex_table.scss index 8e3a9121b..20fe927a6 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/flex_table.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/flex_table.scss @@ -101,6 +101,10 @@ div.flex-table { div.item-row { flex-direction: row; + &.column { // exception + flex-direction: column + } + div.item-col { &:first-child { flex-grow: 0; flex-shrink: 0; flex-basis: auto; @@ -160,6 +164,12 @@ div.wrap-list { & > * { padding-right: 1em; } + + h3, h4 { + font-weight: 700; + font-size: 100%; + font-family: 'Open Sans'; + } } div.wl-col.list { @@ -171,6 +181,10 @@ div.wrap-list { padding: 0em; display: inline-block; } + + blockquote.chill-user-quote { + margin: 0.7em 0; + } } } @@ -183,7 +197,7 @@ div.wrap-list { div.wl-col.list { background-color: cyan; - p.wl-item { + .wl-item { background-color: orange; } } diff --git a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/record_actions.scss b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/record_actions.scss index bdb3c60a6..928468715 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/record_actions.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/record_actions.scss @@ -33,6 +33,14 @@ ul.record_actions { margin-right: auto; } } + + ul.dropdown-menu { + z-index: 2000; + li { + display: block; + margin-right: 0; + } + } } .sticky-form-buttons { margin-top: 4em; diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/api.js b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/api.js index 62065b3ad..1dbc85dee 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/api.js +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/api.js @@ -16,7 +16,8 @@ const fetchCountries = () => { /** * Endpoint chill_api_single_postal_code__index -* method GET, get Country Object +* method GET, get Cities Object +* @params {object} a country object * @returns {Promise} a promise containing all Postal Code objects filtered with country */ const fetchCities = (country) => { @@ -29,6 +30,40 @@ const fetchCities = (country) => { }); }; + +/** +* Endpoint chill_main_postalcodeapi_search +* method GET, get Cities Object +* @params {string} search a search string +* @params {object} country a country object +* @returns {Promise} a promise containing all Postal Code objects filtered with country and a search string +*/ +const searchCities = (search, country) => { + const url = `/api/1.0/main/postal-code/search.json?q=${search}&country=${country.id}`; + return fetch(url) + .then(response => { + if (response.ok) { return response.json(); } + throw Error('Error with request resource response'); + }); +}; + +/** +* Endpoint chill_main_addressreferenceapi_search +* method GET, get AddressReference Object +* @params {string} search a search string +* @params {object} postalCode a postalCode object +* @returns {Promise} a promise containing all Postal Code objects filtered with country and a search string +*/ +const searchReferenceAddresses = (search, postalCode) => { + const url = `/api/1.0/main/address-reference/by-postal-code/${postalCode.id}/search.json?q=${search}`; + return fetch(url) + .then(response => { + if (response.ok) { return response.json(); } + throw Error('Error with request resource response'); + }); +}; + + /** * Endpoint chill_api_single_address_reference__index * method GET, get AddressReference Object @@ -170,5 +205,7 @@ export { postAddress, patchAddress, postPostalCode, - getAddress + getAddress, + searchCities, + searchReferenceAddresses }; diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue index 87ecff7fb..ed1d14633 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue @@ -556,8 +556,8 @@ export default { this.entity.selected.address.distribution = this.context.edit ? this.entity.address.distribution: null; this.entity.selected.address.extra = this.context.edit ? this.entity.address.extra: null; - this.entity.selected.writeNew.address = this.context.edit; - this.entity.selected.writeNew.postcode = this.context.edit; + this.entity.selected.writeNew.address = this.context.edit && this.entity.address.addressReference === null && this.entity.address.street.length > 0 + this.entity.selected.writeNew.postcode = false // NB: this used to be this.context.edit, but think it was erroneous; console.log('!! just set writeNew.postcode to', this.entity.selected.writeNew.postcode); }, @@ -569,7 +569,6 @@ export default { applyChanges() { console.log('apply changes'); - let newAddress = { 'isNoAddress': this.entity.selected.isNoAddress, 'street': this.entity.selected.isNoAddress ? '' : this.entity.selected.address.street, @@ -633,7 +632,6 @@ export default { if (!this.context.edit) { this.addNewAddress(newAddress) .then(payload => this.addressChangedCallback(payload)); - } else { this.updateAddress({ addressId: this.context.addressId, @@ -697,8 +695,7 @@ export default { * Async PATCH transactions, * then update existing address with backend datas when promise is resolved */ - updateAddress(payload) - { + updateAddress(payload) { this.flag.loading = true; // TODO change the condition because it writes new postal code in edit mode now: !writeNewPostalCode diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue index 2409dca53..c333961db 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue @@ -18,6 +18,7 @@ :taggable="true" :multiple="false" @tag="addAddress" + :loading="isLoading" :options="addresses">
    @@ -48,14 +49,17 @@ diff --git a/src/Bundle/ChillMainBundle/Resources/views/Entity/address.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Entity/address.html.twig index b915daf1a..4d871404f 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Entity/address.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Entity/address.html.twig @@ -12,13 +12,11 @@ * extended_infos bool add extra informations (step, floor, etc.) #} -{% macro raw(address, options) %} + +{% macro raw(address, options, streetLine) %} + {% if address.street is not empty %} -

    {{ address.street }} - {% if address.streetNumber is not empty %} - {{ address.streetNumber }} - {% endif %} -

    +

    {{ streetLine }}

    {% endif %} {% if options['extended_infos'] %} {{ _self.extended(address, options) }} @@ -56,7 +54,7 @@ {% endif %} {% endmacro %} -{% macro inline(address, options) %} +{% macro inline(address, options, streetLine) %} {% if options['has_no_address'] == true and address.isNoAddress == true %} {% if address.postCode is not empty %}

    @@ -70,7 +68,7 @@ {% else %} - {{ _self.raw(address, options) }} + {{ _self.raw(address, options, streetLine) }} {% endif %} {{ _self.validity(address, options) }} @@ -99,7 +97,7 @@ {% if options['with_picto'] %} {% endif %} - {{ _self.inline(address, options) }} + {{ _self.inline(address, options, streetLine) }} {%- endif -%} @@ -108,7 +106,7 @@ {% if options['with_picto'] %} {% endif %} - {{ _self.inline(address, options) }} + {{ _self.inline(address, options, streetLine) }} {%- endif -%} @@ -133,7 +131,7 @@ {% if options['with_picto'] %} {% endif %} - {{ _self.raw(address, options) }} + {{ _self.raw(address, options, streetLine) }} {% endif %} {{ _self.validity(address, options) }} diff --git a/src/Bundle/ChillMainBundle/Resources/views/FilterOrder/base.html.twig b/src/Bundle/ChillMainBundle/Resources/views/FilterOrder/base.html.twig index f9924eb11..515685b9e 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/FilterOrder/base.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/FilterOrder/base.html.twig @@ -1,5 +1,5 @@ {{ form_start(form) }} -

    +
    {% if form.vars.has_search_box %}
    diff --git a/src/Bundle/ChillMainBundle/Routing/MenuComposer.php b/src/Bundle/ChillMainBundle/Routing/MenuComposer.php index a94cf41f3..763eab0e5 100644 --- a/src/Bundle/ChillMainBundle/Routing/MenuComposer.php +++ b/src/Bundle/ChillMainBundle/Routing/MenuComposer.php @@ -16,6 +16,7 @@ use Knp\Menu\ItemInterface; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\RouterInterface; use Symfony\Component\Translation\TranslatorInterface; + use function array_key_exists; use function array_merge; use function array_values; diff --git a/src/Bundle/ChillMainBundle/Search/AbstractSearch.php b/src/Bundle/ChillMainBundle/Search/AbstractSearch.php index adadc3422..099c4e438 100644 --- a/src/Bundle/ChillMainBundle/Search/AbstractSearch.php +++ b/src/Bundle/ChillMainBundle/Search/AbstractSearch.php @@ -12,6 +12,7 @@ declare(strict_types=1); namespace Chill\MainBundle\Search; use DateTime; + use function array_key_exists; use function strpos; diff --git a/src/Bundle/ChillMainBundle/Search/Entity/SearchUserApiProvider.php b/src/Bundle/ChillMainBundle/Search/Entity/SearchUserApiProvider.php index 5a68fab37..5c3c6b057 100644 --- a/src/Bundle/ChillMainBundle/Search/Entity/SearchUserApiProvider.php +++ b/src/Bundle/ChillMainBundle/Search/Entity/SearchUserApiProvider.php @@ -14,6 +14,7 @@ namespace Chill\MainBundle\Search\Entity; use Chill\MainBundle\Repository\UserRepository; use Chill\MainBundle\Search\SearchApiInterface; use Chill\MainBundle\Search\SearchApiQuery; + use function array_map; use function in_array; diff --git a/src/Bundle/ChillMainBundle/Search/SearchApi.php b/src/Bundle/ChillMainBundle/Search/SearchApi.php index b0740b383..7436b3303 100644 --- a/src/Bundle/ChillMainBundle/Search/SearchApi.php +++ b/src/Bundle/ChillMainBundle/Search/SearchApi.php @@ -16,6 +16,7 @@ use Chill\MainBundle\Serializer\Model\Collection; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Query\ResultSetMappingBuilder; + use function array_map; use function array_merge; use function count; diff --git a/src/Bundle/ChillMainBundle/Search/SearchApiNoQueryException.php b/src/Bundle/ChillMainBundle/Search/SearchApiNoQueryException.php index 46dfc759b..1f3a1b3df 100644 --- a/src/Bundle/ChillMainBundle/Search/SearchApiNoQueryException.php +++ b/src/Bundle/ChillMainBundle/Search/SearchApiNoQueryException.php @@ -13,6 +13,7 @@ namespace Chill\MainBundle\Search; use RuntimeException; use Throwable; + use function implode; class SearchApiNoQueryException extends RuntimeException diff --git a/src/Bundle/ChillMainBundle/Search/SearchProvider.php b/src/Bundle/ChillMainBundle/Search/SearchProvider.php index 61eb3fcd8..efae25751 100644 --- a/src/Bundle/ChillMainBundle/Search/SearchProvider.php +++ b/src/Bundle/ChillMainBundle/Search/SearchProvider.php @@ -276,8 +276,10 @@ class SearchProvider //remove from search pattern $this->mustBeExtracted[] = $matches[0][$key]; //strip parenthesis - if (mb_substr($match, 0, 1) === '"' - && mb_substr($match, mb_strlen($match) - 1) === '"') { + if ( + mb_substr($match, 0, 1) === '"' + && mb_substr($match, mb_strlen($match) - 1) === '"' + ) { $match = trim(mb_substr($match, 1, mb_strlen($match) - 2)); } $terms[$matches[1][$key]] = $match; diff --git a/src/Bundle/ChillMainBundle/Search/Utils/ExtractDateFromPattern.php b/src/Bundle/ChillMainBundle/Search/Utils/ExtractDateFromPattern.php index 058bfe070..6035744e1 100644 --- a/src/Bundle/ChillMainBundle/Search/Utils/ExtractDateFromPattern.php +++ b/src/Bundle/ChillMainBundle/Search/Utils/ExtractDateFromPattern.php @@ -12,6 +12,7 @@ declare(strict_types=1); namespace Chill\MainBundle\Search\Utils; use DateTimeImmutable; + use function preg_match_all; use function strtr; use function trim; diff --git a/src/Bundle/ChillMainBundle/Search/Utils/ExtractPhonenumberFromPattern.php b/src/Bundle/ChillMainBundle/Search/Utils/ExtractPhonenumberFromPattern.php index caad6d093..b6286fa35 100644 --- a/src/Bundle/ChillMainBundle/Search/Utils/ExtractPhonenumberFromPattern.php +++ b/src/Bundle/ChillMainBundle/Search/Utils/ExtractPhonenumberFromPattern.php @@ -12,6 +12,7 @@ declare(strict_types=1); namespace Chill\MainBundle\Search\Utils; use LogicException; + use function count; use function implode; use function preg_match; diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/AbstractChillVoter.php b/src/Bundle/ChillMainBundle/Security/Authorization/AbstractChillVoter.php index 2cca61e9f..2392457b8 100644 --- a/src/Bundle/ChillMainBundle/Security/Authorization/AbstractChillVoter.php +++ b/src/Bundle/ChillMainBundle/Security/Authorization/AbstractChillVoter.php @@ -13,8 +13,10 @@ namespace Chill\MainBundle\Security\Authorization; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\Voter\Voter; + use function get_class; use function in_array; + use const E_USER_DEPRECATED; /** diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php b/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php index de7bff9ab..c1db57b7f 100644 --- a/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php +++ b/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php @@ -23,6 +23,7 @@ use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\User\UserInterface; use Traversable; use UnexpectedValueException; + use function array_merge; use function get_class; diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelper.php b/src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelper.php index 95f070b3b..01f04acd4 100644 --- a/src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelper.php +++ b/src/Bundle/ChillMainBundle/Security/Authorization/DefaultVoterHelper.php @@ -13,6 +13,7 @@ namespace Chill\MainBundle\Security\Authorization; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface; + use function in_array; final class DefaultVoterHelper implements VoterHelperInterface diff --git a/src/Bundle/ChillMainBundle/Security/ParentRoleHelper.php b/src/Bundle/ChillMainBundle/Security/ParentRoleHelper.php index 137c774b2..317ec4cd1 100644 --- a/src/Bundle/ChillMainBundle/Security/ParentRoleHelper.php +++ b/src/Bundle/ChillMainBundle/Security/ParentRoleHelper.php @@ -14,6 +14,7 @@ namespace Chill\MainBundle\Security; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; + use function array_keys; use function in_array; diff --git a/src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverVoter.php b/src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverVoter.php index 40787fe74..a47443486 100644 --- a/src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverVoter.php +++ b/src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverVoter.php @@ -15,6 +15,7 @@ use Chill\MainBundle\Entity\User; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\Voter\Voter; + use function in_array; class PasswordRecoverVoter extends Voter diff --git a/src/Bundle/ChillMainBundle/Security/PasswordRecover/RecoverPasswordHelper.php b/src/Bundle/ChillMainBundle/Security/PasswordRecover/RecoverPasswordHelper.php index e6f3db0e7..1244e2a61 100644 --- a/src/Bundle/ChillMainBundle/Security/PasswordRecover/RecoverPasswordHelper.php +++ b/src/Bundle/ChillMainBundle/Security/PasswordRecover/RecoverPasswordHelper.php @@ -15,6 +15,7 @@ use Chill\MainBundle\Entity\User; use Chill\MainBundle\Notification\Mailer; use DateTimeInterface; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; + use function array_merge; class RecoverPasswordHelper diff --git a/src/Bundle/ChillMainBundle/Security/PasswordRecover/TokenManager.php b/src/Bundle/ChillMainBundle/Security/PasswordRecover/TokenManager.php index 6a7f6f03e..5d3673b84 100644 --- a/src/Bundle/ChillMainBundle/Security/PasswordRecover/TokenManager.php +++ b/src/Bundle/ChillMainBundle/Security/PasswordRecover/TokenManager.php @@ -17,6 +17,7 @@ use DateTimeImmutable; use DateTimeInterface; use Psr\Log\LoggerInterface; use UnexpectedValueException; + use function bin2hex; use function hash; use function hex2bin; @@ -61,7 +62,7 @@ class TokenManager throw new UnexpectedValueException('username should not be empty to generate a token'); } - $timestamp = $expiration->getTimestamp(); + $timestamp = (string) $expiration->getTimestamp(); $hash = hash('sha1', $token . $username . $timestamp . $this->secret); return [ @@ -72,7 +73,7 @@ class TokenManager ]; } - public function verify($hash, $token, User $user, $timestamp) + public function verify($hash, $token, User $user, string $timestamp) { $token = hex2bin(trim($token)); diff --git a/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverManager.php b/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverManager.php index 2dfe1ecf2..dc873ee79 100644 --- a/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverManager.php +++ b/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverManager.php @@ -13,6 +13,7 @@ namespace Chill\MainBundle\Security\Resolver; use Chill\MainBundle\Entity\Center; use UnexpectedValueException; + use function get_class; use function is_array; diff --git a/src/Bundle/ChillMainBundle/Security/Resolver/ScopeResolverDispatcher.php b/src/Bundle/ChillMainBundle/Security/Resolver/ScopeResolverDispatcher.php index 1cd03e2b7..0e4cfdc78 100644 --- a/src/Bundle/ChillMainBundle/Security/Resolver/ScopeResolverDispatcher.php +++ b/src/Bundle/ChillMainBundle/Security/Resolver/ScopeResolverDispatcher.php @@ -12,6 +12,7 @@ declare(strict_types=1); namespace Chill\MainBundle\Security\Resolver; use Chill\MainBundle\Entity\Scope; +use Doctrine\Common\Collections\Collection; final class ScopeResolverDispatcher { @@ -45,7 +46,13 @@ final class ScopeResolverDispatcher { foreach ($this->resolvers as $resolver) { if ($resolver->supports($entity, $options)) { - return $resolver->resolveScope($entity, $options); + $scopes = $resolver->resolveScope($entity, $options); + + if ($scopes instanceof Collection) { + return $scopes->toArray(); + } + + return $scopes; } } diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/AddressNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/AddressNormalizer.php index f9a73cd07..f66eb4de6 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/AddressNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/AddressNormalizer.php @@ -11,55 +11,126 @@ declare(strict_types=1); namespace Chill\MainBundle\Serializer\Normalizer; +use Chill\DocGeneratorBundle\Serializer\Helper\NormalizeNullValueHelper; use Chill\MainBundle\Entity\Address; +use DateTimeInterface; +use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; +use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -class AddressNormalizer implements NormalizerAwareInterface, NormalizerInterface +class AddressNormalizer implements ContextAwareNormalizerInterface, NormalizerAwareInterface { use NormalizerAwareTrait; + private const NULL_POSTCODE_COUNTRY = [ + 'id', 'name', 'code', + ]; + + private const NULL_VALUE = [ + 'address_id', + 'text', + 'street', + 'streetNumber', + 'postcode', + 'country', + 'floor', + 'corridor', + 'steps', + 'flat', + 'buildingName', + 'distribution', + 'extra', + 'validFrom' => DateTimeInterface::class, + 'validTo' => DateTimeInterface::class, + ]; + /** * @param Address $address + * @param null|string $format */ - public function normalize($address, ?string $format = null, array $context = []) + public function normalize($address, $format = null, array $context = []) { - return [ - 'address_id' => $address->getId(), - 'text' => $address->isNoAddress() ? '' : $address->getStreetNumber() . ', ' . $address->getStreet(), - 'street' => $address->getStreet(), - 'streetNumber' => $address->getStreetNumber(), - 'postcode' => [ - 'id' => $address->getPostCode()->getId(), - 'name' => $address->getPostCode()->getName(), - 'code' => $address->getPostCode()->getCode(), - ], - 'country' => [ - 'id' => $address->getPostCode()->getCountry()->getId(), - 'name' => $address->getPostCode()->getCountry()->getName(), - 'code' => $address->getPostCode()->getCountry()->getCountryCode(), - ], - 'floor' => $address->getFloor(), - 'corridor' => $address->getCorridor(), - 'steps' => $address->getSteps(), - 'flat' => $address->getFlat(), - 'buildingName' => $address->getBuildingName(), - 'distribution' => $address->getDistribution(), - 'extra' => $address->getExtra(), - 'validFrom' => $address->getValidFrom(), - 'validTo' => $address->getValidTo(), - 'addressReference' => $this->normalizer->normalize( - $address->getAddressReference(), - $format, - [AbstractNormalizer::GROUPS => ['read']] - ), - ]; + if ($address instanceof Address) { + $text = $address->isNoAddress() ? '' : $address->getStreet() . ', ' . $address->getStreetNumber(); + + if (null !== $address->getPostCode()->getCountry()->getCountryCode()) { + if ($address->getPostCode()->getCountry()->getCountryCode() === 'FR') { + $text = $address->isNoAddress() ? '' : $address->getStreetNumber() . ', ' . $address->getStreet(); + } else { + $text = $address->isNoAddress() ? '' : $address->getStreetNumber() . ', ' . $address->getStreet(); + } + } + + $data = [ + 'address_id' => $address->getId(), + 'text' => $text, + 'street' => $address->getStreet(), + 'streetNumber' => $address->getStreetNumber(), + 'postcode' => [ + 'id' => $address->getPostCode()->getId(), + 'name' => $address->getPostCode()->getName(), + 'code' => $address->getPostCode()->getCode(), + ], + 'country' => [ + 'id' => $address->getPostCode()->getCountry()->getId(), + 'name' => $address->getPostCode()->getCountry()->getName(), + 'code' => $address->getPostCode()->getCountry()->getCountryCode(), + ], + 'floor' => $address->getFloor(), + 'corridor' => $address->getCorridor(), + 'steps' => $address->getSteps(), + 'flat' => $address->getFlat(), + 'buildingName' => $address->getBuildingName(), + 'distribution' => $address->getDistribution(), + 'extra' => $address->getExtra(), + ]; + + if ('json' === $format) { + $data['addressReference'] = $this->normalizer->normalize( + $address->getAddressReference(), + $format, + [AbstractNormalizer::GROUPS => ['read']] + ); + $data['validFrom'] = $address->getValidFrom(); + $data['validTo'] = $address->getValidTo(); + } elseif ('docgen' === $format) { + $dateContext = array_merge($context, ['docgen:expects' => DateTimeInterface::class]); + $data['validFrom'] = $this->normalizer->normalize($address->getValidFrom(), $format, $dateContext); + $data['validTo'] = $this->normalizer->normalize($address->getValidTo(), $format, $dateContext); + } + + return $data; + } + + if (null === $address) { + $helper = new NormalizeNullValueHelper($this->normalizer); + + return array_merge( + $helper->normalize(self::NULL_VALUE, $format, $context), + [ + 'postcode' => $helper->normalize(self::NULL_POSTCODE_COUNTRY, $format, $context), + 'country' => $helper->normalize(self::NULL_POSTCODE_COUNTRY, $format, $context), + ] + ); + } + + throw new UnexpectedValueException(); } - public function supportsNormalization($data, ?string $format = null) + public function supportsNormalization($data, $format = null, array $context = []): bool { - return $data instanceof Address; + if ('json' === $format) { + return $data instanceof Address; + } + + if ('docgen' === $format) { + return + $data instanceof Address + || (null === $data && Address::class === ($context['docgen:expects'] ?? null)); + } + + return false; } } diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/CenterNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/CenterNormalizer.php index cbe712ee8..c4d7fa871 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/CenterNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/CenterNormalizer.php @@ -17,6 +17,7 @@ use Symfony\Component\Serializer\Exception\InvalidArgumentException; use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; + use function array_key_exists; class CenterNormalizer implements DenormalizerInterface, NormalizerInterface @@ -28,7 +29,7 @@ class CenterNormalizer implements DenormalizerInterface, NormalizerInterface $this->repository = $repository; } - public function denormalize($data, string $type, ?string $format = null, array $context = []) + public function denormalize($data, $type, $format = null, array $context = []) { if (false === array_key_exists('type', $data)) { throw new InvalidArgumentException('missing "type" key in data'); @@ -51,7 +52,7 @@ class CenterNormalizer implements DenormalizerInterface, NormalizerInterface return $center; } - public function normalize($center, ?string $format = null, array $context = []) + public function normalize($center, $format = null, array $context = []) { /** @var Center $center */ return [ @@ -61,12 +62,12 @@ class CenterNormalizer implements DenormalizerInterface, NormalizerInterface ]; } - public function supportsDenormalization($data, string $type, ?string $format = null) + public function supportsDenormalization($data, $type, $format = null) { return Center::class === $type; } - public function supportsNormalization($data, ?string $format = null): bool + public function supportsNormalization($data, $format = null): bool { return $data instanceof Center && 'json' === $format; } diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/CollectionNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/CollectionNormalizer.php index 0c80e0439..7ca4d563c 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/CollectionNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/CollectionNormalizer.php @@ -22,8 +22,9 @@ class CollectionNormalizer implements NormalizerAwareInterface, NormalizerInterf /** * @param Collection $collection + * @param null|string $format */ - public function normalize($collection, ?string $format = null, array $context = []) + public function normalize($collection, $format = null, array $context = []) { $paginator = $collection->getPaginator(); @@ -40,7 +41,7 @@ class CollectionNormalizer implements NormalizerAwareInterface, NormalizerInterf ]; } - public function supportsNormalization($data, ?string $format = null): bool + public function supportsNormalization($data, $format = null): bool { return $data instanceof Collection; } diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/DateNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/DateNormalizer.php index 3050ad268..70958d5a9 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/DateNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/DateNormalizer.php @@ -17,8 +17,10 @@ use DateTimeInterface; use IntlDateFormatter; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; + use function array_key_exists; use function is_array; @@ -34,20 +36,25 @@ class DateNormalizer implements ContextAwareNormalizerInterface, DenormalizerInt $this->parameterBag = $parameterBag; } - public function denormalize($data, string $type, ?string $format = null, array $context = []) + public function denormalize($data, $type, $format = null, array $context = []) { + if (null === $data) { + return null; + } + switch ($type) { case DateTime::class: return DateTime::createFromFormat(DateTimeInterface::ISO8601, $data['datetime']); case DateTimeInterface::class: case DateTimeImmutable::class: - default: return DateTimeImmutable::createFromFormat(DateTimeInterface::ISO8601, $data['datetime']); } + + throw new UnexpectedValueException(); } - public function normalize($date, ?string $format = null, array $context = []) + public function normalize($date, $format = null, array $context = []) { /** @var DateTimeInterface $date */ switch ($format) { @@ -84,7 +91,7 @@ class DateNormalizer implements ContextAwareNormalizerInterface, DenormalizerInt } } - public function supportsDenormalization($data, string $type, ?string $format = null): bool + public function supportsDenormalization($data, $type, $format = null): bool { return DateTimeInterface::class === $type || DateTime::class === $type @@ -92,7 +99,7 @@ class DateNormalizer implements ContextAwareNormalizerInterface, DenormalizerInt || (is_array($data) && array_key_exists('datetime', $data)); } - public function supportsNormalization($data, ?string $format = null, array $context = []): bool + public function supportsNormalization($data, $format = null, array $context = []): bool { if ('json' === $format) { return $data instanceof DateTimeInterface; diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/DiscriminatedObjectDenormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/DiscriminatedObjectDenormalizer.php index f31b5d60d..77f14c8da 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/DiscriminatedObjectDenormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/DiscriminatedObjectDenormalizer.php @@ -16,6 +16,7 @@ use Symfony\Component\Serializer\Exception\RuntimeException; use Symfony\Component\Serializer\Normalizer\ContextAwareDenormalizerInterface; use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait; + use function count; use function implode; @@ -37,7 +38,7 @@ class DiscriminatedObjectDenormalizer implements ContextAwareDenormalizerInterfa */ public const TYPE = '@multi'; - public function denormalize($data, string $type, ?string $format = null, array $context = []) + public function denormalize($data, $type, $format = null, array $context = []) { foreach ($context[self::ALLOWED_TYPES] as $localType) { if ($this->denormalizer->supportsDenormalization($data, $localType, $format)) { @@ -53,7 +54,7 @@ class DiscriminatedObjectDenormalizer implements ContextAwareDenormalizerInterfa 'ALLOWED_TYPES: %s', implode(', ', $context[self::ALLOWED_TYPES]))); } - public function supportsDenormalization($data, string $type, ?string $format = null, array $context = []) + public function supportsDenormalization($data, $type, $format = null, array $context = []) { if (self::TYPE !== $type) { return false; diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/DoctrineExistingEntityNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/DoctrineExistingEntityNormalizer.php index aa9d12e24..1cf94ac9f 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/DoctrineExistingEntityNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/DoctrineExistingEntityNormalizer.php @@ -16,6 +16,7 @@ use Doctrine\ORM\Mapping\ClassMetadata; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; + use function array_key_exists; use function count; use function is_array; @@ -32,7 +33,7 @@ class DoctrineExistingEntityNormalizer implements DenormalizerInterface $this->serializerMetadataFactory = $serializerMetadataFactory; } - public function denormalize($data, string $type, ?string $format = null, array $context = []) + public function denormalize($data, $type, $format = null, array $context = []) { if (array_key_exists(AbstractNormalizer::OBJECT_TO_POPULATE, $context)) { return $context[AbstractNormalizer::OBJECT_TO_POPULATE]; @@ -42,7 +43,7 @@ class DoctrineExistingEntityNormalizer implements DenormalizerInterface ->find($data['id']); } - public function supportsDenormalization($data, string $type, ?string $format = null) + public function supportsDenormalization($data, $type, $format = null) { if (false === is_array($data)) { return false; diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/PointNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/PointNormalizer.php index c8c532802..479cc6864 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/PointNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/PointNormalizer.php @@ -13,14 +13,14 @@ namespace Chill\MainBundle\Serializer\Normalizer; use Chill\MainBundle\Doctrine\Model\Point; use Symfony\Component\Serializer\Exception\InvalidArgumentException; - use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; + use function count; use function is_array; class PointNormalizer implements DenormalizerInterface { - public function denormalize($data, string $type, ?string $format = null, array $context = []) + public function denormalize($data, $type, $format = null, array $context = []) { if (!is_array($data)) { throw new InvalidArgumentException('point data is not an array. It should be an array of 2 coordinates.'); @@ -33,7 +33,7 @@ class PointNormalizer implements DenormalizerInterface return Point::fromLonLat($data[0], $data[1]); } - public function supportsDenormalization($data, string $type, ?string $format = null): bool + public function supportsDenormalization($data, $type, $format = null): bool { return Point::class === $type; } diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/UserNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/UserNormalizer.php index f046cb34f..082491bd0 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/UserNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/UserNormalizer.php @@ -11,16 +11,28 @@ declare(strict_types=1); namespace Chill\MainBundle\Serializer\Normalizer; +use Chill\MainBundle\Entity\Center; +use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\User; +use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Templating\Entity\UserRender; +use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -class UserNormalizer implements NormalizerAwareInterface, NormalizerInterface +class UserNormalizer implements ContextAwareNormalizerInterface, NormalizerAwareInterface { use NormalizerAwareTrait; + public const NULL_USER = [ + 'type' => 'user', + 'id' => '', + 'username' => '', + 'text' => '', + 'label' => '', + 'email' => '', + ]; + private UserRender $userRender; public function __construct(UserRender $userRender) @@ -28,23 +40,53 @@ class UserNormalizer implements NormalizerAwareInterface, NormalizerInterface $this->userRender = $userRender; } - public function normalize($user, ?string $format = null, array $context = []) + public function normalize($user, $format = null, array $context = []) { /** @var User $user */ + $userJobContext = array_merge( + $context, + ['docgen:expects' => UserJob::class, 'groups' => 'docgen:read'] + ); + $scopeContext = array_merge( + $context, + ['docgen:expects' => Scope::class, 'groups' => 'docgen:read'] + ); + $centerContext = array_merge( + $context, + ['docgen:expects' => Center::class, 'groups' => 'docgen:read'] + ); + + if (null === $user && 'docgen' === $format) { + return array_merge(self::NULL_USER, [ + 'user_job' => $this->normalizer->normalize(null, $format, $userJobContext), + 'main_center' => $this->normalizer->normalize(null, $format, $centerContext), + 'main_scope' => $this->normalizer->normalize(null, $format, $scopeContext), + ]); + } + return [ 'type' => 'user', 'id' => $user->getId(), 'username' => $user->getUsername(), 'text' => $this->userRender->renderString($user, []), 'label' => $user->getLabel(), - 'user_job' => $this->normalizer->normalize($user->getUserJob(), $format, $context), - 'main_center' => $this->normalizer->normalize($user->getMainCenter(), $format, $context), - 'main_scope' => $this->normalizer->normalize($user->getMainScope(), $format, $context), + 'email' => (string) $user->getEmail(), + 'user_job' => $this->normalizer->normalize($user->getUserJob(), $format, $userJobContext), + 'main_center' => $this->normalizer->normalize($user->getMainCenter(), $format, $centerContext), + 'main_scope' => $this->normalizer->normalize($user->getMainScope(), $format, $scopeContext), ]; } - public function supportsNormalization($data, ?string $format = null): bool + public function supportsNormalization($data, $format = null, array $context = []): bool { - return 'json' === $format && $data instanceof User; + if ($data instanceof User && ('json' === $format || 'docgen' === $format)) { + return true; + } + + if (null === $data && 'docgen' === $format && User::class === ($context['docgen:expects'] ?? null)) { + return true; + } + + return false; } } diff --git a/src/Bundle/ChillMainBundle/Templating/ChillMarkdownRenderExtension.php b/src/Bundle/ChillMainBundle/Templating/ChillMarkdownRenderExtension.php index 55212c64f..9bb29c21d 100644 --- a/src/Bundle/ChillMainBundle/Templating/ChillMarkdownRenderExtension.php +++ b/src/Bundle/ChillMainBundle/Templating/ChillMarkdownRenderExtension.php @@ -13,7 +13,6 @@ namespace Chill\MainBundle\Templating; use Parsedown; use Twig\Extension\AbstractExtension; - use Twig\TwigFilter; /** diff --git a/src/Bundle/ChillMainBundle/Templating/ChillTwigHelper.php b/src/Bundle/ChillMainBundle/Templating/ChillTwigHelper.php index 4bc0cffd4..782522760 100644 --- a/src/Bundle/ChillMainBundle/Templating/ChillTwigHelper.php +++ b/src/Bundle/ChillMainBundle/Templating/ChillTwigHelper.php @@ -15,6 +15,7 @@ use DateTimeInterface; use Twig\Environment; use Twig\Extension\AbstractExtension; use Twig\TwigFilter; + use function array_merge; class ChillTwigHelper extends AbstractExtension diff --git a/src/Bundle/ChillMainBundle/Templating/Entity/AddressRender.php b/src/Bundle/ChillMainBundle/Templating/Entity/AddressRender.php index 2a29fb2f3..1af5607c9 100644 --- a/src/Bundle/ChillMainBundle/Templating/Entity/AddressRender.php +++ b/src/Bundle/ChillMainBundle/Templating/Entity/AddressRender.php @@ -13,6 +13,7 @@ namespace Chill\MainBundle\Templating\Entity; use Chill\MainBundle\Entity\Address; use Symfony\Component\Templating\EngineInterface; + use function array_merge; use function strtr; @@ -46,6 +47,7 @@ class AddressRender implements ChillEntityRenderInterface return $this->templating ->render('@ChillMain/Entity/address.html.twig', [ 'address' => $addr, + 'streetLine' => $this->renderStreetLine($addr), 'render' => $options['render'] ?? 'bloc', 'options' => $options, ]); @@ -59,13 +61,7 @@ class AddressRender implements ChillEntityRenderInterface { $lines = []; - if (!empty($addr->getStreet())) { - $lines[0] = $addr->getStreet(); - } - - if (!empty($addr->getStreetNumber())) { - $lines[0] .= ', ' . $addr->getStreetNumber(); - } + $lines[0] = $this->renderStreetLine($addr); if (!empty($addr->getPostcode())) { $lines[1] = strtr('{postcode} {label}', [ @@ -81,4 +77,33 @@ class AddressRender implements ChillEntityRenderInterface { return $entity instanceof Address; } + + private function renderStreetLine($addr): string + { + if (!empty($addr->getStreet())) { + $street = $addr->getStreet(); + } else { + $street = ''; + } + + if (!empty($addr->getStreetNumber())) { + $streetNumber = $addr->getStreetNumber(); + } else { + $streetNumber = ''; + } + + $res = trim($street . ', ' . $streetNumber, ', '); + + if (null !== $addr->getPostCode()->getCountry()->getCountryCode()) { + if ($addr->getPostCode()->getCountry()->getCountryCode() === 'FR') { + $res = trim($streetNumber . ', ' . $street, ', '); + } + } + + if (',' === $res) { + $res = ''; + } + + return $res; + } } diff --git a/src/Bundle/ChillMainBundle/Templating/Entity/CommentRender.php b/src/Bundle/ChillMainBundle/Templating/Entity/CommentRender.php index a6285d26b..aa2401c1e 100644 --- a/src/Bundle/ChillMainBundle/Templating/Entity/CommentRender.php +++ b/src/Bundle/ChillMainBundle/Templating/Entity/CommentRender.php @@ -14,6 +14,7 @@ namespace Chill\MainBundle\Templating\Entity; use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable; use Chill\MainBundle\Repository\UserRepository; use Symfony\Component\Templating\EngineInterface; + use function array_merge; class CommentRender extends AbstractChillEntityRender diff --git a/src/Bundle/ChillMainBundle/Templating/Entity/UserRender.php b/src/Bundle/ChillMainBundle/Templating/Entity/UserRender.php index 9247b8ffb..1fc83c2db 100644 --- a/src/Bundle/ChillMainBundle/Templating/Entity/UserRender.php +++ b/src/Bundle/ChillMainBundle/Templating/Entity/UserRender.php @@ -14,6 +14,7 @@ namespace Chill\MainBundle\Templating\Entity; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Templating\TranslatableStringHelper; use Symfony\Component\Templating\EngineInterface; + use function array_merge; class UserRender implements ChillEntityRenderInterface diff --git a/src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelper.php b/src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelper.php index 82b5f8295..64694285e 100644 --- a/src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelper.php +++ b/src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelper.php @@ -15,6 +15,7 @@ use Chill\MainBundle\Form\Type\Listing\FilterOrderType; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\RequestStack; + use function array_merge; use function count; diff --git a/src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelperBuilder.php b/src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelperBuilder.php index 9e6cb813c..38e2f3542 100644 --- a/src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelperBuilder.php +++ b/src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelperBuilder.php @@ -55,11 +55,13 @@ class FilterOrderHelperBuilder $helper->setSearchBox($this->searchBoxFields); - foreach ($this->checkboxes as $name => [ - 'choices' => $choices, - 'default' => $default, - 'trans' => $trans, - ]) { + foreach ( + $this->checkboxes as $name => [ + 'choices' => $choices, + 'default' => $default, + 'trans' => $trans, + ] + ) { $helper->addCheckbox($name, $choices, $default, $trans); } diff --git a/src/Bundle/ChillMainBundle/Templating/TranslatableStringHelper.php b/src/Bundle/ChillMainBundle/Templating/TranslatableStringHelper.php index 5da53f515..66687711c 100644 --- a/src/Bundle/ChillMainBundle/Templating/TranslatableStringHelper.php +++ b/src/Bundle/ChillMainBundle/Templating/TranslatableStringHelper.php @@ -11,20 +11,25 @@ declare(strict_types=1); namespace Chill\MainBundle\Templating; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Contracts\Translation\TranslatorInterface; + use function array_key_exists; final class TranslatableStringHelper implements TranslatableStringHelperInterface { + private string $defaultLocale; + private RequestStack $requestStack; private TranslatorInterface $translator; - public function __construct(RequestStack $requestStack, TranslatorInterface $translator) + public function __construct(RequestStack $requestStack, TranslatorInterface $translator, ParameterBagInterface $parameterBag) { $this->requestStack = $requestStack; $this->translator = $translator; + $this->defaultLocale = $parameterBag->get('kernel.default_locale'); } public function localize(array $translatableStrings): ?string @@ -35,11 +40,7 @@ final class TranslatableStringHelper implements TranslatableStringHelperInterfac $request = $this->requestStack->getCurrentRequest(); - if (null === $request) { - return null; - } - - $language = $request->getLocale(); + $language = null === $request ? $this->defaultLocale : $request->getLocale(); if (array_key_exists($language, $translatableStrings)) { return $translatableStrings[$language]; diff --git a/src/Bundle/ChillMainBundle/Templating/Widget/WidgetRenderingTwig.php b/src/Bundle/ChillMainBundle/Templating/Widget/WidgetRenderingTwig.php index b8b751b81..dd3b8ee7f 100644 --- a/src/Bundle/ChillMainBundle/Templating/Widget/WidgetRenderingTwig.php +++ b/src/Bundle/ChillMainBundle/Templating/Widget/WidgetRenderingTwig.php @@ -16,6 +16,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Twig\Environment; use Twig\Extension\AbstractExtension; use Twig\TwigFunction; + use function array_key_exists; use function ksort; diff --git a/src/Bundle/ChillMainBundle/Test/Export/AbstractAggregatorTest.php b/src/Bundle/ChillMainBundle/Test/Export/AbstractAggregatorTest.php index f5b26b353..9563ed4bf 100644 --- a/src/Bundle/ChillMainBundle/Test/Export/AbstractAggregatorTest.php +++ b/src/Bundle/ChillMainBundle/Test/Export/AbstractAggregatorTest.php @@ -15,6 +15,7 @@ use Doctrine\ORM\AbstractQuery; use Doctrine\ORM\QueryBuilder; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Traversable; + use function call_user_func; use function count; use function is_array; diff --git a/src/Bundle/ChillMainBundle/Test/Export/AbstractExportTest.php b/src/Bundle/ChillMainBundle/Test/Export/AbstractExportTest.php index 99e9779f1..7a888eb01 100644 --- a/src/Bundle/ChillMainBundle/Test/Export/AbstractExportTest.php +++ b/src/Bundle/ChillMainBundle/Test/Export/AbstractExportTest.php @@ -19,6 +19,7 @@ use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Role\Role; use Traversable; + use function call_user_func; use function count; use function is_array; diff --git a/src/Bundle/ChillMainBundle/Test/Export/AbstractFilterTest.php b/src/Bundle/ChillMainBundle/Test/Export/AbstractFilterTest.php index 78cf0083a..d0f4eaa97 100644 --- a/src/Bundle/ChillMainBundle/Test/Export/AbstractFilterTest.php +++ b/src/Bundle/ChillMainBundle/Test/Export/AbstractFilterTest.php @@ -14,6 +14,7 @@ namespace Chill\MainBundle\Test\Export; use Doctrine\ORM\QueryBuilder; use Exception; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; + use function count; use function get_class; use function is_array; @@ -31,7 +32,7 @@ abstract class AbstractFilterTest extends KernelTestCase */ protected $prophet; - public function setUp() + protected function setUp(): void { $this->prepareProphet(); } diff --git a/src/Bundle/ChillMainBundle/Tests/Authorization/ParentRoleHelperTest.php b/src/Bundle/ChillMainBundle/Tests/Authorization/ParentRoleHelperTest.php index de3b95a31..69a3ac733 100644 --- a/src/Bundle/ChillMainBundle/Tests/Authorization/ParentRoleHelperTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Authorization/ParentRoleHelperTest.php @@ -23,7 +23,7 @@ final class ParentRoleHelperTest extends KernelTestCase { private ParentRoleHelper $parentRoleHelper; - public function setUp() + protected function setUp(): void { self::bootKernel(); $this->parentRoleHelper = self::$container->get(ParentRoleHelper::class); diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/AddressControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/AddressControllerTest.php index b36a655c5..441a323ac 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/AddressControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/AddressControllerTest.php @@ -26,7 +26,7 @@ final class AddressControllerTest extends \Symfony\Bundle\FrameworkBundle\Test\W private KernelBrowser $client; - public function setUp() + protected function setUp(): void { self::bootKernel(); $this->client = $this->getClientAuthenticated(); diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/AddressReferenceApiControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/AddressReferenceApiControllerTest.php new file mode 100644 index 000000000..b62d56b0d --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Controller/AddressReferenceApiControllerTest.php @@ -0,0 +1,67 @@ +get(EntityManagerInterface::class); + + $postalCode = $em->createQueryBuilder() + ->select('pc') + ->from(PostalCode::class, 'pc') + ->where('pc.origin = :origin') + ->setParameter('origin', 0) + ->setMaxResults(1) + ->getQuery() + ->getSingleResult(); + + yield [$postalCode->getId(), 'rue']; + } + + /** + * @dataProvider provideData + */ + public function testSearch(int $postCodeId, string $pattern) + { + $client = $this->getClientAuthenticated(); + + $client->request( + 'GET', + "/api/1.0/main/address-reference/by-postal-code/{$postCodeId}/search.json", + ['q' => $pattern] + ); + + $this->assertResponseIsSuccessful(); + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/PostalCodeApiControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/PostalCodeApiControllerTest.php new file mode 100644 index 000000000..5df1e1290 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Controller/PostalCodeApiControllerTest.php @@ -0,0 +1,57 @@ +getClientAuthenticated(); + + $client->request( + 'GET', + '/api/1.0/main/postal-code/search.json', + ['q' => 'fontenay le comte'] + ); + + $this->assertResponseIsSuccessful(); + + $data = json_decode($client->getResponse()->getContent(), true); + + $this->assertEquals('Fontenay Le Comte', $data['results'][0]['name']); + + // test response with invalid search pattern + $client->request( + 'GET', + '/api/1.0/main/postal-code/search.json', + ['q' => ''] + ); + $this->assertResponseStatusCodeSame(400); + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/UserApiControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/UserApiControllerTest.php index 813e9bc40..d96f9647a 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/UserApiControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/UserApiControllerTest.php @@ -55,6 +55,15 @@ final class UserApiControllerTest extends WebTestCase return $data['results'][0]; } + public function testUserCurrentLocation() + { + $client = $this->getClientAuthenticated(); + + $client->request(Request::METHOD_GET, '/api/1.0/main/user-current-location.json'); + + $this->assertResponseIsSuccessful(); + } + public function testWhoami() { $client = $this->getClientAuthenticated(); diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/UserControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/UserControllerTest.php index 00bec29f6..f5d76ef8f 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/UserControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/UserControllerTest.php @@ -26,7 +26,7 @@ final class UserControllerTest extends WebTestCase private array $toDelete = []; - public function setUp() + protected function setUp(): void { self::bootKernel(); @@ -37,7 +37,7 @@ final class UserControllerTest extends WebTestCase ]); } - protected function tearDown() + protected function tearDown(): void { self::bootKernel(); $em = self::$container->get(EntityManagerInterface::class); diff --git a/src/Bundle/ChillMainBundle/Tests/Export/ExportManagerTest.php b/src/Bundle/ChillMainBundle/Tests/Export/ExportManagerTest.php index 645dff22e..c09385e50 100644 --- a/src/Bundle/ChillMainBundle/Tests/Export/ExportManagerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Export/ExportManagerTest.php @@ -16,13 +16,23 @@ use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\ExportManager; use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Form\Type\Export\ExportType; +use Chill\MainBundle\Security\Authorization\AuthorizationHelper; +use Chill\MainBundle\Test\PrepareCenterTrait; +use Chill\MainBundle\Test\PrepareScopeTrait; +use Chill\MainBundle\Test\PrepareUserTrait; +use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\QueryBuilder; use Prophecy\Argument; +use Prophecy\Prophet; +use Psr\Log\LoggerInterface; use RuntimeException; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; +use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Core\Role\Role; +use Symfony\Component\Security\Core\User\UserInterface; use function count; /** @@ -33,23 +43,20 @@ use function count; */ final class ExportManagerTest extends KernelTestCase { - use \Chill\MainBundle\Test\PrepareCenterTrait; - use \Chill\MainBundle\Test\PrepareScopeTrait; - use \Chill\MainBundle\Test\PrepareUserTrait; + use PrepareCenterTrait; + use PrepareScopeTrait; + use PrepareUserTrait; - /** - * @var Prophecy\Prophet - */ - private $prophet; + private Prophet $prophet; - public function setUp() + protected function setUp(): void { self::bootKernel(); $this->prophet = new \Prophecy\Prophet(); } - public function tearDown() + protected function tearDown(): void { $this->prophet->checkPredictions(); } @@ -379,11 +386,10 @@ final class ExportManagerTest extends KernelTestCase $this->assertInstanceof('Chill\MainBundle\Export\AggregatorInterface', $obtained); } - /** - * @expectedException \RuntimeException - */ public function testGetAggregatorNonExistant() { + $this->expectException(\RuntimeException::class); + $exportManager = $this->createExportManager(); $exportManager->getAggregator('non existing'); @@ -438,11 +444,10 @@ final class ExportManagerTest extends KernelTestCase $this->assertInstanceof(ExportInterface::class, $obtained); } - /** - * @expectedException \RuntimeException - */ public function testGetExportNonExistant() { + $this->expectException(\RuntimeException::class); + $exportManager = $this->createExportManager(); $exportManager->getExport('non existing'); @@ -478,11 +483,10 @@ final class ExportManagerTest extends KernelTestCase $this->assertInstanceof('Chill\MainBundle\Export\FilterInterface', $obtained); } - /** - * @expectedException \RuntimeException - */ public function testGetFilterNonExistant() { + $this->expectException(\RuntimeException::class); + $exportManager = $this->createExportManager(); $exportManager->getFilter('non existing'); @@ -640,11 +644,10 @@ final class ExportManagerTest extends KernelTestCase $this->assertFalse($result); } - /** - * @expectedException \RuntimeException - */ public function testNonExistingFormatter() { + $this->expectException(\RuntimeException::class); + $exportManager = $this->createExportManager(); $exportManager->getFormatter('non existing'); @@ -656,35 +659,28 @@ final class ExportManagerTest extends KernelTestCase * If null is provided for an element, this is replaced by the equivalent * from the container; if the user provided is null, this is replaced by the * user 'center a_social' from database. - * - * @param \Psr\Log\LoggerInterface $logger - * @param \Doctrine\ORM\EntityManagerInterface $em - * @param \Symfony\Component\Security\Core\Authorization\AuthorizationChecker $authorizationChecker - * @param \Chill\MainBundle\Security\Authorization\AuthorizationHelper $authorizationHelper - * @param \Symfony\Component\Security\Core\User\UserInterface $user - * - * @return ExportManager */ protected function createExportManager( - ?\Psr\Log\LoggerInterface $logger = null, - ?\Doctrine\ORM\EntityManagerInterface $em = null, + ?LoggerInterface $logger = null, + ?EntityManagerInterface $em = null, ?AuthorizationCheckerInterface $authorizationChecker = null, - ?\Chill\MainBundle\Security\Authorization\AuthorizationHelper $authorizationHelper = null, - ?\Symfony\Component\Security\Core\User\UserInterface $user = null - ) { - $localUser = null === $user ? self::$container->get('doctrine.orm.entity_manager') - ->getRepository('ChillMainBundle:User') - ->findOneBy(['username' => 'center a_social']) : - $user; - $token = new \Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken($localUser, 'password', 'provider'); - $tokenStorage = new \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage(); + ?AuthorizationHelper $authorizationHelper = null, + ?UserInterface $user = null + ): ExportManager { + $localUser = $user ?? self::$container->get( + 'doctrine.orm.entity_manager' + ) + ->getRepository('ChillMainBundle:User') + ->findOneBy(['username' => 'center a_social']); + $token = new UsernamePasswordToken($localUser, 'password', 'provider'); + $tokenStorage = new TokenStorage(); $tokenStorage->setToken($token); return new ExportManager( - null === $logger ? self::$container->get('logger') : $logger, - null === $em ? self::$container->get('doctrine.orm.entity_manager') : $em, - null === $authorizationChecker ? self::$container->get('security.authorization_checker') : $authorizationChecker, - null === $authorizationHelper ? self::$container->get('chill.main.security.authorization.helper') : $authorizationHelper, + $logger ?? self::$container->get('logger'), + $em ?? self::$container->get('doctrine.orm.entity_manager'), + $authorizationChecker ?? self::$container->get('security.authorization_checker'), + $authorizationHelper ?? self::$container->get('chill.main.security.authorization.helper'), $tokenStorage ); } diff --git a/src/Bundle/ChillMainBundle/Tests/Pagination/PageTest.php b/src/Bundle/ChillMainBundle/Tests/Pagination/PageTest.php index c527a1f6a..ca9eef6c6 100644 --- a/src/Bundle/ChillMainBundle/Tests/Pagination/PageTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Pagination/PageTest.php @@ -27,7 +27,7 @@ final class PageTest extends KernelTestCase protected $prophet; - public function setUp() + protected function setUp(): void { $this->prophet = new \Prophecy\Prophet(); } diff --git a/src/Bundle/ChillMainBundle/Tests/Pagination/PaginatorTest.php b/src/Bundle/ChillMainBundle/Tests/Pagination/PaginatorTest.php index 219669825..23bd4d890 100644 --- a/src/Bundle/ChillMainBundle/Tests/Pagination/PaginatorTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Pagination/PaginatorTest.php @@ -28,7 +28,7 @@ final class PaginatorTest extends KernelTestCase protected $prophet; - public function setUp() + protected function setUp(): void { $this->prophet = new \Prophecy\Prophet(); } @@ -204,6 +204,14 @@ final class PaginatorTest extends KernelTestCase ); } + public function testPagesWithoutResult() + { + $paginator = $this->generatePaginator(0, 10); + + $this->assertEquals(0, $paginator->getCurrentPageFirstItemNumber()); + $this->assertEquals(10, $paginator->getItemsPerPage()); + } + /** * @param int $itemPerPage * @param string $route diff --git a/src/Bundle/ChillMainBundle/Tests/Routing/Loader/RouteLoaderTest.php b/src/Bundle/ChillMainBundle/Tests/Routing/Loader/RouteLoaderTest.php index ff8ee423e..9f0291007 100644 --- a/src/Bundle/ChillMainBundle/Tests/Routing/Loader/RouteLoaderTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Routing/Loader/RouteLoaderTest.php @@ -23,7 +23,7 @@ final class RouteLoaderTest extends KernelTestCase { private $router; - public function setUp() + protected function setUp(): void { self::bootKernel(); $this->router = self::$kernel->getContainer()->get('router'); diff --git a/src/Bundle/ChillMainBundle/Tests/Search/AbstractSearchTest.php b/src/Bundle/ChillMainBundle/Tests/Search/AbstractSearchTest.php index c0c3b176a..e04b33e59 100644 --- a/src/Bundle/ChillMainBundle/Tests/Search/AbstractSearchTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Search/AbstractSearchTest.php @@ -24,7 +24,7 @@ final class AbstractSearchTest extends \PHPUnit\Framework\TestCase */ private $stub; - public function setUp() + protected function setUp(): void { $this->stub = $this->getMockForAbstractClass('Chill\MainBundle\Search\AbstractSearch'); } diff --git a/src/Bundle/ChillMainBundle/Tests/Search/SearchProviderTest.php b/src/Bundle/ChillMainBundle/Tests/Search/SearchProviderTest.php index 3bbc2b94b..07d7c7ab7 100644 --- a/src/Bundle/ChillMainBundle/Tests/Search/SearchProviderTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Search/SearchProviderTest.php @@ -11,8 +11,11 @@ declare(strict_types=1); namespace Chill\MainBundle\Test\Search; +use Chill\MainBundle\Search\ParsingException; use Chill\MainBundle\Search\SearchInterface; use Chill\MainBundle\Search\SearchProvider; +use Chill\MainBundle\Search\UnknowSearchDomainException; +use Chill\MainBundle\Search\UnknowSearchNameException; use PHPUnit\Framework\TestCase; /** @@ -26,7 +29,7 @@ final class SearchProviderTest extends TestCase */ private $search; - public function setUp() + protected function setUp(): void { $this->search = new SearchProvider(); @@ -100,20 +103,18 @@ final class SearchProviderTest extends TestCase ], $terms); } - /** - * @expectedException \Chill\MainBundle\Search\UnknowSearchNameException - */ public function testInvalidSearchName() { + $this->expectException(UnknowSearchNameException::class); + $this->search->getByName('invalid name'); } - /** - * @expectedException \Chill\MainBundle\Search\ParsingException - */ public function testMultipleDomainError() { - $term = $this->p('@person @report'); + $this->expectException(ParsingException::class); + + $this->p('@person @report'); } /** @@ -146,14 +147,11 @@ final class SearchProviderTest extends TestCase ], $response); } - /** - * @expectedException \Chill\MainBundle\Search\UnknowSearchDomainException - */ public function testSearchResultDomainUnknow() { - $response = $this->search->getSearchResults('@unknow domain'); + $this->expectException(UnknowSearchDomainException::class); - //$this->markTestSkipped(); + $this->search->getSearchResults('@unknow domain'); } public function testSearchWithinSpecificSearchName() @@ -169,12 +167,11 @@ final class SearchProviderTest extends TestCase $this->assertEquals('I am domain foo', $response); } - /** - * @expectedException \Chill\MainBundle\Search\ParsingException - */ public function testSearchWithinSpecificSearchNameInConflictWithSupport() { - $response = $this->search->getResultByName('@foo default search', 'bar'); + $this->expectException(ParsingException::class); + + $this->search->getResultByName('@foo default search', 'bar'); } public function testSimplePattern() diff --git a/src/Bundle/ChillMainBundle/Tests/Security/Authorization/AuthorizationHelperTest.php b/src/Bundle/ChillMainBundle/Tests/Security/Authorization/AuthorizationHelperTest.php index 0046b5a74..f4984167f 100644 --- a/src/Bundle/ChillMainBundle/Tests/Security/Authorization/AuthorizationHelperTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Security/Authorization/AuthorizationHelperTest.php @@ -38,7 +38,7 @@ final class AuthorizationHelperTest extends KernelTestCase use PrepareUserTrait; use ProphecyTrait; - public function setUp() + protected function setUp(): void { self::bootKernel(); } @@ -247,7 +247,7 @@ final class AuthorizationHelperTest extends KernelTestCase $expectedResult, Scope $testedScope, User $user, - Role $role, + string $role, Center $center, $message ) { diff --git a/src/Bundle/ChillMainBundle/Tests/Security/PasswordRecover/TokenManagerTest.php b/src/Bundle/ChillMainBundle/Tests/Security/PasswordRecover/TokenManagerTest.php index 7083cfdc4..294ddceb6 100644 --- a/src/Bundle/ChillMainBundle/Tests/Security/PasswordRecover/TokenManagerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Security/PasswordRecover/TokenManagerTest.php @@ -25,7 +25,7 @@ final class TokenManagerTest extends KernelTestCase { protected $tokenManager; - public function setUp() + protected function setUp(): void { self::bootKernel(); @@ -55,11 +55,10 @@ final class TokenManagerTest extends KernelTestCase $this->assertEquals($user->getUsernameCanonical(), $tokens['u']); } - /** - * @expectedException \UnexpectedValueException - */ public function testGenerateEmptyUsernameCanonical() { + $this->expectException(\UnexpectedValueException::class); + $tokenManager = $this->tokenManager; // set a username, but not a username canonical $user = (new User())->setUsername('test'); @@ -88,7 +87,7 @@ final class TokenManagerTest extends KernelTestCase $this->assertFalse($tokenManager->verify($hash . '5', $token, $user, $timestamp)); $this->assertFalse($tokenManager->verify($hash, $token . '25', $user, $timestamp)); $this->assertFalse($tokenManager->verify($hash, $token, $user->setUsernameCanonical('test2'), $timestamp)); - $this->assertFalse($tokenManager->verify($hash, $token, $user, $timestamp + 1)); + $this->assertFalse($tokenManager->verify($hash, $token, $user, (string) ($timestamp + 1))); } public function testVerifyExpiredFails() diff --git a/src/Bundle/ChillMainBundle/Tests/Security/Resolver/CenterResolverDispatcherTest.php b/src/Bundle/ChillMainBundle/Tests/Security/Resolver/CenterResolverDispatcherTest.php index 80b01a170..ee7431554 100644 --- a/src/Bundle/ChillMainBundle/Tests/Security/Resolver/CenterResolverDispatcherTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Security/Resolver/CenterResolverDispatcherTest.php @@ -24,7 +24,7 @@ final class CenterResolverDispatcherTest extends KernelTestCase { private CenterResolverDispatcherInterface $dispatcher; - protected function setUp() + protected function setUp(): void { self::bootKernel(); $this->dispatcher = self::$container->get(CenterResolverDispatcher::class); diff --git a/src/Bundle/ChillMainBundle/Tests/Security/Resolver/DefaultScopeResolverTest.php b/src/Bundle/ChillMainBundle/Tests/Security/Resolver/DefaultScopeResolverTest.php index 32c07b04e..bc0e6d8cb 100644 --- a/src/Bundle/ChillMainBundle/Tests/Security/Resolver/DefaultScopeResolverTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Security/Resolver/DefaultScopeResolverTest.php @@ -25,7 +25,7 @@ final class DefaultScopeResolverTest extends TestCase { private DefaultScopeResolver $scopeResolver; - public function setUp() + protected function setUp(): void { $this->scopeResolver = new DefaultScopeResolver(); } diff --git a/src/Bundle/ChillMainBundle/Tests/Security/Resolver/ScopeResolverDispatcherTest.php b/src/Bundle/ChillMainBundle/Tests/Security/Resolver/ScopeResolverDispatcherTest.php index 320d2e326..5d15e7d91 100644 --- a/src/Bundle/ChillMainBundle/Tests/Security/Resolver/ScopeResolverDispatcherTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Security/Resolver/ScopeResolverDispatcherTest.php @@ -26,7 +26,7 @@ final class ScopeResolverDispatcherTest extends TestCase { private ScopeResolverDispatcher $scopeResolverDispatcher; - public function setUp() + protected function setUp(): void { $this->scopeResolverDispatcher = new ScopeResolverDispatcher([new DefaultScopeResolver()]); } diff --git a/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DateNormalizerTest.php b/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DateNormalizerTest.php index fc9612299..c925954bf 100644 --- a/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DateNormalizerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DateNormalizerTest.php @@ -30,7 +30,7 @@ final class DateNormalizerTest extends KernelTestCase { private Prophet $prophet; - public function setUp() + protected function setUp(): void { $this->prophet = new Prophet(); } diff --git a/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DoctrineExistingEntityNormalizerTest.php b/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DoctrineExistingEntityNormalizerTest.php index b45b2c21d..5f5431d7c 100644 --- a/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DoctrineExistingEntityNormalizerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DoctrineExistingEntityNormalizerTest.php @@ -25,7 +25,7 @@ final class DoctrineExistingEntityNormalizerTest extends KernelTestCase { protected DoctrineExistingEntityNormalizer $normalizer; - protected function setUp() + protected function setUp(): void { self::bootKernel(); $em = self::$container->get(EntityManagerInterface::class); diff --git a/src/Bundle/ChillMainBundle/Tests/Services/MenuComposerTest.php b/src/Bundle/ChillMainBundle/Tests/Services/MenuComposerTest.php index bb98b074d..b7df8018e 100644 --- a/src/Bundle/ChillMainBundle/Tests/Services/MenuComposerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Services/MenuComposerTest.php @@ -32,7 +32,7 @@ final class MenuComposerTest extends KernelTestCase */ private $menuComposer; - public function setUp() + protected function setUp(): void { self::bootKernel(['environment' => 'test']); $this->menuComposer = self::$container diff --git a/src/Bundle/ChillMainBundle/Tests/Templating/Entity/AddressRenderTest.php b/src/Bundle/ChillMainBundle/Tests/Templating/Entity/AddressRenderTest.php index c866224e3..e577028ca 100644 --- a/src/Bundle/ChillMainBundle/Tests/Templating/Entity/AddressRenderTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Templating/Entity/AddressRenderTest.php @@ -25,7 +25,7 @@ use Symfony\Component\Templating\EngineInterface; */ final class AddressRenderTest extends KernelTestCase { - protected function setUp() + protected function setUp(): void { self::bootKernel(); } diff --git a/src/Bundle/ChillMainBundle/Timeline/TimelineBuilder.php b/src/Bundle/ChillMainBundle/Timeline/TimelineBuilder.php index c36751960..a6cd9d6df 100644 --- a/src/Bundle/ChillMainBundle/Timeline/TimelineBuilder.php +++ b/src/Bundle/ChillMainBundle/Timeline/TimelineBuilder.php @@ -18,6 +18,7 @@ use Doctrine\ORM\Query; use Doctrine\ORM\Query\ResultSetMapping; use LogicException; use Symfony\Component\DependencyInjection\ContainerAwareInterface; + use function array_key_exists; use function is_string; @@ -291,7 +292,7 @@ class TimelineBuilder implements ContainerAwareInterface $data = $this->getTemplateData( $result['type'], $entitiesByType[$result['type']][$result['id']], //the entity - $context, + $context, $args ); diff --git a/src/Bundle/ChillMainBundle/Util/CountriesInfo.php b/src/Bundle/ChillMainBundle/Util/CountriesInfo.php index 05089a04f..e5b392856 100644 --- a/src/Bundle/ChillMainBundle/Util/CountriesInfo.php +++ b/src/Bundle/ChillMainBundle/Util/CountriesInfo.php @@ -12,6 +12,7 @@ declare(strict_types=1); namespace Chill\MainBundle\Util; use UnexpectedValueException; + use function array_key_exists; /** diff --git a/src/Bundle/ChillMainBundle/Util/DateRangeCovering.php b/src/Bundle/ChillMainBundle/Util/DateRangeCovering.php index 07f8b14ff..253f72aef 100644 --- a/src/Bundle/ChillMainBundle/Util/DateRangeCovering.php +++ b/src/Bundle/ChillMainBundle/Util/DateRangeCovering.php @@ -15,6 +15,7 @@ use DateTimeImmutable; use DateTimeInterface; use DateTimeZone; use LogicException; + use function array_diff; use function array_flip; use function array_intersect_key; @@ -24,6 +25,7 @@ use function array_unique; use function array_values; use function count; use function ksort; + use const PHP_INT_MAX; /** diff --git a/src/Bundle/ChillMainBundle/Validator/Constraints/Entity/UserCircleConsistencyValidator.php b/src/Bundle/ChillMainBundle/Validator/Constraints/Entity/UserCircleConsistencyValidator.php index 5cc283d95..398c7b551 100644 --- a/src/Bundle/ChillMainBundle/Validator/Constraints/Entity/UserCircleConsistencyValidator.php +++ b/src/Bundle/ChillMainBundle/Validator/Constraints/Entity/UserCircleConsistencyValidator.php @@ -14,6 +14,7 @@ namespace Chill\MainBundle\Validator\Constraints\Entity; use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; + use function call_user_func; class UserCircleConsistencyValidator extends ConstraintValidator diff --git a/src/Bundle/ChillMainBundle/chill.api.specs.yaml b/src/Bundle/ChillMainBundle/chill.api.specs.yaml index ff0c844df..db4430e48 100644 --- a/src/Bundle/ChillMainBundle/chill.api.specs.yaml +++ b/src/Bundle/ChillMainBundle/chill.api.specs.yaml @@ -360,6 +360,40 @@ paths: 401: description: "Unauthorized" + /1.0/main/address-reference/by-postal-code/{id}/search.json: + get: + tags: + - address + - search + summary: Return a reference address by id + parameters: + - name: id + in: path + required: true + description: The reference address id + schema: + type: integer + format: integer + minimum: 1 + - name: q + in: query + required: true + description: The search pattern + schema: + type: string + responses: + 200: + description: "ok" + content: + application/json: + schema: + $ref: '#/components/schemas/AddressReference' + 404: + description: "not found" + 401: + description: "Unauthorized" + 400: + description: "Bad request" /1.0/main/postal-code.json: get: tags: @@ -430,6 +464,37 @@ paths: 401: description: "Unauthorized" + /1.0/main/postal-code/search.json: + get: + tags: + - address + - search + summary: Search a postal code + parameters: + - name: q + in: query + required: true + description: The search pattern + schema: + type: string + - name: country + in: query + required: false + description: The country id + schema: + type: integer + responses: + 200: + description: "ok" + content: + application/json: + schema: + $ref: '#/components/schemas/PostalCode' + 404: + description: "not found" + 400: + description: "Bad Request" + /1.0/main/country.json: get: tags: @@ -481,6 +546,14 @@ paths: responses: 200: description: "ok" + /1.0/main/user-current-location.json: + get: + tags: + - user + summary: Return the current location of the currently authenticated user + responses: + 200: + description: "ok" /1.0/main/user/{id}.json: get: tags: diff --git a/src/Bundle/ChillMainBundle/migrations/Version20150821105642.php b/src/Bundle/ChillMainBundle/migrations/Version20150821105642.php index 910a6b028..ac80f2a58 100644 --- a/src/Bundle/ChillMainBundle/migrations/Version20150821105642.php +++ b/src/Bundle/ChillMainBundle/migrations/Version20150821105642.php @@ -16,6 +16,7 @@ use Doctrine\Migrations\AbstractMigration; use Doctrine\ORM\Query\ResultSetMapping; use RuntimeException; use Symfony\Component\DependencyInjection\ContainerInterface; + use function count; /** diff --git a/src/Bundle/ChillMainBundle/migrations/Version20211125142016.php b/src/Bundle/ChillMainBundle/migrations/Version20211125142016.php new file mode 100644 index 000000000..08f3815de --- /dev/null +++ b/src/Bundle/ChillMainBundle/migrations/Version20211125142016.php @@ -0,0 +1,85 @@ +addSql('DROP TRIGGER canonicalize_address_reference_on_insert ON chill_main_address_reference'); + $this->addSql('DROP TRIGGER canonicalize_address_reference_on_update ON chill_main_address_reference'); + $this->addSql('DROP FUNCTION canonicalize_address_reference()'); + $this->addSql('ALTER TABLE chill_main_address_reference DROP COLUMN addressCanonical'); + } + + public function getDescription(): string + { + return 'Add a column "canonicalized" on chill_main_address_reference and add trigger and indexed on it'; + } + + public function up(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_main_address_reference ADD addressCanonical TEXT DEFAULT \'\' NOT NULL'); + + $this->addSql('UPDATE chill_main_address_reference + SET addresscanonical = + TRIM( + UNACCENT( + LOWER( + street || + \' \' || + streetnumber + ) + ) + + )'); + + $this->addSql('CREATE OR REPLACE FUNCTION public.canonicalize_address_reference() RETURNS TRIGGER + LANGUAGE plpgsql + AS + $$ + BEGIN + NEW.addresscanonical = + TRIM( + UNACCENT( + LOWER( + NEW.street || + \' \' || + NEW.streetnumber + ) + ) + + ) + ; + + return NEW; + END + $$'); + + $this->addSql('CREATE TRIGGER canonicalize_address_reference_on_insert + BEFORE INSERT + ON chill_main_address_reference + FOR EACH ROW + EXECUTE procedure canonicalize_address_reference()'); + + $this->addSql('CREATE TRIGGER canonicalize_address_reference_on_update + BEFORE UPDATE + ON chill_main_address_reference + FOR EACH ROW + EXECUTE procedure canonicalize_address_reference()'); + + $this->addSql('CREATE INDEX chill_internal_address_reference_canonicalized ON chill_main_address_reference USING GIST (postcode_id, addressCanonical gist_trgm_ops)'); + } +} diff --git a/src/Bundle/ChillMainBundle/migrations/Version20211125142017.php b/src/Bundle/ChillMainBundle/migrations/Version20211125142017.php new file mode 100644 index 000000000..7f938b241 --- /dev/null +++ b/src/Bundle/ChillMainBundle/migrations/Version20211125142017.php @@ -0,0 +1,85 @@ +addSql('DROP TRIGGER canonicalize_postal_code_on_insert ON chill_main_postal_code'); + $this->addSql('DROP TRIGGER canonicalize_postal_code_on_update ON chill_main_postal_code'); + $this->addSql('DROP FUNCTION canonicalize_postal_code()'); + $this->addSql('ALTER TABLE chill_main_postal_code DROP COLUMN canonical'); + } + + public function getDescription(): string + { + return 'Add a column "canonicalized" on postal code'; + } + + public function up(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_main_postal_code ADD canonical TEXT DEFAULT \'\' NOT NULL'); + + $this->addSql('UPDATE chill_main_postal_code + SET canonical = + TRIM( + UNACCENT( + LOWER( + code || + \' \' || + label + ) + ) + + )'); + + $this->addSql('CREATE OR REPLACE FUNCTION public.canonicalize_postal_code() RETURNS TRIGGER + LANGUAGE plpgsql + AS + $$ + BEGIN + NEW.canonical = + TRIM( + UNACCENT( + LOWER( + NEW.code || + \' \' || + NEW.label + ) + ) + + ) + ; + + return NEW; + END + $$'); + + $this->addSql('CREATE TRIGGER canonicalize_postal_code_on_insert + BEFORE INSERT + ON chill_main_postal_code + FOR EACH ROW + EXECUTE procedure canonicalize_postal_code()'); + + $this->addSql('CREATE TRIGGER canonicalize_postal_code_on_update + BEFORE UPDATE + ON chill_main_postal_code + FOR EACH ROW + EXECUTE procedure canonicalize_postal_code()'); + + $this->addSql('CREATE INDEX chill_internal_postal_code_canonicalized ON chill_main_postal_code USING GIST (canonical gist_trgm_ops) WHERE origin = 0'); + } +} diff --git a/src/Bundle/ChillMainBundle/migrations/Version20211213112628.php b/src/Bundle/ChillMainBundle/migrations/Version20211213112628.php new file mode 100644 index 000000000..012ab27d9 --- /dev/null +++ b/src/Bundle/ChillMainBundle/migrations/Version20211213112628.php @@ -0,0 +1,36 @@ +addSql('ALTER TABLE chill_main_civility DROP "ordering"'); + } + + public function getDescription(): string + { + return 'Add order to civility'; + } + + public function up(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_main_civility ADD "ordering" FLOAT DEFAULT 0.0'); + } +} diff --git a/src/Bundle/ChillMainBundle/migrations/Version20211216213649.php b/src/Bundle/ChillMainBundle/migrations/Version20211216213649.php new file mode 100644 index 000000000..4e5e4d9d9 --- /dev/null +++ b/src/Bundle/ChillMainBundle/migrations/Version20211216213649.php @@ -0,0 +1,33 @@ +addSql('DROP INDEX address_refid'); + } + + public function getDescription(): string + { + return 'add an index on address reference refid'; + } + + public function up(Schema $schema): void + { + $this->addSql('CREATE INDEX address_refid ON chill_main_address_reference (refId) WHERE refid != \'\''); + } +} diff --git a/src/Bundle/ChillMainBundle/translations/messages.fr.yml b/src/Bundle/ChillMainBundle/translations/messages.fr.yml index 78363d080..4ae23f1e3 100644 --- a/src/Bundle/ChillMainBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillMainBundle/translations/messages.fr.yml @@ -56,6 +56,7 @@ centers: centres Centers: Centres comment: commentaire Comment: Commentaire +Pinned comment: Commentaire épinglé Any comment: Aucun commentaire # comment embeddable diff --git a/src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php b/src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php index 930b96e07..63c6313ac 100644 --- a/src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php +++ b/src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php @@ -17,6 +17,7 @@ use Chill\PersonBundle\Entity\Person; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\ClassMetadata; use Symfony\Component\EventDispatcher\EventDispatcherInterface; + use function array_merge; use function implode; use function in_array; diff --git a/src/Bundle/ChillPersonBundle/CRUD/Controller/EntityPersonCRUDController.php b/src/Bundle/ChillPersonBundle/CRUD/Controller/EntityPersonCRUDController.php index d3de0bd3d..5143592b8 100644 --- a/src/Bundle/ChillPersonBundle/CRUD/Controller/EntityPersonCRUDController.php +++ b/src/Bundle/ChillPersonBundle/CRUD/Controller/EntityPersonCRUDController.php @@ -16,6 +16,7 @@ use Chill\PersonBundle\Entity\Person; use Doctrine\ORM\QueryBuilder; use Exception; use Symfony\Component\HttpFoundation\Request; + use function array_merge; /** diff --git a/src/Bundle/ChillPersonBundle/Command/ChillPersonMoveCommand.php b/src/Bundle/ChillPersonBundle/Command/ChillPersonMoveCommand.php index 3af14fb0b..4a2e86236 100644 --- a/src/Bundle/ChillPersonBundle/Command/ChillPersonMoveCommand.php +++ b/src/Bundle/ChillPersonBundle/Command/ChillPersonMoveCommand.php @@ -20,6 +20,7 @@ use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; + use function ctype_digit; final class ChillPersonMoveCommand extends Command diff --git a/src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php b/src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php index d3500acd6..fd328efc4 100644 --- a/src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php +++ b/src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php @@ -39,6 +39,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Form\FormFactory; use Symfony\Component\Form\FormFactoryInterface; + use function array_key_exists; use function count; use function file_get_contents; @@ -46,6 +47,7 @@ use function get_class; use function in_array; use function is_array; use function json_decode; + use const JSON_PRETTY_PRINT; use const LC_TIME; @@ -417,13 +419,15 @@ final class ImportPeopleFromCSVCommand extends Command $line = $this->line = 1; try { - while (false !== ($row = fgetcsv( - $csv, - $input->getOption('length'), - $input->getOption('delimiter'), - $input->getOption('enclosure'), - $input->getOption('escape') - ))) { + while ( + false !== ($row = fgetcsv( + $csv, + $input->getOption('length'), + $input->getOption('delimiter'), + $input->getOption('enclosure'), + $input->getOption('escape') + )) + ) { $this->logger->debug('Processing line ' . $this->line); if (1 === $line) { @@ -450,8 +454,10 @@ final class ImportPeopleFromCSVCommand extends Command $this->eventDispatcher->dispatch('chill_person.person_import', $event); - if ($this->input->getOption('force') === true - && false === $event->skipPerson) { + if ( + $this->input->getOption('force') === true + && false === $event->skipPerson + ) { $this->em->persist($person); } @@ -602,8 +608,10 @@ final class ImportPeopleFromCSVCommand extends Command ->getResult(); if (count($postalCodes) >= 1) { - if ($postalCodes[0]->getCode() === $postalCode - && $postalCodes[0]->getName() === $locality) { + if ( + $postalCodes[0]->getCode() === $postalCode + && $postalCodes[0]->getName() === $locality + ) { return $postalCodes[0]; } } @@ -625,7 +633,7 @@ final class ImportPeopleFromCSVCommand extends Command $question = new ChoiceQuestion( sprintf( 'Which postal code match the ' - . 'name "%s" with postal code "%s" ? (default to "%s")', + . 'name "%s" with postal code "%s" ? (default to "%s")', $locality, $postalCode, $names[0] @@ -658,13 +666,15 @@ final class ImportPeopleFromCSVCommand extends Command $csv = $this->openCSV(); // getting the first row - if (false !== ($row = fgetcsv( - $csv, - $input->getOption('length'), - $input->getOption('delimiter'), - $input->getOption('enclosure'), - $input->getOption('escape') - ))) { + if ( + false !== ($row = fgetcsv( + $csv, + $input->getOption('length'), + $input->getOption('delimiter'), + $input->getOption('enclosure'), + $input->getOption('escape') + )) + ) { try { $this->matchColumnToCustomField($row); } finally { @@ -863,7 +873,9 @@ final class ImportPeopleFromCSVCommand extends Command if (!isset($this->cacheAnswersMapping[$cf->getSlug()][$value])) { // try to find the answer (with array_keys and a search value $values = array_keys( - array_map(static function ($label) { return trim(strtolower($label)); }, $answers), + array_map(static function ($label) { + return trim(strtolower($label)); + }, $answers), trim(strtolower($value)), true ); diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php index 43276c949..3b051a59d 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php @@ -34,8 +34,11 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Serializer\Exception\RuntimeException; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; +use Symfony\Component\Validator\ConstraintViolationList; +use Symfony\Component\Validator\ConstraintViolationListInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Workflow\Registry; + use function array_values; use function count; @@ -294,4 +297,17 @@ final class AccompanyingCourseApiController extends ApiController return null; } + + protected function validate(string $action, Request $request, string $_format, $entity, array $more = []): ConstraintViolationListInterface + { + if ('work' !== $action) { + return parent::validate($action, $request, $_format, $entity, $more); + } + + if (Request::METHOD_POST === $request->getMethod()) { + return $this->getValidator()->validate($more[0], null); + } + + return new ConstraintViolationList([]); + } } diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseCommentController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseCommentController.php new file mode 100644 index 000000000..65e83cdbc --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseCommentController.php @@ -0,0 +1,103 @@ +setAccompanyingPeriod($accompanyingCourse); + + $form = $this->createCommentForm($newComment, 'new'); + $editForm = null; + + if ($request->query->has('edit')) { + foreach ($accompanyingCourse->getComments() as $comment) { + if ($comment->getId() === $request->query->getInt('edit')) { + $editForm = $this->createCommentForm($comment, 'edit'); + $commentEditId = $comment->getId(); + } + } + $pinnedComment = $accompanyingCourse->getPinnedComment(); + + if ($pinnedComment->getId() === $request->query->getInt('edit')) { + $editForm = $this->createCommentForm($pinnedComment, 'edit'); + $commentEditId = $pinnedComment->getId(); + } + } + + if (null === $editForm) { + throw new NotFoundHttpException('Unable to find an edit form.'); + } + + if ($request->getMethod() === Request::METHOD_POST) { + $currentForm = $editForm->handleRequest($request); + + if (array_key_exists('edit', $request->request->all()[$editForm->getName()])) { + $isEditingNew = false; + } else { + $isEditingNew = true; + } + + if ($currentForm->isSubmitted() && $currentForm->isValid()) { + $em = $this->getDoctrine()->getManager(); + + if ($isEditingNew) { + $em->persist($newComment); + } + $em->flush(); + } + + return $this->redirectToRoute('chill_person_accompanying_period_comment_list', [ + 'accompanying_period_id' => $accompanyingCourse->getId(), + ]); + } + + return $this->render('@ChillPerson/AccompanyingCourse/comment_list.html.twig', [ + 'accompanyingCourse' => $accompanyingCourse, + 'form' => $form->createView(), + 'edit_form' => null !== $editForm ? $editForm->createView() : null, + 'commentEditId' => $commentEditId ?? null, + ]); + } + + private function createCommentForm(AccompanyingPeriod\Comment $comment, string $step): FormInterface + { + $form = $this->createForm(AccompanyingCourseCommentType::class, $comment); + + if ('edit' === $step) { + $form->add('edit', HiddenType::class, ['mapped' => false]); + } + + return $form; + } +} diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php index 7d0e841cf..5088b2381 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php @@ -30,6 +30,7 @@ use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Workflow\Registry; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Symfony\Contracts\Translation\TranslatorInterface; + use function is_array; /** diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php index 1da7424bf..7e7b9a0c2 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php @@ -67,7 +67,7 @@ class AccompanyingCourseWorkController extends AbstractController 'error', $this->trans->trans( 'accompanying_work.You must add at least ' . - 'one social issue on accompanying period' + 'one social issue on accompanying period' ) ); diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php index bfc85a5b3..bb0081c27 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php @@ -27,6 +27,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Validator\ConstraintViolationListInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; + use function array_filter; use function count; @@ -170,8 +171,10 @@ class AccompanyingPeriodController extends AbstractController $errors = $this->_validatePerson($person); $flashBag = $this->get('session')->getFlashBag(); - if ($form->isValid(['Default', 'closed']) - && count($errors) === 0) { + if ( + $form->isValid(['Default', 'closed']) + && count($errors) === 0 + ) { $em = $this->getDoctrine()->getManager(); $em->persist($accompanyingPeriod); $em->flush(); @@ -405,8 +408,10 @@ class AccompanyingPeriodController extends AbstractController $errors = $this->_validatePerson($person); $flashBag = $this->get('session')->getFlashBag(); - if ($form->isValid(['Default', 'closed']) - && count($errors) === 0) { + if ( + $form->isValid(['Default', 'closed']) + && count($errors) === 0 + ) { $em->flush(); $flashBag->add( diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodWorkEvaluationApiController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodWorkEvaluationApiController.php new file mode 100644 index 000000000..de9433558 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodWorkEvaluationApiController.php @@ -0,0 +1,79 @@ +docGeneratorTemplateRepository = $docGeneratorTemplateRepository; + $this->serializer = $serializer; + $this->paginatorFactory = $paginatorFactory; + } + + /** + * @Route("/api/1.0/person/docgen/template/by-evaluation/{id}.{_format}", + * requirements={"format": "json"}) + */ + public function listTemplateByEvaluation(Evaluation $evaluation, string $_format): JsonResponse + { + if ('json' !== $_format) { + throw new BadRequestHttpException('format not supported'); + } + + $evaluations = + array_filter( + $this->docGeneratorTemplateRepository + ->findByEntity(AccompanyingPeriodWorkEvaluation::class), + static function (DocGeneratorTemplate $t) use ($evaluation) { + $ids = $t->getOptions()['evaluations'] ?? []; + + return in_array($evaluation->getId(), $ids, true); + } + ); + + $paginator = $this->paginatorFactory->create(count($evaluations)); + $paginator->setItemsPerPage(count($evaluations)); + + return new JsonResponse($this->serializer->serialize( + new Collection($evaluations, $paginator), + 'json', + [ + AbstractNormalizer::GROUPS => ['read'], + ] + ), JsonResponse::HTTP_OK, [], true); + } +} diff --git a/src/Bundle/ChillPersonBundle/Controller/HouseholdApiController.php b/src/Bundle/ChillPersonBundle/Controller/HouseholdApiController.php index 62f4fc68f..da8655f3d 100644 --- a/src/Bundle/ChillPersonBundle/Controller/HouseholdApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/HouseholdApiController.php @@ -24,6 +24,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; + use function array_filter; use function array_values; @@ -93,8 +94,10 @@ class HouseholdApiController extends ApiController $addresses[$a->getId()] = $a; } - if (null !== $personLocation = $participation - ->getAccompanyingPeriod()->getPersonLocation()) { + if ( + null !== $personLocation = $participation + ->getAccompanyingPeriod()->getPersonLocation() + ) { $a = $personLocation->getCurrentHouseholdAddress(); if (null !== $a) { diff --git a/src/Bundle/ChillPersonBundle/Controller/HouseholdController.php b/src/Bundle/ChillPersonBundle/Controller/HouseholdController.php index 6ce73d508..ba4b788d7 100644 --- a/src/Bundle/ChillPersonBundle/Controller/HouseholdController.php +++ b/src/Bundle/ChillPersonBundle/Controller/HouseholdController.php @@ -25,6 +25,7 @@ use Symfony\Component\Security\Core\Security; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Translation\TranslatorInterface; + use function array_key_exists; use function count; diff --git a/src/Bundle/ChillPersonBundle/Controller/HouseholdMemberController.php b/src/Bundle/ChillPersonBundle/Controller/HouseholdMemberController.php index 802f9fd6c..78234d114 100644 --- a/src/Bundle/ChillPersonBundle/Controller/HouseholdMemberController.php +++ b/src/Bundle/ChillPersonBundle/Controller/HouseholdMemberController.php @@ -27,6 +27,7 @@ use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Serializer\Exception; use Symfony\Component\Translation\TranslatorInterface; + use function count; class HouseholdMemberController extends ApiController diff --git a/src/Bundle/ChillPersonBundle/Controller/PersonAddressController.php b/src/Bundle/ChillPersonBundle/Controller/PersonAddressController.php index d387ff737..2d4a60c15 100644 --- a/src/Bundle/ChillPersonBundle/Controller/PersonAddressController.php +++ b/src/Bundle/ChillPersonBundle/Controller/PersonAddressController.php @@ -18,6 +18,7 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Validator\Validator\ValidatorInterface; + use function count; /** diff --git a/src/Bundle/ChillPersonBundle/Controller/PersonApiController.php b/src/Bundle/ChillPersonBundle/Controller/PersonApiController.php index 9bd54945e..77c0e296d 100644 --- a/src/Bundle/ChillPersonBundle/Controller/PersonApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/PersonApiController.php @@ -21,7 +21,7 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; -use Symfony\Component\Security\Core\Role\Role; + use function array_filter; use function array_values; @@ -76,14 +76,6 @@ class PersonApiController extends ApiController return $this->json(array_values($addresses), Response::HTTP_OK, [], ['groups' => ['read']]); } - protected function createEntity(string $action, Request $request): object - { - return parent::createEntity($action, $request); - // TODO temporary hack to allow creation of person with fake center - /* $centers = $this->authorizationHelper->getReachableCenters($this->getUser(), - new Role(PersonVoter::CREATE)); - $person->setCenter($centers[0]); */ - } /** * @Route("/api/1.0/person/config/alt_names.{_format}", @@ -120,17 +112,4 @@ class PersonApiController extends ApiController return $this->json($configAltNames, Response::HTTP_OK, [], ['groups' => ['read']]); } - protected function getValidationGroups(string $action, Request $request, string $_format, $entity): ?array - { - if ($action === '_entity'){ - if ($request->getMethod() === Request::METHOD_POST){ - return ["creation"]; - } - if (($request->getMethod() === Request::METHOD_PATCH) || ($request->getMethod() === Request::METHOD_PUT)){ - return ["general"]; - } - }; - return parent::getValidationGroups($action, $request, $_format, $entity); - } - } diff --git a/src/Bundle/ChillPersonBundle/Controller/PersonController.php b/src/Bundle/ChillPersonBundle/Controller/PersonController.php index 6247b92bb..02c77ebd3 100644 --- a/src/Bundle/ChillPersonBundle/Controller/PersonController.php +++ b/src/Bundle/ChillPersonBundle/Controller/PersonController.php @@ -32,6 +32,7 @@ use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Core\Security; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; + use function count; use function hash; use function implode; @@ -131,6 +132,8 @@ final class PersonController extends AbstractController ->getFlashBag()->add('error', $this->translator ->trans('This form contains errors')); } elseif ($form->isSubmitted() && $form->isValid()) { + $this->em->flush(); + $this->get('session')->getFlashBag() ->add( 'success', @@ -138,8 +141,6 @@ final class PersonController extends AbstractController ->trans('The person data has been updated') ); - $this->em->flush(); - return $this->redirectToRoute('chill_person_view', [ 'person_id' => $person->getId(), ]); @@ -207,8 +208,10 @@ final class PersonController extends AbstractController { $person = new Person(); - if (1 === count($this->security->getUser() - ->getGroupCenters())) { + if ( + 1 === count($this->security->getUser() + ->getGroupCenters()) + ) { $person->setCenter( $this->security->getUser() ->getGroupCenters()[0] @@ -216,22 +219,21 @@ final class PersonController extends AbstractController ); } - $form = $this->createForm(CreationPersonType::class, $person, [ - 'validation_groups' => ['create'], - ])->add('editPerson', SubmitType::class, [ - 'label' => 'Add the person', - ])->add('createPeriod', SubmitType::class, [ - 'label' => 'Add the person and create an accompanying period', - ])->add('createHousehold', SubmitType::class, [ - 'label' => 'Add the person and create an household', - ]); // TODO createHousehold form action + $form = $this->createForm(CreationPersonType::class, $person) + ->add('editPerson', SubmitType::class, [ + 'label' => 'Add the person', + ])->add('createPeriod', SubmitType::class, [ + 'label' => 'Add the person and create an accompanying period', + ]); $form->handleRequest($request); if ($request->getMethod() === Request::METHOD_GET) { $this->lastPostDataReset(); - } elseif ($request->getMethod() === Request::METHOD_POST - && $form->isValid()) { + } elseif ( + $request->getMethod() === Request::METHOD_POST + && $form->isValid() + ) { $alternatePersons = $this->similarPersonMatcher ->matchPerson($person); diff --git a/src/Bundle/ChillPersonBundle/Controller/PersonDuplicateController.php b/src/Bundle/ChillPersonBundle/Controller/PersonDuplicateController.php index 0b3f36b1c..182a90d5a 100644 --- a/src/Bundle/ChillPersonBundle/Controller/PersonDuplicateController.php +++ b/src/Bundle/ChillPersonBundle/Controller/PersonDuplicateController.php @@ -29,6 +29,7 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Translation\TranslatorInterface; + use function count; class PersonDuplicateController extends Controller diff --git a/src/Bundle/ChillPersonBundle/Controller/RelationshipApiController.php b/src/Bundle/ChillPersonBundle/Controller/RelationshipApiController.php index 72e92ac92..271b0cff7 100644 --- a/src/Bundle/ChillPersonBundle/Controller/RelationshipApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/RelationshipApiController.php @@ -14,10 +14,10 @@ namespace Chill\PersonBundle\Controller; use Chill\MainBundle\CRUD\Controller\ApiController; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Repository\Relationships\RelationshipRepository; +use Chill\PersonBundle\Security\Authorization\PersonVoter; use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Validator\Validator\ValidatorInterface; -use function array_values; class RelationshipApiController extends ApiController { @@ -36,9 +36,10 @@ class RelationshipApiController extends ApiController */ public function getRelationshipsByPerson(Person $person) { - //TODO: add permissions? (voter?) + $this->denyAccessUnlessGranted(PersonVoter::SEE, $person); + $relationships = $this->repository->findByPerson($person); - return $this->json(array_values($relationships), Response::HTTP_OK, [], ['groups' => ['read']]); + return $this->json($relationships, Response::HTTP_OK, [], ['groups' => ['read']]); } } diff --git a/src/Bundle/ChillPersonBundle/Controller/SocialWorkSocialActionApiController.php b/src/Bundle/ChillPersonBundle/Controller/SocialWorkSocialActionApiController.php index 24c1c6645..a6042b0a6 100644 --- a/src/Bundle/ChillPersonBundle/Controller/SocialWorkSocialActionApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/SocialWorkSocialActionApiController.php @@ -17,6 +17,7 @@ use Chill\MainBundle\Serializer\Model\Collection; use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; + use function count; class SocialWorkSocialActionApiController extends ApiController diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/Helper/PersonRandomHelper.php b/src/Bundle/ChillPersonBundle/DataFixtures/Helper/PersonRandomHelper.php index 4f5a51fd4..5b4eeb723 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/Helper/PersonRandomHelper.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/Helper/PersonRandomHelper.php @@ -13,6 +13,7 @@ namespace Chill\PersonBundle\DataFixtures\Helper; use Chill\PersonBundle\Entity\Person; use Doctrine\ORM\EntityManagerInterface; + use function array_pop; use function random_int; diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/Helper/RandomPersonHelperTrait.php b/src/Bundle/ChillPersonBundle/DataFixtures/Helper/RandomPersonHelperTrait.php index 516914f5f..00281311e 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/Helper/RandomPersonHelperTrait.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/Helper/RandomPersonHelperTrait.php @@ -13,6 +13,7 @@ namespace Chill\PersonBundle\DataFixtures\Helper; use Chill\PersonBundle\Entity\Person; use Doctrine\ORM\EntityManagerInterface; + use function random_int; trait RandomPersonHelperTrait diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodOrigin.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodOrigin.php index be352aa9b..2d368d2f4 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodOrigin.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodOrigin.php @@ -14,7 +14,6 @@ namespace Chill\PersonBundle\DataFixtures\ORM; use Chill\PersonBundle\Entity\AccompanyingPeriod\Origin; use Doctrine\Common\DataFixtures\AbstractFixture; use Doctrine\Common\DataFixtures\OrderedFixtureInterface; - use Doctrine\Persistence\ObjectManager; /** @@ -36,7 +35,7 @@ class LoadAccompanyingPeriodOrigin extends AbstractFixture implements OrderedFix public function load(ObjectManager $manager) { $o = new Origin(); - $o->setLabel(json_encode($this->phoneCall)); + $o->setLabel($this->phoneCall); $manager->persist($o); diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodWork.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodWork.php index 64c7d2701..83698735e 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodWork.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodWork.php @@ -19,6 +19,7 @@ use Chill\PersonBundle\Repository\AccompanyingPeriodRepository; use Chill\PersonBundle\Repository\SocialWork\EvaluationRepository; use DateTimeImmutable; use Doctrine\Persistence\ObjectManager; + use function array_pop; use function array_rand; use function count; @@ -95,7 +96,7 @@ class LoadAccompanyingPeriodWork extends \Doctrine\Bundle\FixturesBundle\Fixture // 1 of 10, force an evaluation if (0 === $i % 10) { $evaluation = $this->getRandomEvaluation(); - $action = $evaluation->getSocialAction(); + $action = $evaluation->getSocialActions()->first(); $issue = $action->getIssue(); $period->addSocialIssue($issue); diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadCustomFields.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadCustomFields.php index 9541aa76b..1e6435c8b 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadCustomFields.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadCustomFields.php @@ -28,7 +28,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Contracts\Translation\TranslatorInterface; class LoadCustomFields extends AbstractFixture implements - ContainerAwareInterface, + ContainerAwareInterface, OrderedFixtureInterface { /** @@ -115,7 +115,9 @@ class LoadCustomFields extends AbstractFixture implements // get possible values for cfGroup $choices = array_map( - static function ($a) { return $a['slug']; }, + static function ($a) { + return $a['slug']; + }, $this->customFieldChoice->getOptions()['choices'] ); // create faker diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadHousehold.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadHousehold.php index 6f9edd768..02b5ef2e7 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadHousehold.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadHousehold.php @@ -25,6 +25,7 @@ use Doctrine\Common\DataFixtures\DependentFixtureInterface; use Doctrine\ORM\EntityManagerInterface; use Doctrine\Persistence\ObjectManager; use Nelmio\Alice\Loader\NativeLoader; + use function array_pop; use function array_rand; use function random_int; diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadHouseholdPosition.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadHouseholdPosition.php index 42d2b7dd8..1642a71b9 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadHouseholdPosition.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadHouseholdPosition.php @@ -31,8 +31,10 @@ class LoadHouseholdPosition extends Fixture public function load(ObjectManager $manager) { - foreach (self::POSITIONS_DATA as [$name, $share, $allowHolder, - $ordering, $ref, ]) { + foreach ( + self::POSITIONS_DATA as [$name, $share, $allowHolder, + $ordering, $ref, ] + ) { $position = (new Position()) ->setLabel(['fr' => $name]) ->setAllowHolder($allowHolder) diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php index 924155955..b3bdd908f 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php @@ -42,6 +42,7 @@ use Nelmio\Alice\Loader\NativeLoader; use Nelmio\Alice\ObjectSet; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\Workflow\Registry; + use function count; use function random_int; use function ucfirst; diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadRelationships.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadRelationships.php index 80f3e711d..4fa9802f8 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadRelationships.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadRelationships.php @@ -20,6 +20,7 @@ use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Common\DataFixtures\DependentFixtureInterface; use Doctrine\ORM\EntityManagerInterface; use Doctrine\Persistence\ObjectManager; + use function count; class LoadRelationships extends Fixture implements DependentFixtureInterface diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/data/social_work_metadata.csv b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/data/social_work_metadata.csv index 6257b904b..9d6d40081 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/data/social_work_metadata.csv +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/data/social_work_metadata.csv @@ -1,32 +1,38 @@ AD - PREVENTION, ACCES AUX DROITS, BUDGET;ACCES AUX DROITS;Informer, conseiller;;;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;ACCES AUX DROITS;Aider à l'inclusion numérique;;;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;ACCES AUX DROITS;Demander une aide juridictionnelle;;;; AD - PREVENTION, ACCES AUX DROITS, BUDGET;ACCES AUX DROITS;Aider à l'ouverture aux droits;;;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;ACCES AUX DROITS;Demander une aide alimentaire;;;;Demande aide alimentaire +AD - PREVENTION, ACCES AUX DROITS, BUDGET;ACCES AUX DROITS;Demander une aide de 1ère nécessité (aide alimentaire, vêtement, …);;;;Demande aide 1ère nécessité +AD - PREVENTION, ACCES AUX DROITS, BUDGET;ACCES AUX DROITS;Demander une aide juridictionnelle;;;;https://www.service-public.fr/particuliers/vosdroits/R1444 +AD - PREVENTION, ACCES AUX DROITS, BUDGET;ACCES AUX DROITS;Aider à l'inclusion numérique;;;; AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Informer, conseiller;;;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : Centre Communal d’Action Sociale;;Demande aide impayé CCAS -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : CAF/MSA - Secours d’urgence;;Demande aide impayé CAF -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : CAF/MSA - Aide financière;;Demande aide impayé CAF -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : Caisse Primaire d’Assurance Maladie;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : FSL Maintien - Impayés de loyer;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : FSL Maintien - Énergie / Fluides;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : FSL Maintien - Impayés télécommunication;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : FSL Maintien - Impayés aire d'accueil GDV ;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : FSL Maintien - Lié à la COVID;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : Secours exceptionnels;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Instruire le dossier de surendettement;;;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une mesure de protection adulte;;Objectif : Sauvegarde de justice;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une mesure de protection adulte;;Objectif : Mesure d'Accompagnement Judiciaire (MAJ);; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une mesure de protection adulte;;Objectif : Signalement personne vulnérable;;Formulaire signalement personne vulnérable -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une mesure de protection adulte;;Objectif : Mesure de protection personne majeure (tutelle, curatelle);; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Faire une demande auprès des associations caritatives;;;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Instruire des formulaires auprès d'autres organismes (Locapass, Fastt, …);;;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Instruire une première demande d'AEB;;;;Demande AEB -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander un renouvellement d'AEB;;Objectif : Dans l'attente d'une mesure de protection ;;Renouvellement AEB -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander un renouvellement d'AEB;;Objectif : Pour poursuivre les objectifs engagés;;Renouvellement AEB -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Instruire une première demande de MASP;;;;Demande MAPS -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander un renouvellement MASP;;Objectif : Dans l'attente d'une mesure de protection ;;Renouvellement MASP -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander un renouvellement MASP;;Objectif : Pour poursuivre les objectifs engagés;;Renouvellement MASP +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : Centre Communal d’Action Sociale;ACCORD;Imprimé unique +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : Centre Communal d’Action Sociale;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : CAF/MSA - Secours d’urgence;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : CAF/MSA - Secours d’urgence;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : CAF/MSA - Aide financière;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : CAF/MSA - Aide financière;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : Caisse Primaire d’Assurance Maladie ;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : Caisse Primaire d’Assurance Maladie ;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : FSL Maintien - Impayés de loyer;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : FSL Maintien - Impayés de loyer;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : FSL Maintien - Énergie / Fluides;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : FSL Maintien - Énergie / Fluides;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : FSL Maintien - Impayés télécommunication;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : FSL Maintien - Impayés télécommunication;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : FSL Maintien - Impayés aire d'accueil GDV ;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : FSL Maintien - Impayés aire d'accueil GDV ;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : Secours exceptionnels Cabinet;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander une aide pour des impayés;;Objectif : Secours exceptionnels Cabinet;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Instruire le dossier de surendettement;;;Moratoire ;https://particuliers.banque-france.fr/sites/default/files/media/2020/05/12/1947_0.pdf +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Instruire le dossier de surendettement;;;Plan d'apurement ; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Instruire le dossier de surendettement;;;PRP ; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Instruire le dossier de surendettement;;;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Faire une demande auprès des associations caritatives;;;;Demande auprès d'une association +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Instruire une première demande d'AEB;;;;Formulaire AEB +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander un renouvellement d'AEB;;Objectif : Dans l'attente d'une mesure de protection ;ACCORD;Formulaire AEB +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander un renouvellement d'AEB;;Objectif : Pour poursuivre les objectifs engagés;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Instruire une première demande de MASP;;;;Evaluation demande de MASP +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander un renouvellement MASP;;Objectif : Dans l'attente d'une mesure de protection ;ACCORD;Evaluation demande de MASP +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Demander un renouvellement MASP;;Objectif : Pour poursuivre les objectifs engagés;REFUS; AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Cibler des objectifs avec l'usager;Objectif : Soutenir dans les démarches administratives;; AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Cibler des objectifs avec l'usager;Objectif : Aider au tri, au classement et à l’archivage des documents administratifs;; AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Cibler des objectifs avec l'usager;Objectif : Soutenir les ménages dans l’apurement des dettes, accompagner les ménages endettées, surendettées;; @@ -39,33 +45,60 @@ AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AE AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Cibler des objectifs avec l'usager;Objectif : Instruire des formulaires d'autres organismes non référencés…;; AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Cibler des objectifs avec l'usager;Objectif : Instruire le dossier de surendettement ;; AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Cibler des objectifs avec l'usager;Objectif : Demander ou renouveler la couverture santé (ACS);; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide alimentaire;;;Demande aide alimentaire -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : Centre Communal d’Action Sociale;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : CAF/MSA - Secours d’urgence;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : CAF/MSA - Aide financière;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : Caisse Primaire d’Assurance Maladie ;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Cautionnement;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Dépôt de garantie;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - 1er loyer;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Frais d’agence;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Assurances;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Déménagement;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Aide à l’installation;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Facture résiliation énergie (nv logement);; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés de loyer;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Énergie / Fluides;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés télécommunication;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés aire d'accueil GDV ;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Lié à la COVID;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : Secours exceptionnels;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : Mesure ASLL;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Faire une demande auprès de Association caritative;;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une mesure de protection ;Objectif : Sauvegarde de justice;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une mesure de protection ;Objectif : Signalement personne vulnérable;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une mesure de protection ;Objectif : Mesure de protection personne majeure (tutelle, curatelle);; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une mesure de protection ;Objectif : Mesure d'Accompagnement Judiciaire (MAJ);; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une mesure de protection ;Objectif : Mesure Judiciaire d'Aide à la Gestion du Budget Familial (MJAGBF);; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Conclure l'AEB;;Résultat : Arrêt à l'initiative du ménage pour déménagement; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide de 1ère nécessité (aide alimentaire, vêtement, …);;ACCORD;Demande aide 1ère nécessité +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide de 1ère nécessité (aide alimentaire, vêtement, …);;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : Centre Communal d’Action Sociale;ACCORD;Imprimé unique +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : Centre Communal d’Action Sociale;REFUS;FSL Justificatif accès logement +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : CAF/MSA - Secours d’urgence;ACCORD;FSL Justificatif impayés loyers +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : CAF/MSA - Secours d’urgence;REFUS;"Demande d'accompagnement lié au logement (ASLL) +" +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : CAF/MSA - Aide financière;ACCORD;Cautionnement +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : CAF/MSA - Aide financière;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : Caisse Primaire d’Assurance Maladie ;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : Caisse Primaire d’Assurance Maladie ;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Cautionnement;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Cautionnement;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Dépôt de garantie;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Dépôt de garantie;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - 1er loyer;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - 1er loyer;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Frais d’agence;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Frais d’agence;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Assurances;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Assurances;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Déménagement;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Déménagement;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Aide à l’installation;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Aide à l’installation;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Facture résiliation énergie (nv logement);ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Facture résiliation énergie (nv logement);REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés de loyer;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés de loyer;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Énergie / Fluides;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Énergie / Fluides;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés télécommunication;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés télécommunication;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés aire d'accueil GDV ;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés aire d'accueil GDV ;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Lié à la COVID;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Lié à la COVID;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : Secours exceptionnels;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : Secours exceptionnels;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : Mesure ASLL;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une aide pour des impayés ou accès logement;Objectif : Mesure ASLL;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Faire une demande auprès d'une association caritative;;ACCORD;Demande auprès d'une association +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Faire une demande auprès d'une association caritative;;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une mesure de protection ;Objectif : Sauvegarde de justice;ACCORD;Rapport d'évaluation signalement personne vulnérable +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une mesure de protection ;Objectif : Sauvegarde de justice;REFUS;URL sur Grille d'aide à l'évaluation d'une situation de vulnérabilité +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une mesure de protection ;Objectif : Signalement personne vulnérable;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une mesure de protection ;Objectif : Signalement personne vulnérable;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une mesure de protection ;Objectif : Mesure de protection personne majeure (tutelle, curatelle);ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une mesure de protection ;Objectif : Mesure de protection personne majeure (tutelle, curatelle);REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une mesure de protection ;Objectif : Mesure d'Accompagnement Judiciaire (MAJ);ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une mesure de protection ;Objectif : Mesure d'Accompagnement Judiciaire (MAJ);REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une mesure de protection ;Objectif : Mesure Judiciaire d'Aide à la Gestion du Budget Familial (MJAGBF);ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Demander une mesure de protection ;Objectif : Mesure Judiciaire d'Aide à la Gestion du Budget Familial (MJAGBF);REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Conclure l'AEB;;Résultat : Arrêt à l'initiative du ménage pour déménagement;Formulaire AEB AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Conclure l'AEB;;Résultat : Suspension momentanée de l'accompagnement par le ménage ou le professionnel; AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Conclure l'AEB;;Résultat : Arrêt pour absence d'adhésion; AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer un AEB;Conclure l'AEB;;Résultat : Arrêt à l'initiative du ménage pour séparation; @@ -88,31 +121,57 @@ AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une M AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Cibler des objectifs avec l'usager;Objectif : Instruire des formulaires d'autres organismes non référencés…;; AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Cibler des objectifs avec l'usager;Objectif : Instruire le dossier de surendettement ;; AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Cibler des objectifs avec l'usager;Objectif : Demander ou renouveler la couverture santé (ACS);; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide alimentaire;;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : Centre Communal d’Action Sociale;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : CAF/MSA - Secours d’urgence;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : CAF/MSA - Aide financière;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : Caisse Primaire d’Assurance Maladie ;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Cautionnement;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Dépôt de garantie;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - 1er loyer;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Frais d’agence;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Assurances;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Déménagement;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Aide à l’installation;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Facture résiliation énergie (nv logement);; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés de loyer;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Énergie / Fluides;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés télécommunication;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés aire d'accueil GDV ;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Lié à la COVID;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : Secours exceptionnels;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : Mesure ASLL;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une mesure de protection adulte;Objectif : Sauvegarde de justice;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une mesure de protection adulte;Objectif : Signalement personne vulnérable;; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une mesure de protection adulte;Objectif : Mesure de protection personne majeure (tutelle, curatelle);; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une mesure de protection adulte;Objectif : Mesure d'Accompagnement Judiciaire (MAJ);; -AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une mesure de protection adulte;Objectif : Mesure Judiciaire d'Aide à la Gestion du Budget Familial (MJAGBF);; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide de 1ère nécessité (aide alimentaire, vêtement, …);;ACCORD;Demande aide 1ère nécessité +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide de 1ère nécessité (aide alimentaire, vêtement, …);;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : Centre Communal d’Action Sociale;ACCORD;Imprimé unique +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : Centre Communal d’Action Sociale;REFUS;FSL Justificatif accès logement +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : CAF/MSA - Secours d’urgence;ACCORD;FSL Justificatif impayés loyers +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : CAF/MSA - Secours d’urgence;REFUS;"Demande d'accompagnement lié au logement (ASLL) +" +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : CAF/MSA - Aide financière;ACCORD;Cautionnement +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : CAF/MSA - Aide financière;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : Caisse Primaire d’Assurance Maladie ;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : Caisse Primaire d’Assurance Maladie ;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Cautionnement;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Cautionnement;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Dépôt de garantie;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Dépôt de garantie;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - 1er loyer;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - 1er loyer;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Frais d’agence;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Frais d’agence;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Assurances;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Assurances;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Déménagement;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Déménagement;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Aide à l’installation;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Aide à l’installation;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Facture résiliation énergie (nv logement);ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Accès - Facture résiliation énergie (nv logement);REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés de loyer;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés de loyer;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Énergie / Fluides;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Énergie / Fluides;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés télécommunication;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés télécommunication;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés aire d'accueil GDV ;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Impayés aire d'accueil GDV ;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Lié à la COVID;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : FSL Maintien - Lié à la COVID;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : Secours exceptionnels;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : Secours exceptionnels;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : Mesure ASLL;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une aide pour des impayés ou accès logement;Objectif : Mesure ASLL;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une mesure de protection adulte;Objectif : Sauvegarde de justice;ACCORD;Rapport d'évaluation signalement personne vulnérable +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une mesure de protection adulte;Objectif : Sauvegarde de justice;REFUS;Grille d'aide à l'évaluation d'une situation de vulnérabilité +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une mesure de protection adulte;Objectif : Signalement personne vulnérable;ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une mesure de protection adulte;Objectif : Signalement personne vulnérable;REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une mesure de protection adulte;Objectif : Mesure de protection personne majeure (tutelle, curatelle);ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une mesure de protection adulte;Objectif : Mesure de protection personne majeure (tutelle, curatelle);REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une mesure de protection adulte;Objectif : Mesure d'Accompagnement Judiciaire (MAJ);ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une mesure de protection adulte;Objectif : Mesure d'Accompagnement Judiciaire (MAJ);REFUS; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une mesure de protection adulte;Objectif : Mesure Judiciaire d'Aide à la Gestion du Budget Familial (MJAGBF);ACCORD; +AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Demander une mesure de protection adulte;Objectif : Mesure Judiciaire d'Aide à la Gestion du Budget Familial (MJAGBF);REFUS; AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Conclure la MASP;;Résultat : Arrêt à l'initiative du ménage pour déménagement; AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Conclure la MASP;;Résultat : Suspension momentanée de l'accompagnement par le ménage ou le professionnel; AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Conclure la MASP;;Résultat : Arrêt pour absence d'adhésion; @@ -123,64 +182,117 @@ AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une M AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Conclure la MASP;;Résultat : Transmission pour une mesure d'accompagnement judiciaire ; AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Conclure la MASP;;Résultat : Renouvellement de MASP dans l'attente d'une mesure de protection ; AD - PREVENTION, ACCES AUX DROITS, BUDGET;SOUTIEN EQUILIBRE BUDGET;Exercer une MASP;Conclure la MASP;;Résultat : Renouvellement de MASP pour poursuivre les objectifs engagés; -AD - LOGEMENT;ACCES LOGEMENT (RE);Informer, conseiller;;;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Demander une aide pour l'accès;;Objectif : FSL Accès - Cautionnement;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Demander une aide pour l'accès;;Objectif : FSL Accès - Dépôt de garantie;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Demander une aide pour l'accès;;Objectif : FSL Accès - 1er loyer;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Demander une aide pour l'accès;;Objectif : FSL Accès - Frais d’agence;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Demander une aide pour l'accès;;Objectif : FSL Accès - Assurances;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Demander une aide pour l'accès;;Objectif : FSL Accès - Déménagement;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Demander une aide pour l'accès;;Objectif : FSL Accès - Aide à l’installation;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Demander une aide pour l'accès;;Objectif : FSL Accès - Facture résiliation énergie (nv logement);; -AD - LOGEMENT;ACCES LOGEMENT (RE);Demander une aide pour l'accès;;Objectif : FSL Accès - Mesure ASLL;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Demander auprès des Bailleurs sociaux, mairies, partenaires;;;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Instruire une demande DALO, DAHO;;;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Instruire une demande SIAO;;;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Instruire une demande ASLL;;;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Instruire une demande au Contingent préfectoral;;;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Instruire une demande au 115;;;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Prévenir de l'expulsion;;Objectif : Intervenir au commandement de payer;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Prévenir de l'expulsion;;Objectif : Instruire la fiche Assignation;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Prévenir de l'expulsion;;Objectif : Répondre au commandement de quitter les lieux;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Prévenir de l'expulsion;;Objectif : Répondre au concours de la force publique;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Prévenir de l'expulsion;;Objectif : Demander une aide financière FSL pour impayé de loyer;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Prévenir de l'expulsion;;Objectif : Déposer un dossier de surendettement;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Prévenir de l'expulsion;;Objectif : Demander auprès des Bailleurs sociaux, mairies, partenaires;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Prévenir de l'expulsion;;Objectif : Instruire une demande DALO, DAHO;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Prévenir de l'expulsion;;Objectif : Instruire une demande SIAO;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Prévenir de l'expulsion;;Objectif : Instruire une demande ASLL;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Prévenir de l'expulsion;;Objectif : Instruire une demande au Contingent préfectoral;; -AD - LOGEMENT;ACCES LOGEMENT (RE);Prévenir de l'expulsion;;Objectif : Instruire une demande au 115;; +AD - PROTECTION;;Demander une mesure de protection adulte;;Objectif : Sauvegarde de justice;ACCORD;Rapport d'évaluation signalement personne vulnérable +AD - PROTECTION;;Demander une mesure de protection adulte;;Objectif : Sauvegarde de justice;REFUS;Grille d'aide à l'évaluation d'une situation de vulnérabilité +AD - PROTECTION;;Demander une mesure de protection adulte;;Objectif : Mesure d'Accompagnement Judiciaire (MAJ);ACCORD; +AD - PROTECTION;;Demander une mesure de protection adulte;;Objectif : Mesure d'Accompagnement Judiciaire (MAJ);REFUS; +AD - PROTECTION;;Demander une mesure de protection adulte;;Objectif : Signalement personne vulnérable;ACCORD; +AD - PROTECTION;;Demander une mesure de protection adulte;;Objectif : Signalement personne vulnérable;REFUS; +AD - PROTECTION;;Demander une mesure de protection adulte;;Objectif : Mesure de protection personne majeure (tutelle, curatelle);ACCORD; +AD - PROTECTION;;Demander une mesure de protection adulte;;Objectif : Mesure de protection personne majeure (tutelle, curatelle);REFUS; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Informer, conseiller;;;; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - Cautionnement;ACCORD;Imprimé unique +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - Cautionnement;REFUS;FSL Justificatif accès logement +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - Dépôt de garantie;ACCORD;FSL Justificatif impayés loyers +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - Dépôt de garantie;REFUS;Cautionnement +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - 1er loyer;ACCORD; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - 1er loyer;REFUS; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - Frais d’agence;ACCORD; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - Frais d’agence;REFUS; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - Assurances;ACCORD; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - Assurances;REFUS; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - Déménagement;ACCORD; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - Déménagement;REFUS; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - Aide à l’installation;ACCORD; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - Aide à l’installation;REFUS; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - Facture résiliation énergie (nv logement);ACCORD; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - Facture résiliation énergie (nv logement);REFUS; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - Mesure ASLL;ACCORD; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - Mesure ASLL;REFUS; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - CAF pré-équipement;ACCORD; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander une aide pour l'accès;;Objectif : FSL Accès - CAF pré-équipement;REFUS; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Demander auprès des Bailleurs sociaux, mairies, partenaires;;;; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Instruire une demande DALO, DAHO;;;;http://www.dalo13.fr/formulaires-de-demande +AD - LOGEMENT;ACCES (RE)LOGEMENT;Instruire une demande SIAO;;;;URL Demande SIAO +AD - LOGEMENT;ACCES (RE)LOGEMENT;Instruire une demande ASLL;;;ACCORD;"Demande d'accompagnement lié au logement (ASLL) +" +AD - LOGEMENT;ACCES (RE)LOGEMENT;Instruire une demande ASLL;;;REFUS; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Instruire une demande au Contingent préfectoral;;;;Fiche de signalement contingent préfectoral +AD - LOGEMENT;ACCES (RE)LOGEMENT;Instruire une demande au 115;;;; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Prévenir de l'expulsion;;Objectif : Intervenir au commandement de payer;;http://www.dalo13.fr/formulaires-de-demande +AD - LOGEMENT;ACCES (RE)LOGEMENT;Prévenir de l'expulsion;;Objectif : Instruire la fiche Assignation;;URL Demande SIAO +AD - LOGEMENT;ACCES (RE)LOGEMENT;Prévenir de l'expulsion;;Objectif : Répondre au commandement de quitter les lieux;;Fiche de signalement contingent préfectoral +AD - LOGEMENT;ACCES (RE)LOGEMENT;Prévenir de l'expulsion;;Objectif : Répondre au concours de la force publique;; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Prévenir de l'expulsion;;Objectif : Demander une aide financière FSL pour impayé de loyer;; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Prévenir de l'expulsion;;Objectif : Déposer un dossier de surendettement;; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Prévenir de l'expulsion;;Objectif : Instruire une demande auprès des Bailleurs sociaux, mairies, partenaires;; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Prévenir de l'expulsion;;Objectif : Instruire une demande DALO, DAHO;ACCORD; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Prévenir de l'expulsion;;Objectif : Instruire une demande DALO, DAHO;REFUS; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Prévenir de l'expulsion;;Objectif : Instruire une demande SIAO;; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Prévenir de l'expulsion;;Objectif : Instruire une demande ASLL;ACCORD; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Prévenir de l'expulsion;;Objectif : Instruire une demande ASLL;REFUS; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Prévenir de l'expulsion;;Objectif : Instruire une demande au Contingent préfectoral;; +AD - LOGEMENT;ACCES (RE)LOGEMENT;Prévenir de l'expulsion;;Objectif : Instruire une demande au 115;; AD - LOGEMENT;HABITAT INDIGNE;Informer, conseiller;;;; -AD - LOGEMENT;HABITAT INDIGNE;Demander une aide pour incurie;;Objectif : FSL maintien - aide incurie;; -AD - LOGEMENT;HABITAT INDIGNE;Instruire la grille de signalement;;;; +AD - LOGEMENT;HABITAT INDIGNE;Demander une aide pour incurie;;Objectif : FSL maintien - aide incurie;ACCORD;Imprimé unique +AD - LOGEMENT;HABITAT INDIGNE;Demander une aide pour incurie;;Objectif : FSL maintien - aide incurie;REFUS; +AD - LOGEMENT;HABITAT INDIGNE;Instruire la grille de signalement;;;;Grille signalement incurie habitat indigne AD - LOGEMENT;HABITAT INDIGNE;Faire intervenir d'autres partenaires;;;; AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Informer, conseiller;;;; -AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Demander un accompagnement psychologue insertion;;;; -AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement psychologue insertion;;;; -AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Renouveller l'accompagnement psychologue insertion;;;; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Demander un accompagnement psychologue insertion;;;ACCORD; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Demander un accompagnement psychologue insertion;;;REFUS; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement psychologue insertion;;;;Fiche d’orientation, prescription psychologique +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement psychologue insertion;;;;Accompagnement psychologique Fiche suivi +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Renouveller l'accompagnement psychologue insertion;;;ACCORD;Accompagnement psychologique Demande de renouvellement +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Renouveller l'accompagnement psychologue insertion;;;REFUS; AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Réorienter l'usager vers autres structures pour un accompagnement psychologique;;;; -AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Demander l'accompagnement global;;Objectif : Axe 2;; -AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global;;Objectif : Axe 2;; -AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Renouveller l'accompagnement global;;Objectif : Axe 2;; -AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Demander l'accompagnement global;;Objectif : Axe 3 (agent d'insertion);; -AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global;;Objectif : Axe 3 (agent d'insertion);; -AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Renouveller l'accompagnement global;;Objectif : Axe 3 (agent d'insertion);; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Demander l'accompagnement global;;Objectif : Axe 2;ACCORD;Fiche prescription Axe 2 et 3 +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Demander l'accompagnement global;;Objectif : Axe 2;REFUS; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Demander l'accompagnement global;;Objectif : Axe 3 (agent d'insertion);ACCORD; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Demander l'accompagnement global;;Objectif : Axe 3 (agent d'insertion);REFUS; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 2;;Motif : Accès aux droits;Résultat : Réalisé; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 2;;Motif : Difficultés financières;Résultat : Arrêt avant terme; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 2;;Motif : Santé;Résultat : Non entré, absence au RDV ; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 2;;Motif : Logement;Résultat : Non entré, hors cadre; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 2;;Motif : Mobilité;Résultat : Relai vers un autre professionnel ; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 2;;Motif : Peu d'expérience professionnelle, reconversion, mise en mouvement;; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 2;;Motif : Numérique;; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 2;;Motif : Difficultés, contraintes familiales;; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 2;;Motif : Burn out, épuisement professionnel;; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 2;;Motif : Difficultés à suivre l'administratif;; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 2;;Motif : Isolement social;; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 2;;Motif : Difficultés avec la langue française;; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 3;;Motif : Accès aux droits;Résultat : Réalisé; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 3;;Motif : Difficultés financières;Résultat : Arrêt avant terme; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 3;;Motif : Santé;Résultat : Non entré, absence au RDV ; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 3;;Motif : Logement;Résultat : Non entré, hors cadre; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 3;;Motif : Mobilité;Résultat : Relai vers un autre professionnel ; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 3;;Motif : Peu d'expérience professionnelle, reconversion, mise en mouvement;; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 3;;Motif : Numérique;; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 3;;Motif : Difficultés, contraintes familiales;; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 3;;Motif : Burn out, épuisement professionnel;; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 3;;Motif : Difficultés à suivre l'administratif;; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 3;;Motif : Isolement social;; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Exercer l'accompagnement global AXE 3;;Motif : Difficultés avec la langue française;; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Renouveller l'accompagnement global;;Objectif : Axe 2(agent d'insertion);ACCORD;Fiche prescription Axe 2 et 3 +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Renouveller l'accompagnement global;;Objectif : Axe 2(agent d'insertion);REFUS; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Renouveller l'accompagnement global;;Objectif : Axe 3 (agent d'insertion);ACCORD; +AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Renouveller l'accompagnement global;;Objectif : Axe 3 (agent d'insertion);REFUS; AD - INSERTION SOCIALE PROFESSIONNELLE;ACCOMPAGNEMENT INSERTION;Instruire une demande MOVEA;;;; AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Informer, conseiller;;;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;"Aider à l'ouverture de droits +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;"Aider à l'ouverture de droits ";;;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renseigner la plateforme INCLUSION@COM pour les chantiers d'insertion;;;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Soutenir le parcours professionnel (emploi, formation, …);; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement global Axe 2 (orientation Pôle Emploi);; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Orienter vers une structure de l'insertion (chantier, AI, ETTI, …);; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Demander la médiation emploi;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Création d'entreprise;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement travailleur non salarié;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement ASR CEIDRE;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Déposer un dossier MDPH;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Déposer un dossier retraite;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Soutenir l'accès au logement;; +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renseigner la plateforme INCLUSION@COM pour les chantiers d'insertion;;;;Avenant au contrat +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Soutenir le parcours professionnel (emploi, formation, …);;Contrat d'Engagement Réciproque +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement global Axe 2 (avec orientation Pôle Emploi);;Fiche prescription axe 2 et 3 +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Orienter vers une structure de l'insertion (chantier, AI, ETTI, …);;Fiche de demande Action PVI +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Demander la médiation emploi;;Fiche prescription PDIE FAII PST +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Création d'entreprise;;Fiche orientation prescription médiation emploi +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement travailleur non salarié;;Demande Diagnostic T.I. BRSA +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement ASR CEIDRE;;Fiche d’orientation, prescription psychologique +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Déposer un dossier MDPH;;https://www.service-public.fr/particuliers/vosdroits/R19993 +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Déposer un dossier retraite;;https://mdphenligne.cnsa.fr/v2/mdph/85/inscription +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Soutenir l'accès au logement;;https://aleop.paysdelaloire.fr/carte-mobi AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Accompagner le budget;; AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Soutenir la mobilité (MOVEA, transport solidaire, PST, …);; AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Demander le psychologue insertion;; @@ -188,17 +300,17 @@ AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Ré AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Initier ou maintenir un parcours santé (cure, hospitalisation, CMP, …);; AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Solliciliter un FAII;; AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Demander un réorientation Pôle Emploi;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Autre;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Soutenir le parcours professionnel (emploi, formation, …);; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement global Axe 2 (orientation Pôle Emploi);; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Orienter vers une structure de l'insertion (chantier, AI, ETTI, …);; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Demander la médiation emploi;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Création d'entreprise;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement travailleur non salarié;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement ASR CEIDRE;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Déposer un dossier MDPH;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Déposer un dossier retraite;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Soutenir l'accès au logement;; +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire le 1er Contrat d'Engagement Réciproque;;Objectif : Autres;; +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Soutenir le parcours professionnel (emploi, formation, …);;Contrat d'Engagement Réciproque +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement global Axe 2 (orientation Pôle Emploi);;Fiche prescription axe 2 et 3 +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Orienter vers une structure de l'insertion (chantier, AI, ETTI, …);;Fiche de demande Action PVI +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Demander la médiation emploi;;Fiche prescription PDIE FAII PST +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Création d'entreprise;;Fiche orientation prescription médiation emploi +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement travailleur non salarié;;Demande Diagnostic T.I. BRSA +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement ASR CEIDRE;;Fiche d’orientation, prescription psychologique +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Déposer un dossier MDPH;;https://www.service-public.fr/particuliers/vosdroits/R19993 +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Déposer un dossier retraite;;https://mdphenligne.cnsa.fr/v2/mdph/85/inscription +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Soutenir l'accès au logement;;https://aleop.paysdelaloire.fr/carte-mobi AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Accompagner le budget;; AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Soutenir la mobilité (MOVEA, transport solidaire, PST, …);; AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Demander le psychologue insertion;; @@ -206,17 +318,17 @@ AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement R AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Initier ou maintenir un parcours santé;; AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Solliciliter un FAII;; AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Demander un réorientation Pôle Emploi;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Autre;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Soutenir le parcours professionnel (emploi, formation, …);; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement global Axe 2 (orientation Pôle Emploi);; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Orienter vers une structure de l'insertion (chantier, AI, ETTI, …);; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Demander la médiation emploi;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Création d'entreprise;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement travailleur non salarié;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement ASR CEIDRE;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Déposer un dossier MDPH;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Déposer un dossier retraite;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Soutenir l'accès au logement;; +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Renouveler le Contrat d'Engagement Réciproque;;Objectif : Autres;; +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Soutenir le parcours professionnel (emploi, formation, …);;Contrat d'Engagement Réciproque +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement global Axe 2 (orientation Pôle Emploi);;Fiche prescription axe 2 et 3 +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Orienter vers une structure de l'insertion (chantier, AI, ETTI, …);;Fiche de demande Action PVI +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Demander la médiation emploi;;Fiche prescription PDIE FAII PST +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Création d'entreprise;;Fiche orientation prescription médiation emploi +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement travailleur non salarié;;Demande Diagnostic T.I. BRSA +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Demander l'accompagnement ASR CEIDRE;;Fiche d’orientation, prescription psychologique +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Déposer un dossier MDPH;;https://www.service-public.fr/particuliers/vosdroits/R19993 +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Déposer un dossier retraite;;https://mdphenligne.cnsa.fr/v2/mdph/85/inscription +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Soutenir l'accès au logement;;https://aleop.paysdelaloire.fr/carte-mobi AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Accompagner le budget;; AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Soutenir la mobilité (MOVEA, transport solidaire, PST, …);; AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Demander le psychologue insertion;; @@ -224,34 +336,85 @@ AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagem AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Initié ou maintenir un parcours santé;; AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Solliciliter un FAII;; AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Demander un réorientation Pôle Emploi;; -AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Autre;; +AD - INSERTION SOCIALE PROFESSIONNELLE;RSA;Faire un avenant au Contrat d'Engagement Réciproque;;Objectif : Autres;; AD - INSERTION SOCIALE PROFESSIONNELLE;JEUNES 16/25 AIDE FINANCIERE INSERTION;Informer, conseiller;;;; -AD - INSERTION SOCIALE PROFESSIONNELLE;JEUNES 16/25 AIDE FINANCIERE INSERTION;Demander une aide FAJ;;Objectif : SU bons alimentaires;; -AD - INSERTION SOCIALE PROFESSIONNELLE;JEUNES 16/25 AIDE FINANCIERE INSERTION;Demander une aide FAJ;;Objectif : SU bons hygiène;; -AD - INSERTION SOCIALE PROFESSIONNELLE;JEUNES 16/25 AIDE FINANCIERE INSERTION;Demander une aide FAJ;;Objectif : SU bons carburant;; -AD - INSERTION SOCIALE PROFESSIONNELLE;JEUNES 16/25 AIDE FINANCIERE INSERTION;Demander une aide FAJ;;Objectif : SU virement;; -AD - INSERTION SOCIALE PROFESSIONNELLE;JEUNES 16/25 AIDE FINANCIERE INSERTION;Solliciter le comité FAJ;;Objectif : Aide financière;; +AD - INSERTION SOCIALE PROFESSIONNELLE;JEUNES 16/25 AIDE FINANCIERE INSERTION;Demander une aide FAJ;;Objectif : SU bons alimentaires;ACCORD;Imprimé unique +AD - INSERTION SOCIALE PROFESSIONNELLE;JEUNES 16/25 AIDE FINANCIERE INSERTION;Demander une aide FAJ;;Objectif : SU bons alimentaires;REFUS;Imprimé unique +AD - INSERTION SOCIALE PROFESSIONNELLE;JEUNES 16/25 AIDE FINANCIERE INSERTION;Demander une aide FAJ;;Objectif : SU bons hygiène;ACCORD;FAJ Attestation de prise en charge +AD - INSERTION SOCIALE PROFESSIONNELLE;JEUNES 16/25 AIDE FINANCIERE INSERTION;Demander une aide FAJ;;Objectif : SU bons hygiène;REFUS;FAJ Attestation de prise en charge +AD - INSERTION SOCIALE PROFESSIONNELLE;JEUNES 16/25 AIDE FINANCIERE INSERTION;Demander une aide FAJ;;Objectif : SU bons carburant;ACCORD; +AD - INSERTION SOCIALE PROFESSIONNELLE;JEUNES 16/25 AIDE FINANCIERE INSERTION;Demander une aide FAJ;;Objectif : SU bons carburant;REFUS; +AD - INSERTION SOCIALE PROFESSIONNELLE;JEUNES 16/25 AIDE FINANCIERE INSERTION;Demander une aide FAJ;;Objectif : SU virement;ACCORD; +AD - INSERTION SOCIALE PROFESSIONNELLE;JEUNES 16/25 AIDE FINANCIERE INSERTION;Demander une aide FAJ;;Objectif : SU virement;REFUS; +AD - INSERTION SOCIALE PROFESSIONNELLE;JEUNES 16/25 AIDE FINANCIERE INSERTION;Solliciter le comité FAJ;;Objectif : Aide financière;ACCORD;Imprimé unique +AD - INSERTION SOCIALE PROFESSIONNELLE;JEUNES 16/25 AIDE FINANCIERE INSERTION;Solliciter le comité FAJ;;Objectif : Aide financière;REFUS;Imprimé unique AD - INSERTION SOCIALE PROFESSIONNELLE;JEUNES 16/25 AIDE FINANCIERE INSERTION;Solliciter le comité FAJ;;Objectif : Action d’accompagnement;; AD - SANTE;;Informer, conseiller;;;; AD - SANTE;;Orienter vers une structure de soins (CMP, psychologue, cure, …);;;; +AD - SANTE;;Instruire un dossier MDPH;;;;https://www.service-public.fr/particuliers/vosdroits/R19993 AD - SANTE;;Instruire un dossier MDPH;;;; +AD - SANTE;;Instruire un dossier MDPH;;;;https://mdphenligne.cnsa.fr/v2/mdph/85/inscription AD - SANTE;;Accompagner le dépôt de dossier de pension d'invalidité;;;; -AD - SANTE;;Instruire le dossier Complémentaire santé ACS;;;; +AD - SANTE;;Instruire le dossier Complémentaire santé ACS;;;;https://www.ameli.fr/sites/default/files/formulaires/596542/formulaire_s3711_-_demande_complementaire_sante_solidaire_-_assurance_maladie.pdf AD – ACCOMPAGNEMENT SPECIFIQUE;;Informer, conseiller;;;; -AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Procéder à une élection de domicile;; -AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Demander une aide financière;; -AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Demander un interprète;; -AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Prendre contact avec le CADA;; +AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Procéder à une élection de domicile;Première demande;https://www.service-public.fr/particuliers/vosdroits/R44660 +AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Procéder à une élection de domicile;Renouvellement;https://www.ameli.fr/sites/default/files/formulaires/93/s3720g-demande-aide-medicale-etat-ame-2021.pdf +AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Procéder à une élection de domicile;Radiation;https://aleop.paysdelaloire.fr/carte-mobi +AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Demander une aide financière;ACCORD; +AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Demander une aide financière;REFUS; +AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Demander un interprète;ACCORD; +AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Demander un interprète;REFUS; +AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Prendre contact avec le CADA ou les associations;; AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Aider à la constitution de dossier auprès de la préfecture;; -AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Faire le lien avec les associations;; -AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Demander une aide médicale d'état;; -AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Demander une carte mobilité;; +AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Demander une aide médicale d'état;ACCORD; +AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Demander une aide médicale d'état;REFUS; +AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Demander une carte mobilité;ACCORD; +AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Demander une carte mobilité;REFUS; AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Accompagner pour la scolarité des enfants (crèches, collège, péri scolaire, cantine…);; AD – ACCOMPAGNEMENT SPECIFIQUE;;Accompagner des publics spécifiques;;Objectif : Aider à la compréhension du français;; ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Informer, conseiller;;;; ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Orienter vers une autre structure;;;; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Instruire une première demande d'Accompagnement Educatif de Prevention;;;; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Demander le renouvellement de l'Accompagnement Educatif de Prévention;;;; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Médiatiser les relations familiales;;Evaluation demande de passage en IRCP +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander le passage en IRCP;ACCORD;Demande ASE +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander le passage en IRCP;REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une mise en place TISF;ACCORD; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une mise en place TISF;REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander le renouvellement TISF;ACCORD; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander le renouvellement TISF;REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une mise en place AED;ACCORD; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une mise en place AED;REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une mise en place AESF;ACCORD; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une mise en place AESF;REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une mise en place d'un AP (accueil provisoire);ACCORD; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une mise en place d'un AP (accueil provisoire);REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une mesure ASMI;ACCORD; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une mesure ASMI;REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une entrée en centre maternelle;ACCORD; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une entrée en centre maternelle;REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une entrée en centre parental;ACCORD; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une entrée en centre parental;REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une entrée en Unité Mère Enfant (UME);ACCORD; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une entrée en Unité Mère Enfant (UME);REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une MJAGBF;ACCORD; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une MJAGBF;REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une AED TDC;ACCORD; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une AED TDC;REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander la désignation un TDC;ACCORD; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander la désignation un TDC;REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander un CAP ASE;ACCORD; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander un CAP ASE;REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une AMAE (allocation mensuelle d'aide éducative);ACCORD; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une AMAE (allocation mensuelle d'aide éducative);REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une allocation socio-éducatif spécifique;ACCORD; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une allocation socio-éducatif spécifique;REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander un CAFI (aides fi);ACCORD; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander un CAFI (aides fi);REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une autre aide (associations…);ACCORD; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une autre aide (associations…);REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Instruire une première demande d'Accompagnement Educatif de Prevention;;;ACCORD;Formulaire AEP +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Instruire une première demande d'Accompagnement Educatif de Prevention;;;REFUS; +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Demander le renouvellement de l'Accompagnement Educatif de Prévention;;;ACCORD;Formulaire AEP +ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Demander le renouvellement de l'Accompagnement Educatif de Prévention;;;REFUS; ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Excercer un Accompagnement Educatif de Prévention;;Problèmatique : : Conduite à risque / Passage à l'acte isolé de l'enfant/adolescent;; ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Excercer un Accompagnement Educatif de Prévention;;Problèmatique : Comportement de l'enfant/adolescent en difficulté avec les limites, les interdits, les règles sociales;; ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Excercer un Accompagnement Educatif de Prévention;;Problèmatique : Difficultés de l'enfant en milieu scolaire ou extra-scolaire;; @@ -284,77 +447,66 @@ ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Conclure un Accompagnement Educatif de ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Conclure un Accompagnement Educatif de Prévention;;;Résultat : Renouvellement de l’AEP dans l’attente d’une mesure ASE; ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Conclure un Accompagnement Educatif de Prévention;;;Résultat : Renouvellement de l’AEP pour poursuivre les objectifs engagés; ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Réaliser une permanence éducative;;;; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Médiatiser les relations familiales;; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander le passage en IRCP;; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une mise en place TISF;; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander le renouvellement TISF;; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une mise en place AED;; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une mise en place AESF;; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une mise en place d'un AP (accueil provisoire);; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une mesure ASMI;; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une entrée en centre maternelle;; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une entrée en centre parental;; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une entrée en Unité Mère Enfant (UME);; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une MJAGBF;; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une AED TDC;; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander la désignation un TDC;; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander un CAP ASE;; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une AMAE (allocation mensuelle d'aide éducative);; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une allocation socio-éducatif spécifique;; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander un CAFI (aides fi);; -ENFANT / FAMILLE;SOUTIEN A LA PARENTALITE;Solliciter les moyens dans le cadre d'un accompagnement à la parentalité ;;Demander une autre aide (associations…);; -ENFANT / FAMILLE;ENFANT PREVENTION;Alerter la CRIP;;Motif : arrêt de l'adhésion des parents à l'accompagnement du soutien à la parentalité;; +ENFANT / FAMILLE;ENFANT PREVENTION;Alerter la CRIP;;Motif : arrêt de l'adhésion des parents à l'accompagnement du soutien à la parentalité;;FRIP ENFANT / FAMILLE;ENFANT PREVENTION;Alerter la CRIP;;Motif : violence intra-familiale;; ENFANT / FAMILLE;ENFANT PREVENTION;Alerter la CRIP;;Motif : suite à une ISG;; ENFANT / FAMILLE;ENFANT PREVENTION;Alerter la CRIP;;;Faire une FRIP; ENFANT / FAMILLE;ENFANT PREVENTION;Alerter la CRIP;;;Demander une MJIE; -ENFANT / FAMILLE;ENFANT PREVENTION;Alerter la CRIP;;;Demander une mesure de protection; +ENFANT / FAMILLE;ENFANT PREVENTION;Alerter la CRIP;;;Demander une mesure de protection enfant; ENFANT / FAMILLE;ENFANT PREVENTION;Alerter la CRIP;;;Demander un OPP; ENFANT / FAMILLE;ENFANT PREVENTION;Alerter la CRIP;;;Demander un placement; -ENFANT / FAMILLE;ENFANT PREVENTION;Alerter l'ASE (RJA) pour situation connue;;Motif : arrêt de l'adhésion des parents à l'accompagnement du soutien à la parentalité;; -ENFANT / FAMILLE;ENFANT PREVENTION;Alerter l'ASE (RJA) pour situation connue;;Motif : violence intra-familiale;; +ENFANT / FAMILLE;ENFANT PREVENTION;Alerter l'ASE (RJA) pour situation connue;;Motif : arrêt de l'adhésion des parents à l'accompagnement du soutien à la parentalité;;Evaluation type +ENFANT / FAMILLE;ENFANT PREVENTION;Alerter l'ASE (RJA) pour situation connue;;Motif : violence intra-familiale;;Demande ASE ENFANT / FAMILLE;ENFANT PREVENTION;Alerter l'ASE (RJA) pour situation connue;;Motif : suite à une ISG;; ENFANT / FAMILLE;ENFANT PREVENTION;Alerter l'ASE (RJA) pour situation connue;;;Demander une MJIE; ENFANT / FAMILLE;ENFANT PREVENTION;Alerter l'ASE (RJA) pour situation connue;;;Demander une mesure de protection; ENFANT / FAMILLE;ENFANT PREVENTION;Alerter l'ASE (RJA) pour situation connue;;;Demander un OPP; ENFANT / FAMILLE;ENFANT PREVENTION;Alerter l'ASE (RJA) pour situation connue;;;Demander un placement; -ENFANT / FAMILLE;ENFANT PREVENTION;Répondre à Eléments en votre possession;;;; -ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation IP pour la CRIP;;;Evaluation sans suite; -ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation IP pour la CRIP;;;Evaluation demande d'accompagnement médico-sociale; -ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation IP pour la CRIP;;;Evaluation pur demande de MJIE; +ENFANT / FAMILLE;ENFANT PREVENTION;Répondre à Eléments en votre possession;;;;Trame éléments en votre possession +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation IP pour la CRIP;;;Evaluation sans suite;Evaluation IP +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation IP pour la CRIP;;;Evaluation demande d'accompagnement médico-sociale;Premier courrier parents +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation IP pour la CRIP;;;Evaluation pur demande de MJIE;Second courrier parents ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation IP pour la CRIP;;;Evaluation pour demande d'AEMO; ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation IP pour la CRIP;;;Evaluation pour demande de placement; ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation IP pour la CRIP;;;Evaluation pour demande d'OPP; ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation IP pour la CRIP;;;Note complémentaire actualisation; -ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation pour l'ASE;;;Evaluation sans suite; +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation pour l'ASE;;;Evaluation sans suite;Evaluation IP ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation pour l'ASE;;;Evaluation demande d'accompagnement médico-sociale; ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation pour l'ASE;;;Evaluation pur demande de MJIE; ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation pour l'ASE;;;Evaluation pour demande d'AEMO; ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation pour l'ASE;;;Evaluation pour demande de placement; ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation pour l'ASE;;;Evaluation pour demande d'OPP; ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Réaliser une Evaluation pour l'ASE;;;Note complémentaire actualisation; -ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander un AEP;; -ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander une mise en place AED;; -ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander une mise en place TISF;; -ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander la mise en place d'un Accueil Provisoire;; -ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander l'orientation vers d'autres structures (soins, MDA, …);; -ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander l'entrée en centre maternel ;; -ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander l'entrée unité mère / enfant;; +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander un AEP;ACCORD;Demande ASE +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander un AEP;REFUS; +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander une mise en place AED;ACCORD; +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander une mise en place AED;REFUS; +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander une mise en place TISF;ACCORD; +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander une mise en place TISF;REFUS; +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander la mise en place d'un Accueil Provisoire;ACCORD; +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander la mise en place d'un Accueil Provisoire;REFUS; +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander l'orientation vers d'autres structures (soins, MDA, …);ACCORD; +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander l'orientation vers d'autres structures (soins, MDA, …);REFUS; +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander l'entrée en centre maternel ;ACCORD; +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander l'entrée en centre maternel ;REFUS; +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander l'entrée unité mère / enfant;ACCORD; +ENFANT / FAMILLE;INFORMATIONS PREOCCUPANTES;Mettre en place un accompagnement médicosocial suite à une IP;;Demander l'entrée unité mère / enfant;REFUS; ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Informer, conseiller;;;; -ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Protéger des violences intra familiales;;Orienter vers SOS femme;; -ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Protéger des violences intra familiales;;Proposer un conseiller ou une thérapie conjugale;; +ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Protéger des violences intra familiales;;Orienter vers SOS femme;;VIF +ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Protéger des violences intra familiales;;Proposer un conseiller ou une thérapie conjugale;;FRIP ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Protéger des violences intra familiales;;Proposer une médiation familiale;; ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Protéger des violences intra familiales;;Aider au dépôt de plainte;; ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Protéger des violences intra familiales;;Signaler un adulte vulnérable au procureur ;; ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Protéger des violences intra familiales;;Demander une mesure de protection majeur;; ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Protéger des violences intra familiales;;Faire une FRIP pour enfant en danger;; ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Protéger des violences intra familiales;;Instruire la fiche VIF;; -ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Conseiller ;; -ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Problématique : VIF;; -ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Problématique : Difficultés éducatives;; -ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Problématique : Protection de l’enfance;; -ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Problématique : Violences sexuelles;; -ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Problématique : Information suite à une séparation;; +ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Conseiller ;;VIF +ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Echanger les violences intra-familiales;;FRIP +ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Intervenir dans le cadre de la protection de l’enfance;FRIP;Rapport d'évaluation signalement personne vulnérable +ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Intervenir dans le cadre de la protection de l’enfance;FRIP, orientation MDA, orientation MDSF;Grille d'aide à l'évaluation d'une situation de vulnérabilité +ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Intervenir dans le cadre de la protection de l’enfance;FRIP, orientation MDA, orientation MDSF; +ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Echanger sur les violences sexuelles;; +ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Informer suite à une séparation;; ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Orienter vers l'AS de secteur;; ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Orienter vers SOS femme;; ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Orienter vers un accompagnement CMP/libéral;; @@ -362,59 +514,261 @@ ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Aider au dépôt de plainte;; ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Signaler un adulte vulnérable au procureur ;; ENFANT / FAMILLE;VIOLENCES INTRA-FAMILIALES;Réaliser l'intervention sociale en gendarmerie;;Demander une mesure de protection majeur;; -ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le lieu d'accueil;;;; -ENFANT PROTECTION;ACCUEIL PROVISOIRE;Mettre en place un soutien parental;;Mise en place TISF;; -ENFANT PROTECTION;ACCUEIL PROVISOIRE;Mettre en place un soutien parental;;Demande aide financière / SU;; -ENFANT PROTECTION;ACCUEIL PROVISOIRE;Mettre en place un soutien parental;;Demande SU;; -ENFANT PROTECTION;ACCUEIL PROVISOIRE;Mettre en place un soutien parental;;Participation à des actions collectives;; -ENFANT PROTECTION;ACCUEIL PROVISOIRE;Mettre en place un soutien parental;;Mise en place d'un loisir familial ;; -ENFANT PROTECTION;ACCUEIL PROVISOIRE;Mettre en place un soutien parental;;Mise en place d'une aide transport;; -ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le mineur;;Demande mise en place d'un accompagnement psychologique;; -ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le mineur;;Construire le PPE;; -ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le mineur;;Mise en place CJM;; -ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le mineur;;Demande MDPH ;; -ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le mineur;;Organiser la mise en place d'un loisir;; -ENFANT PROTECTION;ACCUEIL PROVISOIRE;Elaborer le lien partenarial;;;; -ENFANT PROTECTION;ACCUEIL PROVISOIRE;Demander une protection majeur vulnérable;;;; -ENFANT PROTECTION;ACCUEIL PROVISOIRE;Demande de MJIE (mesure judiciaire d'investigation éducative);;;; -ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Accompagner le lieu d'accueil;;;; -ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Mettre en place un soutien parental;;Mise en place TISF;; -ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Mettre en place un soutien parental;;Demande aide financière;; -ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Mettre en place un soutien parental;;Demande SU;; -ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Mettre en place un soutien parental;;Demande de protection majeur vulnérable;; -ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Accompagner le mineur;;;; -ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Elaborer le lien partenarial;;;; -ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Mettre en place un soutien parental;;;; -ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Accompagner le mineur;;Construire le PPE;; -ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Accompagner le mineur;;Mise en place CJM;; -ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Accompagner le mineur;;Organiser la participation à un camp de vacances;; -ENFANT PROTECTION;DELEGATION D'AUTORITE PARENTALE;Accompagner le lieu d'accueil;;;; -ENFANT PROTECTION;DELEGATION D'AUTORITE PARENTALE;Accompagner le mineur;;;; -ENFANT PROTECTION;DELEGATION D'AUTORITE PARENTALE;Elaborer le lien partenarial;;;; -ENFANT PROTECTION;TUTELLE DEPARTEMENTALE;;;;; -ENFANT PROTECTION;TUTELLE D'ETAT;Accompagner le lieu d'accueil;;;; -ENFANT PROTECTION;TUTELLE D'ETAT;Accompagner le mineur;;;; -ENFANT PROTECTION;TUTELLE D'ETAT;Elaborer le lien partenarial;;;; -ENFANT PROTECTION;AEMO TDC;Accompagner le lieu d'accueil;;;; -ENFANT PROTECTION;AEMO TDC;Mettre en place un soutien parental;;;; -ENFANT PROTECTION;AEMO TDC;Accompagner le mineur;;;; -ENFANT PROTECTION;AEMO TDC;Elaborer le lien partenarial;;;; -ENFANT PROTECTION;AEMO FAMILLE;Mettre en place un soutien parental;;;; -ENFANT PROTECTION;AEMO FAMILLE;Accompagner le mineur;;;; -ENFANT PROTECTION;AEMO FAMILLE;Elaborer le lien partenarial;;;; -AGREMENT;ASSISTANT MATERNEL;Instruire une première demande;;;; -AGREMENT;ASSISTANT MATERNEL;Instruire un renouvellement;;;; -AGREMENT;ASSISTANT MATERNEL;Instruire une modification;;;; -AGREMENT;ASSISTANT MATERNEL;Suivre un(e) ASSMAT;;;; -AGREMENT;ASSISTANT MATERNEL;Contrôler un(e) ASSMAT;;;; -AGREMENT;ASSISTANT MATERNEL;Accompagner un(e) ASSMAT;;;; -AGREMENT;ASSISTANT FAMILIAL;Instruire une première demande;;;; -AGREMENT;ASSISTANT FAMILIAL;Instruire un renouvellement;;;; -AGREMENT;ASSISTANT FAMILIAL;Instruire une modification;;;; -AGREMENT;ASSISTANT FAMILIAL;Suivre un(e) ASSFAM;;;; -AGREMENT;ASSISTANT FAMILIAL;Contrôler un(e) ASSFAM;;;; -AGREMENT;ASSISTANT FAMILIAL;Accompagner un(e) ASSFAM;;;; -AGREMENT;FAMILLE D'ACCUEIL PA/PH;Contribuer à l'évaluation si Famille d'Accueil connue;;Première demande;; -AGREMENT;FAMILLE D'ACCUEIL PA/PH;Contribuer à l'évaluation si Famille d'Accueil connue;;Renouvellement;; -AGREMENT;FAMILLE D'ACCUEIL PA/PH;Contribuer à l'évaluation si Famille d'Accueil connue;;Modification;; -AGREMENT;FAMILLE D'ACCUEIL PA/PH;Contribuer à l'évaluation si Famille d'Accueil connue;;Suivi;; +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le lieu d'accueil;;Accord préalable;;Accord préalable +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le lieu d'accueil;;Suggestion exceptionnelle;;Relance fiche observation +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le lieu d'accueil;;Relance ASSFAM pour fiche observation;;Note circonstanciée +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le lieu d'accueil;;Transmettre une IP;; +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le lieu d'accueil;;Informer le DA;; +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Mettre en place un soutien parental;;Mise en place TISF / aide ménagère;;Demande TISF aide-ménagère +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Mettre en place un soutien parental;;Demande aide financière / SU;;Demande aide financière +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Mettre en place un soutien parental;;Mise en place d'un loisir familial ;;Demande Secours Urgence +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Mettre en place un soutien parental;;Participation à des actions collectives;;Accord préalable +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Mettre en place un soutien parental;;Aide aux transports;;Demande transport +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Mettre en place un soutien parental;;Informer l'autorité administrative;; +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Mettre en place un soutien parental;;Informer l'autorité judiciaire;; +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le mineur;;PPE;;Projet Pour l'Enfant +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le mineur;;Demande MDPH ;;https://www.formulaires.service-public.fr/gf/cerfa_15692.do +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le mineur;;Loisirs;;Dossier MDPH pour impression +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le mineur;;Santé;;Accord préalable +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le mineur;;Accompagnement psychologique;;Rapport d'échéance +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le mineur;;Aide aux transports;;Note circonstanciée +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le mineur;;Informer l'autorité administrative;;Bilan neuropsychologique +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le mineur;;Informer l'autorité judiciaire;; +ENFANT PROTECTION;ACCUEIL PROVISOIRE;Accompagner le mineur;;Requête majeur vulnérable;; +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Accompagner le lieu d'accueil;;Accord préalable;;Accord préalable +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Accompagner le lieu d'accueil;;Suggestion exceptionnelle;;Relance fiche observation +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Accompagner le lieu d'accueil;;Relance ASSFAM pour fiche observation;;Note circonstanciée +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Accompagner le lieu d'accueil;;Transmettre une IP;; +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Accompagner le lieu d'accueil;;Informer le DA;; +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Mettre en place un soutien parental;;Mise en place TISF / aide ménagère;;Demande TISF aide-ménagère +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Mettre en place un soutien parental;;Demande aide financière / SU;;Demande aide financière +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Mettre en place un soutien parental;;Mise en place d'un loisir familial ;;Demande Secours Urgence +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Mettre en place un soutien parental;;Participation à des actions collectives;;Accord préalable +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Mettre en place un soutien parental;;Aide aux transports;;Demande transport +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Mettre en place un soutien parental;;Informer l'autorité administrative;; +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Mettre en place un soutien parental;;Informer l'autorité judiciaire;; +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Accompagner le mineur;;PPE;;Projet Pour l'Enfant +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Accompagner le mineur;;Rdv 17 ans;;https://www.formulaires.service-public.fr/gf/cerfa_15692.do +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Accompagner le mineur;;Demande MDPH ;;Dossier MDPH pour impression +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Accompagner le mineur;;Loisirs;;Accord préalable +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Accompagner le mineur;;Santé;;Rapport d'échéance +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Accompagner le mineur;;Accompagnement psychologique;;Note circonstanciée +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Accompagner le mineur;;Aide aux transports;;Bilan neuropsychologique +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Accompagner le mineur;;Requête majeur vulnérable;;Contrat Jeune Majeur +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Accompagner le mineur;;Informer l'autorité administrative;; +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT DANS UN LIEU D'ACCUEIL;Accompagner le mineur;;Informer l'autorité judiciaire;; +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Mettre en place un soutien parental;;Mise en place TISF / aide ménagère;;Demande TISF aide-ménagère +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Mettre en place un soutien parental;;Demande aide financière / SU;;Demande aide financière +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Mettre en place un soutien parental;;Mise en place d'un loisir familial ;;Demande Secours Urgence +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Mettre en place un soutien parental;;Participation à des actions collectives;;Accord préalable +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Mettre en place un soutien parental;;Aide aux transports;;Demande transport +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Mettre en place un soutien parental;;Informer l'autorité administrative;; +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Mettre en place un soutien parental;;Informer l'autorité judiciaire;; +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Accompagner le mineur;;PPE;;Projet Pour l'Enfant +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Accompagner le mineur;;Demande MDPH ;;https://www.formulaires.service-public.fr/gf/cerfa_15692.do +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Accompagner le mineur;;Accord préalable;;Dossier MDPH pour impression +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Accompagner le mineur;;Accompagnement psychologique;;Accord préalable +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Accompagner le mineur;;Aide aux transports;;Rapport d'échéance +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Accompagner le mineur;;Informer l'autorité administrative;;Note circonstanciée +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Accompagner le mineur;;Informer l'autorité judiciaire;;Bilan neuropsychologique +ENFANT PROTECTION;ASSISTANCE EDUCATIVE DE PLACEMENT CHEZ LE PARENT;Accompagner le mineur;;Requête majeur vulnérable;; +ENFANT PROTECTION;DELEGATION D'AUTORITE PARENTALE;Accompagner le lieu d'accueil;;Accord préalable;;Accord préalable +ENFANT PROTECTION;DELEGATION D'AUTORITE PARENTALE;Accompagner le lieu d'accueil;;Transmettre une IP;;Note circonstanciée +ENFANT PROTECTION;DELEGATION D'AUTORITE PARENTALE;Accompagner le lieu d'accueil;;Informer le DA;; +ENFANT PROTECTION;DELEGATION D'AUTORITE PARENTALE;Accompagner le mineur;;PPE;;Projet Pour l'Enfant +ENFANT PROTECTION;DELEGATION D'AUTORITE PARENTALE;Accompagner le mineur;;Demande MDPH ;;https://www.formulaires.service-public.fr/gf/cerfa_15692.do +ENFANT PROTECTION;DELEGATION D'AUTORITE PARENTALE;Accompagner le mineur;;Loisirs;;Dossier MDPH pour impression +ENFANT PROTECTION;DELEGATION D'AUTORITE PARENTALE;Accompagner le mineur;;Santé;;Accord préalable +ENFANT PROTECTION;DELEGATION D'AUTORITE PARENTALE;Accompagner le mineur;;Accompagnement psychologique;;Rapport d'échéance +ENFANT PROTECTION;DELEGATION D'AUTORITE PARENTALE;Accompagner le mineur;;Aide aux transports;;Note circonstanciée +ENFANT PROTECTION;DELEGATION D'AUTORITE PARENTALE;Accompagner le mineur;;Informer l'autorité administrative;;Bilan neuropsychologique +ENFANT PROTECTION;DELEGATION D'AUTORITE PARENTALE;Accompagner le mineur;;Informer l'autorité judiciaire;;Accord préalable +ENFANT PROTECTION;DELEGATION D'AUTORITE PARENTALE;Accompagner le mineur;;Requête majeur vulnérable;; +ENFANT PROTECTION;TUTELLE DEPARTEMENTALE;Accompagner le lieu d'accueil;;Accord préalable;;Accord préalable +ENFANT PROTECTION;TUTELLE DEPARTEMENTALE;Accompagner le lieu d'accueil;;Transmettre une IP;;Note circonstanciée +ENFANT PROTECTION;TUTELLE DEPARTEMENTALE;Accompagner le lieu d'accueil;;Informer le DA;; +ENFANT PROTECTION;TUTELLE DEPARTEMENTALE;Accompagner le mineur;;PPE;;Projet Pour l'Enfant +ENFANT PROTECTION;TUTELLE DEPARTEMENTALE;Accompagner le mineur;;Rdv 17 ans;;https://www.formulaires.service-public.fr/gf/cerfa_15692.do +ENFANT PROTECTION;TUTELLE DEPARTEMENTALE;Accompagner le mineur;;Demande MDPH ;;Dossier MDPH pour impression +ENFANT PROTECTION;TUTELLE DEPARTEMENTALE;Accompagner le mineur;;Loisirs;;Accord préalable +ENFANT PROTECTION;TUTELLE DEPARTEMENTALE;Accompagner le mineur;;Santé;;Rapport d'échéance +ENFANT PROTECTION;TUTELLE DEPARTEMENTALE;Accompagner le mineur;;Accompagnement psychologique;;Note circonstanciée +ENFANT PROTECTION;TUTELLE DEPARTEMENTALE;Accompagner le mineur;;Aide aux transports;;Bilan neuropsychologique +ENFANT PROTECTION;TUTELLE DEPARTEMENTALE;Accompagner le mineur;;Informer le conseil de famille;; +ENFANT PROTECTION;TUTELLE DEPARTEMENTALE;Accompagner le mineur;;Requête majeur vulnérable;; +ENFANT PROTECTION;TUTELLE D'ETAT;Accompagner le lieu d'accueil;;Accord préalable;;Accord préalable +ENFANT PROTECTION;TUTELLE D'ETAT;Accompagner le lieu d'accueil;;Transmettre une IP;;Note circonstanciée +ENFANT PROTECTION;TUTELLE D'ETAT;Accompagner le lieu d'accueil;;Informer le DA;; +ENFANT PROTECTION;TUTELLE D'ETAT;Accompagner le mineur;;PPE;;Projet Pour l'Enfant +ENFANT PROTECTION;TUTELLE D'ETAT;Accompagner le mineur;;Rdv 17 ans;;https://www.formulaires.service-public.fr/gf/cerfa_15692.do +ENFANT PROTECTION;TUTELLE D'ETAT;Accompagner le mineur;;Demande MDPH ;;Dossier MDPH pour impression +ENFANT PROTECTION;TUTELLE D'ETAT;Accompagner le mineur;;Loisirs;;Accord préalable +ENFANT PROTECTION;TUTELLE D'ETAT;Accompagner le mineur;;Santé;;Rapport d'échéance +ENFANT PROTECTION;TUTELLE D'ETAT;Accompagner le mineur;;Accompagnement psychologique;;Note circonstanciée +ENFANT PROTECTION;TUTELLE D'ETAT;Accompagner le mineur;;Aide aux transports;;Bilan neuropsychologique +ENFANT PROTECTION;TUTELLE D'ETAT;Accompagner le mineur;;Informer le conseil de famille;; +ENFANT PROTECTION;TUTELLE D'ETAT;Accompagner le mineur;;Requête majeur vulnérable;; +ENFANT PROTECTION;TUTELLE D'ETAT;Accompagner le mineur;;Informer l'autorité administrative;; +ENFANT PROTECTION;TUTELLE D'ETAT;Accompagner le mineur;;Informer l'autorité judiciaire;; +ENFANT PROTECTION;AEMO TDC;Accompagner le lieu d'accueil;;Demande aide financière / SU;;Demande aide financière +ENFANT PROTECTION;AEMO TDC;Accompagner le lieu d'accueil;;Accord préalable;;Demande Secours Urgence +ENFANT PROTECTION;AEMO TDC;Accompagner le lieu d'accueil;;Aide aux transports;;Accord préalable +ENFANT PROTECTION;AEMO TDC;Accompagner le lieu d'accueil;;Informer l'autorité judiciaire;; +ENFANT PROTECTION;AEMO TDC;Mettre en place un soutien parental;;Mise en place TISF / aide ménagère;;Demande TISF aide-ménagère +ENFANT PROTECTION;AEMO TDC;Mettre en place un soutien parental;;Mise en place d'un loisir familial ;;Accord préalable +ENFANT PROTECTION;AEMO TDC;Mettre en place un soutien parental;;Participation à des actions collectives;;Demande transport +ENFANT PROTECTION;AEMO TDC;Mettre en place un soutien parental;;Aide aux transports;;Note circonstanciée +ENFANT PROTECTION;AEMO TDC;Mettre en place un soutien parental;;Informer l'autorité administrative;; +ENFANT PROTECTION;AEMO TDC;Mettre en place un soutien parental;;Informer l'autorité judiciaire;; +ENFANT PROTECTION;AEMO TDC;Accompagner le mineur;;PPE;;Projet Pour l'Enfant +ENFANT PROTECTION;AEMO TDC;Accompagner le mineur;;Demande MDPH ;;https://www.formulaires.service-public.fr/gf/cerfa_15692.do +ENFANT PROTECTION;AEMO TDC;Accompagner le mineur;;Accompagnement psychologique;;Dossier MDPH pour impression +ENFANT PROTECTION;AEMO TDC;Accompagner le mineur;;Aide aux transports;;Accord préalable +ENFANT PROTECTION;AEMO TDC;Accompagner le mineur;;Requête majeur vulnérable;;Rapport d'échéance +ENFANT PROTECTION;AEMO TDC;Accompagner le mineur;;Informer l'autorité administrative;;Note circonstanciée +ENFANT PROTECTION;AEMO TDC;Accompagner le mineur;;Informer l'autorité judiciaire;;Bilan neuropsychologique +ENFANT PROTECTION;AEMO FAMILLE;Mettre en place un soutien parental;;Mise en place TISF / aide ménagère;;Demande TISF aide-ménagère +ENFANT PROTECTION;AEMO FAMILLE;Mettre en place un soutien parental;;Demande aide financière / SU;;Demande aide financière +ENFANT PROTECTION;AEMO FAMILLE;Mettre en place un soutien parental;;Mise en place d'un loisir familial ;;Demande Secours Urgence +ENFANT PROTECTION;AEMO FAMILLE;Mettre en place un soutien parental;;Participation à des actions collectives;;Accord préalable +ENFANT PROTECTION;AEMO FAMILLE;Mettre en place un soutien parental;;Aide aux transports;;Demande transport +ENFANT PROTECTION;AEMO FAMILLE;Mettre en place un soutien parental;;Informer l'autorité administrative;;Note circonstanciée +ENFANT PROTECTION;AEMO FAMILLE;Mettre en place un soutien parental;;Informer l'autorité judiciaire;; +ENFANT PROTECTION;AEMO FAMILLE;Accompagner le mineur;;PPE;;Projet Pour l'Enfant +ENFANT PROTECTION;AEMO FAMILLE;Accompagner le mineur;;Demande MDPH ;;https://www.formulaires.service-public.fr/gf/cerfa_15692.do +ENFANT PROTECTION;AEMO FAMILLE;Accompagner le mineur;;Loisirs;;Dossier MDPH pour impression +ENFANT PROTECTION;AEMO FAMILLE;Accompagner le mineur;;Santé;;Accord préalable +ENFANT PROTECTION;AEMO FAMILLE;Accompagner le mineur;;Accompagnement psychologique;;Rapport d'échéance +ENFANT PROTECTION;AEMO FAMILLE;Accompagner le mineur;;Aide aux transports;;Note circonstanciée +ENFANT PROTECTION;AEMO FAMILLE;Accompagner le mineur;;Requête majeur vulnérable;;Bilan neuropsychologique +ENFANT PROTECTION;AEMO FAMILLE;Accompagner le mineur;;Informer l'autorité administrative;; +ENFANT PROTECTION;AEMO FAMILLE;Accompagner le mineur;;Informer l'autorité judiciaire;; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Analyse des besoins à domicile;;Information - conseil - orientation;Refus de l'usager ou famille;Certificat d'accompagnement +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Analyse des besoins à domicile;;Accompagnement dans la démarche;Refus de l'usager ou famille;Projet personnalisé personnes âgées à domicile +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Analyse des besoins à domicile;;Accompagnement dans la démarche;Refus de l'usager ou famille;Courrier mise à disposition +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Analyse des besoins à domicile;;Accompagnement dans la démarche;Refus de l'usager ou famille;Formulaire Parcours +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Aide humaine/ Auxiliaire de Vie;;Information - conseil - orientation;Refus de l'usager ou famille;https://www.vendee-senior.fr/Services-d-aide-Etablissements/Annuaire-des-services-d-aide-a-domicile +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Aide humaine/ Auxiliaire de Vie;;Information - conseil - orientation;Refus du service / solution manquante;Liste mandataires autorisés +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Aide humaine/ Auxiliaire de Vie;;Accompagnement dans la démarche;Refus de l'usager ou famille;Fiche adhésion au CESU +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Aide humaine/ Auxiliaire de Vie;;Accompagnement dans la démarche;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Garde de nuit / Accueil de nuit;;Information - conseil - orientation;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Garde de nuit / Accueil de nuit;;Information - conseil - orientation;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Garde de nuit / Accueil de nuit;;Accompagnement dans la démarche;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Garde de nuit / Accueil de nuit;;Accompagnement dans la démarche;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Accueil de jour;;Information - conseil - orientation;Refus de l'usager ou famille;Liste accueils de jour +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Accueil de jour;;Information - conseil - orientation;Refus du service / solution manquante;https://trajectoire.sante-ra.fr/Trajectoire/ +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Accueil de jour;;Accompagnement dans la démarche;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Accueil de jour;;Accompagnement dans la démarche;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Portage de repas;;Information - conseil - orientation;Refus de l'usager ou famille;Liste portages de repas +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Portage de repas;;Information - conseil - orientation;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Portage de repas;;Accompagnement dans la démarche;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Portage de repas;;Accompagnement dans la démarche;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Téléalarme;;Information - conseil - orientation;Refus de l'usager ou famille;Liste téléalarmes +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Téléalarme;;Accompagnement dans la démarche;Refus de l'usager ou famille;Aide installation téléalarme +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Suivi en sortie d'hospitalisation, HAD;;Information - conseil - orientation;Refus de l'usager ou famille;Formulaire Parcours +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Suivi en sortie d'hospitalisation, HAD;;Accompagnement dans la démarche;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Transport;;Information - conseil - orientation;Refus du service / solution manquante;https://www.agirc-arrco.fr/action-sociale/personnes-agees/ +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Transport;;Accompagnement dans la démarche;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;CESU;;Information - conseil - orientation;;Fiche adhésion CESU +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;CESU;;Accompagnement dans la démarche;; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Isolement / Animation;;Service Prévention Séniors;; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Isolement / Animation;;Dispositif lutte contre l'isolement;; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Médiation familiale;;;;http://www.udaf85.fr/services-formations/mediation-familiale/ +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;Médiation familiale;;;;http://www.areams.fr/nos-activites/mediation-familiale/ +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;MAIA, gestion de cas;;accompagnement en gestion cas;Refus de l'usager ou famille;Formulaire Parcours +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;MAINTIEN A DOMICILE;MAIA, gestion de cas;;accompagnement en gestion cas;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;Aide sociale;;Information - conseil - orientation;;https://www.vendee-senior.fr/Formulaires-utiles +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;ADPA;;Information - conseil - orientation;;"https://www.vendee-senior.fr/Formulaires-utiles +" +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;ADPA;;Accompagnement dans la démarche;;Courrier demande certificat médical +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;ADPA;;Constitution du dossier de 1ère demande;;Courrier demande révision ADPA +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;ADPA;;Demande de révision APA simplifié;;Fiche plan d'aide seul +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;ADPA;;Demande de révision APA classique;;Support d'évaluation multidimentionnel +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;ADPA;;Substitution;;Fiche majoration pour hospitalisation du proche aidant +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;ADPA;;Demande d'ADPA accélérée;;Fiche identification du proche aidant +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;ADPA;;Evaluation ADPA - 1ère demande;;Grille AGGIR +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;ADPA;;Evaluation ADPA - révision classique;;Courrier demande avis d'impôt +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;ADPA;;Evaluation ADPA - révision simplifiée;; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;ADPA;;Evaluation ADPA accélérée;; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;ADPA;;Majoration pour hospitalisation de l'aidant;; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;CARSAT;;Information - conseil - orientation;;https://www.partenairesactionsociale.fr/sites/ppas/home.html +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;CARSAT;;Constitution du dossier de 1ère demande;;Dossier ASIR +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;CARSAT;;Evaluation CARSAT;;Dossier PAP Fonction Publique +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;MDPH;;Information - conseil - orientation;;https://www.formulaires.service-public.fr/gf/cerfa_15692.do +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;MDPH;;Accompagnement dans la démarche;; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;Autres (ONAC, caisse de retraite, protection sociale, budget…);;Information - conseil - orientation;;Dossier ONAC +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;ACCES AUX DROITS;Autres (ONAC, caisse de retraite, protection sociale, budget…);;Accompagnement dans la démarche;;Dossier ligue contre le cancer +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;EQAAR, équipe d'appui;;Information - conseil - orientation;Refus de l'usager ou famille;Formulaire Parcours +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;EQAAR, équipe d'appui;;Information - conseil - orientation;Refus du service / solution manquante;Formulaire EQAAR - ADAMAD +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;EQAAR, équipe d'appui;;Accompagnement dans la démarche;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;EQAAR, équipe d'appui;;Accompagnement dans la démarche;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;ESA;;Information - conseil - orientation;Refus de l'usager ou famille;Formulaire Parcours +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;ESA;;Information - conseil - orientation;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;ESA;;Accompagnement dans la démarche;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;ESA;;Accompagnement dans la démarche;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;Paramédicaux (kiné, ortho…);;Information - conseil - orientation;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;Paramédicaux (kiné, ortho…);;Information - conseil - orientation;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;Paramédicaux (kiné, ortho…);;Accompagnement dans la démarche;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;Paramédicaux (kiné, ortho…);;Accompagnement dans la démarche;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;Médecins libéraux;;Coordination;; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;Médecins libéraux;;;Solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;Hospitalisation;;Information - conseil - orientation;;Formulaire Parcours +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;Hospitalisation;;Accompagnement dans la démarche;; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;RESPA, EMM;;Information - conseil - orientation;;Formulaire Parcours +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;Consultation mémoire, HDJ;;Information - conseil - orientation;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;Consultation mémoire, HDJ;;Information - conseil - orientation;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;Consultation mémoire, HDJ;;Accompagnement dans la démarche;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;Consultation mémoire, HDJ;;Accompagnement dans la démarche;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;SSIAD, IDEL;;Information - conseil - orientation;Refus de l'usager ou famille;Formulaire Parcours +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;SSIAD, IDEL;;Information - conseil - orientation;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;SSIAD, IDEL;;Accompagnement dans la démarche;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;SOINS / SANTE;SSIAD, IDEL;;Accompagnement dans la démarche;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;LOGEMENT;Adaptation / aide technique;;Information - conseil - réorientation;;Formulaire Parcours +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;LOGEMENT;Adaptation / aide technique;;Accompagnement dans la démarche;;Formulaire EQAAR - ADAMAD +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;LOGEMENT;Insalubrité/incurie;;Information - conseil - réorientation;;Grille signalement incurie habitat indigne +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;LOGEMENT;Insalubrité/incurie;;Accompagnement dans la démarche;; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;AIDANT;Soutien psychologique;;Information - conseil - réorientation;Refus de l'usager ou famille;Formulaire Parcours +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;AIDANT;Soutien psychologique;;Accompagnement dans la démarche;Refus du service / solution manquante;Formulaire EQAAR - ADAMAD +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;AIDANT;Soutien psychologique;;Information - conseil - réorientation;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;AIDANT;Soutien psychologique;;Accompagnement dans la démarche;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;AIDANT;Aides aux aidants (association, nid des aidants …);;Information - conseil - réorientation;Refus de l'usager ou famille;Formulaire Parcours +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;AIDANT;Aides aux aidants (association, nid des aidants …);;Accompagnement dans la démarche;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;PROTECTION JURIDIQUE;Requête pour protection juridique;;Information - conseil - réorientation;;Rapport d'évaluation signalement personne vulnérable +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;PROTECTION JURIDIQUE;Requête pour protection juridique;;Accompagnement dans la démarche;;URL sur Grille d'aide à l'évaluation d'une situation de vulnérabilité +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;PROTECTION JURIDIQUE;Requête pour protection juridique;;Accompagnement dans la démarche;;https://www.service-public.fr/simulateur/calcul/15891 +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;PROTECTION JURIDIQUE;Signalement au procureur;;;;Rapport d'évaluation signalement personne vulnérable +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;PROTECTION JURIDIQUE;Signalement au procureur;;;;URL sur Grille d'aide à l'évaluation d'une situation de vulnérabilité +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;PROTECTION JURIDIQUE;Signalement au procureur;;;;Courrier accompagnement signalement au procureur +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Famille d'accueil;;Information - conseil - orientation;Refus de l'usager ou famille;https://trajectoire.sante-ra.fr/Trajectoire/ +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Famille d'accueil;;Information - conseil - orientation;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Famille d'accueil;;Accompagnement dans la démarche;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Famille d'accueil;;Accompagnement dans la démarche;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Hebergement Permanent Médicalisé;;Information - conseil - orientation;Refus de l'usager ou famille;https://trajectoire.sante-ra.fr/Trajectoire/ +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Hebergement Permanent Médicalisé;;Information - conseil - orientation;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Hebergement Permanent Médicalisé;;Accompagnement dans la démarche;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Hebergement Permanent Médicalisé;;Accompagnement dans la démarche;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Hébergement temporaire Médicalisé;;Information - conseil - orientation;Refus de l'usager ou famille;https://trajectoire.sante-ra.fr/Trajectoire/ +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Hébergement temporaire Médicalisé;;Information - conseil - orientation;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Hébergement temporaire Médicalisé;;Accompagnement dans la démarche;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Hébergement temporaire Médicalisé;;Accompagnement dans la démarche;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Hébergement Spécialisé Médicalisé;;Information - conseil - orientation;Refus de l'usager ou famille;https://trajectoire.sante-ra.fr/Trajectoire/ +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Hébergement Spécialisé Médicalisé;;Information - conseil - orientation;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Hébergement Spécialisé Médicalisé;;Accompagnement dans la démarche;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Hébergement Spécialisé Médicalisé;;Accompagnement dans la démarche;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Structure non médicalisé Temporaire;;Information - conseil - orientation;Refus de l'usager ou famille;https://trajectoire.sante-ra.fr/Trajectoire/ +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Structure non médicalisé Temporaire;;Information - conseil - orientation;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Structure non médicalisé Temporaire;;Accompagnement dans la démarche;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Structure non médicalisé Temporaire;;Accompagnement dans la démarche;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Structure non médicalisé (Résidence autonomie…);;Information - conseil - orientation;Refus de l'usager ou famille;https://trajectoire.sante-ra.fr/Trajectoire/ +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Structure non médicalisé (Résidence autonomie…);;Information - conseil - orientation;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Structure non médicalisé (Résidence autonomie…);;Accompagnement dans la démarche;Refus de l'usager ou famille; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Structure non médicalisé (Résidence autonomie…);;Accompagnement dans la démarche;Refus du service / solution manquante; +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Via trajectoire;;Information - conseil - orientation;;https://trajectoire.sante-ra.fr/Trajectoire/ +PROBLEMATIQUES LIEES AU VIEILLISSEMENT;STRUCTURE D'ACCUEIL;Via trajectoire;;Accompagnement dans les démarches;; +PROBLEMATIQUE DEV PARENT;PROBLEMATIQUE DEV ENFANT;ACTION DEV PARENT;;;; +PROBLEMATIQUE DEV PARENT;PROBLEMATIQUE DEV ENFANT;ACTION DEV PARENT;ACTION DEV ENFANT;Objectif dev;Résultat dev 1;Evaluation dev +PROBLEMATIQUE DEV PARENT;ACTION DEV ENFANT;ACTION DEV PARENT;ACTION DEV ENFANT;Objectif dev;Résultat dev 2;Evaluation dev 2 +PROBLEMATIQUE DEV PARENT;ACTION DEV ENFANT;ACTION DEV PARENT;ACTION DEV ENFANT;Objectif dev 2;Résultat dev 3; +PROBLEMATIQUE DEV PARENT;ACTION DEV ENFANT;ACTION DEV PARENT;ACTION DEV ENFANT;Objectif dev 2;Résultat dev 4; +PROBLEMATIQUE DEV PARENT;ACTION DEV ENFANT;ACTION DEV PARENT;ACTION DEV ENFANT;;Résultat dev sans objectif 1; +PROBLEMATIQUE DEV PARENT;ACTION DEV ENFANT;ACTION DEV PARENT;ACTION DEV ENFANT;;Résultat dev sans objectif 1; diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php index 1e4d5022f..000720a7f 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php @@ -23,6 +23,7 @@ use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; use Symfony\Component\DependencyInjection\Loader; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\DependencyInjection\Extension; + use function array_key_exists; /** @@ -79,6 +80,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac $loader->load('services/serializer.yaml'); $loader->load('services/security.yaml'); $loader->load('services/doctrineEventListener.yaml'); + $loader->load('services/accompanyingPeriodConsistency.yaml'); if ($container->getParameter('chill_person.accompanying_period') !== 'hidden') { $loader->load('services/exports_accompanying_period.yaml'); diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/CompilerPass/AccompanyingPeriodTimelineCompilerPass.php b/src/Bundle/ChillPersonBundle/DependencyInjection/CompilerPass/AccompanyingPeriodTimelineCompilerPass.php index c4f4dbdf3..31c04a59b 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/CompilerPass/AccompanyingPeriodTimelineCompilerPass.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/CompilerPass/AccompanyingPeriodTimelineCompilerPass.php @@ -13,6 +13,7 @@ namespace Chill\PersonBundle\DependencyInjection\CompilerPass; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; + use function in_array; /** diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php index d3e1b7f82..8a0cab301 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php @@ -80,6 +80,7 @@ class Configuration implements ConfigurationInterface ->append($this->addFieldNode('memo')) ->append($this->addFieldNode('number_of_children')) ->append($this->addFieldNode('acceptEmail')) + ->append($this->addFieldNode('deathdate')) ->arrayNode('alt_names') ->defaultValue([]) ->arrayPrototype() diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php index 13109cc98..9628da187 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php @@ -25,6 +25,7 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod\Comment; use Chill\PersonBundle\Entity\AccompanyingPeriod\Origin; use Chill\PersonBundle\Entity\AccompanyingPeriod\Resource; use Chill\PersonBundle\Entity\SocialWork\SocialIssue; +use Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\AccompanyingPeriodValidity; use Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\ParticipationOverlap; use Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\ResourceDuplicateCheck; use Chill\ThirdPartyBundle\Entity\ThirdParty; @@ -41,8 +42,10 @@ use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\GroupSequenceProviderInterface; use UnexpectedValueException; + use function count; use function in_array; + use const SORT_REGULAR; /** @@ -58,6 +61,8 @@ use const SORT_REGULAR; * "this.isConfidential and this.getUser === NULL", * message="If the accompanying course is confirmed and confidential, a referrer must remain assigned." * ) + * + * @AccompanyingPeriodValidity(groups={AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED}) */ class AccompanyingPeriod implements GroupSequenceProviderInterface, @@ -117,11 +122,11 @@ class AccompanyingPeriod implements * @var DateTime * * @ORM\Column(type="date", nullable=true) - * @Groups({"read", "write"}) + * @Groups({"read", "write", "docgen:read"}) * @Assert\NotBlank(groups={AccompanyingPeriod::STEP_CLOSED}) * @Assert\GreaterThan(propertyPath="openingDate", groups={AccompanyingPeriod::STEP_CLOSED}) */ - private $closingDate; + private ?DateTime $closingDate = null; /** * @var AccompanyingPeriod\ClosingMotive @@ -132,11 +137,9 @@ class AccompanyingPeriod implements * @Groups({"read", "write"}) * @Assert\NotBlank(groups={AccompanyingPeriod::STEP_CLOSED}) */ - private $closingMotive; + private ?ClosingMotive $closingMotive = null; /** - * @var Collection - * * @ORM\OneToMany(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\Comment", * mappedBy="accompanyingPeriod", * cascade={"persist", "remove"}, @@ -144,51 +147,40 @@ class AccompanyingPeriod implements * ) * @Assert\NotBlank(groups={AccompanyingPeriod::STEP_DRAFT}) */ - private $comments; + private Collection $comments; /** - * @var bool * @ORM\Column(type="boolean", options={"default": false}) - * @Groups({"read", "write"}) + * @Groups({"read", "write", "docgen:read"}) */ - private $confidential = false; + private bool $confidential = false; /** * @ORM\Column(type="datetime", nullable=true, options={"default": NULL}) + * @Groups({"docgen:read"}) */ - private DateTimeInterface $createdAt; + private ?DateTimeInterface $createdAt = null; /** * @ORM\ManyToOne(targetEntity=User::class) * @ORM\JoinColumn(nullable=true) - * @Groups({"read"}) + * @Groups({"read", "docgen:read"}) */ - private $createdBy; + private ?User $createdBy = null; /** - * @var bool * @ORM\Column(type="boolean", options={"default": false}) - * @Groups({"read", "write"}) + * @Groups({"read", "write", "docgen:read"}) */ - private $emergency = false; + private bool $emergency = false; /** - * @var int - * * @ORM\Id * @ORM\Column(name="id", type="integer") * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"read"}) + * @Groups({"read", "docgen:read"}) */ - private $id; - - /** - * @ORM\ManyToOne( - * targetEntity=Comment::class - * ) - * @Groups({"read"}) - */ - private ?Comment $initialComment = null; + private ?int $id = null; /** * @var string @@ -202,9 +194,9 @@ class AccompanyingPeriod implements * @var DateTime * * @ORM\Column(type="date") - * @Groups({"read", "write"}) + * @Groups({"read", "write", "docgen:read"}) */ - private $openingDate; + private ?DateTime $openingDate = null; /** * @ORM\ManyToOne(targetEntity=Origin::class) @@ -212,18 +204,16 @@ class AccompanyingPeriod implements * @Groups({"read", "write"}) * @Assert\NotBlank(groups={AccompanyingPeriod::STEP_CONFIRMED}) */ - private $origin; + private ?Origin $origin = null; /** - * @var Collection - * * @ORM\OneToMany(targetEntity=AccompanyingPeriodParticipation::class, * mappedBy="accompanyingPeriod", orphanRemoval=true, * cascade={"persist", "refresh", "remove", "merge", "detach"}) - * @Groups({"read"}) + * @Groups({"read", "docgen:read"}) * @ParticipationOverlap(groups={AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED}) */ - private $participations; + private Collection $participations; /** * @ORM\ManyToOne( @@ -234,48 +224,50 @@ class AccompanyingPeriod implements private ?Person $personLocation = null; /** - * @var string - * + * @ORM\ManyToOne( + * targetEntity=Comment::class + * ) + * @Groups({"read"}) + */ + private ?Comment $pinnedComment = null; + + /** * @ORM\Column(type="text") * @Groups({"read", "write"}) */ - private $remark = ''; + private string $remark = ''; /** - * @var bool * @ORM\Column(type="boolean", options={"default": false}) - * @Groups({"read", "write"}) + * @Groups({"read", "write", "docgen:read"}) */ - private $requestorAnonymous = false; + private bool $requestorAnonymous = false; /** * @ORM\ManyToOne(targetEntity=Person::class, inversedBy="accompanyingPeriodRequested") * @ORM\JoinColumn(nullable=true) */ - private $requestorPerson; + private ?Person $requestorPerson = null; /** * @ORM\ManyToOne(targetEntity=ThirdParty::class) * @ORM\JoinColumn(nullable=true) */ - private $requestorThirdParty; + private ?ThirdParty $requestorThirdParty = null; /** - * @var Collection - * * @ORM\OneToMany( * targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\Resource", * mappedBy="accompanyingPeriod", * cascade={"persist", "remove"}, * orphanRemoval=true * ) - * @Groups({"read"}) + * @Groups({"read", "docgen:read"}) * @ResourceDuplicateCheck(groups={AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED, "Default", "default"}) */ - private $resources; + private Collection $resources; /** - * @var Collection * @ORM\ManyToMany( * targetEntity=Scope::class, * cascade={} @@ -285,10 +277,10 @@ class AccompanyingPeriod implements * joinColumns={@ORM\JoinColumn(name="accompanying_period_id", referencedColumnName="id")}, * inverseJoinColumns={@ORM\JoinColumn(name="scope_id", referencedColumnName="id")} * ) - * @Groups({"read"}) + * @Groups({"read", "docgen:read"}) * @Assert\Count(min=1, groups={AccompanyingPeriod::STEP_CONFIRMED}, minMessage="A course must be associated to at least one scope") */ - private $scopes; + private Collection $scopes; /** * @ORM\ManyToMany( @@ -297,36 +289,35 @@ class AccompanyingPeriod implements * @ORM\JoinTable( * name="chill_person_accompanying_period_social_issues" * ) - * @Groups({"read"}) + * @Groups({"read", "docgen:read"}) * @Assert\Count(min=1, groups={AccompanyingPeriod::STEP_CONFIRMED}, minMessage="A course must contains at least one social issue") */ private Collection $socialIssues; /** - * @var string * @ORM\Column(type="string", length=32, nullable=true) * @Groups({"read"}) */ - private $step = self::STEP_DRAFT; + private string $step = self::STEP_DRAFT; /** * @ORM\Column(type="datetime", nullable=true, options={"default": NULL}) */ - private DateTimeInterface $updatedAt; + private ?DateTimeInterface $updatedAt = null; /** * @ORM\ManyToOne( * targetEntity=User::class * ) */ - private User $updatedBy; + private ?User $updatedBy = null; /** * @ORM\ManyToOne(targetEntity=User::class) * @ORM\JoinColumn(nullable=true) - * @Groups({"read", "write"}) + * @Groups({"read", "write", "docgen:read"}) */ - private $user; + private ?User $user = null; /** * @ORM\OneToMany( @@ -352,6 +343,7 @@ class AccompanyingPeriod implements $this->socialIssues = new ArrayCollection(); $this->comments = new ArrayCollection(); $this->works = new ArrayCollection(); + $this->resources = new ArrayCollection(); } /** @@ -483,7 +475,7 @@ class AccompanyingPeriod implements $participation = $this->getOpenParticipationContainsPerson($person); if ($participation instanceof AccompanyingPeriodParticipation) { - $participation->setEndDate(new DateTimeImmutable('now')); + $participation->setEndDate(new DateTime('now')); } return $participation; @@ -543,8 +535,10 @@ class AccompanyingPeriod implements public function getCenters(): ?iterable { foreach ($this->getPersons() as $person) { - if (!in_array($person->getCenter(), $centers ?? [], true) - && null !== $person->getCenter()) { + if ( + !in_array($person->getCenter(), $centers ?? [], true) + && null !== $person->getCenter() + ) { $centers[] = $person->getCenter(); } } @@ -573,15 +567,23 @@ class AccompanyingPeriod implements public function getComments(): Collection { return $this->comments->filter(function (Comment $c) { - return $c !== $this->initialComment; + return $c !== $this->pinnedComment; }); } + public function getCreatedAt(): ?DateTime + { + return $this->createdAt; + } + public function getCreatedBy(): ?User { return $this->createdBy; } + /** + * @Groups({"docgen:read"}) + */ public function getCurrentParticipations(): Collection { return $this->getOpenParticipations(); @@ -600,24 +602,11 @@ class AccompanyingPeriod implements throw new LogicException('no validation group permitted with this step'); } - /** - * Get id. - * - * @return int - */ - public function getId() + public function getId(): ?int { return $this->id; } - /** - * @Groups({"read"}) - */ - public function getInitialComment(): ?Comment - { - return $this->initialComment; - } - public function getIntensity(): ?string { return $this->intensity; @@ -631,7 +620,7 @@ class AccompanyingPeriod implements public function getLocation(?DateTimeImmutable $at = null): ?Address { if ($this->getPersonLocation() instanceof Person) { - return $this->getPersonLocation()->getCurrentHouseholdAddress($at); + return $this->getPersonLocation()->getCurrentPersonAddress(); } return $this->getAddressLocation(); @@ -660,7 +649,7 @@ class AccompanyingPeriod implements * * @return DateTime */ - public function getOpeningDate() + public function getOpeningDate(): ?DateTime { return $this->openingDate; } @@ -745,6 +734,14 @@ class AccompanyingPeriod implements ); } + /** + * @Groups({"read"}) + */ + public function getPinnedComment(): ?Comment + { + return $this->pinnedComment; + } + /** * @return Collection|SocialAction[] All the descendant social actions of all * the descendants of the entity @@ -796,6 +793,22 @@ class AccompanyingPeriod implements return $this->requestorPerson ?? $this->requestorThirdParty; } + /** + * @return string 'person' if requestor is an instanceof @see{Person::class}, 'thirdparty' if this is an instanceof @see{ThirdParty::class}, or 'none' + */ + public function getRequestorKind(): string + { + if ($this->getRequestor() instanceof ThirdParty) { + return 'thirdparty'; + } + + if ($this->getRequestor() instanceof Person) { + return 'person'; + } + + return 'none'; + } + public function getRequestorPerson(): ?Person { return $this->requestorPerson; @@ -1018,24 +1031,6 @@ class AccompanyingPeriod implements return $this; } - /** - * @Groups({"write"}) - */ - public function setInitialComment(?Comment $comment = null): self - { - if (null !== $this->initialComment) { - $this->removeComment($this->initialComment); - } - - if ($comment instanceof Comment) { - $this->addComment($comment); - } - - $this->initialComment = $comment; - - return $this; - } - public function setIntensity(string $intensity): self { $this->intensity = $intensity; @@ -1074,6 +1069,24 @@ class AccompanyingPeriod implements return $this; } + /** + * @Groups({"write"}) + */ + public function setPinnedComment(?Comment $comment = null): self + { + if (null !== $this->pinnedComment) { + $this->removeComment($this->pinnedComment); + } + + if ($comment instanceof Comment) { + $this->addComment($comment); + } + + $this->pinnedComment = $comment; + + return $this; + } + public function setRemark(?string $remark = null): self { $this->remark = (string) $remark; diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php index 2d0bfe918..97424c2e3 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php @@ -14,10 +14,12 @@ namespace Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\MainBundle\Doctrine\Model\TrackCreationInterface; use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface; use Chill\MainBundle\Entity\User; +use Chill\PersonBundle\AccompanyingPeriod\SocialIssueConsistency\AccompanyingPeriodLinkedWithSocialIssuesEntityInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\SocialWork\Result; use Chill\PersonBundle\Entity\SocialWork\SocialAction; +use Chill\PersonBundle\Entity\SocialWork\SocialIssue; use Chill\ThirdPartyBundle\Entity\ThirdParty; use DateTimeImmutable; use DateTimeInterface; @@ -28,456 +30,472 @@ use LogicException; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Assert; - /** - * @ORM\Entity - * @ORM\Table(name="chill_person_accompanying_period_work") - * @Serializer\DiscriminatorMap( - * typeProperty="type", - * mapping={ - * "accompanying_period_work": AccompanyingPeriodWork::class - * } - * ) - */ - class AccompanyingPeriodWork implements TrackCreationInterface, TrackUpdateInterface - { - /** - * @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class) - * @Serializer\Groups({"read"}) - */ - private ?AccompanyingPeriod $accompanyingPeriod = null; - - /** - * @ORM\OneToMany( - * targetEntity=AccompanyingPeriodWorkEvaluation::class, - * mappedBy="accompanyingPeriodWork", - * cascade={"remove", "persist"}, - * orphanRemoval=true - * ) - * @Serializer\Groups({"read"}) - * - * @internal /!\ the serialization for write evaluations is handled in `AccompanyingPeriodWorkDenormalizer` - */ - private Collection $accompanyingPeriodWorkEvaluations; - - /** - * @ORM\Column(type="datetime_immutable") - * @Serializer\Groups({"read"}) - */ - private ?DateTimeImmutable $createdAt = null; - - /** - * @ORM\Column(type="boolean") - */ - private bool $createdAutomatically = false; - - /** - * @ORM\Column(type="text") - */ - private string $createdAutomaticallyReason = ''; - - /** - * @ORM\ManyToOne(targetEntity=User::class) - * @ORM\JoinColumn(nullable=false) - * @Serializer\Groups({"read"}) - */ - private ?User $createdBy = null; - - /** - * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * @Serializer\Groups({"accompanying_period_work:create"}) - * @Serializer\Groups({"accompanying_period_work:edit"}) - * @Serializer\Groups({"read"}) - * @Assert\GreaterThan(propertyPath="startDate", - * message="accompanying_course_work.The endDate should be greater than the start date" - * ) - */ - private ?DateTimeImmutable $endDate = null; - - /** - * @ORM\OneToMany( - * targetEntity=AccompanyingPeriodWorkGoal::class, - * mappedBy="accompanyingPeriodWork", - * cascade={"persist"}, - * orphanRemoval=true - * ) - * @Serializer\Groups({"read"}) - * @Serializer\Groups({"accompanying_period_work:edit"}) - */ - private Collection $goals; - - /** - * @ORM\ManyToOne(targetEntity=ThirdParty::class) - * @Serializer\Groups({"read"}) - * @Serializer\Groups({"accompanying_period_work:edit"}) - * - * In schema : traitant - */ - private ?ThirdParty $handlingThierParty = null; - - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - * @Serializer\Groups({"read"}) - */ - private ?int $id; - - /** - * @ORM\Column(type="text") - * @Serializer\Groups({"read", "accompanying_period_work:edit"}) - */ - private string $note = ''; - - /** - * @ORM\ManyToMany(targetEntity=Person::class) - * @ORM\JoinTable(name="chill_person_accompanying_period_work_person") - * @Serializer\Groups({"read"}) - * @Serializer\Groups({"accompanying_period_work:edit"}) - * @Serializer\Groups({"accompanying_period_work:create"}) - */ - private Collection $persons; - - /** - * @ORM\ManyToMany(targetEntity=Result::class, inversedBy="accompanyingPeriodWorks") - * @ORM\JoinTable(name="chill_person_accompanying_period_work_result") - * @Serializer\Groups({"read"}) - * @Serializer\Groups({"accompanying_period_work:edit"}) - */ - private Collection $results; - - /** - * @ORM\ManyToOne(targetEntity=SocialAction::class) - * @Serializer\Groups({"read"}) - * @Serializer\Groups({"accompanying_period_work:create"}) - */ - private ?SocialAction $socialAction = null; - - /** - * @ORM\Column(type="date_immutable") - * @Serializer\Groups({"accompanying_period_work:create"}) - * @Serializer\Groups({"accompanying_period_work:edit"}) - * @Serializer\Groups({"read"}) - */ - private DateTimeImmutable $startDate; - - /** - * @ORM\ManyToMany(targetEntity=ThirdParty::class) - * @ORM\JoinTable(name="chill_person_accompanying_period_work_third_party") - * - * In schema : intervenants - * @Serializer\Groups({"read"}) - * @Serializer\Groups({"accompanying_period_work:edit"}) - */ - private Collection $thirdParties; - - /** - * @ORM\Column(type="datetime_immutable") - * @Serializer\Groups({"read"}) - */ - private ?DateTimeImmutable $updatedAt = null; - - /** - * @ORM\ManyToOne(targetEntity=User::class) - * @ORM\JoinColumn(nullable=false) - * @Serializer\Groups({"read"}) - */ - private ?User $updatedBy = null; - - public function __construct() - { - $this->goals = new ArrayCollection(); - $this->results = new ArrayCollection(); - $this->thirdParties = new ArrayCollection(); - $this->persons = new ArrayCollection(); - $this->accompanyingPeriodWorkEvaluations = new ArrayCollection(); - } - - public function addAccompanyingPeriodWorkEvaluation(AccompanyingPeriodWorkEvaluation $evaluation): self - { - if (!$this->accompanyingPeriodWorkEvaluations->contains($evaluation)) { - $this->accompanyingPeriodWorkEvaluations[] = $evaluation; - $evaluation->setAccompanyingPeriodWork($this); - } - - return $this; - } - - public function addGoal(AccompanyingPeriodWorkGoal $goal): self - { - if (!$this->goals->contains($goal)) { - $this->goals[] = $goal; - $goal->setAccompanyingPeriodWork($this); - } - - return $this; - } - - public function addPerson(Person $person): self - { - if (!$this->persons->contains($person)) { - $this->persons[] = $person; - } - - return $this; - } - - public function addResult(Result $result): self - { - if (!$this->results->contains($result)) { - $this->results[] = $result; - } - - return $this; - } - - public function addThirdParty(ThirdParty $thirdParty): self - { - if (!$this->thirdParties->contains($thirdParty)) { - $this->thirdParties[] = $thirdParty; - } - - return $this; - } - - public function getAccompanyingPeriod(): ?AccompanyingPeriod - { - return $this->accompanyingPeriod; - } - - /** - * @return Collection - */ - public function getAccompanyingPeriodWorkEvaluations() - { - return $this->accompanyingPeriodWorkEvaluations; - } - - public function getCreatedAt(): ?DateTimeImmutable - { - return $this->createdAt; - } - - public function getCreatedAutomatically(): ?bool - { - return $this->createdAutomatically; - } - - public function getCreatedAutomaticallyReason(): ?string - { - return $this->createdAutomaticallyReason; - } - - public function getCreatedBy(): ?User - { - return $this->createdBy; - } - - public function getEndDate(): ?DateTimeInterface - { - return $this->endDate; - } - - /** - * @return AccompanyingPeriodWorkGoal[]|Collection - */ - public function getGoals(): Collection - { - return $this->goals; - } - - public function getHandlingThierParty(): ?ThirdParty - { - return $this->handlingThierParty; - } - - public function getId(): ?int - { - return $this->id; - } - - public function getNote(): ?string - { - return $this->note; - } - - public function getPersons(): Collection - { - return $this->persons; - } - - /** - * @return Collection|Result[] - */ - public function getResults(): Collection - { - return $this->results; - } - - public function getSocialAction(): ?SocialAction - { - return $this->socialAction; - } - - public function getStartDate(): ?DateTimeInterface - { - return $this->startDate; - } - - /** - * @return Collection|ThirdParty[] - */ - public function getThirdParties(): Collection - { - return $this->thirdParties; - } - - public function getThirdPartys(): Collection - { - return $this->getThirdParties(); - } - - public function getUpdatedAt(): ?DateTimeImmutable - { - return $this->updatedAt; - } - - public function getUpdatedBy(): ?User - { - return $this->updatedBy; - } - - public function removeAccompanyingPeriodWorkEvaluation(AccompanyingPeriodWorkEvaluation $evaluation): self - { - $this->accompanyingPeriodWorkEvaluations - ->removeElement($evaluation); - $evaluation->setAccompanyingPeriodWork(null); - - return $this; - } - - public function removeGoal(AccompanyingPeriodWorkGoal $goal): self - { - if ($this->goals->removeElement($goal)) { - // set the owning side to null (unless already changed) - if ($goal->getAccompanyingPeriodWork() === $this) { - $goal->setAccompanyingPeriodWork(null); - } - } - - return $this; - } - - public function removePerson(Person $person): self - { - $this->persons->removeElement($person); - - return $this; - } - - public function removeResult(Result $result): self - { - $this->results->removeElement($result); - - return $this; - } - - public function removeThirdParty(ThirdParty $thirdParty): self - { - $this->thirdParties->removeElement($thirdParty); - - return $this; - } - - /** - * Internal: you should use `$accompanyingPeriod->removeWork($work);` or - * `$accompanyingPeriod->addWork($work);`. - */ - public function setAccompanyingPeriod(?AccompanyingPeriod $accompanyingPeriod): self - { - if ($this->accompanyingPeriod instanceof AccompanyingPeriod - && $accompanyingPeriod !== $this->accompanyingPeriod) { - throw new LogicException('A work cannot change accompanyingPeriod'); - } - - $this->accompanyingPeriod = $accompanyingPeriod; - - return $this; - } - - public function setCreatedAt(DateTimeInterface $createdAt): self - { - $this->createdAt = $createdAt; - - return $this; - } - - public function setCreatedAutomatically(bool $createdAutomatically): self - { - $this->createdAutomatically = $createdAutomatically; - - return $this; - } - - public function setCreatedAutomaticallyReason(string $createdAutomaticallyReason): self - { - $this->createdAutomaticallyReason = $createdAutomaticallyReason; - - return $this; - } - - public function setCreatedBy(?User $createdBy): self - { - $this->createdBy = $createdBy; +/** + * @ORM\Entity + * @ORM\Table(name="chill_person_accompanying_period_work") + * @Serializer\DiscriminatorMap( + * typeProperty="type", + * mapping={ + * "accompanying_period_work": AccompanyingPeriodWork::class + * } + * ) + */ +class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterface, TrackCreationInterface, TrackUpdateInterface +{ + /** + * @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class) + * @Serializer\Groups({"read"}) + */ + private ?AccompanyingPeriod $accompanyingPeriod = null; + + /** + * @ORM\OneToMany( + * targetEntity=AccompanyingPeriodWorkEvaluation::class, + * mappedBy="accompanyingPeriodWork", + * cascade={"remove", "persist"}, + * orphanRemoval=true + * ) + * @Serializer\Groups({"read", "docgen:read"}) + * + * @internal /!\ the serialization for write evaluations is handled in `AccompanyingPeriodWorkDenormalizer` + */ + private Collection $accompanyingPeriodWorkEvaluations; + + /** + * @ORM\Column(type="datetime_immutable") + * @Serializer\Groups({"read", "docgen:read"}) + */ + private ?DateTimeImmutable $createdAt = null; + + /** + * @ORM\Column(type="boolean") + * @Serializer\Groups({"read", "docgen:read"}) + */ + private bool $createdAutomatically = false; + + /** + * @ORM\Column(type="text") + * @Serializer\Groups({"read", "docgen:read"}) + */ + private string $createdAutomaticallyReason = ''; + + /** + * @ORM\ManyToOne(targetEntity=User::class) + * @ORM\JoinColumn(nullable=false) + * @Serializer\Groups({"read", "docgen:read"}) + */ + private ?User $createdBy = null; + + /** + * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) + * @Serializer\Groups({"accompanying_period_work:create"}) + * @Serializer\Groups({"accompanying_period_work:edit"}) + * @Serializer\Groups({"read", "docgen:read"}) + * @Assert\GreaterThan(propertyPath="startDate", + * message="accompanying_course_work.The endDate should be greater than the start date" + * ) + */ + private ?DateTimeImmutable $endDate = null; + + /** + * @ORM\OneToMany( + * targetEntity=AccompanyingPeriodWorkGoal::class, + * mappedBy="accompanyingPeriodWork", + * cascade={"persist"}, + * orphanRemoval=true + * ) + * @Serializer\Groups({"read", "docgen:read"}) + * @Serializer\Groups({"accompanying_period_work:edit"}) + */ + private Collection $goals; + + /** + * @ORM\ManyToOne(targetEntity=ThirdParty::class) + * @Serializer\Groups({"read", "docgen:read"}) + * @Serializer\Groups({"accompanying_period_work:edit"}) + * + * In schema : traitant + */ + private ?ThirdParty $handlingThierParty = null; + + /** + * @ORM\Id + * @ORM\GeneratedValue + * @ORM\Column(type="integer") + * @Serializer\Groups({"read", "docgen:read"}) + */ + private ?int $id = null; + + /** + * @ORM\Column(type="text") + * @Serializer\Groups({"read", "accompanying_period_work:edit", "docgen:read"}) + */ + private string $note = ''; + + /** + * @ORM\ManyToMany(targetEntity=Person::class) + * @ORM\JoinTable(name="chill_person_accompanying_period_work_person") + * @Serializer\Groups({"read", "docgen:read"}) + * @Serializer\Groups({"accompanying_period_work:edit"}) + * @Serializer\Groups({"accompanying_period_work:create"}) + */ + private Collection $persons; + + /** + * @ORM\ManyToMany(targetEntity=Result::class, inversedBy="accompanyingPeriodWorks") + * @ORM\JoinTable(name="chill_person_accompanying_period_work_result") + * @Serializer\Groups({"read", "docgen:read"}) + * @Serializer\Groups({"accompanying_period_work:edit"}) + */ + private Collection $results; + + /** + * @ORM\ManyToOne(targetEntity=SocialAction::class) + * @Serializer\Groups({"read", "docgen:read"}) + * @Serializer\Groups({"accompanying_period_work:create"}) + */ + private ?SocialAction $socialAction = null; + + /** + * @ORM\Column(type="date_immutable") + * @Serializer\Groups({"accompanying_period_work:create"}) + * @Serializer\Groups({"accompanying_period_work:edit"}) + * @Serializer\Groups({"read", "docgen:read"}) + */ + private ?DateTimeImmutable $startDate = null; + + /** + * @ORM\ManyToMany(targetEntity=ThirdParty::class) + * @ORM\JoinTable(name="chill_person_accompanying_period_work_third_party") + * + * In schema : intervenants + * @Serializer\Groups({"read", "docgen:read"}) + * @Serializer\Groups({"accompanying_period_work:edit"}) + */ + private Collection $thirdParties; + + /** + * @ORM\Column(type="datetime_immutable") + * @Serializer\Groups({"read", "docgen:read"}) + */ + private ?DateTimeImmutable $updatedAt = null; + + /** + * @ORM\ManyToOne(targetEntity=User::class) + * @ORM\JoinColumn(nullable=false) + * @Serializer\Groups({"read", "docgen:read"}) + */ + private ?User $updatedBy = null; + + public function __construct() + { + $this->goals = new ArrayCollection(); + $this->results = new ArrayCollection(); + $this->thirdParties = new ArrayCollection(); + $this->persons = new ArrayCollection(); + $this->accompanyingPeriodWorkEvaluations = new ArrayCollection(); + } + + public function addAccompanyingPeriodWorkEvaluation(AccompanyingPeriodWorkEvaluation $evaluation): self + { + if (!$this->accompanyingPeriodWorkEvaluations->contains($evaluation)) { + $this->accompanyingPeriodWorkEvaluations[] = $evaluation; + $evaluation->setAccompanyingPeriodWork($this); + } + + return $this; + } + + public function addGoal(AccompanyingPeriodWorkGoal $goal): self + { + if (!$this->goals->contains($goal)) { + $this->goals[] = $goal; + $goal->setAccompanyingPeriodWork($this); + } + + return $this; + } + + public function addPerson(Person $person): self + { + if (!$this->persons->contains($person)) { + $this->persons[] = $person; + } + + return $this; + } + + public function addResult(Result $result): self + { + if (!$this->results->contains($result)) { + $this->results[] = $result; + } + + return $this; + } + + public function addThirdParty(ThirdParty $thirdParty): self + { + if (!$this->thirdParties->contains($thirdParty)) { + $this->thirdParties[] = $thirdParty; + } + + return $this; + } + + public function getAccompanyingPeriod(): ?AccompanyingPeriod + { + return $this->accompanyingPeriod; + } + + /** + * @return Collection + */ + public function getAccompanyingPeriodWorkEvaluations() + { + return $this->accompanyingPeriodWorkEvaluations; + } + + public function getCreatedAt(): ?DateTimeImmutable + { + return $this->createdAt; + } + + public function getCreatedAutomatically(): ?bool + { + return $this->createdAutomatically; + } + + public function getCreatedAutomaticallyReason(): ?string + { + return $this->createdAutomaticallyReason; + } + + public function getCreatedBy(): ?User + { + return $this->createdBy; + } + + public function getEndDate(): ?DateTimeInterface + { + return $this->endDate; + } + + /** + * @return AccompanyingPeriodWorkGoal[]|Collection + */ + public function getGoals(): Collection + { + return $this->goals; + } + + public function getHandlingThierParty(): ?ThirdParty + { + return $this->handlingThierParty; + } + + public function getId(): ?int + { + return $this->id; + } + + public function getNote(): ?string + { + return $this->note; + } + + public function getPersons(): Collection + { + return $this->persons; + } + + /** + * @return Collection|Result[] + */ + public function getResults(): Collection + { + return $this->results; + } + + public function getSocialAction(): ?SocialAction + { + return $this->socialAction; + } + + public function getSocialIssues(): Collection + { + return new ArrayCollection([$this->getSocialAction()->getIssue()]); + } + + public function getStartDate(): ?DateTimeInterface + { + return $this->startDate; + } + + /** + * @return Collection|ThirdParty[] + */ + public function getThirdParties(): Collection + { + return $this->thirdParties; + } + + public function getThirdPartys(): Collection + { + return $this->getThirdParties(); + } + + public function getUpdatedAt(): ?DateTimeImmutable + { + return $this->updatedAt; + } + + public function getUpdatedBy(): ?User + { + return $this->updatedBy; + } + + public function removeAccompanyingPeriodWorkEvaluation(AccompanyingPeriodWorkEvaluation $evaluation): self + { + $this->accompanyingPeriodWorkEvaluations + ->removeElement($evaluation); + $evaluation->setAccompanyingPeriodWork(null); + + return $this; + } + + public function removeGoal(AccompanyingPeriodWorkGoal $goal): self + { + if ($this->goals->removeElement($goal)) { + // set the owning side to null (unless already changed) + if ($goal->getAccompanyingPeriodWork() === $this) { + $goal->setAccompanyingPeriodWork(null); + } + } + + return $this; + } + + public function removePerson(Person $person): self + { + $this->persons->removeElement($person); + + return $this; + } + + public function removeResult(Result $result): self + { + $this->results->removeElement($result); + + return $this; + } + + public function removeSocialIssue(SocialIssue $issue): AccompanyingPeriodLinkedWithSocialIssuesEntityInterface + { + $this->getSocialIssues()->removeElement($issue); + + return $this; + } + + public function removeThirdParty(ThirdParty $thirdParty): self + { + $this->thirdParties->removeElement($thirdParty); + + return $this; + } + + /** + * Internal: you should use `$accompanyingPeriod->removeWork($work);` or + * `$accompanyingPeriod->addWork($work);`. + */ + public function setAccompanyingPeriod(?AccompanyingPeriod $accompanyingPeriod): self + { + if ( + $this->accompanyingPeriod instanceof AccompanyingPeriod + && $accompanyingPeriod !== $this->accompanyingPeriod + ) { + throw new LogicException('A work cannot change accompanyingPeriod'); + } + + $this->accompanyingPeriod = $accompanyingPeriod; + + return $this; + } + + public function setCreatedAt(DateTimeInterface $createdAt): self + { + $this->createdAt = $createdAt; + + return $this; + } + + public function setCreatedAutomatically(bool $createdAutomatically): self + { + $this->createdAutomatically = $createdAutomatically; + + return $this; + } + + public function setCreatedAutomaticallyReason(string $createdAutomaticallyReason): self + { + $this->createdAutomaticallyReason = $createdAutomaticallyReason; - return $this; - } + return $this; + } - public function setEndDate(?DateTimeInterface $endDate = null): self - { - $this->endDate = $endDate; + public function setCreatedBy(?User $createdBy): self + { + $this->createdBy = $createdBy; - return $this; - } + return $this; + } - public function setHandlingThierParty(?ThirdParty $handlingThierParty): self - { - $this->handlingThierParty = $handlingThierParty; + public function setEndDate(?DateTimeInterface $endDate = null): self + { + $this->endDate = $endDate; - return $this; - } + return $this; + } - public function setNote(string $note): self - { - $this->note = $note; + public function setHandlingThierParty(?ThirdParty $handlingThierParty): self + { + $this->handlingThierParty = $handlingThierParty; - return $this; - } + return $this; + } - public function setSocialAction(?SocialAction $socialAction): self - { - $this->socialAction = $socialAction; + public function setNote(string $note): self + { + $this->note = $note; - return $this; - } + return $this; + } - public function setStartDate(DateTimeInterface $startDate): self - { - $this->startDate = $startDate; + public function setSocialAction(?SocialAction $socialAction): self + { + $this->socialAction = $socialAction; - return $this; - } + return $this; + } - public function setUpdatedAt(DateTimeInterface $datetime): TrackUpdateInterface - { - $this->updatedAt = $datetime; + public function setStartDate(DateTimeInterface $startDate): self + { + $this->startDate = $startDate; - return $this; - } + return $this; + } - public function setUpdatedBy(User $user): TrackUpdateInterface - { - $this->updatedBy = $user; + public function setUpdatedAt(DateTimeInterface $datetime): TrackUpdateInterface + { + $this->updatedAt = $datetime; - return $this; - } - } + return $this; + } + + public function setUpdatedBy(User $user): TrackUpdateInterface + { + $this->updatedBy = $user; + + return $this; + } +} diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php index cdcad98bd..f9fbc95f9 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php @@ -44,7 +44,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU /** * @ORM\Column(type="text", nullable=false, options={"default": ""}) - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) * @Serializer\Groups({"write"}) * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) */ @@ -52,7 +52,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU /** * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ private ?DateTimeImmutable $createdAt = null; @@ -60,7 +60,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU * @ORM\ManyToOne( * targetEntity=User::class * ) - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ private ?User $createdBy = null; @@ -76,7 +76,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU /** * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) * @Serializer\Groups({"write"}) * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) */ @@ -86,7 +86,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU * @ORM\ManyToOne( * targetEntity=Evaluation::class * ) - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) */ private ?Evaluation $evaluation = null; @@ -95,7 +95,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ private ?int $id = null; @@ -116,14 +116,14 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU /** * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) */ private ?DateTimeImmutable $maxDate = null; /** * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) * @Serializer\Groups({"write"}) * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) */ @@ -131,7 +131,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU /** * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ private ?DateTimeImmutable $updatedAt = null; @@ -139,7 +139,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU * @ORM\ManyToOne( * targetEntity=User::class * ) - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ private ?User $updatedBy = null; @@ -239,6 +239,18 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU return $this->updatedBy; } + /** + * @Serializer\Groups({"docgen:read"}) + */ + public function getWarningDate(): ?DateTimeImmutable + { + if (null === $this->getEndDate() || null === $this->getWarningInterval()) { + return null; + } + + return $this->getEndDate()->sub($this->getWarningInterval()); + } + public function getWarningInterval(): ?DateInterval { return $this->warningInterval; @@ -256,7 +268,8 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU if ( $accompanyingPeriodWork instanceof AccompanyingPeriodWork && $this->accompanyingPeriodWork instanceof AccompanyingPeriodWork - && $this->accompanyingPeriodWork->getId() !== $accompanyingPeriodWork->getId()) { + && $this->accompanyingPeriodWork->getId() !== $accompanyingPeriodWork->getId() + ) { throw new RuntimeException('Changing the ' . 'accompanyingPeriodWork is not allowed'); } diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocument.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocument.php index 538cffc36..cbb4231b8 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocument.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocument.php @@ -144,8 +144,10 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct { // if an evaluation is already associated, we cannot change the association (removing the association, // by setting a null value, is allowed. - if ($this->accompanyingPeriodWorkEvaluation instanceof AccompanyingPeriodWorkEvaluation - && $accompanyingPeriodWorkEvaluation instanceof AccompanyingPeriodWorkEvaluation) { + if ( + $this->accompanyingPeriodWorkEvaluation instanceof AccompanyingPeriodWorkEvaluation + && $accompanyingPeriodWorkEvaluation instanceof AccompanyingPeriodWorkEvaluation + ) { if ($this->accompanyingPeriodWorkEvaluation !== $accompanyingPeriodWorkEvaluation) { throw new RuntimeException('It is not allowed to change the evaluation for a document'); } diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkGoal.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkGoal.php index c31dfaa83..0c5517b71 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkGoal.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkGoal.php @@ -117,7 +117,8 @@ class AccompanyingPeriodWorkGoal public function setAccompanyingPeriodWork(?AccompanyingPeriodWork $accompanyingPeriodWork): self { - if ($this->accompanyingPeriodWork instanceof AccompanyingPeriodWork + if ( + $this->accompanyingPeriodWork instanceof AccompanyingPeriodWork && $accompanyingPeriodWork !== $this->accompanyingPeriodWork && null !== $accompanyingPeriodWork ) { diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/ClosingMotive.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/ClosingMotive.php index b7d4c00b1..aa12f0416 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/ClosingMotive.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/ClosingMotive.php @@ -14,6 +14,7 @@ namespace Chill\PersonBundle\Entity\AccompanyingPeriod; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation as Serializer; /** * ClosingMotive give an explanation why we closed the Accompanying period. @@ -24,22 +25,18 @@ use Doctrine\ORM\Mapping as ORM; class ClosingMotive { /** - * @var bool - * * @ORM\Column(type="boolean") */ - private $active = true; + private bool $active = true; /** * Child Accompanying periods. * - * @var Collection - * * @ORM\OneToMany( * targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive", * mappedBy="parent") */ - private $children; + private Collection $children; /** * @var int @@ -47,22 +44,21 @@ class ClosingMotive * @ORM\Id * @ORM\Column(name="id", type="integer") * @ORM\GeneratedValue(strategy="AUTO") + * @Serializer\Groups({"docgen:read"}) */ - private $id; + private ?int $id = null; /** - * @var array - * * @ORM\Column(type="json") + * @Serializer\Groups({"docgen:read"}) + * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) */ - private $name; + private array $name = []; /** - * @var float - * * @ORM\Column(type="float") */ - private $ordering = 0.0; + private float $ordering = 0.0; /** * @var self @@ -71,7 +67,7 @@ class ClosingMotive * targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive", * inversedBy="children") */ - private $parent; + private ?ClosingMotive $parent = null; /** * ClosingMotive constructor. diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php index 75d1b2857..105633e43 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php @@ -112,6 +112,11 @@ class Comment implements TrackCreationInterface, TrackUpdateInterface return $this->updatedBy; } + public function isPinned(): bool + { + return $this->getAccompanyingPeriod()->getPinnedComment() === $this; + } + public function setAccompanyingPeriod(?AccompanyingPeriod $accompanyingPeriod): self { $this->accompanyingPeriod = $accompanyingPeriod; diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Origin.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Origin.php index 7d35b8684..7a1114b3e 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Origin.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Origin.php @@ -31,28 +31,29 @@ class Origin * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") - * @Groups({"read"}) + * @Groups({"read", "docgen:read"}) */ - private $id; + private ?int $id = null; /** * @ORM\Column(type="json") - * @Groups({"read"}) + * @Groups({"read", "docgen:read"}) + * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) */ - private $label; + private array $label = []; /** * @ORM\Column(type="date_immutable", nullable=true) * @Groups({"read"}) */ - private $noActiveAfter; + private ?DateTimeImmutable $noActiveAfter = null; public function getId(): ?int { return $this->id; } - public function getLabel() + public function getLabel(): array { return $this->label; } @@ -62,7 +63,7 @@ class Origin return $this->noActiveAfter; } - public function setLabel(string $label): self + public function setLabel(array $label): self { $this->label = $label; diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php index ea20666fb..a11dc9b3d 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php @@ -41,11 +41,10 @@ class Resource * ) * @ORM\JoinColumn(nullable=false) */ - private $accompanyingPeriod; + private ?AccompanyingPeriod $accompanyingPeriod = null; /** * @ORM\ManyToOne(targetEntity=Comment::class) - * @ORM\JoinColumn(nullable=true) */ private $comment; @@ -53,21 +52,23 @@ class Resource * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") - * @Groups({"read"}) + * @Groups({"read", "docgen:read"}) */ - private $id; + private ?int $id = null; /** * @ORM\ManyToOne(targetEntity=Person::class) * @ORM\JoinColumn(nullable=true) + * @Groups({"docgen:read"}) */ - private $person; + private ?Person $person = null; /** * @ORM\ManyToOne(targetEntity=ThirdParty::class) * @ORM\JoinColumn(nullable=true) + * @Groups({"docgen:read"}) */ - private $thirdParty; + private ?ThirdParty $thirdParty = null; public function getAccompanyingPeriod(): ?AccompanyingPeriod { diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php index 3478b2631..42e57185e 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php @@ -11,7 +11,7 @@ declare(strict_types=1); namespace Chill\PersonBundle\Entity; -use DateTimeImmutable; +use DateTime; use DateTimeInterface; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\DiscriminatorMap; @@ -32,38 +32,38 @@ class AccompanyingPeriodParticipation * @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class, inversedBy="participations", cascade={"persist"}) * @ORM\JoinColumn(name="accompanyingperiod_id", referencedColumnName="id", nullable=false) */ - private $accompanyingPeriod; + private ?AccompanyingPeriod $accompanyingPeriod = null; /** * @ORM\Column(type="date", nullable=true) - * @Groups({"read"}) + * @Groups({"read", "docgen:read"}) */ - private $endDate; + private ?DateTime $endDate = null; /** * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") - * @Groups({"read"}) + * @Groups({"read", "docgen:read"}) */ - private $id; + private ?int $id = null; /** * @ORM\ManyToOne(targetEntity=Person::class, inversedBy="accompanyingPeriodParticipations") * @ORM\JoinColumn(name="person_id", referencedColumnName="id", nullable=false) - * @Groups({"read"}) + * @Groups({"read", "docgen:read"}) */ - private $person; + private ?Person $person = null; /** * @ORM\Column(type="date", nullable=false) - * @Groups({"read"}) + * @Groups({"read", "docgen:read"}) */ - private $startDate; + private ?DateTime $startDate = null; public function __construct(AccompanyingPeriod $accompanyingPeriod, Person $person) { - $this->startDate = new DateTimeImmutable('now'); + $this->startDate = new DateTime('now'); $this->accompanyingPeriod = $accompanyingPeriod; $this->person = $person; } @@ -73,10 +73,6 @@ class AccompanyingPeriodParticipation return $this->accompanyingPeriod; } - /* - * public function setStartDate(\DateTimeInterface $startDate): self { $this->startDate = $startDate; return $this; } - */ - public function getEndDate(): ?DateTimeInterface { return $this->endDate; @@ -109,7 +105,7 @@ class AccompanyingPeriodParticipation return $this; } - public function setEndDate(?DateTimeInterface $endDate): self + public function setEndDate(?DateTime $endDate): self { $this->endDate = $endDate; diff --git a/src/Bundle/ChillPersonBundle/Entity/Household/Household.php b/src/Bundle/ChillPersonBundle/Entity/Household/Household.php index c03644214..865526250 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Household/Household.php +++ b/src/Bundle/ChillPersonBundle/Entity/Household/Household.php @@ -24,6 +24,7 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Context\ExecutionContextInterface; + use function count; /** @@ -59,7 +60,7 @@ class Household * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ private ?int $id = null; @@ -68,17 +69,19 @@ class Household * targetEntity=HouseholdMember::class, * mappedBy="household" * ) - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ private Collection $members; /** * @ORM\Column(type="boolean", name="waiting_for_birth", options={"default": false}) + * @Serializer\Groups({"docgen:read"}) */ private bool $waitingForBirth = false; /** * @ORM\Column(type="date_immutable", name="waiting_for_birth_date", nullable=true, options={"default": null}) + * @Serializer\Groups({"docgen:read"}) */ private ?DateTimeImmutable $waitingForBirthDate = null; @@ -134,7 +137,7 @@ class Household } /** - * @Serializer\Groups({ "read" }) + * @Serializer\Groups({"read", "docgen:read"}) * @Serializer\SerializedName("current_address") */ public function getCurrentAddress(?DateTime $at = null): ?Address @@ -154,6 +157,9 @@ class Household return null; } + /** + * @Serializer\Groups({"docgen:read"}) + */ public function getCurrentMembers(?DateTimeImmutable $now = null): Collection { return $this->getMembers()->matching($this->buildCriteriaCurrentMembers($now)); @@ -249,7 +255,9 @@ class Household public function getCurrentPersons(?DateTimeImmutable $now = null): Collection { return $this->getCurrentMembers($now) - ->map(static function (HouseholdMember $m) { return $m->getPerson(); }); + ->map(static function (HouseholdMember $m) { + return $m->getPerson(); + }); } public function getId(): ?int diff --git a/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMember.php b/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMember.php index af3ead806..22c33f85f 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMember.php +++ b/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMember.php @@ -28,13 +28,13 @@ class HouseholdMember { /** * @ORM\Column(type="string", length=255, nullable=true) - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ private ?string $comment = null; /** * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) * @Assert\GreaterThan( * propertyPath="startDate", * message="household_membership.The end date must be after start date", @@ -45,7 +45,7 @@ class HouseholdMember /** * @ORM\Column(type="boolean", options={"default": false}) - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ private bool $holder = false; @@ -63,16 +63,17 @@ class HouseholdMember * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ - private $id; + private ?int $id = null; /** * @var Person * @ORM\ManyToOne( * targetEntity="\Chill\PersonBundle\Entity\Person" * ) - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) + * @Serializer\Context({"docgen:person:with-household": false}) * @Assert\Valid(groups={"household_memberships"}) * @Assert\NotNull(groups={"household_memberships"}) */ @@ -80,7 +81,7 @@ class HouseholdMember /** * @ORM\ManyToOne(targetEntity=Position::class) - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) * @Assert\NotNull(groups={"household_memberships_created"}) */ private ?Position $position = null; @@ -92,7 +93,7 @@ class HouseholdMember /** * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) * @Assert\NotNull(groups={"household_memberships"}) */ private ?DateTimeImmutable $startDate = null; diff --git a/src/Bundle/ChillPersonBundle/Entity/Household/Position.php b/src/Bundle/ChillPersonBundle/Entity/Household/Position.php index 721c35433..378bc0d9f 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Household/Position.php +++ b/src/Bundle/ChillPersonBundle/Entity/Household/Position.php @@ -33,25 +33,26 @@ class Position * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") - * @Serializer\Groups({ "read" }) + * @Serializer\Groups({"read", "docgen:read"}) */ - private ?int $id; + private ?int $id = null; /** * @ORM\Column(type="json") - * @Serializer\Groups({ "read" }) + * @Serializer\Groups({"read", "docgen:read"}) + * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) */ private array $label = []; /** * @ORM\Column(type="float") - * @Serializer\Groups({ "read" }) + * @Serializer\Groups({"read"}) */ private float $ordering = 0.00; /** * @ORM\Column(type="boolean") - * @Serializer\Groups({ "read" }) + * @Serializer\Groups({"read"}) */ private bool $shareHouseHold = true; diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php index f58cee747..73b83f246 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person.php @@ -62,9 +62,7 @@ use function in_array; * @DiscriminatorMap(typeProperty="type", mapping={ * "person": Person::class * }) - * @PersonHasCenter( - * groups={"general", "creation"} - * ) + * @PersonHasCenter * @HouseholdMembershipSequential( * groups={"household_memberships"} * ) @@ -153,12 +151,8 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @var DateTime * * @ORM\Column(type="date", nullable=true) - * @Assert\Date( - * groups={"general", "creation"} - * ) - * @Birthdate( - * groups={"general", "creation"} - * ) + * @Assert\Date + * @Birthdate */ private $birthdate; @@ -241,9 +235,9 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @var DateTimeImmutable * * @ORM\Column(type="date_immutable", nullable=true) - * @Assert\Date( - * groups={"general", "creation"} - * ) + * @Assert\Date + * @Assert\GreaterThanOrEqual(propertyPath="birthdate") + * @Assert\LessThanOrEqual("today") */ private ?DateTimeImmutable $deathdate = null; @@ -254,8 +248,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * * @ORM\Column(type="text", nullable=true) * @Assert\Email( - * checkMX=true, - * groups={"general", "creation"} + * checkMX=true * ) */ private $email = ''; @@ -266,12 +259,9 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @var string * * @ORM\Column(type="string", length=255) - * @Assert\NotBlank( - * groups={"general", "creation"} - * ) + * @Assert\NotBlank * @Assert\Length( * max=255, - * groups={"general", "creation"} * ) */ private $firstName; @@ -292,9 +282,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @var string * * @ORM\Column(type="string", length=9, nullable=true) - * @Assert\NotNull( - * groups={"general", "creation"} - * ) + * @Assert\NotNull */ private $gender; @@ -338,12 +326,9 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @var string * * @ORM\Column(type="string", length=255) - * @Assert\NotBlank( - * groups={"general", "creation"} - * ) + * @Assert\NotBlank * @Assert\Length( * max=255, - * groups={"general", "creation"} * ) */ private $lastName; @@ -371,9 +356,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @var DateTime * * @ORM\Column(type="date", nullable=true) - * @Assert\Date( - * groups={"general", "creation"} - * ) + * @Assert\Date */ private ?DateTime $maritalStatusDate = null; @@ -392,11 +375,9 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @ORM\Column(type="text") * @Assert\Regex( * pattern="/^([\+{1}])([0-9\s*]{4,20})$/", - * groups={"general", "creation"} * ) * @PhonenumberConstraint( * type="mobile", - * groups={"general", "creation"} * ) */ private string $mobilenumber = ''; @@ -434,7 +415,6 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * ) * @Assert\Valid( * traverse=true, - * groups={"general", "creation"} * ) */ private $otherPhoneNumbers; @@ -453,11 +433,9 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @ORM\Column(type="text") * @Assert\Regex( * pattern="/^([\+{1}])([0-9\s*]{4,20})$/", - * groups={"general", "creation"} * ) * @PhonenumberConstraint( * type="landline", - * groups={"general", "creation"} * ) */ private string $phonenumber = ''; @@ -588,8 +566,6 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI return $this; } - // a period opened and another one after it - /** * Function used for validation that check if the accompanying periods of * the person are not collapsing (i.e. have not shared days) or having @@ -1776,7 +1752,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI return $this; } - public function setNumberOfChildren(int $numberOfChildren): self + public function setNumberOfChildren(?int $numberOfChildren): self { $this->numberOfChildren = $numberOfChildren; diff --git a/src/Bundle/ChillPersonBundle/Entity/Relationships/Relation.php b/src/Bundle/ChillPersonBundle/Entity/Relationships/Relation.php index 3b7c75a06..c78e5df33 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Relationships/Relation.php +++ b/src/Bundle/ChillPersonBundle/Entity/Relationships/Relation.php @@ -41,12 +41,14 @@ class Relation /** * @ORM\Column(type="json", nullable=true) * @Serializer\Groups({"read"}) + * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) */ private array $reverseTitle = []; /** * @ORM\Column(type="json", nullable=true) * @Serializer\Groups({"read"}) + * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) */ private array $title = []; diff --git a/src/Bundle/ChillPersonBundle/Entity/Relationships/Relationship.php b/src/Bundle/ChillPersonBundle/Entity/Relationships/Relationship.php index 45cd546b0..d51881bb2 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Relationships/Relationship.php +++ b/src/Bundle/ChillPersonBundle/Entity/Relationships/Relationship.php @@ -19,6 +19,7 @@ use DateTimeImmutable; use DateTimeInterface; use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping\DiscriminatorColumn; +use RuntimeException; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Serializer\Annotation\DiscriminatorMap; use Symfony\Component\Validator\Constraints as Assert; @@ -116,6 +117,27 @@ class Relationship implements TrackCreationInterface, TrackUpdateInterface return $this->id; } + /** + * Return the opposite person of the @see{counterpart} person. + * + * this is the from person if the given is associated to the To, + * or the To person otherwise. + * + * @throw RuntimeException if the counterpart is neither in the from or to person + */ + public function getOpposite(Person $counterpart): Person + { + if ($this->fromPerson !== $counterpart && $this->toPerson !== $counterpart) { + throw new RuntimeException('the counterpart is neither the from nor to person for this relationship'); + } + + if ($this->fromPerson === $counterpart) { + return $this->toPerson; + } + + return $this->fromPerson; + } + public function getRelation(): ?Relation { return $this->relation; diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Evaluation.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Evaluation.php index 6b1d81700..1350ae6d8 100644 --- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Evaluation.php +++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Evaluation.php @@ -12,6 +12,8 @@ declare(strict_types=1); namespace Chill\PersonBundle\Entity\SocialWork; use DateInterval; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; @@ -28,35 +30,51 @@ class Evaluation * @ORM\Column(type="dateinterval", nullable=true, options={"default": null}) * @Serializer\Groups({"read"}) */ - private $delay; + private ?DateInterval $delay = null; /** * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ - private $id; + private ?int $id = null; /** * @ORM\Column(type="dateinterval", nullable=true, options={"default": null}) * @Serializer\Groups({"read"}) */ - private $notificationDelay; + private ?DateInterval $notificationDelay = null; /** - * @ORM\ManyToOne( + * @ORM\ManyToMany( * targetEntity=SocialAction::class, * inversedBy="evaluations" * ) + * @ORM\JoinTable(name="chill_person_social_work_evaluation_action") */ - private $socialAction; + private Collection $socialActions; /** * @ORM\Column(type="json") - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) + * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) */ - private $title = []; + private array $title = []; + + public function __construct() + { + $this->socialActions = new ArrayCollection(); + } + + public function addSocialAction(SocialAction $socialAction): self + { + if (!$this->socialActions->contains($socialAction)) { + $this->socialActions->add($socialAction); + } + + return $this; + } public function getDelay(): ?DateInterval { @@ -73,9 +91,9 @@ class Evaluation return $this->notificationDelay; } - public function getSocialAction(): ?SocialAction + public function getSocialActions(): Collection { - return $this->socialAction; + return $this->socialActions; } public function getTitle(): array @@ -83,6 +101,15 @@ class Evaluation return $this->title; } + public function removeSocialAction(SocialAction $socialAction): self + { + if ($this->socialActions->contains($socialAction)) { + $this->socialActions->remove($socialAction); + } + + return $this; + } + public function setDelay(DateInterval $delay): self { $this->delay = $delay; @@ -97,13 +124,6 @@ class Evaluation return $this; } - public function setSocialAction(?SocialAction $socialAction): self - { - $this->socialAction = $socialAction; - - return $this; - } - public function setTitle(array $title): self { $this->title = $title; diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Goal.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Goal.php index 9c02a129d..30abaa3ef 100644 --- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Goal.php +++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Goal.php @@ -38,26 +38,27 @@ class Goal * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ - private $id; + private ?int $id = null; /** * @ORM\ManyToMany(targetEntity=Result::class, inversedBy="goals") * @ORM\JoinTable(name="chill_person_social_work_goal_result") */ - private $results; + private Collection $results; /** * @ORM\ManyToMany(targetEntity=SocialAction::class, mappedBy="goals") */ - private $socialActions; + private Collection $socialActions; /** * @ORM\Column(type="json") - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) + * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) */ - private $title = []; + private array $title = []; public function __construct() { diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Result.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Result.php index b2894d210..b4a9b6aa2 100644 --- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Result.php +++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Result.php @@ -13,6 +13,7 @@ namespace Chill\PersonBundle\Entity\SocialWork; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkGoal; +use DateTime; use DateTimeInterface; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -34,41 +35,42 @@ class Result /** * @ORM\ManyToMany(targetEntity=AccompanyingPeriodWorkGoal::class, mappedBy="results") */ - private $accompanyingPeriodWorkGoals; + private Collection $accompanyingPeriodWorkGoals; /** * @ORM\ManyToMany(targetEntity=AccompanyingPeriodWork::class, mappedBy="results") */ - private $accompanyingPeriodWorks; + private Collection $accompanyingPeriodWorks; /** * @ORM\Column(type="datetime", nullable=true) */ - private $desactivationDate; + private DateTime $desactivationDate; /** * @ORM\ManyToMany(targetEntity=Goal::class, mappedBy="results") */ - private $goals; + private Collection $goals; /** * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) */ - private $id; + private ?int $id = null; /** * @ORM\ManyToMany(targetEntity=SocialAction::class, mappedBy="results") */ - private $socialActions; + private Collection $socialActions; /** * @ORM\Column(type="json") - * @Serializer\Groups({"read"}) + * @Serializer\Groups({"read", "docgen:read"}) + * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"}) */ - private $title = []; + private array $title = []; public function __construct() { diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php index c5ca7d18a..ec5e5a8e5 100644 --- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php +++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php @@ -46,9 +46,9 @@ class SocialAction private $desactivationDate; /** - * @ORM\OneToMany( + * @ORM\ManyToMany( * targetEntity=Evaluation::class, - * mappedBy="socialAction" + * mappedBy="socialActions" * ) */ private Collection $evaluations; @@ -71,6 +71,11 @@ class SocialAction */ private $issue; + /** + * @ORM\Column(type="float", name="ordering", options={"default": 0.0}) + */ + private float $ordering = 0.0; + /** * @ORM\ManyToOne(targetEntity=SocialAction::class, inversedBy="children") */ @@ -92,13 +97,14 @@ class SocialAction $this->children = new ArrayCollection(); $this->goals = new ArrayCollection(); $this->results = new ArrayCollection(); + $this->evaluations = new ArrayCollection(); } public function addChild(self $child): self { if (!$this->children->contains($child)) { $this->children[] = $child; - $child->setParent($this); + $child->setParent($this)->setIssue($this->getIssue()); } return $this; @@ -199,6 +205,11 @@ class SocialAction return $this->issue; } + public function getOrdering(): float + { + return $this->ordering; + } + public function getParent(): ?self { return $this->parent; @@ -266,9 +277,23 @@ class SocialAction { $this->issue = $issue; + foreach ($this->getChildren() as $child) { + $child->setIssue($issue); + } + return $this; } + public function setOrdering(float $ordering): SocialAction + { + $this->ordering = $ordering; + + return $this; + } + + /** + * @internal use $parent->addChild() instead (@see{self::addChild()}) + */ public function setParent(?self $parent): self { $this->parent = $parent; diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php index 84d47796b..c735c0132 100644 --- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php +++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php @@ -44,6 +44,11 @@ class SocialIssue */ private $id; + /** + * @ORM\Column(type="float", name="ordering", options={"default": 0.0}) + */ + private float $ordering = 0.0; + /** * @ORM\ManyToOne(targetEntity=SocialIssue::class, inversedBy="children") */ @@ -121,6 +126,28 @@ class SocialIssue return $ancestors; } + /** + * get all the ancestors of the social issue. + * + * @param bool $includeThis if the array in the result must include the present SocialIssue + */ + public function getAncestors(bool $includeThis = true): array + { + $ancestors = []; + + if ($includeThis) { + $ancestors[] = $this; + } + + $current = $this; + + while ($current->hasParent()) { + $ancestors[] = $current = $current->getParent(); + } + + return $ancestors; + } + /** * @return Collection|self[] */ @@ -193,6 +220,11 @@ class SocialIssue return $this->id; } + public function getOrdering(): float + { + return $this->ordering; + } + public function getParent(): ?self { return $this->parent; @@ -283,6 +315,16 @@ class SocialIssue return $this; } + public function setOrdering(float $ordering): SocialIssue + { + $this->ordering = $ordering; + + return $this; + } + + /** + * @internal use @see{SocialIssue::addChild()} instead + */ public function setParent(?self $parent): self { $this->parent = $parent; diff --git a/src/Bundle/ChillPersonBundle/EventListener/PersonEventListener.php b/src/Bundle/ChillPersonBundle/EventListener/PersonEventListener.php index d3b4beb47..993435ce5 100644 --- a/src/Bundle/ChillPersonBundle/EventListener/PersonEventListener.php +++ b/src/Bundle/ChillPersonBundle/EventListener/PersonEventListener.php @@ -13,6 +13,7 @@ namespace Chill\PersonBundle\EventListener; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\PersonAltName; + use const MB_CASE_TITLE; class PersonEventListener diff --git a/src/Bundle/ChillPersonBundle/Export/AbstractAccompanyingPeriodExportElement.php b/src/Bundle/ChillPersonBundle/Export/AbstractAccompanyingPeriodExportElement.php index b570c83de..264f47955 100644 --- a/src/Bundle/ChillPersonBundle/Export/AbstractAccompanyingPeriodExportElement.php +++ b/src/Bundle/ChillPersonBundle/Export/AbstractAccompanyingPeriodExportElement.php @@ -13,6 +13,7 @@ namespace Chill\PersonBundle\Export; use Doctrine\ORM\QueryBuilder; use LogicException; + use function in_array; class AbstractAccompanyingPeriodExportElement diff --git a/src/Bundle/ChillPersonBundle/Export/Export/CountPerson.php b/src/Bundle/ChillPersonBundle/Export/Export/CountPerson.php index ffa69026a..27774c885 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/CountPerson.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/CountPerson.php @@ -90,7 +90,9 @@ class CountPerson implements ExportInterface */ public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) { - $centers = array_map(static function ($el) { return $el['center']; }, $acl); + $centers = array_map(static function ($el) { + return $el['center']; + }, $acl); $qb = $this->entityManager->createQueryBuilder(); diff --git a/src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php b/src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php index 6c02f4033..4528f1c92 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php @@ -32,6 +32,7 @@ use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Context\ExecutionContextInterface; + use function addcslashes; use function array_key_exists; use function array_keys; @@ -266,7 +267,9 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) { - $centers = array_map(static function ($el) { return $el['center']; }, $acl); + $centers = array_map(static function ($el) { + return $el['center']; + }, $acl); // throw an error if any fields are present if (!array_key_exists('fields', $data)) { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/GenderFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/GenderFilter.php index c7587874b..a1adee826 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/GenderFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/GenderFilter.php @@ -20,6 +20,7 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface; + use function array_filter; use function count; use function implode; diff --git a/src/Bundle/ChillPersonBundle/Form/AccompanyingCourseCommentType.php b/src/Bundle/ChillPersonBundle/Form/AccompanyingCourseCommentType.php new file mode 100644 index 000000000..b123a4c4d --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Form/AccompanyingCourseCommentType.php @@ -0,0 +1,37 @@ +add('content', ChillTextareaType::class, []); + } + + /** + * @return void + */ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefault('class', Comment::class); + } +} diff --git a/src/Bundle/ChillPersonBundle/Form/ChoiceLoader/PersonChoiceLoader.php b/src/Bundle/ChillPersonBundle/Form/ChoiceLoader/PersonChoiceLoader.php index 2924b7e35..7ff30524f 100644 --- a/src/Bundle/ChillPersonBundle/Form/ChoiceLoader/PersonChoiceLoader.php +++ b/src/Bundle/ChillPersonBundle/Form/ChoiceLoader/PersonChoiceLoader.php @@ -16,6 +16,7 @@ use Chill\PersonBundle\Repository\PersonRepository; use RuntimeException; use Symfony\Component\Form\ChoiceList\ChoiceListInterface; use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; + use function call_user_func; use function count; use function in_array; @@ -76,8 +77,10 @@ class PersonChoiceLoader implements ChoiceLoaderInterface $person = $this->personRepository->find($value); - if ($this->hasCenterFilter() - && !in_array($person->getCenter(), $this->centers, true)) { + if ( + $this->hasCenterFilter() + && !in_array($person->getCenter(), $this->centers, true) + ) { throw new RuntimeException('chosen a person not in correct center'); } diff --git a/src/Bundle/ChillPersonBundle/Form/DataMapper/PersonAltNameDataMapper.php b/src/Bundle/ChillPersonBundle/Form/DataMapper/PersonAltNameDataMapper.php index 13de3b9f5..d63c5f214 100644 --- a/src/Bundle/ChillPersonBundle/Form/DataMapper/PersonAltNameDataMapper.php +++ b/src/Bundle/ChillPersonBundle/Form/DataMapper/PersonAltNameDataMapper.php @@ -16,6 +16,7 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Symfony\Component\Form\DataMapperInterface; use Symfony\Component\Form\Exception\UnexpectedTypeException; + use function array_key_exists; use function is_array; diff --git a/src/Bundle/ChillPersonBundle/Form/HouseholdMemberType.php b/src/Bundle/ChillPersonBundle/Form/HouseholdMemberType.php index a5284afdb..e0d2d9d47 100644 --- a/src/Bundle/ChillPersonBundle/Form/HouseholdMemberType.php +++ b/src/Bundle/ChillPersonBundle/Form/HouseholdMemberType.php @@ -14,7 +14,6 @@ namespace Chill\PersonBundle\Form; use Chill\MainBundle\Form\Type\ChillDateType; use Chill\MainBundle\Form\Type\ChillTextareaType; use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormBuilderInterface; class HouseholdMemberType extends AbstractType @@ -26,17 +25,6 @@ class HouseholdMemberType extends AbstractType 'label' => 'household.Start date', 'input' => 'datetime_immutable', ]); - - if ($options['data']->getPosition()->isAllowHolder()) { - $builder - ->add('holder', ChoiceType::class, [ - 'label' => 'household.holder', - 'choices' => [ - 'household.is holder' => true, - 'household.is not holder' => false, - ], - ]); - } $builder ->add('comment', ChillTextareaType::class, [ 'label' => 'household.Comment', diff --git a/src/Bundle/ChillPersonBundle/Form/PersonType.php b/src/Bundle/ChillPersonBundle/Form/PersonType.php index eddf8c751..bafe21277 100644 --- a/src/Bundle/ChillPersonBundle/Form/PersonType.php +++ b/src/Bundle/ChillPersonBundle/Form/PersonType.php @@ -21,6 +21,7 @@ use Chill\MainBundle\Form\Type\Select2CountryType; use Chill\MainBundle\Form\Type\Select2LanguageType; use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper; +use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\PersonPhone; use Chill\PersonBundle\Form\Type\GenderType; use Chill\PersonBundle\Form\Type\PersonAltNameType; @@ -93,6 +94,7 @@ class PersonType extends AbstractType ]) ->add('numberOfChildren', IntegerType::class, [ 'required' => false, + 'attr' => ['min' => 0], ]); if ($this->configAltNamesHelper->hasAltNames()) { @@ -114,10 +116,10 @@ class PersonType extends AbstractType $builder->get('placeOfBirth')->addModelTransformer(new CallbackTransformer( static function ($string) { - return strtoupper($string); + return strtoupper((string) $string); }, static function ($string) { - return strtoupper($string); + return strtoupper((string) $string); } )); } @@ -196,7 +198,8 @@ class PersonType extends AbstractType }, 'query_builder' => static function (EntityRepository $er): QueryBuilder { return $er->createQueryBuilder('c') - ->where('c.active = true'); + ->where('c.active = true') + ->orderBy('c.order'); }, 'placeholder' => 'choose civility', 'required' => false, @@ -232,8 +235,7 @@ class PersonType extends AbstractType public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ - 'data_class' => 'Chill\PersonBundle\Entity\Person', - 'validation_groups' => ['general', 'creation'], + 'data_class' => Person::class, ]); $resolver->setRequired([ diff --git a/src/Bundle/ChillPersonBundle/Form/Type/GenderType.php b/src/Bundle/ChillPersonBundle/Form/Type/GenderType.php index 43edfb8d0..90d548265 100644 --- a/src/Bundle/ChillPersonBundle/Form/Type/GenderType.php +++ b/src/Bundle/ChillPersonBundle/Form/Type/GenderType.php @@ -14,7 +14,6 @@ namespace Chill\PersonBundle\Form\Type; use Chill\PersonBundle\Entity\Person; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; - use Symfony\Component\OptionsResolver\OptionsResolver; /** diff --git a/src/Bundle/ChillPersonBundle/Form/Type/PickPersonType.php b/src/Bundle/ChillPersonBundle/Form/Type/PickPersonType.php index 98572b8bc..55d242f2d 100644 --- a/src/Bundle/ChillPersonBundle/Form/Type/PickPersonType.php +++ b/src/Bundle/ChillPersonBundle/Form/Type/PickPersonType.php @@ -28,6 +28,7 @@ use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInt use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Translation\TranslatorInterface; + use function in_array; use function is_array; @@ -161,10 +162,14 @@ class PickPersonType extends AbstractType . 'option must be an instance of ' . Center::class); } - if (!in_array($c->getId(), array_map( - static function (Center $c) { return $c->getId(); }, - $centers - ), true)) { + if ( + !in_array($c->getId(), array_map( + static function (Center $c) { + return $c->getId(); + }, + $centers + ), true) + ) { throw new AccessDeniedException('The given center is not reachable'); } $selectedCenters[] = $c; diff --git a/src/Bundle/ChillPersonBundle/Form/Type/Select2MaritalStatusType.php b/src/Bundle/ChillPersonBundle/Form/Type/Select2MaritalStatusType.php index c75b93f7a..742efbc7d 100644 --- a/src/Bundle/ChillPersonBundle/Form/Type/Select2MaritalStatusType.php +++ b/src/Bundle/ChillPersonBundle/Form/Type/Select2MaritalStatusType.php @@ -19,6 +19,7 @@ use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; + use const SORT_FLAG_CASE; use const SORT_STRING; diff --git a/src/Bundle/ChillPersonBundle/Household/MembersEditor.php b/src/Bundle/ChillPersonBundle/Household/MembersEditor.php index 2d3749fa7..4d855a980 100644 --- a/src/Bundle/ChillPersonBundle/Household/MembersEditor.php +++ b/src/Bundle/ChillPersonBundle/Household/MembersEditor.php @@ -21,6 +21,7 @@ use LogicException; use Symfony\Component\Validator\ConstraintViolationList; use Symfony\Component\Validator\ConstraintViolationListInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; + use function in_array; use function spl_object_hash; diff --git a/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php b/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php index fed840954..60455b201 100644 --- a/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php +++ b/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php @@ -73,6 +73,13 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface ], ]) ->setExtras(['order' => 40]); + $menu->addChild($this->translator->trans('Accompanying Course Comment'), [ + 'route' => 'chill_person_accompanying_period_comment_list', + 'routeParameters' => [ + 'accompanying_period_id' => $period->getId(), + ], ]) + ->setExtras(['order' => 50]); + $workflow = $this->registry->get($period, 'accompanying_period_lifecycle'); if ($workflow->can($period, 'close')) { diff --git a/src/Bundle/ChillPersonBundle/Menu/HouseholdMenuBuilder.php b/src/Bundle/ChillPersonBundle/Menu/HouseholdMenuBuilder.php index feb465f8d..a144bf65b 100644 --- a/src/Bundle/ChillPersonBundle/Menu/HouseholdMenuBuilder.php +++ b/src/Bundle/ChillPersonBundle/Menu/HouseholdMenuBuilder.php @@ -57,7 +57,7 @@ class HouseholdMenuBuilder implements LocalMenuBuilderInterface 'routeParameters' => [ 'household_id' => $household->getId(), ], ]) - ->setExtras(['order' => 40]); + ->setExtras(['order' => 15]); } public static function getMenuIds(): array diff --git a/src/Bundle/ChillPersonBundle/Menu/PersonMenuBuilder.php b/src/Bundle/ChillPersonBundle/Menu/PersonMenuBuilder.php index ee359434b..d83fa29dd 100644 --- a/src/Bundle/ChillPersonBundle/Menu/PersonMenuBuilder.php +++ b/src/Bundle/ChillPersonBundle/Menu/PersonMenuBuilder.php @@ -82,7 +82,8 @@ class PersonMenuBuilder implements LocalMenuBuilderInterface 'order' => 99999, ]); - if ('visible' === $this->showAccompanyingPeriod + if ( + 'visible' === $this->showAccompanyingPeriod && $this->security->isGranted(AccompanyingPeriodVoter::SEE, $parameters['person']) ) { $menu->addChild($this->translator->trans('Accompanying period list'), [ diff --git a/src/Bundle/ChillPersonBundle/Privacy/PrivacyEvent.php b/src/Bundle/ChillPersonBundle/Privacy/PrivacyEvent.php index 0bfd7a435..10e25c327 100644 --- a/src/Bundle/ChillPersonBundle/Privacy/PrivacyEvent.php +++ b/src/Bundle/ChillPersonBundle/Privacy/PrivacyEvent.php @@ -33,6 +33,7 @@ namespace Chill\PersonBundle\Privacy; use Chill\PersonBundle\Entity\Person; use Symfony\Component\EventDispatcher\Event; + use function count; /** diff --git a/src/Bundle/ChillPersonBundle/Privacy/PrivacyEventSubscriber.php b/src/Bundle/ChillPersonBundle/Privacy/PrivacyEventSubscriber.php index 5018743dc..480ddcb24 100644 --- a/src/Bundle/ChillPersonBundle/Privacy/PrivacyEventSubscriber.php +++ b/src/Bundle/ChillPersonBundle/Privacy/PrivacyEventSubscriber.php @@ -35,6 +35,7 @@ use Chill\PersonBundle\Entity\Person; use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; + use function array_map; class PrivacyEventSubscriber implements EventSubscriberInterface @@ -75,7 +76,9 @@ class PrivacyEventSubscriber implements EventSubscriberInterface $involved = $this->getInvolved(); $involved['period_id'] = $event->getPeriod()->getId(); $involved['persons'] = $event->getPeriod()->getPersons() - ->map(static function (Person $p) { return $p->getId(); }) + ->map(static function (Person $p) { + return $p->getId(); + }) ->toArray(); $this->logger->notice( @@ -99,7 +102,9 @@ class PrivacyEventSubscriber implements EventSubscriberInterface if ($event->hasPersons()) { $involved['persons'] = array_map( - static function (Person $p) { return $p->getId(); }, + static function (Person $p) { + return $p->getId(); + }, $event->getPersons() ); } diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php index 965231e3f..6e6c3ca44 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php @@ -16,6 +16,7 @@ use Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\Person; use Symfony\Component\Security\Core\Security; + use function count; final class AccompanyingPeriodACLAwareRepository implements AccompanyingPeriodACLAwareRepositoryInterface diff --git a/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdRepository.php b/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdRepository.php index 8becf4409..196bfc269 100644 --- a/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/Household/HouseholdRepository.php @@ -17,6 +17,7 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\Query\ResultSetMappingBuilder; use Doctrine\Persistence\ObjectRepository; + use function strtr; final class HouseholdRepository implements ObjectRepository diff --git a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php index 972264282..78745af1d 100644 --- a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php @@ -23,6 +23,7 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\NonUniqueResultException; use Doctrine\ORM\Query; use Symfony\Component\Security\Core\Security; + use function array_fill; use function array_map; use function array_merge; @@ -316,7 +317,9 @@ final class PersonACLAwareRepository implements PersonACLAwareRepositoryInterfac ), ] ), - array_map(static function (Center $c) {return $c->getId(); }, $authorizedCenters) + array_map(static function (Center $c) { + return $c->getId(); + }, $authorizedCenters) ); } } diff --git a/src/Bundle/ChillPersonBundle/Repository/PersonRepository.php b/src/Bundle/ChillPersonBundle/Repository/PersonRepository.php index 57cea2d55..bd8347852 100644 --- a/src/Bundle/ChillPersonBundle/Repository/PersonRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/PersonRepository.php @@ -17,6 +17,7 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ObjectRepository; use Exception; + use function count; use function in_array; use function str_replace; diff --git a/src/Bundle/ChillPersonBundle/Repository/Relationships/RelationshipRepository.php b/src/Bundle/ChillPersonBundle/Repository/Relationships/RelationshipRepository.php index ab172e459..9549a4564 100644 --- a/src/Bundle/ChillPersonBundle/Repository/Relationships/RelationshipRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/Relationships/RelationshipRepository.php @@ -11,18 +11,31 @@ declare(strict_types=1); namespace Chill\PersonBundle\Repository\Relationships; +use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\Relationships\Relationship; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; +use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ObjectRepository; class RelationshipRepository implements ObjectRepository { + private EntityManagerInterface $em; + private EntityRepository $repository; public function __construct(EntityManagerInterface $em) { $this->repository = $em->getRepository(Relationship::class); + $this->em = $em; + } + + public function countByPerson(Person $person): int + { + return $this->buildQueryByPerson($person) + ->select('COUNT(p)') + ->getQuery() + ->getSingleScalarResult(); } public function find($id): ?Relationship @@ -40,15 +53,13 @@ class RelationshipRepository implements ObjectRepository return $this->repository->findBy($criteria, $orderBy, $limit, $offset); } - public function findByPerson($personId): array + /** + * @return array|Relationship[] + */ + public function findByPerson(Person $person): array { - // return all relationships of which person is part? or only where person is the fromPerson? - return $this->repository->createQueryBuilder('r') - ->select('r, t') // entity Relationship - ->join('r.relation', 't') - ->where('r.fromPerson = :val') - ->orWhere('r.toPerson = :val') - ->setParameter('val', $personId) + return $this->buildQueryByPerson($person) + ->select('r') ->getQuery() ->getResult(); } @@ -62,4 +73,20 @@ class RelationshipRepository implements ObjectRepository { return Relationship::class; } + + private function buildQueryByPerson(Person $person): QueryBuilder + { + $qb = $this->em->createQueryBuilder(); + $qb + ->from(Relationship::class, 'r') + ->where( + $qb->expr()->orX( + $qb->expr()->eq('r.fromPerson', ':person'), + $qb->expr()->eq('r.toPerson', ':person') + ) + ) + ->setParameter('person', $person); + + return $qb; + } } diff --git a/src/Bundle/ChillPersonBundle/Repository/SocialWork/SocialIssueRepository.php b/src/Bundle/ChillPersonBundle/Repository/SocialWork/SocialIssueRepository.php index 7c5983fd3..0900796d6 100644 --- a/src/Bundle/ChillPersonBundle/Repository/SocialWork/SocialIssueRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/SocialWork/SocialIssueRepository.php @@ -8,6 +8,7 @@ */ declare(strict_types=1); + /* * Chill is a software for social workers * diff --git a/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/accompanying_period_work.scss b/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/accompanying_period_work.scss index d246b3c92..ed474911f 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/accompanying_period_work.scss +++ b/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/accompanying_period_work.scss @@ -1,100 +1,56 @@ /// AccompanyingCourse Work list Page div.accompanying_course_work-list { - div.timeline { + table.obj-res-eval { + border-collapse: collapse; + border-radius: 5px; width: 100%; - ul { - display: flex; - align-items: center; - justify-content: center; - - padding: 0; - list-style-type: none; - - > li { - flex-grow: 1; flex-shrink: 1; flex-basis: auto; - - div { - display: flex; - flex-direction: column; - align-items: center; - - &.date { - margin-bottom: 1em; - } - &.label { - border-top: 3px solid $chill-green; - - &:before { - content: ''; - display: inline-block; - position: relative; - width: 15px; - height: 15px; - top: -9px; - - background-color: $white; - border-radius: 12px; - border: 2px solid $chill-green; - } - &.no-label:before { - display: none; - } - } - } + &, tr, th, td { + border: 1px solid lightgray; + padding: 0.3em; + } + th { + h4.title_label { + font-weight: 700; + font-size: 100%; + font-family: 'Open Sans'; + margin: 0; } } + td { + font-size: 85%; + } + td.obj, + td.res { + width: 50%; + } + td.eval { + width: 100%; + } } - div.objective_results { - width: 100%; - display: grid; - grid-template-areas: "obj res"; - grid-template-columns: 50%; - column-gap: 0.2rem; - padding: 0.3rem; - - div.objective { - grid-area: obj; - h4.title_label { - border-radius: 0.35rem 0 0 0.35rem; - } + ul { + &.goal_title, + &.result_list, + &.eval_title { + padding-left: 1em; + margin-bottom: 0; } - div.results { - grid-area: res; - h4.title_label { - border-radius: 0 0.35rem 0.35rem 0; - } + &.goal_title { + @include list_marker_triangle($social-issue-color); } - //&:nth-child(even) { background-color: $chill-llight-gray; } - &.without-objectives {} - &.with-objectives {} - - - h4.title_label { - display: block; - margin: 0.4em 0; - padding: 0.1em 0.5em; - font-variant-caps: small-caps; - font-size: 95%; - background-color: tint-color($chill-orange, 80%); - + * { - margin-top: 0; - } + &.result_list { + @include list_marker_triangle($pink); } - ul { - &.goal_title, - &.result_list { - padding-left: 1em; - margin-bottom: 0; - } - &.goal_title { - @include list_marker_triangle($social-issue-color); - } - &.result_list { - @include list_marker_triangle($pink); - } + &.eval_title { + @include list_marker_triangle($orange); } } } + +div.flex-table div.item-bloc:nth-child(2n) table.obj-res-eval { + &, tr, th, td { + background-color: $chill-llight-gray; + } +} diff --git a/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/badge.scss b/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/badge.scss index 6ffe0ac9d..b0147ebdf 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/badge.scss +++ b/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/badge.scss @@ -1,7 +1,8 @@ /* -* BADGES PERSON AND THIRDPARTY +* BADGES USER, PERSON AND THIRDPARTY */ +span.badge-user, span.badge-person, span.badge-thirdparty { display: inline-block; @@ -16,6 +17,10 @@ span.badge-thirdparty { text-decoration: none; } } + +span.badge-user { + border-bottom-width: 1px; +} span.badge-person { border-bottom-color: $chill-green; } @@ -39,69 +44,15 @@ span.fa-holder { } /* -* BADGE_TITLE -* Display Title like a badge (with background-colored label) +* DASHBOARDS */ -h2.badge-title { - display: flex; - flex-direction: row; - width: 100%; - color: $dark; - - span.title_label { - border-radius: 0.35rem 0 0 0.35rem; - color: $white; - font-size: 80%; - padding: 0.5em; - padding-right: 0; - h3 { - margin-bottom: 0.5rem; - } - - //position: relative; - span { - display: none; - //position: absolute; - //top: 0; - //left: 0; - //transform: rotate(270deg); - //transform-origin: 0 0; - } - } - span.title_action { - flex-grow: 1; - margin: 0 0 0 auto; - border-radius: 0 0.35rem 0.35rem 0; - background-color: $chill-llight-gray; - padding: 0.2em 1em; - - ul.small_in_title { - margin: 0; - //margin-top: 0.5em; - font-size: 70%; - padding-left: 1rem; - &.evaluations { - @include list_marker_triangle($orange); - } - } - ul.columns { // XS:1 SM:2 MD:1 LG:2 XL:2 XXL:2 - @include media-breakpoint-only(sm) { - columns: 2; -webkit-columns: 2; -moz-columns: 2; - } - @include media-breakpoint-up(lg) { - columns: 2; -webkit-columns: 2; -moz-columns: 2; - } - } - } -} - -/// Theses links apply on badge as parent tag. +/// Theses links apply on dashboards as parent tag. /// They don't look like button, picto or simple text links -a.badge-link { +a.dashboard-link { color: unset; text-decoration: unset; - & > h2.badge-title { + & > div.dashboard { &:hover { //box-shadow: 0 0 7px 0 $chill-gray; //opacity: 0.8; @@ -114,21 +65,79 @@ a.badge-link { } } -/// badge_title in AccompanyingCourse Work list Page -div.accompanying_course_work-list { +div.dashboard { + font-weight: 700; + font-size: 1.5rem; + margin-bottom: 0.5rem; + line-height: 1.2; + span.like-h3 { + color: #334d5c; + } +} +div.dashboard, +h2.badge-title { + display: flex; + flex-direction: row; + width: 100%; + color: $dark; + span.title_label { + color: $white; + font-size: 80%; + padding: 0.5em; + padding-right: 0; + border-radius: 0.35rem 0 0 0.35rem; + h3 { + margin-bottom: 0.5rem; + } + } + span.title_action { + flex-grow: 1; + margin: 0 0 0 auto; + background-color: $chill-llight-gray; + padding: 0.2em 1em; + border-radius: 0 0.35rem 0.35rem 0; + + ul.small_in_title { + font-size: 70%; + } + } +} + +ul.small_in_title { + margin: 0; + //margin-top: 0.5em; + padding-left: 1rem; + &.evaluations { + @include list_marker_triangle($orange); + } +} +ul.columns { // XS:1 SM:2 MD:1 LG:2 XL:2 XXL:2 + @include media-breakpoint-only(sm) { + columns: 2; -webkit-columns: 2; -moz-columns: 2; + } + @include media-breakpoint-up(lg) { + columns: 2; -webkit-columns: 2; -moz-columns: 2; + } +} + +/// dashboard_like_badge in AccompanyingCourse Work list Page +div[class*='accompanying_course_work'] { + div.dashboard, h2.badge-title { span.title_label { // Calculate same color then border:groove background-color: shade-color($social-action-color, 34%); } span.title_action { - @include badge_title($social-action-color); + @include dashboard_like_badge($social-action-color); } + } } -/// badge_title in Activities on resume page -div.activity-list { +/// dashboard_like_badge in Activities on resume page +div[class*='activity-'] { + div.dashboard, h2.badge-title { span.title_label { // Calculate same color then border:groove @@ -138,7 +147,7 @@ div.activity-list { } } span.title_action { - @include badge_title($activity-color); + @include dashboard_like_badge($activity-color); } span.title_label { div.duration { @@ -157,6 +166,18 @@ div.activity-list { } /* +* Pill badge by entity */ - +.badge { + &.bg-person { + //@extend .$chill-ll-gray; + background-color: $chill-ll-gray; + color: $chill-green; + } + &.bg-user { + //@extend .$chill-ll-gray; + background-color: $chill-ll-gray; + color: $chill-blue; + } +} diff --git a/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/flex_table.scss b/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/flex_table.scss index 0229f53b1..2383e43b1 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/flex_table.scss +++ b/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/flex_table.scss @@ -18,12 +18,6 @@ div.accompanyingcourse-list { //&:nth-child(2) { flex-direction: row; } //&:last-child { flex-direction: column; } } - div.title h3 { - font-weight: 700; - font-size: 100%; - font-family: 'Open Sans'; - } - div.list {} } /// Search Page (list_with_period.html.twig) diff --git a/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/mixins.scss b/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/mixins.scss index 8a3d21ece..228f10178 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/mixins.scss +++ b/src/Bundle/ChillPersonBundle/Resources/public/chill/scss/mixins.scss @@ -27,11 +27,10 @@ } /// -/// Generic mixin for titles like badge -// define visual badge used in title area +/// Mixin for dashboards (with design like badge_social) /// -@mixin badge_title($color) { +@mixin dashboard_like_badge($color) { @include chill_badge($color); &:before { margin: 0 0.3em 0 -1.05em; diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/api.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/api.js index 4eb6f2a33..8e4134205 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/api.js +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/api.js @@ -22,9 +22,9 @@ const getUsers = () => { }; const getReferrersSuggested = (course) => { - const url = `/api/1.0/person/accompanying-course/${course.id}/referrers-suggested.json`; + const url = `/api/1.0/person/accompanying-course/${course.id}/referrers-suggested.json`; - return fetchResults(url); + return fetchResults(url); } /* diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Comment.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Comment.vue index 7f5b04f99..5df43cdac 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Comment.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Comment.vue @@ -20,10 +20,10 @@ tag-name="textarea"> -