* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ namespace Chill\PersonBundle\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\FileLocator; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\Loader; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; use Chill\MainBundle\DependencyInjection\MissingBundleException; use Chill\PersonBundle\Security\Authorization\PersonVoter; use Chill\MainBundle\Security\Authorization\ChillExportVoter; use Chill\PersonBundle\Doctrine\DQL\AddressPart; use Symfony\Component\HttpFoundation\Request; /** * Class ChillPersonExtension * Loads and manages your bundle configuration * * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html} * @package Chill\PersonBundle\DependencyInjection */ class ChillPersonExtension extends Extension implements PrependExtensionInterface { /** * {@inheritDoc} * @param array $configs * @param ContainerBuilder $container * @throws \Exception */ public function load(array $configs, ContainerBuilder $container) { $configuration = new Configuration(); $config = $this->processConfiguration($configuration, $configs); // set configuration for validation $container->setParameter('chill_person.validation.birtdate_not_before', $config['validation']['birthdate_not_after']); $this->handlePersonFieldsParameters($container, $config['person_fields']); $this->handleAccompanyingPeriodsFieldsParameters($container, $config['accompanying_periods_fields']); $container->setParameter('chill_person.allow_multiple_simultaneous_accompanying_periods', $config['allow_multiple_simultaneous_accompanying_periods']); $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config')); $loader->load('services.yaml'); $loader->load('services/widgets.yaml'); $loader->load('services/exports.yaml'); $loader->load('services/fixtures.yaml'); $loader->load('services/controller.yaml'); $loader->load('services/search.yaml'); $loader->load('services/menu.yaml'); $loader->load('services/privacyEvent.yaml'); $loader->load('services/command.yaml'); $loader->load('services/actions.yaml'); $loader->load('services/form.yaml'); $loader->load('services/alt_names.yaml'); $loader->load('services/household.yaml'); // We can get rid of this file when the service 'chill.person.repository.person' is no more used. // We should use the PersonRepository service instead of a custom service name. $loader->load('services/repository.yaml'); $loader->load('services/serializer.yaml'); $loader->load('services/security.yaml'); // load service advanced search only if configure if ($config['search']['search_by_phone'] != 'never') { $loader->load('services/search_by_phone.yaml'); $container->setParameter('chill_person.search.search_by_phone', $config['search']['search_by_phone']); } if ($container->getParameter('chill_person.accompanying_period') !== 'hidden') { $loader->load('services/exports_accompanying_period.yaml'); } } /** * @param ContainerBuilder $container * @param $config */ private function handlePersonFieldsParameters(ContainerBuilder $container, $config) { if (array_key_exists('enabled', $config)) { unset($config['enabled']); } $container->setParameter('chill_person.person_fields', $config); foreach ($config as $key => $value) { switch($key) { case 'accompanying_period': $container->setParameter('chill_person.accompanying_period', $value); break; default: $container->setParameter('chill_person.person_fields.'.$key, $value); break; } } } /** * @param ContainerBuilder $container * @param $config */ private function handleAccompanyingPeriodsFieldsParameters(ContainerBuilder $container, $config) { $container->setParameter('chill_person.accompanying_period_fields', $config); foreach ($config as $key => $value) { switch($key) { case 'enabled': break; default: $container->setParameter('chill_person.accompanying_period_fields.'.$key, $value); break; } } } /** * @param ContainerBuilder $container * @throws MissingBundleException */ private function declarePersonAsCustomizable (ContainerBuilder $container) { $bundles = $container->getParameter('kernel.bundles'); if (!isset($bundles['ChillCustomFieldsBundle'])) { throw new MissingBundleException('ChillCustomFieldsBundle'); } $container->prependExtensionConfig('chill_custom_fields', array('customizables_entities' => array( array('class' => 'Chill\PersonBundle\Entity\Person', 'name' => 'PersonEntity') ) ) ); } /** * @param ContainerBuilder $container * @throws MissingBundleException */ public function prepend(ContainerBuilder $container) { $this->prependRoleHierarchy($container); $this->prependHomepageWidget($container); $this->prependDoctrineDQL($container); $this->prependCruds($container); $this->prependWorkflows($container); //add person_fields parameter as global $chillPersonConfig = $container->getExtensionConfig($this->getAlias()); $config = $this->processConfiguration(new Configuration(), $chillPersonConfig); $twigConfig = array( 'globals' => array( 'chill_person' => array( 'fields' => $config['person_fields'] ), 'chill_accompanying_periods' => [ 'fields' => $config['accompanying_periods_fields'] ] ), 'form_themes' => array('ChillPersonBundle:Export:ListPersonFormFields.html.twig') ); $container->prependExtensionConfig('twig', $twigConfig); $this-> declarePersonAsCustomizable($container); //declare routes for person bundle $container->prependExtensionConfig('chill_main', array( 'routing' => array( 'resources' => array( '@ChillPersonBundle/config/routes.yaml' ) ) )); } protected function prependWorkflows(ContainerBuilder $container) { $container->prependExtensionConfig('framework', [ 'workflows' => [ 'accompanying_period_lifecycle' => [ 'type' => 'state_machine', 'audit_trail' => [ 'enabled' => true ], 'marking_store' => [ 'type' => 'method', 'property' => 'step', ], 'supports' => [ 'Chill\PersonBundle\Entity\AccompanyingPeriod' ], 'initial_marking' => 'DRAFT', 'places' => [ 'DRAFT', 'CONFIRMED', ], 'transitions' => [ 'confirm' => [ 'from' => 'DRAFT', 'to' => 'CONFIRMED' ], ], ], ] ]); } /** * Add a widget "add a person" on the homepage, automatically * * @param \Chill\PersonBundle\DependencyInjection\containerBuilder $container */ protected function prependHomepageWidget(containerBuilder $container) { $container->prependExtensionConfig('chill_main', array( 'widgets' => array( 'homepage' => array( array( 'widget_alias' => 'add_person', 'order' => 2 ) ) ) )); } /** * Add role hierarchy. * * @param ContainerBuilder $container */ protected function prependRoleHierarchy(ContainerBuilder $container) { $container->prependExtensionConfig('security', array( 'role_hierarchy' => array( 'CHILL_PERSON_UPDATE' => array('CHILL_PERSON_SEE'), 'CHILL_PERSON_CREATE' => array('CHILL_PERSON_SEE'), PersonVoter::LISTS => [ ChillExportVoter::EXPORT ], PersonVoter::STATS => [ ChillExportVoter::EXPORT ] ) )); } /** * Add DQL function linked with person * * @param ContainerBuilder $container */ protected function prependDoctrineDQL(ContainerBuilder $container) { //add DQL function to ORM (default entity_manager) $container->prependExtensionConfig('doctrine', array( 'orm' => array( 'dql' => array( 'string_functions' => array( 'GET_PERSON_ADDRESS_ADDRESS_ID' => AddressPart\AddressPartAddressId::class, 'GET_PERSON_ADDRESS_STREET_ADDRESS_1' => AddressPart\AddressPartStreetAddress1::class, 'GET_PERSON_ADDRESS_STREET_ADDRESS_2' => AddressPart\AddressPartStreetAddress2::class, 'GET_PERSON_ADDRESS_VALID_FROM' => AddressPart\AddressPartValidFrom::class, 'GET_PERSON_ADDRESS_POSTCODE_LABEL' => AddressPart\AddressPartPostCodeLabel::class, 'GET_PERSON_ADDRESS_POSTCODE_CODE' => AddressPart\AddressPartPostCodeCode::class, 'GET_PERSON_ADDRESS_POSTCODE_ID' => AddressPart\AddressPartPostCodeId::class, 'GET_PERSON_ADDRESS_COUNTRY_NAME' => AddressPart\AddressPartCountryName::class, 'GET_PERSON_ADDRESS_COUNTRY_CODE' => AddressPart\AddressPartCountryCode::class, 'GET_PERSON_ADDRESS_COUNTRY_ID' => AddressPart\AddressPartCountryId::class, ), 'numeric_functions' => [ 'GET_PERSON_ADDRESS_ISNOADDRESS' => AddressPart\AddressPartIsNoAddress::class, ] ) ) )); } /** * @param ContainerBuilder $container */ protected function prependCruds(ContainerBuilder $container) { $container->prependExtensionConfig('chill_main', [ 'cruds' => [ [ 'class' => \Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive::class, 'name' => 'closing_motive', 'base_path' => '/admin/closing-motive', 'form_class' => \Chill\PersonBundle\Form\ClosingMotiveType::class, 'controller' => \Chill\PersonBundle\Controller\AdminClosingMotiveController::class, 'actions' => [ 'index' => [ 'template' => '@ChillPerson/ClosingMotive/index.html.twig', 'role' => 'ROLE_ADMIN' ], 'new' => [ 'role' => 'ROLE_ADMIN', 'template' => '@ChillPerson/ClosingMotive/new.html.twig', ], 'edit' => [ 'role' => 'ROLE_ADMIN', 'template' => '@ChillPerson/ClosingMotive/edit.html.twig', ] ] ], [ 'class' => \Chill\PersonBundle\Entity\MaritalStatus::class, 'name' => 'marital_status', 'base_path' => '/admin/marital-status', 'form_class' => \Chill\PersonBundle\Form\MaritalStatusType::class, 'controller' => \Chill\PersonBundle\Controller\AdminMaritalStatusController::class, 'actions' => [ 'index' => [ 'role' => 'ROLE_ADMIN', 'template' => '@ChillPerson/MaritalStatus/index.html.twig', ], 'new' => [ 'role' => 'ROLE_ADMIN', 'template' => '@ChillPerson/MaritalStatus/new.html.twig', ], 'edit' => [ 'role' => 'ROLE_ADMIN', 'template' => '@ChillPerson/MaritalStatus/edit.html.twig', ] ] ], ], 'apis' => [ [ 'class' => \Chill\PersonBundle\Entity\AccompanyingPeriod::class, 'name' => 'accompanying_course', 'base_path' => '/api/1.0/person/accompanying-course', 'controller' => \Chill\PersonBundle\Controller\AccompanyingCourseApiController::class, 'actions' => [ '_entity' => [ 'roles' => [ Request::METHOD_GET => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, Request::METHOD_PATCH => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, Request::METHOD_PUT => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, ], 'methods' => [ Request::METHOD_GET => true, Request::METHOD_PUT => true, Request::METHOD_PATCH => true, ] ], 'participation' => [ 'methods' => [ Request::METHOD_POST => true, Request::METHOD_DELETE => true, Request::METHOD_GET => false, Request::METHOD_HEAD => false, ], 'roles' => [ Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE ] ], 'resource' => [ 'methods' => [ Request::METHOD_POST => true, Request::METHOD_DELETE => true, Request::METHOD_GET => false, Request::METHOD_HEAD => false, ], 'roles' => [ Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE ] ], 'comment' => [ 'methods' => [ Request::METHOD_POST => true, Request::METHOD_DELETE => true, Request::METHOD_GET => false, Request::METHOD_HEAD => false, ], 'roles' => [ Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE ] ], 'requestor' => [ 'methods' => [ Request::METHOD_POST => true, Request::METHOD_DELETE => true, Request::METHOD_GET => false, Request::METHOD_HEAD => false, ], 'roles' => [ Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE ] ], 'scope' => [ 'methods' => [ Request::METHOD_POST => true, Request::METHOD_DELETE => true, Request::METHOD_GET => false, Request::METHOD_HEAD => false, ], 'roles' => [ Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE ] ], 'socialissue' => [ 'methods' => [ Request::METHOD_POST => true, Request::METHOD_DELETE => true, Request::METHOD_GET => false, Request::METHOD_HEAD => false, ], 'controller_action' => 'socialIssueApi', 'roles' => [ Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE ] ], 'work' => [ 'methods' => [ Request::METHOD_POST => true, Request::METHOD_DELETE => false, Request::METHOD_GET => false, Request::METHOD_HEAD => false, ], 'controller_action' => 'workApi', 'roles' => [ Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, Request::METHOD_DELETE => 'ALWAYS_FAILS', ] ], 'confirm' => [ 'methods' => [ Request::METHOD_POST => true, Request::METHOD_GET => false, Request::METHOD_HEAD => false, ], 'roles' => [ Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, ] ], ] ], [ 'class' => \Chill\PersonBundle\Entity\AccompanyingPeriod\Origin::class, 'name' => 'accompanying_period_origin', 'base_path' => '/api/1.0/person/accompanying-period/origin', 'controller' => \Chill\PersonBundle\Controller\OpeningApiController::class, 'base_role' => 'ROLE_USER', 'actions' => [ '_index' => [ 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true ], ], '_entity' => [ 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true ] ], ] ], [ 'class' => \Chill\PersonBundle\Entity\SocialWork\SocialIssue::class, 'name' => 'social_work_social_issue', 'base_path' => '/api/1.0/person/social-work/social-issue', 'base_role' => 'ROLE_USER', 'actions' => [ '_index' => [ 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true ], ], '_entity' => [ 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true ] ], ] ], [ 'class' => \Chill\PersonBundle\Entity\Person::class, 'name' => 'person', 'base_path' => '/api/1.0/person/person', 'base_role' => \Chill\PersonBundle\Security\Authorization\PersonVoter::SEE, 'controller' => \Chill\PersonBundle\Controller\PersonApiController::class, 'actions' => [ '_entity' => [ 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true, Request::METHOD_POST=> true, ], 'roles' => [ Request::METHOD_GET => \Chill\PersonBundle\Security\Authorization\PersonVoter::SEE, Request::METHOD_HEAD => \Chill\PersonBundle\Security\Authorization\PersonVoter::SEE, Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\PersonVoter::CREATE, ], ], 'address' => [ 'methods' => [ Request::METHOD_POST => true, Request::METHOD_DELETE => true, Request::METHOD_GET => false, Request::METHOD_HEAD => false, ], 'controller_action' => 'personAddressApi' ], ] ], [ 'class' => \Chill\PersonBundle\Entity\Household\Household::class, 'controller' => \Chill\PersonBundle\Controller\HouseholdApiController::class, 'name' => 'household', 'base_path' => '/api/1.0/person/household', 'base_role' => 'ROLE_USER', 'actions' => [ '_index' => [ 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true, ], ], '_entity' => [ 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true, ] ], 'address' => [ 'methods' => [ Request::METHOD_POST => true, Request::METHOD_DELETE => true, Request::METHOD_GET => false, Request::METHOD_HEAD => false, ], 'controller_action' => 'householdAddressApi' ], ] ], [ 'class' => \Chill\PersonBundle\Entity\SocialWork\SocialAction::class, 'name' => 'social_action', 'base_path' => '/api/1.0/person/social/social-action', 'controller' => \Chill\PersonBundle\Controller\SocialWorkSocialActionApiController::class, // TODO: acl 'base_role' => 'ROLE_USER', 'actions' => [ '_entity' => [ 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true, ], 'roles' => [ Request::METHOD_GET => 'ROLE_USER', Request::METHOD_HEAD => 'ROLE_USER', ] ], '_index' => [ 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true, ], 'roles' => [ Request::METHOD_GET => 'ROLE_USER', Request::METHOD_HEAD => 'ROLE_USER', ] ], 'listBySocialIssue' => [ 'single-collection' => 'collection', 'path' => '/by-social-issue/{id}.{_format}', 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true, ], 'roles' => [ Request::METHOD_GET => 'ROLE_USER', Request::METHOD_HEAD => 'ROLE_USER', ] ] ] ], [ 'class' => \Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork::class, 'name' => 'accompanying_period_work', 'base_path' => '/api/1.0/person/accompanying-course/work', 'controller' => \Chill\PersonBundle\Controller\AccompanyingCourseWorkApiController::class, // TODO: acl 'base_role' => 'ROLE_USER', 'actions' => [ '_entity' => [ 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true, Request::METHOD_PATCH => true, Request::METHOD_PUT => true, ], 'roles' => [ Request::METHOD_GET => 'ROLE_USER', Request::METHOD_HEAD => 'ROLE_USER', Request::METHOD_PATCH => 'ROLE_USER', Request::METHOD_PUT => 'ROLE_USER', ] ], ] ], [ 'class' => \Chill\PersonBundle\Entity\SocialWork\Result::class, 'controller' => \Chill\PersonBundle\Controller\SocialWorkResultApiController::class, 'name' => 'social_work_result', 'base_path' => '/api/1.0/person/social-work/result', 'base_role' => 'ROLE_USER', 'actions' => [ '_entity' => [ 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true, ], 'roles' => [ Request::METHOD_GET => 'ROLE_USER', Request::METHOD_HEAD => 'ROLE_USER', ] ], '_index' => [ 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true, ], 'roles' => [ Request::METHOD_GET => 'ROLE_USER', Request::METHOD_HEAD => 'ROLE_USER', ] ], 'by-social-action' => [ 'single-collection' => 'collection', 'path' => '/by-social-action/{id}.{_format}', 'controller_action' => 'listBySocialAction', 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true, ], 'roles' => [ Request::METHOD_GET => 'ROLE_USER', Request::METHOD_HEAD => 'ROLE_USER', ] ], 'by-goal' => [ 'single-collection' => 'collection', 'path' => '/by-goal/{id}.{_format}', 'controller_action' => 'listByGoal', 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true, ], 'roles' => [ Request::METHOD_GET => 'ROLE_USER', Request::METHOD_HEAD => 'ROLE_USER', ] ], ] ], [ 'class' => \Chill\PersonBundle\Entity\SocialWork\Goal::class, 'controller' => \Chill\PersonBundle\Controller\SocialWorkGoalApiController::class, 'name' => 'social_work_goal', 'base_path' => '/api/1.0/person/social-work/goal', 'base_role' => 'ROLE_USER', 'actions' => [ '_entity' => [ 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true, ], 'roles' => [ Request::METHOD_GET => 'ROLE_USER', Request::METHOD_HEAD => 'ROLE_USER', ] ], '_index' => [ 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true, ], 'roles' => [ Request::METHOD_GET => 'ROLE_USER', Request::METHOD_HEAD => 'ROLE_USER', ] ], 'by-social-action' => [ 'single-collection' => 'collection', 'path' => '/by-social-action/{id}.{_format}', 'controller_action' => 'listBySocialAction', 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true, ], 'roles' => [ Request::METHOD_GET => 'ROLE_USER', Request::METHOD_HEAD => 'ROLE_USER', ] ], ] ], ] ]); } }