PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/symfony2/vendor/symfony/src/Symfony/Component/Form/Extension/Validator/Validator/DelegatingValidator.php

http://github.com/eryx/php-framework-benchmark
PHP | 264 lines | 188 code | 47 blank | 29 comment | 31 complexity | 1180ed1a19c1034aaab4173904b8b990 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause, Apache-2.0, LGPL-2.1, LGPL-3.0, BSD-2-Clause
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Form\Extension\Validator\Validator;
  11. use Symfony\Component\Form\FormInterface;
  12. use Symfony\Component\Form\FormValidatorInterface;
  13. use Symfony\Component\Form\FormError;
  14. use Symfony\Component\Form\Util\VirtualFormAwareIterator;
  15. use Symfony\Component\Form\Exception\FormException;
  16. use Symfony\Component\Validator\ValidatorInterface;
  17. use Symfony\Component\Validator\ExecutionContext;
  18. use Symfony\Component\Form\Util\PropertyPath;
  19. class DelegatingValidator implements FormValidatorInterface
  20. {
  21. private $validator;
  22. public function __construct(ValidatorInterface $validator)
  23. {
  24. $this->validator = $validator;
  25. }
  26. /**
  27. * Validates the form and its domain object.
  28. *
  29. * @param FormInterface $form A FormInterface instance
  30. */
  31. public function validate(FormInterface $form)
  32. {
  33. if ($form->isRoot()) {
  34. $mapping = array();
  35. $forms = array();
  36. $this->buildFormPathMapping($form, $mapping);
  37. $this->buildDataPathMapping($form, $mapping);
  38. $this->buildNamePathMapping($form, $forms);
  39. $this->resolveMappingPlaceholders($mapping, $forms);
  40. // Validate the form in group "Default"
  41. // Validation of the data in the custom group is done by validateData(),
  42. // which is constrained by the Execute constraint
  43. if ($form->hasAttribute('validation_constraint')) {
  44. $violations = $this->validator->validateValue(
  45. $form->getData(),
  46. $form->getAttribute('validation_constraint'),
  47. self::getFormValidationGroups($form)
  48. );
  49. if ($violations) {
  50. foreach ($violations as $violation) {
  51. $propertyPath = new PropertyPath($violation->getPropertyPath());
  52. $template = $violation->getMessageTemplate();
  53. $parameters = $violation->getMessageParameters();
  54. $error = new FormError($template, $parameters);
  55. $child = $form;
  56. foreach ($propertyPath->getElements() as $element) {
  57. $children = $child->getChildren();
  58. if (!isset($children[$element])) {
  59. if ($form->isSynchronized()) {
  60. $form->addError($error);
  61. }
  62. break;
  63. }
  64. $child = $children[$element];
  65. }
  66. if ($child->isSynchronized()) {
  67. $child->addError($error);
  68. }
  69. }
  70. }
  71. } elseif (count($violations = $this->validator->validate($form))) {
  72. foreach ($violations as $violation) {
  73. $propertyPath = $violation->getPropertyPath();
  74. $template = $violation->getMessageTemplate();
  75. $parameters = $violation->getMessageParameters();
  76. $error = new FormError($template, $parameters);
  77. foreach ($mapping as $mappedPath => $child) {
  78. if (preg_match($mappedPath, $propertyPath)) {
  79. if ($child->isSynchronized()) {
  80. $child->addError($error);
  81. }
  82. continue 2;
  83. }
  84. }
  85. if ($form->isSynchronized()) {
  86. $form->addError($error);
  87. }
  88. }
  89. }
  90. }
  91. }
  92. /**
  93. * Validates the data of a form
  94. *
  95. * This method is called automatically during the validation process.
  96. *
  97. * @param FormInterface $form The validated form
  98. * @param ExecutionContext $context The current validation context
  99. */
  100. public static function validateFormData(FormInterface $form, ExecutionContext $context)
  101. {
  102. if (is_object($form->getData()) || is_array($form->getData())) {
  103. $propertyPath = $context->getPropertyPath();
  104. $graphWalker = $context->getGraphWalker();
  105. // The Execute constraint is called on class level, so we need to
  106. // set the property manually
  107. $context->setCurrentProperty('data');
  108. // Adjust the property path accordingly
  109. if (!empty($propertyPath)) {
  110. $propertyPath .= '.';
  111. }
  112. $propertyPath .= 'data';
  113. foreach (self::getFormValidationGroups($form) as $group) {
  114. $graphWalker->walkReference($form->getData(), $group, $propertyPath, true);
  115. }
  116. }
  117. }
  118. protected static function getFormValidationGroups(FormInterface $form)
  119. {
  120. $groups = null;
  121. if ($form->hasAttribute('validation_groups')) {
  122. $groups = $form->getAttribute('validation_groups');
  123. }
  124. $currentForm = $form;
  125. while (!$groups && $currentForm->hasParent()) {
  126. $currentForm = $currentForm->getParent();
  127. if ($currentForm->hasAttribute('validation_groups')) {
  128. $groups = $currentForm->getAttribute('validation_groups');
  129. }
  130. }
  131. if (null === $groups) {
  132. $groups = array('Default');
  133. }
  134. return (array) $groups;
  135. }
  136. private function buildFormPathMapping(FormInterface $form, array &$mapping, $formPath = 'children', $namePath = '')
  137. {
  138. foreach ($form->getAttribute('error_mapping') as $nestedDataPath => $nestedNamePath) {
  139. $mapping['/^'.preg_quote($formPath.'.data.'.$nestedDataPath).'(?!\w)/'] = $namePath.'.'.$nestedNamePath;
  140. }
  141. $iterator = new VirtualFormAwareIterator($form->getChildren());
  142. $iterator = new \RecursiveIteratorIterator($iterator);
  143. foreach ($iterator as $child) {
  144. $path = (string) $child->getAttribute('property_path');
  145. $parts = explode('.', $path, 2);
  146. $nestedNamePath = $namePath.'.'.$child->getName();
  147. if ($child->hasChildren() || isset($parts[1])) {
  148. $nestedFormPath = $formPath.'['.trim($parts[0], '[]').']';
  149. } else {
  150. $nestedFormPath = $formPath.'.data.'.$parts[0];
  151. }
  152. if (isset($parts[1])) {
  153. $nestedFormPath .= '.data.'.$parts[1];
  154. }
  155. if ($child->hasChildren()) {
  156. $this->buildFormPathMapping($child, $mapping, $nestedFormPath, $nestedNamePath);
  157. }
  158. $mapping['/^'.preg_quote($nestedFormPath, '/').'(?!\w)/'] = $child;
  159. }
  160. }
  161. private function buildDataPathMapping(FormInterface $form, array &$mapping, $dataPath = 'data', $namePath = '')
  162. {
  163. foreach ($form->getAttribute('error_mapping') as $nestedDataPath => $nestedNamePath) {
  164. $mapping['/^'.preg_quote($dataPath.'.'.$nestedDataPath).'(?!\w)/'] = $namePath.'.'.$nestedNamePath;
  165. }
  166. $iterator = new VirtualFormAwareIterator($form->getChildren());
  167. $iterator = new \RecursiveIteratorIterator($iterator);
  168. foreach ($iterator as $child) {
  169. $path = (string) $child->getAttribute('property_path');
  170. $nestedNamePath = $namePath.'.'.$child->getName();
  171. if (strpos($path, '[') === 0) {
  172. $nestedDataPaths = array($dataPath.$path);
  173. } else {
  174. $nestedDataPaths = array($dataPath.'.'.$path);
  175. if ($child->hasChildren()) {
  176. $nestedDataPaths[] = $dataPath.'['.$path.']';
  177. }
  178. }
  179. if ($child->hasChildren()) {
  180. // Needs when collection implements the Iterator
  181. // or for array used the Valid validator.
  182. if (is_array($child->getData()) || $child->getData() instanceof \Traversable) {
  183. $this->buildDataPathMapping($child, $mapping, $dataPath, $nestedNamePath);
  184. }
  185. foreach ($nestedDataPaths as $nestedDataPath) {
  186. $this->buildDataPathMapping($child, $mapping, $nestedDataPath, $nestedNamePath);
  187. }
  188. }
  189. foreach ($nestedDataPaths as $nestedDataPath) {
  190. $mapping['/^'.preg_quote($nestedDataPath, '/').'(?!\w)/'] = $child;
  191. }
  192. }
  193. }
  194. private function buildNamePathMapping(FormInterface $form, array &$forms, $namePath = '')
  195. {
  196. $iterator = new VirtualFormAwareIterator($form->getChildren());
  197. $iterator = new \RecursiveIteratorIterator($iterator);
  198. foreach ($iterator as $child) {
  199. $nestedNamePath = $namePath.'.'.$child->getName();
  200. $forms[$nestedNamePath] = $child;
  201. if ($child->hasChildren()) {
  202. $this->buildNamePathMapping($child, $forms, $nestedNamePath);
  203. }
  204. }
  205. }
  206. private function resolveMappingPlaceholders(array &$mapping, array $forms)
  207. {
  208. foreach ($mapping as $pattern => $form) {
  209. if (is_string($form)) {
  210. if (!isset($forms[$form])) {
  211. throw new FormException(sprintf('The child form with path "%s" does not exist', $form));
  212. }
  213. $mapping[$pattern] = $forms[$form];
  214. }
  215. }
  216. }
  217. }