/vendor/symfony/src/Symfony/Component/Form/Extension/Validator/Validator/DelegatingValidator.php
https://github.com/xbojer/gfw · PHP · 259 lines · 183 code · 47 blank · 29 comment · 27 complexity · 696301aa5b901248d0d5888281fe2af9 MD5 · raw file
- <?php
- /*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- namespace Symfony\Component\Form\Extension\Validator\Validator;
- use Symfony\Component\Form\FormInterface;
- use Symfony\Component\Form\FormValidatorInterface;
- use Symfony\Component\Form\FormError;
- use Symfony\Component\Form\Util\VirtualFormAwareIterator;
- use Symfony\Component\Form\Exception\FormException;
- use Symfony\Component\Validator\ValidatorInterface;
- use Symfony\Component\Validator\ExecutionContext;
- use Symfony\Component\Form\Util\PropertyPath;
- class DelegatingValidator implements FormValidatorInterface
- {
- private $validator;
- public function __construct(ValidatorInterface $validator)
- {
- $this->validator = $validator;
- }
- /**
- * Validates the form and its domain object.
- *
- * @param FormInterface $form A FormInterface instance
- */
- public function validate(FormInterface $form)
- {
- if ($form->isRoot()) {
- $mapping = array();
- $forms = array();
- $this->buildFormPathMapping($form, $mapping);
- $this->buildDataPathMapping($form, $mapping);
- $this->buildNamePathMapping($form, $forms);
- $this->resolveMappingPlaceholders($mapping, $forms);
- // Validate the form in group "Default"
- // Validation of the data in the custom group is done by validateData(),
- // which is constrained by the Execute constraint
- if ($form->hasAttribute('validation_constraint')) {
- $violations = $this->validator->validateValue(
- $form->getData(),
- $form->getAttribute('validation_constraint'),
- self::getFormValidationGroups($form)
- );
- if ($violations) {
- foreach ($violations as $violation) {
- $propertyPath = new PropertyPath($violation->getPropertyPath());
- $template = $violation->getMessageTemplate();
- $parameters = $violation->getMessageParameters();
- $error = new FormError($template, $parameters);
- $child = $form;
- foreach ($propertyPath->getElements() as $element) {
- $children = $child->getChildren();
- if (!isset($children[$element])) {
- $form->addError($error);
- break;
- }
- $child = $children[$element];
- }
- $child->addError($error);
- }
- }
- } elseif ($violations = $this->validator->validate($form)) {
- foreach ($violations as $violation) {
- $propertyPath = $violation->getPropertyPath();
- $template = $violation->getMessageTemplate();
- $parameters = $violation->getMessageParameters();
- $error = new FormError($template, $parameters);
- foreach ($mapping as $mappedPath => $child) {
- if (preg_match($mappedPath, $propertyPath)) {
- $child->addError($error);
- continue 2;
- }
- }
- $form->addError($error);
- }
- }
- }
- }
- /**
- * Validates the data of a form
- *
- * This method is called automatically during the validation process.
- *
- * @param FormInterface $form The validated form
- * @param ExecutionContext $context The current validation context
- */
- static public function validateFormData(FormInterface $form, ExecutionContext $context)
- {
- if (is_object($form->getData()) || is_array($form->getData())) {
- $propertyPath = $context->getPropertyPath();
- $graphWalker = $context->getGraphWalker();
- // The Execute constraint is called on class level, so we need to
- // set the property manually
- $context->setCurrentProperty('data');
- // Adjust the property path accordingly
- if (!empty($propertyPath)) {
- $propertyPath .= '.';
- }
- $propertyPath .= 'data';
- foreach (self::getFormValidationGroups($form) as $group) {
- $graphWalker->walkReference($form->getData(), $group, $propertyPath, true);
- }
- }
- }
- static protected function getFormValidationGroups(FormInterface $form)
- {
- $groups = null;
- if ($form->hasAttribute('validation_groups')) {
- $groups = $form->getAttribute('validation_groups');
- }
- $currentForm = $form;
- while (!$groups && $currentForm->hasParent()) {
- $currentForm = $currentForm->getParent();
- if ($currentForm->hasAttribute('validation_groups')) {
- $groups = $currentForm->getAttribute('validation_groups');
- }
- }
- if (null === $groups) {
- $groups = array('Default');
- }
- return (array) $groups;
- }
- private function buildFormPathMapping(FormInterface $form, array &$mapping, $formPath = 'children', $namePath = '')
- {
- foreach ($form->getAttribute('error_mapping') as $nestedDataPath => $nestedNamePath)
- {
- $mapping['/^'.preg_quote($formPath.'.data.'.$nestedDataPath).'(?!\w)/'] = $namePath.'.'.$nestedNamePath;
- }
- $iterator = new VirtualFormAwareIterator($form->getChildren());
- $iterator = new \RecursiveIteratorIterator($iterator);
- foreach ($iterator as $child) {
- $path = (string) $child->getAttribute('property_path');
- $parts = explode('.', $path, 2);
- $nestedNamePath = $namePath.'.'.$child->getName();
- if ($child->hasChildren() || isset($parts[1])) {
- $nestedFormPath = $formPath.'['.trim($parts[0], '[]').']';
- }
- else {
- $nestedFormPath = $formPath.'.data.'.$parts[0];
- }
- if (isset($parts[1])) {
- $nestedFormPath .= '.data.'.$parts[1];
- }
- if ($child->hasChildren()) {
- $this->buildFormPathMapping($child, $mapping, $nestedFormPath, $nestedNamePath);
- }
- $mapping['/^'.preg_quote($nestedFormPath, '/').'(?!\w)/'] = $child;
- }
- }
- private function buildDataPathMapping(FormInterface $form, array &$mapping, $dataPath = 'data', $namePath = '')
- {
- foreach ($form->getAttribute('error_mapping') as $nestedDataPath => $nestedNamePath)
- {
- $mapping['/^'.preg_quote($dataPath.'.'.$nestedDataPath).'(?!\w)/'] = $namePath.'.'.$nestedNamePath;
- }
- $iterator = new VirtualFormAwareIterator($form->getChildren());
- $iterator = new \RecursiveIteratorIterator($iterator);
- foreach ($iterator as $child) {
- $path = (string) $child->getAttribute('property_path');
- $nestedNamePath = $namePath.'.'.$child->getName();
- if (strpos($path, '[') === 0) {
- $nestedDataPaths = array($dataPath.$path);
- } else {
- $nestedDataPaths = array($dataPath.'.'.$path);
- if ($child->hasChildren()) {
- $nestedDataPaths[] = $dataPath.'['.$path.']';
- }
- }
- if ($child->hasChildren()) {
- // Needs when collection implements the Iterator
- // or for array used the Valid validator.
- if (is_array($child->getData()) || $child->getData() instanceof \Traversable) {
- $this->buildDataPathMapping($child, $mapping, $dataPath, $nestedNamePath);
- }
- foreach ($nestedDataPaths as $nestedDataPath) {
- $this->buildDataPathMapping($child, $mapping, $nestedDataPath, $nestedNamePath);
- }
- }
- foreach ($nestedDataPaths as $nestedDataPath) {
- $mapping['/^'.preg_quote($nestedDataPath, '/').'(?!\w)/'] = $child;
- }
- }
- }
- private function buildNamePathMapping(FormInterface $form, array &$forms, $namePath = '')
- {
- $iterator = new VirtualFormAwareIterator($form->getChildren());
- $iterator = new \RecursiveIteratorIterator($iterator);
- foreach ($iterator as $child) {
- $nestedNamePath = $namePath.'.'.$child->getName();
- $forms[$nestedNamePath] = $child;
- if ($child->hasChildren()) {
- $this->buildNamePathMapping($child, $forms, $nestedNamePath);
- }
- }
- }
- private function resolveMappingPlaceholders(array &$mapping, array $forms)
- {
- foreach ($mapping as $pattern => $form) {
- if (is_string($form)) {
- if (!isset($forms[$form])) {
- throw new FormException(sprintf('The child form with path "%s" does not exist', $form));
- }
- $mapping[$pattern] = $forms[$form];
- }
- }
- }
- }