From 6c47ce53e7ef3848861eb329c6497381da9dcb0c Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Tue, 14 Sep 2021 15:06:22 +0200 Subject: [PATCH 01/37] chore: Remove duplicated entry from composer.json. --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index 88e3c520a..ab244d40d 100644 --- a/composer.json +++ b/composer.json @@ -53,7 +53,6 @@ "symfony/validator": "4.*", "sensio/framework-extra-bundle": "^5.5", "symfony/yaml": "4.*", - "symfony/webpack-encore-bundle": "^1.11", "knplabs/knp-menu": "^3.1", "knplabs/knp-menu-bundle": "^3.0", "symfony/templating": "4.*", From fe533bc716105660d8c98ee1f2b1a98dacab1676 Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Tue, 14 Sep 2021 15:07:23 +0200 Subject: [PATCH 02/37] chore: Normalize `composer.json` file. --- composer.json | 116 +++++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/composer.json b/composer.json index ab244d40d..a2aa29a5a 100644 --- a/composer.json +++ b/composer.json @@ -1,12 +1,69 @@ { "name": "chill-project/chill-bundles", - "license": "AGPL-3.0-only", "type": "library", "description": "Most used bundles for chill-project", "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", + "doctrine/doctrine-bundle": "^2.1", + "doctrine/doctrine-migrations-bundle": "^3.0", + "doctrine/orm": "^2.7", + "erusev/parsedown": "^1.7", + "graylog2/gelf-php": "^1.5", + "knplabs/knp-menu": "^3.1", + "knplabs/knp-menu-bundle": "^3.0", + "knplabs/knp-time-bundle": "^1.12", + "league/csv": "^9.7.1", + "nyholm/psr7": "^1.4", + "phpoffice/phpspreadsheet": "^1.16", + "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/monolog-bundle": "^3.5", + "symfony/security-bundle": "4.*", + "symfony/serializer": "^5.2", + "symfony/swiftmailer-bundle": "^3.5", + "symfony/templating": "4.*", + "symfony/translation": "4.*", + "symfony/twig-bundle": "^4.4", + "symfony/validator": "4.*", + "symfony/webpack-encore-bundle": "^1.11", + "symfony/workflow": "4.*", + "symfony/yaml": "4.*", + "twig/extra-bundle": "^2.12 || ^3.0", + "twig/intl-extra": "^3.0", + "twig/markdown-extra": "^3.3", + "twig/twig": "^2.12 || ^3.0" + }, + "conflict": { + "symfony/symfony": "*" + }, + "require-dev": { + "doctrine/doctrine-fixtures-bundle": "^3.3", + "fakerphp/faker": "^1.13", + "nelmio/alice": "^3.8", + "phpunit/phpunit": "^7.0", + "symfony/debug-bundle": "^5.1", + "symfony/dotenv": "^5.1", + "symfony/maker-bundle": "^1.20", + "symfony/phpunit-bridge": "^5.2", + "symfony/stopwatch": "^5.1", + "symfony/var-dumper": "4.*", + "symfony/web-profiler-bundle": "^5.0" + }, + "config": { + "bin-dir": "bin" + }, "autoload": { "psr-4": { "Chill\\ActivityBundle\\": "src/Bundle/ChillActivityBundle", @@ -33,67 +90,10 @@ }, "minimum-stability": "dev", "prefer-stable": true, - "require": { - "champs-libres/async-uploader-bundle": "dev-sf4", - "champs-libres/wopi-bundle": "dev-master", - "nyholm/psr7": "^1.4", - "graylog2/gelf-php": "^1.5", - "symfony/form": "4.*", - "symfony/twig-bundle": "^4.4", - "twig/extra-bundle": "^2.12|^3.0", - "twig/twig": "^2.12|^3.0", - "composer/package-versions-deprecated": "^1.10", - "doctrine/doctrine-bundle": "^2.1", - "doctrine/doctrine-migrations-bundle": "^3.0", - "doctrine/orm": "^2.7", - "symfony/asset": "4.*", - "symfony/monolog-bundle": "^3.5", - "symfony/security-bundle": "4.*", - "symfony/translation": "4.*", - "symfony/validator": "4.*", - "sensio/framework-extra-bundle": "^5.5", - "symfony/yaml": "4.*", - "knplabs/knp-menu": "^3.1", - "knplabs/knp-menu-bundle": "^3.0", - "symfony/templating": "4.*", - "twig/intl-extra": "^3.0", - "symfony/workflow": "4.*", - "symfony/expression-language": "4.*", - "knplabs/knp-time-bundle": "^1.12", - "symfony/intl": "4.*", - "symfony/swiftmailer-bundle": "^3.5", - "league/csv": "^9.7.1", - "phpoffice/phpspreadsheet": "^1.16", - "symfony/browser-kit": "^5.2", - "symfony/css-selector": "^5.2", - "twig/markdown-extra": "^3.3", - "erusev/parsedown": "^1.7", - "symfony/serializer": "^5.2", - "symfony/webpack-encore-bundle": "^1.11" - }, - "conflict": { - "symfony/symfony": "*" - }, - "require-dev": { - "fakerphp/faker": "^1.13", - "phpunit/phpunit": "^7.0", - "symfony/dotenv": "^5.1", - "symfony/maker-bundle": "^1.20", - "doctrine/doctrine-fixtures-bundle": "^3.3", - "symfony/stopwatch": "^5.1", - "symfony/web-profiler-bundle": "^5.0", - "symfony/var-dumper": "4.*", - "symfony/debug-bundle": "^5.1", - "symfony/phpunit-bridge": "^5.2", - "nelmio/alice": "^3.8" - }, "scripts": { "auto-scripts": { "cache:clear": "symfony-cmd", "assets:install %PUBLIC_DIR%": "symfony-cmd" } - }, - "config": { - "bin-dir": "bin" } } From 951d686366cd778374f32e9a835a13d2fc79725a Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Tue, 14 Sep 2021 15:08:00 +0200 Subject: [PATCH 03/37] refactor: Update WOPI related stuff based on upstream changes. --- src/Bundle/ChillWopiBundle/src/Resources/config/services.php | 2 +- src/Bundle/ChillWopiBundle/src/Service/Wopi/ChillWopi.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Bundle/ChillWopiBundle/src/Resources/config/services.php b/src/Bundle/ChillWopiBundle/src/Resources/config/services.php index a40796607..455e658e2 100644 --- a/src/Bundle/ChillWopiBundle/src/Resources/config/services.php +++ b/src/Bundle/ChillWopiBundle/src/Resources/config/services.php @@ -10,7 +10,7 @@ declare(strict_types=1); namespace Symfony\Component\DependencyInjection\Loader\Configurator; use ChampsLibres\AsyncUploaderBundle\TempUrl\TempUrlGeneratorInterface; -use ChampsLibres\WopiLib\WopiInterface; +use ChampsLibres\WopiLib\Service\Contract\WopiInterface; use Chill\WopiBundle\Service\Wopi\ChillWopi; return static function (ContainerConfigurator $container) { diff --git a/src/Bundle/ChillWopiBundle/src/Service/Wopi/ChillWopi.php b/src/Bundle/ChillWopiBundle/src/Service/Wopi/ChillWopi.php index bb0dfb8e2..fc4e526a1 100644 --- a/src/Bundle/ChillWopiBundle/src/Service/Wopi/ChillWopi.php +++ b/src/Bundle/ChillWopiBundle/src/Service/Wopi/ChillWopi.php @@ -11,7 +11,7 @@ namespace Chill\WopiBundle\Service\Wopi; use ChampsLibres\AsyncUploaderBundle\TempUrl\TempUrlGeneratorInterface; use ChampsLibres\WopiLib\Discovery\WopiDiscoveryInterface; -use ChampsLibres\WopiLib\WopiInterface; +use ChampsLibres\WopiLib\Service\Contract\WopiInterface; use Chill\DocStoreBundle\Repository\StoredObjectRepository; use Exception; use loophp\psr17\Psr17Interface; @@ -228,7 +228,7 @@ final class ChillWopi implements WopiInterface ->withBody($this->psr17->createStream((string) json_encode([]))); } - public function putRelativeFile(string $fileId, ?string $accessToken, RequestInterface $request): ResponseInterface + public function putRelativeFile(string $fileId, string $accessToken, ?string $suggestedTarget, ?string $relativeTarget, bool $overwriteRelativeTarget, int $size, RequestInterface $request): ResponseInterface { return $this->getDebugResponse(__FUNCTION__, $request); } From 03e86245281d01c1ad9ca37cbb7fd45392814494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 1 Sep 2021 14:03:23 +0200 Subject: [PATCH 04/37] entity person: allow center to be not null --- .../ChillPersonBundle/Entity/Person.php | 1 - .../migrations/Version20210831140339.php | 29 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/Bundle/ChillPersonBundle/migrations/Version20210831140339.php diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php index 35db2ef83..5bfe3bd10 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person.php @@ -254,7 +254,6 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @var Center * * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Center") - * @ORM\JoinColumn(nullable=false) */ private $center; diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20210831140339.php b/src/Bundle/ChillPersonBundle/migrations/Version20210831140339.php new file mode 100644 index 000000000..dd3a60d75 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20210831140339.php @@ -0,0 +1,29 @@ +addSql('ALTER TABLE chill_person_person ALTER center_id DROP NOT NULL'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_person_person ALTER center_id SET NOT NULL'); + } +} From eec798cfd3b908de56b591a406e8f5f50a9237df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 1 Sep 2021 14:04:40 +0200 Subject: [PATCH 05/37] entity person: create a validator to check a person entity is linked with a center This validator take a parameter in configuration --- .../ChillPersonExtension.php | 3 ++ .../DependencyInjection/Configuration.php | 33 ++++++------ .../Person/PersonHasCenterValidatorTest.php | 50 +++++++++++++++++++ .../Constraints/Person/PersonHasCenter.php | 15 ++++++ .../Person/PersonHasCenterValidator.php | 41 +++++++++++++++ 5 files changed, 127 insertions(+), 15 deletions(-) create mode 100644 src/Bundle/ChillPersonBundle/Tests/Validator/Person/PersonHasCenterValidatorTest.php create mode 100644 src/Bundle/ChillPersonBundle/Validator/Constraints/Person/PersonHasCenter.php create mode 100644 src/Bundle/ChillPersonBundle/Validator/Constraints/Person/PersonHasCenterValidator.php diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php index 07d5dc88f..48ac993c3 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php @@ -60,6 +60,9 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac $container->setParameter('chill_person.allow_multiple_simultaneous_accompanying_periods', $config['allow_multiple_simultaneous_accompanying_periods']); + // register all configuration in a unique parameter + $container->setParameter('chill_person', $config); + $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config')); $loader->load('services.yaml'); $loader->load('services/widgets.yaml'); diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php index 927612d5f..7daec4f63 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php @@ -44,22 +44,25 @@ class Configuration implements ConfigurationInterface ->canBeDisabled() ->children() ->scalarNode('birthdate_not_after') - ->info($this->validationBirthdateNotAfterInfos) - ->defaultValue('P1D') - ->validate() - ->ifTrue(function($period) { - try { - $interval = new \DateInterval($period); - } catch (\Exception $ex) { - return true; - } - return false; - }) - ->thenInvalid('Invalid period for birthdate validation : "%s" ' - . 'The parameter should match duration as defined by ISO8601 : ' - . 'https://en.wikipedia.org/wiki/ISO_8601#Durations') + ->info($this->validationBirthdateNotAfterInfos) + ->defaultValue('P1D') + ->validate() + ->ifTrue(function($period) { + try { + $interval = new \DateInterval($period); + } catch (\Exception $ex) { + return true; + } + return false; + }) + ->thenInvalid('Invalid period for birthdate validation : "%s" ' + . 'The parameter should match duration as defined by ISO8601 : ' + . 'https://en.wikipedia.org/wiki/ISO_8601#Durations') ->end() // birthdate_not_after, parent = children of validation - + ->booleanNode('center_required') + ->info('Enable a center for each person entity. If disabled, you must provide your own center provider') + ->defaultValue(true) + ->end() ->end() // children for 'validation', parent = validation ->end() //validation, parent = children of root ->end() // children of root, parent = root diff --git a/src/Bundle/ChillPersonBundle/Tests/Validator/Person/PersonHasCenterValidatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Validator/Person/PersonHasCenterValidatorTest.php new file mode 100644 index 000000000..8cd0e6b83 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Validator/Person/PersonHasCenterValidatorTest.php @@ -0,0 +1,50 @@ +getConstraint(); + $personHasCenter = (new Person())->setCenter(new Center()); + $personNoCenter = new Person(); + + $this->validator->validate($personHasCenter, $constraint); + $this->assertNoViolation(); + + $this->validator->validate($personNoCenter, $constraint); + $this->buildViolation('msg') + ->atPath('property.path.center') + ->assertRaised(); + } + + protected function getConstraint() + { + return new PersonHasCenter([ + 'message' => 'msg' + ]); + } + + protected function createValidator() + { + $parameterBag = $this->createMock(ParameterBagInterface::class); + $parameterBag + ->method('get') + ->with($this->equalTo('chill_person')) + ->willReturn([ + 'validation' => [ + 'center_required' => true + ] + ]) + ; + + return new PersonHasCenterValidator($parameterBag); + } +} diff --git a/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/PersonHasCenter.php b/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/PersonHasCenter.php new file mode 100644 index 000000000..c6c8c7c14 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/PersonHasCenter.php @@ -0,0 +1,15 @@ +centerRequired = $parameterBag->get('chill_person')['validation']['center_required']; + } + + /** + * @inheritDoc + */ + public function validate($person, Constraint $constraint) + { + if (!$person instanceof Person) { + throw new UnexpectedTypeException($constraint, Person::class); + } + + if (!$this->centerRequired) { + return; + } + + if (NULL === $person->getCenter()) { + $this + ->context + ->buildViolation($constraint->message) + ->atPath('center') + ->addViolation() + ; + } + } +} From 7faddbe3feaf7b41b0bec1613909d3598fe54e68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 1 Sep 2021 14:41:27 +0200 Subject: [PATCH 06/37] move birthday validator to namespace person + rewrite tests --- .../Validator/BirthdateValidatorTest.php | 112 ------------------ .../Person/BirthdateValidatorTest.php | 72 +++++++++++ .../Constraints/{ => Person}/Birthdate.php | 11 +- .../{ => Person}/BirthdateValidator.php | 22 ++-- 4 files changed, 86 insertions(+), 131 deletions(-) delete mode 100644 src/Bundle/ChillPersonBundle/Tests/Validator/BirthdateValidatorTest.php create mode 100644 src/Bundle/ChillPersonBundle/Tests/Validator/Person/BirthdateValidatorTest.php rename src/Bundle/ChillPersonBundle/Validator/Constraints/{ => Person}/Birthdate.php (89%) rename src/Bundle/ChillPersonBundle/Validator/Constraints/{ => Person}/BirthdateValidator.php (94%) diff --git a/src/Bundle/ChillPersonBundle/Tests/Validator/BirthdateValidatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Validator/BirthdateValidatorTest.php deleted file mode 100644 index 57b4c2577..000000000 --- a/src/Bundle/ChillPersonBundle/Tests/Validator/BirthdateValidatorTest.php +++ /dev/null @@ -1,112 +0,0 @@ - - * - * 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\Tests\Validator; - -use Chill\PersonBundle\Validator\Constraints\BirthdateValidator; -use Chill\PersonBundle\Validator\Constraints\Birthdate; -use Prophecy\Argument; -use Prophecy\Prophet; - -/** - * Test the behaviour of BirthdayValidator - * - * @author Julien Fastré - */ -class BirthdateValidatorTest extends \PHPUnit\Framework\TestCase -{ - /** - * A prophecy for \Symfony\Component\Validator\Context\ExecutionContextInterface - * - * Will reveal \Symfony\Component\Validator\Context\ExecutionContextInterface - */ - private $context; - - private $prophet; - - /** - * - * @var Birthdate - */ - private $constraint; - - public function setUp() - { - $this->prophet = new Prophet; - - $constraintViolationBuilder = $this->prophet->prophesize(); - $constraintViolationBuilder->willImplement('Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface'); - - $constraintViolationBuilder->setParameter(Argument::any(), Argument::any()) - ->willReturn($constraintViolationBuilder->reveal()); - $constraintViolationBuilder->addViolation() - ->willReturn($constraintViolationBuilder->reveal()); - - $this->context = $this->prophet->prophesize(); - $this->context->willImplement('Symfony\Component\Validator\Context\ExecutionContextInterface'); - $this->context->buildViolation(Argument::type('string')) - ->willReturn($constraintViolationBuilder->reveal()); - - $this->constraint = new Birthdate(); - } - - public function testValidBirthDate() - { - - $date = new \DateTime('2015-01-01'); - - $birthdateValidator = new BirthdateValidator(); - $birthdateValidator->initialize($this->context->reveal()); - - $birthdateValidator->validate($date, $this->constraint); - - $this->context->buildViolation(Argument::any())->shouldNotHaveBeenCalled(); - } - - public function testInvalidBirthDate() - { - $date = new \DateTime('tomorrow'); - - $birthdateValidator = new BirthdateValidator(); - $birthdateValidator->initialize($this->context->reveal()); - - $birthdateValidator->validate($date, $this->constraint); - - $this->context->buildViolation(Argument::type('string'))->shouldHaveBeenCalled(); - } - - public function testInvalidBirthDateWithParameter() - { - $date = (new \DateTime('today'))->sub(new \DateInterval('P1M')); - - $birthdateValidator = new BirthdateValidator('P1Y'); - $birthdateValidator->initialize($this->context->reveal()); - - $birthdateValidator->validate($date, $this->constraint); - - $this->context->buildViolation(Argument::type('string'))->shouldHaveBeenCalled(); - } - - public function tearDown() - { - $this->prophet->checkPredictions(); - } - - -} diff --git a/src/Bundle/ChillPersonBundle/Tests/Validator/Person/BirthdateValidatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Validator/Person/BirthdateValidatorTest.php new file mode 100644 index 000000000..2e7df4817 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Validator/Person/BirthdateValidatorTest.php @@ -0,0 +1,72 @@ + + * + * 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\Tests\Validator\Person; + +use Chill\PersonBundle\Validator\Constraints\Person\BirthdateValidator; +use Chill\PersonBundle\Validator\Constraints\Person\Birthdate; +use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; +use Chill\PersonBundle\Entity\Person; + +/** + * Test the behaviour of BirthdayValidator + * + * @author Julien Fastré + */ +class BirthdateValidatorTest extends ConstraintValidatorTestCase +{ + + public function testValidateTodayInvalid() + { + $bornToday = new \DateTime('now'); + $this->validator->validate($bornToday, $this->createConstraint()); + $this->buildViolation('msg') + ->setParameter('%date%', (new \DateTime('yesterday'))->format('d-m-Y')) + ->assertRaised(); + } + + public function testValidateYesterdayValid() + { + $bornYesterday = new \DateTime('yesterday'); + $this->validator->validate($bornYesterday, $this->createConstraint()); + $this->assertNoViolation(); + } + + public function testTomorrowInvalid() + { + $bornAfter = new \DateTime('+2 days'); + $this->validator->validate($bornAfter, $this->createConstraint()); + $this->buildViolation('msg') + ->setParameter('%date%', (new \DateTime('yesterday'))->format('d-m-Y')) + ->assertRaised(); + } + + private function createConstraint() + { + return new Birthdate([ + 'message' => 'msg' + ]); + } + + + protected function createValidator() + { + return new BirthdateValidator('P1D'); + } +} diff --git a/src/Bundle/ChillPersonBundle/Validator/Constraints/Birthdate.php b/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/Birthdate.php similarity index 89% rename from src/Bundle/ChillPersonBundle/Validator/Constraints/Birthdate.php rename to src/Bundle/ChillPersonBundle/Validator/Constraints/Person/Birthdate.php index d09d549fd..b8cf6d8c2 100644 --- a/src/Bundle/ChillPersonBundle/Validator/Constraints/Birthdate.php +++ b/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/Birthdate.php @@ -17,14 +17,14 @@ * along with this program. If not, see . */ -namespace Chill\PersonBundle\Validator\Constraints; +namespace Chill\PersonBundle\Validator\Constraints\Person; use Symfony\Component\Validator\Constraint; /** * Create a constraint on birth date: the birthdate after today are not allowed. - * - * It is possible to add a delay before today, expressed as described in + * + * It is possible to add a delay before today, expressed as described in * interval_spec : http://php.net/manual/en/dateinterval.construct.php * (this interval_spec itself is based on ISO8601 : * https://en.wikipedia.org/wiki/ISO_8601#Durations) @@ -34,9 +34,4 @@ use Symfony\Component\Validator\Constraint; class Birthdate extends Constraint { public $message = "The birthdate must be before %date%"; - - public function validatedBy() - { - return 'birthdate_not_before'; - } } diff --git a/src/Bundle/ChillPersonBundle/Validator/Constraints/BirthdateValidator.php b/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/BirthdateValidator.php similarity index 94% rename from src/Bundle/ChillPersonBundle/Validator/Constraints/BirthdateValidator.php rename to src/Bundle/ChillPersonBundle/Validator/Constraints/Person/BirthdateValidator.php index cba955ef6..5d16be230 100644 --- a/src/Bundle/ChillPersonBundle/Validator/Constraints/BirthdateValidator.php +++ b/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/BirthdateValidator.php @@ -17,49 +17,49 @@ * along with this program. If not, see . */ -namespace Chill\PersonBundle\Validator\Constraints; +namespace Chill\PersonBundle\Validator\Constraints\Person; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** - * + * * * @author Julien Fastré */ class BirthdateValidator extends ConstraintValidator { private $interval_spec = null; - + public function __construct($interval_spec = null) { $this->interval_spec = $interval_spec; } - + public function validate($value, Constraint $constraint) { if ($value === NULL) { - + return; } - + if (!$value instanceof \DateTime) { throw new \LogicException('The input should a be a \DateTime interface,' . (is_object($value) ? get_class($value) : gettype($value))); } - + $limitDate = $this->getLimitDate(); - + if ($limitDate < $value) { $this->context->buildViolation($constraint->message) ->setParameter('%date%', $limitDate->format('d-m-Y')) ->addViolation(); } - + } - + /** - * + * * @return \DateTime */ private function getLimitDate() From 41d76542b4682443e37da4f5a559baf695118313 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 1 Sep 2021 16:06:20 +0200 Subject: [PATCH 07/37] move validation on person into annotations --- .../DependencyInjection/Configuration.php | 32 +++---- .../ChillPersonBundle/Entity/Person.php | 84 +++++++++++++++++-- .../Person/BirthdateValidatorTest.php | 2 + .../Validator/Person/PersonValidationTest.php | 55 ++++++++++++ .../Constraints/Person/Birthdate.php | 4 +- .../Constraints/Person/BirthdateValidator.php | 1 + .../Constraints/Person/PersonHasCenter.php | 3 + .../ChillPersonBundle/config/services.yaml | 14 ++-- .../ChillPersonBundle/config/validation.yaml | 67 --------------- 9 files changed, 165 insertions(+), 97 deletions(-) create mode 100644 src/Bundle/ChillPersonBundle/Tests/Validator/Person/PersonValidationTest.php diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php index 7daec4f63..bf2d18922 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php @@ -43,26 +43,26 @@ class Configuration implements ConfigurationInterface ->arrayNode('validation') ->canBeDisabled() ->children() - ->scalarNode('birthdate_not_after') - ->info($this->validationBirthdateNotAfterInfos) - ->defaultValue('P1D') - ->validate() - ->ifTrue(function($period) { - try { - $interval = new \DateInterval($period); - } catch (\Exception $ex) { - return true; - } - return false; - }) - ->thenInvalid('Invalid period for birthdate validation : "%s" ' - . 'The parameter should match duration as defined by ISO8601 : ' - . 'https://en.wikipedia.org/wiki/ISO_8601#Durations') - ->end() // birthdate_not_after, parent = children of validation ->booleanNode('center_required') ->info('Enable a center for each person entity. If disabled, you must provide your own center provider') ->defaultValue(true) ->end() + ->scalarNode('birthdate_not_after') + ->info($this->validationBirthdateNotAfterInfos) + ->defaultValue('P1D') + ->validate() + ->ifTrue(function($period) { + try { + $interval = new \DateInterval($period); + } catch (\Exception $ex) { + return true; + } + return false; + }) + ->thenInvalid('Invalid period for birthdate validation : "%s" ' + . 'The parameter should match duration as defined by ISO8601 : ' + . 'https://en.wikipedia.org/wiki/ISO_8601#Durations') + ->end() // birthdate_not_after, parent = children of validation ->end() // children for 'validation', parent = validation ->end() //validation, parent = children of root ->end() // children of root, parent = root diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php index 5bfe3bd10..f42ca6f00 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person.php @@ -43,6 +43,11 @@ use Doctrine\Common\Collections\Criteria; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Serializer\Annotation\DiscriminatorMap; use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress; +use Symfony\Component\Validator\Constraints as Assert; +use Chill\PersonBundle\Validator\Constraints\Person\Birthdate; +use Chill\MainBundle\Validation\Constraint\PhonenumberConstraint; +use Chill\PersonBundle\Validator\Constraints\Person\PersonHasCenter; +use Chill\PersonBundle\Validator\Constraints\Household\HouseholdMembershipSequential; /** * Person Class @@ -57,6 +62,12 @@ use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress; * @DiscriminatorMap(typeProperty="type", mapping={ * "person"=Person::class * }) + * @PersonHasCenter( + * groups={"general", "creation"} + * ) + * @HouseholdMembershipSequential( + * groups={"household_memberships"} + * ) */ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateInterface { @@ -75,6 +86,13 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @var string * * @ORM\Column(type="string", length=255) + * @Assert\NotBlank( + * groups={"general", "creation"} + * ) + * @Assert\Length( + * max=255, + * groups={"general", "creation"} + * ) */ private $firstName; @@ -83,6 +101,13 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @var string * * @ORM\Column(type="string", length=255) + * @Assert\NotBlank( + * groups={"general", "creation"} + * ) + * @Assert\Length( + * max=255, + * groups={"general", "creation"} + * ) */ private $lastName; @@ -102,6 +127,12 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @var \DateTime * * @ORM\Column(type="date", nullable=true) + * @Assert\Date( + * groups={"general", "creation"} + * ) + * @Birthdate( + * groups={"general", "creation"} + * ) */ private $birthdate; @@ -110,6 +141,9 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @var \DateTimeImmutable * * @ORM\Column(type="date_immutable", nullable=true) + * @Assert\Date( + * groups={"general", "creation"} + * ) */ private ?\DateTimeImmutable $deathdate; @@ -150,6 +184,9 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @var string * * @ORM\Column(type="string", length=9, nullable=true) + * @Assert\NotNull( + * groups={"general", "creation"} + * ) */ private $gender; @@ -179,8 +216,11 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @var \DateTime * * @ORM\Column(type="date", nullable=true) + * @Assert\Date( + * groups={"general", "creation"} + * ) */ - private $maritalStatusDate; + private ?\DateTime $maritalStatusDate; /** * Comment on marital status @@ -202,6 +242,10 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @var string * * @ORM\Column(type="text", nullable=true) + * @Assert\Email( + * checkMX=true, + * groups={"general", "creation"} + * ) */ private $email = ''; @@ -210,6 +254,14 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @var string * * @ORM\Column(type="text", length=40, nullable=true) + * @Assert\Regex( + * pattern="/^([\+{1}])([0-9\s*]{4,20})$/", + * groups={"general", "creation"} + * ) + * @PhonenumberConstraint( + * type="landline", + * groups={"general", "creation"} + * ) */ private $phonenumber = ''; @@ -218,6 +270,14 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @var string * * @ORM\Column(type="text", length=40, nullable=true) + * @Assert\Regex( + * pattern="/^([\+{1}])([0-9\s*]{4,20})$/", + * groups={"general", "creation"} + * ) + * @PhonenumberConstraint( + * type="mobile", + * groups={"general", "creation"} + * ) */ private $mobilenumber = ''; @@ -230,12 +290,13 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * cascade={"persist", "remove", "merge", "detach"}, * orphanRemoval=true * ) + * @Assert\Valid( + * traverse=true, + * groups={"general", "creation"} + * ) */ private $otherPhoneNumbers; - //TO-ADD caseOpeningDate - //TO-ADD nativeLanguag - /** * The person's spoken languages * @var ArrayCollection @@ -352,6 +413,8 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI private $addresses; /** + * fullname canonical. Read-only field, which is calculated by + * the database. * @var string * * @ORM\Column(type="text", nullable=true) @@ -372,6 +435,8 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI private array $currentHouseholdAt = []; /** + * Read-only field, computed by the database + * * @ORM\OneToMany( * targetEntity=PersonHouseholdAddress::class, * mappedBy="person" @@ -389,8 +454,6 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI /** * Person constructor. - * - * @param \DateTime|null $opening */ public function __construct() { @@ -403,6 +466,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI $this->householdAddresses = new ArrayCollection(); $this->genderComment = new CommentEmbeddable(); $this->maritalStatusComment = new CommentEmbeddable(); + $this->periodLocatedOn = new ArrayCollection(); } /** @@ -1200,6 +1264,10 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * Validation callback that checks if the accompanying periods are valid * * This method add violation errors. + * + * @Assert\Callback( + * groups={"accompanying_period_consistent"} + * ) */ public function isAccompanyingPeriodValid(ExecutionContextInterface $context) { @@ -1245,6 +1313,10 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * two addresses with the same validFrom date) * * This method add violation errors. + * + * @Assert\Callback( + * groups={"addresses_consistent"} + * ) */ public function isAddressesValid(ExecutionContextInterface $context) { diff --git a/src/Bundle/ChillPersonBundle/Tests/Validator/Person/BirthdateValidatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Validator/Person/BirthdateValidatorTest.php index 2e7df4817..6c726dd1c 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Validator/Person/BirthdateValidatorTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Validator/Person/BirthdateValidatorTest.php @@ -38,6 +38,7 @@ class BirthdateValidatorTest extends ConstraintValidatorTestCase $this->validator->validate($bornToday, $this->createConstraint()); $this->buildViolation('msg') ->setParameter('%date%', (new \DateTime('yesterday'))->format('d-m-Y')) + ->setCode('3f42fd96-0b2d-11ec-8cf3-0f3b1b1ca1c4') ->assertRaised(); } @@ -54,6 +55,7 @@ class BirthdateValidatorTest extends ConstraintValidatorTestCase $this->validator->validate($bornAfter, $this->createConstraint()); $this->buildViolation('msg') ->setParameter('%date%', (new \DateTime('yesterday'))->format('d-m-Y')) + ->setCode('3f42fd96-0b2d-11ec-8cf3-0f3b1b1ca1c4') ->assertRaised(); } diff --git a/src/Bundle/ChillPersonBundle/Tests/Validator/Person/PersonValidationTest.php b/src/Bundle/ChillPersonBundle/Tests/Validator/Person/PersonValidationTest.php new file mode 100644 index 000000000..8d6c930d9 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Validator/Person/PersonValidationTest.php @@ -0,0 +1,55 @@ +validator = self::$container->get(ValidatorInterface::class); + } + + public function testFirstnameValidation() + { + $person = (new Person()) + ->setFirstname(\str_repeat('a', 500)); + $errors = $this->validator->validate($person, null, ["creation"]); + foreach ($errors->getIterator() as $error) { + if (Length::TOO_LONG_ERROR === $error->getCode()) { + $this->assertTrue(true, + "error code for firstname too long is present"); + return; + } + } + $this->assertTrue(false, + "error code for fistname too long is present"); + + } + + public function testBirthdateInFuture() + { + $person = (new Person()) + ->setBirthdate(new \Datetime('+2 months')); + $errors = $this->validator->validate($person, null, ["creation"]); + foreach ($errors->getIterator() as $error) { + if (Birthdate::BIRTHDATE_INVALID_CODE === $error->getCode()) { + $this->assertTrue(true, + "error code for birthdate invalid is present"); + return; + } + } + $this->assertTrue(false, + "error code for birthdate invalid is present"); + + } + +} diff --git a/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/Birthdate.php b/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/Birthdate.php index b8cf6d8c2..20f3ed97b 100644 --- a/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/Birthdate.php +++ b/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/Birthdate.php @@ -29,9 +29,11 @@ use Symfony\Component\Validator\Constraint; * (this interval_spec itself is based on ISO8601 : * https://en.wikipedia.org/wiki/ISO_8601#Durations) * - * @author Julien Fastré + * @Annotation */ class Birthdate extends Constraint { + public const BIRTHDATE_INVALID_CODE = '3f42fd96-0b2d-11ec-8cf3-0f3b1b1ca1c4'; + public $message = "The birthdate must be before %date%"; } diff --git a/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/BirthdateValidator.php b/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/BirthdateValidator.php index 5d16be230..238a3d160 100644 --- a/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/BirthdateValidator.php +++ b/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/BirthdateValidator.php @@ -53,6 +53,7 @@ class BirthdateValidator extends ConstraintValidator if ($limitDate < $value) { $this->context->buildViolation($constraint->message) ->setParameter('%date%', $limitDate->format('d-m-Y')) + ->setCode(Birthdate::BIRTHDATE_INVALID_CODE) ->addViolation(); } diff --git a/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/PersonHasCenter.php b/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/PersonHasCenter.php index c6c8c7c14..5cabd8838 100644 --- a/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/PersonHasCenter.php +++ b/src/Bundle/ChillPersonBundle/Validator/Constraints/Person/PersonHasCenter.php @@ -2,6 +2,9 @@ namespace Chill\PersonBundle\Validator\Constraints\Person; +/** + * @Annotation + */ class PersonHasCenter extends \Symfony\Component\Validator\Constraint { public string $message = "A center is required"; diff --git a/src/Bundle/ChillPersonBundle/config/services.yaml b/src/Bundle/ChillPersonBundle/config/services.yaml index c2f60a729..bf4b8ddd8 100644 --- a/src/Bundle/ChillPersonBundle/config/services.yaml +++ b/src/Bundle/ChillPersonBundle/config/services.yaml @@ -62,18 +62,18 @@ services: - { name: security.voter } - { name: chill.role } - chill.person.birthdate_validation: - class: Chill\PersonBundle\Validator\Constraints\BirthdateValidator + Chill\PersonBundle\Validator\Constraints\: + autowire: true + autoconfigure: true + resource: '../Validator/Constraints/' + + # override default config, must be loaded after resource + Chill\PersonBundle\Validator\Constraints\BirthdateValidator: arguments: - "%chill_person.validation.birtdate_not_before%" tags: - { name: validator.constraint_validator, alias: birthdate_not_before } - Chill\PersonBundle\Validator\Constraints\Household\HouseholdMembershipSequentialValidator: - autowire: true - tags: - - { name: validator.constraint_validator } - Chill\PersonBundle\Repository\: autowire: true autoconfigure: true diff --git a/src/Bundle/ChillPersonBundle/config/validation.yaml b/src/Bundle/ChillPersonBundle/config/validation.yaml index 23369a467..c41513778 100644 --- a/src/Bundle/ChillPersonBundle/config/validation.yaml +++ b/src/Bundle/ChillPersonBundle/config/validation.yaml @@ -1,70 +1,3 @@ -Chill\PersonBundle\Entity\Person: - properties: - firstName: - - NotBlank: - groups: [general, creation] - - Length: - min: 2 - max: 255 - minMessage: 'This name is too short. It must containt {{ limit }} chars' - maxMessage: 'This name is too long. It must containt {{ limit }} chars' - groups: [general, creation] - lastName: - - NotBlank: - groups: [general, creation] - - Length: - min: 2 - max: 255 - minMessage: 'This name is too short. It must containt {{ limit }} chars' - maxMessage: 'This name is too long. It must containt {{ limit }} chars' - groups: [general, creation] - birthdate: - - Date: - message: 'Birthdate not valid' - groups: [general, creation] - - Chill\PersonBundle\Validator\Constraints\Birthdate: - groups: [general, creation] - gender: - - NotNull: - groups: [general, creation] - #accompanyingPeriods: - # - Valid: - # traverse: true - email: - - Email: - groups: [general, creation] - message: 'The email is not valid' - checkMX: true - phonenumber: - - Regex: - pattern: '/^([\+{1}])([0-9\s*]{4,20})$/' - groups: [general, creation] - message: 'Invalid phone number: it should begin with the international prefix starting with "+", hold only digits and be smaller than 20 characters. Ex: +33123456789' - - Chill\MainBundle\Validation\Constraint\PhonenumberConstraint: - type: landline - groups: [ general, creation ] - mobilenumber: - - Regex: - pattern: '/^([\+{1}])([0-9\s*]{4,20})$/' - groups: [general, creation] - message: 'Invalid phone number: it should begin with the international prefix starting with "+", hold only digits and be smaller than 20 characters. Ex: +33623456789' - - Chill\MainBundle\Validation\Constraint\PhonenumberConstraint: - type: mobile - groups: [ general, creation ] - otherPhoneNumbers: - - Valid: - traverse: true - constraints: - - Callback: - callback: isAccompanyingPeriodValid - groups: [accompanying_period_consistent] - - Callback: - callback: isAddressesValid - groups: [addresses_consistent] - - Chill\PersonBundle\Validator\Constraints\Household\HouseholdMembershipSequential: - groups: [ 'household_memberships' ] - - Chill\PersonBundle\Entity\AccompanyingPeriod: properties: openingDate: From 24506554523dd0997ef257637d64ae5e01dc464e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 1 Sep 2021 17:04:24 +0200 Subject: [PATCH 08/37] enable autoloading for form in person bundle --- .../Form/Type/Select2MaritalStatusType.php | 18 ++--- .../ChillPersonBundle/config/services.yaml | 8 --- .../config/services/form.yaml | 71 ++----------------- 3 files changed, 15 insertions(+), 82 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Form/Type/Select2MaritalStatusType.php b/src/Bundle/ChillPersonBundle/Form/Type/Select2MaritalStatusType.php index 0cff8ee51..34fd9897e 100644 --- a/src/Bundle/ChillPersonBundle/Form/Type/Select2MaritalStatusType.php +++ b/src/Bundle/ChillPersonBundle/Form/Type/Select2MaritalStatusType.php @@ -20,6 +20,9 @@ namespace Chill\PersonBundle\Form\Type; +use Chill\MainBundle\Templating\TranslatableStringHelper; +use Chill\PersonBundle\Entity\MaritalStatus; +use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\OptionsResolver; use Chill\MainBundle\Form\Type\DataTransformer\ObjectToIdTransformer; @@ -35,15 +38,13 @@ use Chill\MainBundle\Form\Type\Select2ChoiceType; */ class Select2MaritalStatusType extends AbstractType { - /** @var RequestStack */ - private $requestStack; + private EntityManagerInterface $em; - /** @var ObjectManager */ - private $em; + private TranslatableStringHelper $translatableStringHelper; - public function __construct(RequestStack $requestStack,ObjectManager $em) + public function __construct(TranslatableStringHelper $translatableStringHelper, EntityManagerInterface $em) { - $this->requestStack = $requestStack; + $this->translatableStringHelper = $translatableStringHelper; $this->em = $em; } @@ -63,18 +64,17 @@ class Select2MaritalStatusType extends AbstractType public function configureOptions(OptionsResolver $resolver) { - $locale = $this->requestStack->getCurrentRequest()->getLocale(); $maritalStatuses = $this->em->getRepository('Chill\PersonBundle\Entity\MaritalStatus')->findAll(); $choices = array(); foreach ($maritalStatuses as $ms) { - $choices[$ms->getId()] = $ms->getName()[$locale]; + $choices[$ms->getId()] = $this->translatableStringHelper->localize($ms->getName()); } asort($choices, SORT_STRING | SORT_FLAG_CASE); $resolver->setDefaults(array( - 'class' => 'Chill\PersonBundle\Entity\MaritalStatus', + 'class' => MaritalStatus::class, 'choices' => array_combine(array_values($choices),array_keys($choices)) )); } diff --git a/src/Bundle/ChillPersonBundle/config/services.yaml b/src/Bundle/ChillPersonBundle/config/services.yaml index bf4b8ddd8..43e042e6b 100644 --- a/src/Bundle/ChillPersonBundle/config/services.yaml +++ b/src/Bundle/ChillPersonBundle/config/services.yaml @@ -24,14 +24,6 @@ services: tags: - { name: console.command } - chill.person.form.type.select2maritalstatus: - class: Chill\PersonBundle\Form\Type\Select2MaritalStatusType - arguments: - - "@request_stack" - - "@doctrine.orm.entity_manager" - tags: - - { name: form.type, alias: select2_chill_marital_status } - chill.person.timeline.accompanying_period_opening: class: Chill\PersonBundle\Timeline\TimelineAccompanyingPeriodOpening arguments: diff --git a/src/Bundle/ChillPersonBundle/config/services/form.yaml b/src/Bundle/ChillPersonBundle/config/services/form.yaml index b61de615d..dacfa41de 100644 --- a/src/Bundle/ChillPersonBundle/config/services/form.yaml +++ b/src/Bundle/ChillPersonBundle/config/services/form.yaml @@ -1,5 +1,10 @@ services: + Chill\PersonBundle\Form\: + autowire: true + autoconfigure: true + resource: '../../Form/' + Chill\PersonBundle\Form\PersonType: arguments: - '%chill_person.person_fields%' @@ -7,14 +12,7 @@ services: tags: - { name: form.type, alias: '@chill.person.form.person_creation' } - Chill\PersonBundle\Form\CreationPersonType: - arguments: - - '@chill.main.form.data_transformer.center_transformer' - - '@Chill\PersonBundle\Config\ConfigPersonAltNamesHelper' - tags: - - { name: form.type, alias: '@chill.main.form.person_creation' } - - chill.person.accompanying_period_closing_motive: + Chill\PersonBundle\Form\Type\ClosingMotivePickerType: class: Chill\PersonBundle\Form\Type\ClosingMotivePickerType arguments: $translatableStringHelper: '@Chill\MainBundle\Templating\TranslatableStringHelper' @@ -28,60 +26,3 @@ services: $config: "%chill_person.accompanying_period_fields%" tags: - { name: form.type } - - chill.person.form.type.pick_person: - class: Chill\PersonBundle\Form\Type\PickPersonType - arguments: - - '@Chill\PersonBundle\Repository\PersonRepository' - - "@security.token_storage" - - "@chill.main.security.authorization.helper" - - '@Symfony\Component\Routing\Generator\UrlGeneratorInterface' - - '@Symfony\Component\Translation\TranslatorInterface' - tags: - - { name: form.type } - - Chill\PersonBundle\Form\Type\PersonAltNameType: - arguments: - $configHelper: '@Chill\PersonBundle\Config\ConfigPersonAltNamesHelper' - $translatableStringHelper: '@chill.main.helper.translatable_string' - tags: - - { name: form.type } - - Chill\PersonBundle\Form\Type\PersonPhoneType: - arguments: - $phonenumberHelper: '@Chill\MainBundle\Phonenumber\PhonenumberHelper' - $em: '@Doctrine\ORM\EntityManagerInterface' - tags: - - { name: form.type } - - Chill\PersonBundle\Form\SocialWork\SocialIssueType: - arguments: - $translatableStringHelper: '@chill.main.helper.translatable_string' - tags: - - { name: form.type } - - Chill\PersonBundle\Form\SocialWork\SocialActionType: - arguments: - $translatableStringHelper: '@chill.main.helper.translatable_string' - tags: - - { name: form.type } - - Chill\PersonBundle\Form\SocialWork\EvaluationType: - arguments: - $translatableStringHelper: '@chill.main.helper.translatable_string' - tags: - - { name: form.type } - - - Chill\PersonBundle\Form\SocialWork\GoalType: - arguments: - $translatableStringHelper: '@chill.main.helper.translatable_string' - tags: - - { name: form.type } - - - Chill\PersonBundle\Form\SocialWork\ResultType: - arguments: - $translatableStringHelper: '@chill.main.helper.translatable_string' - tags: - - { name: form.type } From 5b70fb2ee569b8dc186d8af616e50c77abeb7d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Fri, 3 Sep 2021 12:41:41 +0200 Subject: [PATCH 09/37] adapt UI and controller for Person without centers --- .../ChillMainBundle/Form/Type/CenterType.php | 7 ++- .../Resolver/CenterResolverDispatcher.php | 34 +++++++++++++ .../Resolver/CenterResolverInterface.php | 19 ++++++++ .../Resolver/DefaultCenterResolver.php | 30 ++++++++++++ .../Resolver/ResolverTwigExtension.php | 36 ++++++++++++++ .../translations/messages.fr.yml | 1 + .../Controller/PersonController.php | 15 +++--- .../Form/CreationPersonType.php | 22 ++++++--- .../Resources/views/Entity/person.html.twig | 4 +- .../views/Person/banner_custom.html.twig | 4 +- .../Resources/views/Person/create.html.twig | 7 ++- .../ChillPersonBundle/Search/PersonSearch.php | 17 ++++--- .../Security/Authorization/PersonVoter.php | 48 ++++++++++--------- .../config/services/security.yaml | 5 +- 14 files changed, 196 insertions(+), 53 deletions(-) create mode 100644 src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverDispatcher.php create mode 100644 src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverInterface.php create mode 100644 src/Bundle/ChillMainBundle/Security/Resolver/DefaultCenterResolver.php create mode 100644 src/Bundle/ChillMainBundle/Security/Resolver/ResolverTwigExtension.php diff --git a/src/Bundle/ChillMainBundle/Form/Type/CenterType.php b/src/Bundle/ChillMainBundle/Form/Type/CenterType.php index ba039c938..0366e8ccf 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/CenterType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/CenterType.php @@ -95,9 +95,12 @@ class CenterType extends AbstractType public function configureOptions(OptionsResolver $resolver) { if (count($this->reachableCenters) > 1) { - $resolver->setDefault('class', Center::class); - $resolver->setDefault('choices', $this->reachableCenters); + $resolver->setDefault('class', Center::class) + ->setDefault('choices', $this->reachableCenters) + ->setDefault('placeholder', 'Pick a center') + ; } + } /** diff --git a/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverDispatcher.php b/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverDispatcher.php new file mode 100644 index 000000000..6b1f2a897 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverDispatcher.php @@ -0,0 +1,34 @@ +resolvers = $resolvers; + } + + /** + * @param mixed $entity + * @param array|null $options + * @return null|Center|Center[] + */ + public function resolveCenter($entity, ?array $options = []) + { + foreach($this->resolvers as $priority => $resolver) { + if ($resolver->supports($entity, $options)) { + return $resolver->resolveCenter($entity, $options); + } + } + + return null; + } +} diff --git a/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverInterface.php b/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverInterface.php new file mode 100644 index 000000000..db49874b7 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Security/Resolver/CenterResolverInterface.php @@ -0,0 +1,19 @@ +getCenter(); + } + + public static function getDefaultPriority(): int + { + return -256; + } +} diff --git a/src/Bundle/ChillMainBundle/Security/Resolver/ResolverTwigExtension.php b/src/Bundle/ChillMainBundle/Security/Resolver/ResolverTwigExtension.php new file mode 100644 index 000000000..21ece21a3 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Security/Resolver/ResolverTwigExtension.php @@ -0,0 +1,36 @@ +centerResolverDispatcher = $centerResolverDispatcher; + } + + public function getFilters() + { + return [ + new TwigFilter('chill_resolve_center', [$this, 'resolveCenter']) + ]; + } + + /** + * @param mixed $entity + * @param array|null $options + * @return Center|Center[]|null + */ + public function resolveCenter($entity, ?array $options = []) + { + return $this->centerResolverDispatcher->resolveCenter($entity, $options); + } + +} diff --git a/src/Bundle/ChillMainBundle/translations/messages.fr.yml b/src/Bundle/ChillMainBundle/translations/messages.fr.yml index b230b6ac1..59dcd8c73 100644 --- a/src/Bundle/ChillMainBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillMainBundle/translations/messages.fr.yml @@ -177,6 +177,7 @@ Exports list: Liste des exports Create an export: Créer un export #export creation step 'center' : pick a center Pick centers: Choisir les centres +Pick a center: Choisir un centre The export will contains only data from the picked centers.: L'export ne contiendra que les données des centres choisis. This will eventually restrict your possibilities in filtering the data.: Les possibilités de filtrages seront adaptées aux droits de consultation pour les centres choisis. Go to export options: Vers la préparation de l'export diff --git a/src/Bundle/ChillPersonBundle/Controller/PersonController.php b/src/Bundle/ChillPersonBundle/Controller/PersonController.php index 759f892b2..03da97d5f 100644 --- a/src/Bundle/ChillPersonBundle/Controller/PersonController.php +++ b/src/Bundle/ChillPersonBundle/Controller/PersonController.php @@ -230,13 +230,16 @@ final class PersonController extends AbstractController */ public function newAction(Request $request) { - $defaultCenter = $this->security - ->getUser() - ->getGroupCenters()[0] - ->getCenter(); + $person = new Person(); - $person = (new Person(new \DateTime('now'))) - ->setCenter($defaultCenter); + if (1 === count($this->security->getUser() + ->getGroupCenters())) { + $person->setCenter( + $this->security->getUser() + ->getGroupCenters()[0] + ->getCenter() + ); + } $form = $this->createForm(CreationPersonType::class, $person, [ 'validation_groups' => ['create'] diff --git a/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php b/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php index 32b7a69f2..36d088c25 100644 --- a/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php +++ b/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php @@ -21,7 +21,9 @@ namespace Chill\PersonBundle\Form; +use Chill\MainBundle\Form\Event\CustomizeFormEvent; use Chill\PersonBundle\Entity\Person; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -33,6 +35,7 @@ use Chill\PersonBundle\Form\Type\GenderType; use Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer; use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper; use Chill\PersonBundle\Form\Type\PersonAltNameType; +use Chill\MainBundle\Form\Type\Export\PickCenterType; final class CreationPersonType extends AbstractType { @@ -40,10 +43,6 @@ final class CreationPersonType extends AbstractType // TODO: See if this is still valid and update accordingly. const NAME = 'chill_personbundle_person_creation'; - const FORM_NOT_REVIEWED = 'not_reviewed'; - const FORM_REVIEWED = 'reviewed' ; - const FORM_BEING_REVIEWED = 'being_reviewed'; - /** * * @var CenterTransformer @@ -56,12 +55,16 @@ final class CreationPersonType extends AbstractType */ protected $configPersonAltNamesHelper; + private EventDispatcherInterface $dispatcher; + public function __construct( CenterTransformer $centerTransformer, - ConfigPersonAltNamesHelper $configPersonAltNamesHelper + ConfigPersonAltNamesHelper $configPersonAltNamesHelper, + EventDispatcherInterface $dispatcher ) { $this->centerTransformer = $centerTransformer; $this->configPersonAltNamesHelper = $configPersonAltNamesHelper; + $this->dispatcher = $dispatcher; } /** @@ -79,7 +82,9 @@ final class CreationPersonType extends AbstractType ->add('gender', GenderType::class, array( 'required' => true, 'placeholder' => null )) - ->add('center', CenterType::class) + ->add('center', CenterType::class, [ + 'required' => false + ]) ; if ($this->configPersonAltNamesHelper->hasAltNames()) { @@ -87,6 +92,11 @@ final class CreationPersonType extends AbstractType 'by_reference' => false ]); } + + $this->dispatcher->dispatch( + new CustomizeFormEvent(static::class, $builder), + CustomizeFormEvent::NAME + ); } /** diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Entity/person.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Entity/person.html.twig index f60b7dc9e..612a5609c 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/Entity/person.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/Entity/person.html.twig @@ -146,10 +146,10 @@ {% endif %} {% endif %} - {% if options['addCenter'] %} + {% if options['addCenter'] and person|chill_resolve_center is not null %}
  • - {{ person.center }} + {{ person|chill_resolve_center.name }}
  • {% endif %} diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Person/banner_custom.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Person/banner_custom.html.twig index d01a53c22..564f1803e 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/Person/banner_custom.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/Person/banner_custom.html.twig @@ -17,11 +17,11 @@ {%- endif -%}
    - {%- if chill_person.fields.spoken_languages == 'visible' -%} + {% if person|chill_resolve_center is not null%} {{ 'Center'|trans|upper}} : - {{ person.center.name|upper }} + {{ person|chill_resolve_center.name|upper }} {%- endif -%}
    diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Person/create.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Person/create.html.twig index 7056f25a3..bd1042dd7 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/Person/create.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/Person/create.html.twig @@ -76,10 +76,9 @@ {{ form_row(form.gender, { 'label' : 'Gender'|trans }) }} -
    - {# TODO remove this field (vendee) #} - {{ form_row(form.center, { 'label' : 'Center'|trans }) }} -
    + {% if form.center is defined %} + {{ form_row(form.center) }} + {% endif %}