From 5c0ca70ebff671ef8580f7d5268cee4fc1b3c29b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Thu, 2 Feb 2017 22:32:02 +0100 Subject: [PATCH] add api to add a validation on export elements Exports elements should implements "ExportElementValidatedInterface" --- DependencyInjection/ChillMainExtension.php | 1 + Export/ExportElementValidatedInterface.php | 46 +++++++++++++++ Form/Type/Export/AggregatorType.php | 6 +- Form/Type/Export/ExportType.php | 57 ++++++++++++++++--- Form/Type/Export/FilterType.php | 12 +++- Resources/config/services/export.yml | 6 ++ Resources/translations/validators.fr.yml | 2 +- Resources/views/Export/new.html.twig | 3 + .../Export/ExportElementConstraint.php | 47 +++++++++++++++ .../ExportElementConstraintValidator.php | 40 +++++++++++++ 10 files changed, 209 insertions(+), 11 deletions(-) create mode 100644 Export/ExportElementValidatedInterface.php create mode 100644 Resources/config/services/export.yml create mode 100644 Validator/Constraints/Export/ExportElementConstraint.php create mode 100644 Validator/Constraints/Export/ExportElementConstraintValidator.php diff --git a/DependencyInjection/ChillMainExtension.php b/DependencyInjection/ChillMainExtension.php index 0399cc512..531716c35 100644 --- a/DependencyInjection/ChillMainExtension.php +++ b/DependencyInjection/ChillMainExtension.php @@ -90,6 +90,7 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface, $loader->load('services/logger.yml'); $loader->load('services/repositories.yml'); $loader->load('services/pagination.yml'); + $loader->load('services/export.yml'); } diff --git a/Export/ExportElementValidatedInterface.php b/Export/ExportElementValidatedInterface.php new file mode 100644 index 000000000..cbc2f3881 --- /dev/null +++ b/Export/ExportElementValidatedInterface.php @@ -0,0 +1,46 @@ + + * + * 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\MainBundle\Export; + +use Symfony\Component\Validator\Context\ExecutionContextInterface; + +/** + * Add a validation method to validate data collected by Export Element + * + * Implements this interface on other `ExportElementInterface` to validate + * the form submitted by users. + * + * **note**: When this interface is implemented on filters or aggregators, + * the form is validated **only** if the filter/aggregator is `enabled` by the + * user. + * + * @link http://symfony.com/doc/current/validation/custom_constraint.html#class-constraint-validator Example of building violations + * + * @author Julien Fastré + */ +interface ExportElementValidatedInterface +{ + /** + * validate the form's data and, if required, build a contraint + * violation on the data. + * + * @param mixed $data the data, as returned by the user + * @param ExecutionContextInterface $context + */ + public function validateForm($data, ExecutionContextInterface $context); +} diff --git a/Form/Type/Export/AggregatorType.php b/Form/Type/Export/AggregatorType.php index 92999a1b6..0d4280d91 100644 --- a/Form/Type/Export/AggregatorType.php +++ b/Form/Type/Export/AggregatorType.php @@ -55,7 +55,10 @@ class AggregatorType extends AbstractType )); $filterFormBuilder = $builder->create('form', 'form', array( - 'compound' => true, 'required' => false)); + 'compound' => true, + 'required' => false, + 'error_bubbling' => false + )); $aggregator->buildForm($filterFormBuilder); $builder->add($filterFormBuilder); @@ -66,6 +69,7 @@ class AggregatorType extends AbstractType { $resolver->setRequired('aggregator_alias') ->setDefault('compound', true) + ->setDefault('error_bubbling', false) ; } diff --git a/Form/Type/Export/ExportType.php b/Form/Type/Export/ExportType.php index 11e893c73..4bab1bcf2 100644 --- a/Form/Type/Export/ExportType.php +++ b/Form/Type/Export/ExportType.php @@ -29,6 +29,10 @@ use Chill\MainBundle\Export\ExportManager; use Chill\MainBundle\Form\Type\Export\FilterType; use Chill\MainBundle\Form\Type\Export\AggregatorType; use Symfony\Component\Form\Extension\Core\Type\FormType; +use Chill\MainBundle\Validator\Constraints\Export\ExportElementConstraint; +use Chill\MainBundle\Export\ExportElementWithValidationInterface; +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Context\ExecutionContextInterface; /** * @@ -57,11 +61,36 @@ class ExportType extends AbstractType { $export = $this->exportManager->getExport($options['export_alias']); - $exportBuilder = $builder->create(self::EXPORT_KEY, null, array('compound' => true)); - //if ($export->hasForm()) { - $export->buildForm($exportBuilder); - //} - $builder->add($exportBuilder); + $exportOptions = array( + 'compound' => true, + 'constraints' => array( + //new \Chill\MainBundle\Validator\Constraints\Export\ExportElementConstraint() +// new Assert\Callback(array( +// 'callback' => function($data, ExecutionContextInterface $context, $payload) use ($export) { +// dump('i call back'); +// } +// )) + ) + ); + + // add a contraint if required by export + /*if ($export instanceof ExportElementWithValidationInterface) { + dump('export instance of export element with validation'); + $exportOptions = array_merge($exportOptions, array( + 'constraints' => [new Assert\Callback([ + 'callback' => function($data, ExecutionContextInterface $context, $payload) use ($export) { + dump('i will execute callback'); + $export->validateForm($data[self::EXPORT_KEY], $context); + } + ])], + 'cascade_validation' => true + )); + } */; + $exportBuilder = $builder->create(self::EXPORT_KEY/*, FormType::class, $exportOptions*/); + + $export->buildForm($exportBuilder); + + $builder->add($exportBuilder, null, $exportOptions); //add filters $filters = $this->exportManager->getFiltersApplyingOn($export, $options['picked_centers']); @@ -70,7 +99,10 @@ class ExportType extends AbstractType foreach($filters as $alias => $filter) { $filterBuilder->add($alias, new FilterType($this->exportManager), array( 'filter_alias' => $alias, - 'label' => $filter->getTitle() + 'label' => $filter->getTitle(), + 'constraints' => array( + new ExportElementConstraint(['element' => $filter]) + ) )); } @@ -85,7 +117,10 @@ class ExportType extends AbstractType foreach($aggregators as $alias => $aggregator) { $aggregatorBuilder->add($alias, new AggregatorType($this->exportManager), array( 'aggregator_alias' => $alias, - 'label' => $aggregator->getTitle() + 'label' => $aggregator->getTitle(), + 'constraints' => array( + new ExportElementConstraint(['element' => $aggregator]) + ) )); } @@ -109,7 +144,15 @@ class ExportType extends AbstractType $resolver->setRequired(array('export_alias', 'picked_centers')) ->setAllowedTypes('export_alias', array('string')) ->setDefault('compound', true) + ->setDefault('constraints', array( + //new \Chill\MainBundle\Validator\Constraints\Export\ExportElementConstraint() + )) ; } + + public function getParent() + { + return FormType::class; + } } diff --git a/Form/Type/Export/FilterType.php b/Form/Type/Export/FilterType.php index 4e8a10e2d..bd23e664a 100644 --- a/Form/Type/Export/FilterType.php +++ b/Form/Type/Export/FilterType.php @@ -24,6 +24,10 @@ use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Form\FormBuilderInterface; use Chill\MainBundle\Export\ExportManager; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; +use Chill\MainBundle\Export\ExportElementWithValidationInterface; +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Context\ExecutionContextInterface; +use Symfony\Component\Form\Extension\Core\Type\FormType; /** * @@ -56,8 +60,11 @@ class FilterType extends AbstractType 'required' => false )); - $filterFormBuilder = $builder->create('form', null, array( - 'compound' => true, 'required' => false)); + $filterFormBuilder = $builder->create('form', FormType::class, array( + 'compound' => true, + 'error_bubbling' => false, + 'required' => false, + )); $filter->buildForm($filterFormBuilder); $builder->add($filterFormBuilder); @@ -68,6 +75,7 @@ class FilterType extends AbstractType { $resolver->setRequired('filter_alias') ->setDefault('compound', true) + ->setDefault('error_bubbling', false) ; } diff --git a/Resources/config/services/export.yml b/Resources/config/services/export.yml new file mode 100644 index 000000000..84925f97a --- /dev/null +++ b/Resources/config/services/export.yml @@ -0,0 +1,6 @@ +services: + chill.main.export_element_validator: + class: Chill\MainBundle\Validator\Constraints\Export\ExportElementConstraintValidator + tags: + - { name: validator.constraint_validator } + \ No newline at end of file diff --git a/Resources/translations/validators.fr.yml b/Resources/translations/validators.fr.yml index 1293504ba..d350da82c 100644 --- a/Resources/translations/validators.fr.yml +++ b/Resources/translations/validators.fr.yml @@ -3,4 +3,4 @@ The role "%role%" require to be associated with a scope.: Le rôle "%role%" doit être associé à un cercle. The role "%role%" should not be associated with a scope.: Le rôle "%role%" ne doit pas être associé à un cercle. "The password must contains one letter, one capitalized letter, one number and one special character as *[@#$%!,;:+\"'-/{}~=µ()£]). Other characters are allowed.": "Le mot de passe doit contenir une majuscule, une minuscule, et au moins un caractère spécial parmi *[@#$%!,;:+\"'-/{}~=µ()£]). Les autres caractères sont autorisés." -The password fields must match: Les mots de passe doivent correspondre \ No newline at end of file +The password fields must match: Les mots de passe doivent correspondre diff --git a/Resources/views/Export/new.html.twig b/Resources/views/Export/new.html.twig index 95983376d..42f952085 100644 --- a/Resources/views/Export/new.html.twig +++ b/Resources/views/Export/new.html.twig @@ -46,9 +46,11 @@
{{ form_widget(filter_form.form) }} + {{ form_errors(filter_form) }}
{% endfor %} + {{ form_errors(form.children.export.children.filters) }} {% else %} {# render the children, to mark the widget as 'rendered' #} @@ -67,6 +69,7 @@
{{ form_widget(aggregator_form.form) }} + {{ form_errors(aggregator_form) }}
{% endfor %} diff --git a/Validator/Constraints/Export/ExportElementConstraint.php b/Validator/Constraints/Export/ExportElementConstraint.php new file mode 100644 index 000000000..d00962e39 --- /dev/null +++ b/Validator/Constraints/Export/ExportElementConstraint.php @@ -0,0 +1,47 @@ + + * + * 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\MainBundle\Validator\Constraints\Export; + +use Symfony\Component\Validator\Constraint; + +/** + * Constraint which will check the ExportElement. + * + * @see ExportElementConstraintValidator + * @author Julien Fastré + */ +class ExportElementConstraint extends Constraint +{ + public $element; + + + public function validatedBy() + { + return ExportElementConstraintValidator::class; + } + + public function getRequiredOptions() + { + return array('element'); + } + + public function getTargets() + { + return self::PROPERTY_CONSTRAINT; + } +} diff --git a/Validator/Constraints/Export/ExportElementConstraintValidator.php b/Validator/Constraints/Export/ExportElementConstraintValidator.php new file mode 100644 index 000000000..b6a61a0b4 --- /dev/null +++ b/Validator/Constraints/Export/ExportElementConstraintValidator.php @@ -0,0 +1,40 @@ + + * + * 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\MainBundle\Validator\Constraints\Export; + +use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\ConstraintValidator; +use Chill\MainBundle\Export\ExportElementValidatedInterface; + +/** + * This validator validate the _export element_ if this element implements + * {@link ExportElementValidatedInterface}. + * + * @author Julien Fastré + */ +class ExportElementConstraintValidator extends ConstraintValidator +{ + public function validate($value, Constraint $constraint) + { + if ($constraint->element instanceof ExportElementValidatedInterface) { + if ($value["enabled"] === true) { + $constraint->element->validateForm($value["form"], $this->context); + } + } + } +}