diff options
Diffstat (limited to 'vendor/symfony/form/Symfony/Component/Form/Extension/Validator')
16 files changed, 1720 insertions, 0 deletions
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Constraints/Form.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Constraints/Form.php new file mode 100644 index 00000000..87e33297 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Constraints/Form.php | |||
@@ -0,0 +1,33 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
7 | * | ||
8 | * For the full copyright and license information, please view the LICENSE | ||
9 | * file that was distributed with this source code. | ||
10 | */ | ||
11 | |||
12 | namespace Symfony\Component\Form\Extension\Validator\Constraints; | ||
13 | |||
14 | use Symfony\Component\Validator\Constraint; | ||
15 | |||
16 | /** | ||
17 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
18 | */ | ||
19 | class Form extends Constraint | ||
20 | { | ||
21 | /** | ||
22 | * Violation code marking an invalid form. | ||
23 | */ | ||
24 | const ERR_INVALID = 1; | ||
25 | |||
26 | /** | ||
27 | * {@inheritdoc} | ||
28 | */ | ||
29 | public function getTargets() | ||
30 | { | ||
31 | return self::CLASS_CONSTRAINT; | ||
32 | } | ||
33 | } | ||
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php new file mode 100644 index 00000000..bad5a007 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php | |||
@@ -0,0 +1,236 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
7 | * | ||
8 | * For the full copyright and license information, please view the LICENSE | ||
9 | * file that was distributed with this source code. | ||
10 | */ | ||
11 | |||
12 | namespace Symfony\Component\Form\Extension\Validator\Constraints; | ||
13 | |||
14 | use Symfony\Component\Form\ClickableInterface; | ||
15 | use Symfony\Component\Form\FormInterface; | ||
16 | use Symfony\Component\Form\Extension\Validator\Util\ServerParams; | ||
17 | use Symfony\Component\Validator\Constraint; | ||
18 | use Symfony\Component\Validator\ConstraintValidator; | ||
19 | |||
20 | /** | ||
21 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
22 | */ | ||
23 | class FormValidator extends ConstraintValidator | ||
24 | { | ||
25 | /** | ||
26 | * @var ServerParams | ||
27 | */ | ||
28 | private $serverParams; | ||
29 | |||
30 | /** | ||
31 | * Creates a validator with the given server parameters. | ||
32 | * | ||
33 | * @param ServerParams $params The server parameters. Default | ||
34 | * parameters are created if null. | ||
35 | */ | ||
36 | public function __construct(ServerParams $params = null) | ||
37 | { | ||
38 | $this->serverParams = $params ?: new ServerParams(); | ||
39 | } | ||
40 | |||
41 | /** | ||
42 | * {@inheritdoc} | ||
43 | */ | ||
44 | public function validate($form, Constraint $constraint) | ||
45 | { | ||
46 | if (!$form instanceof FormInterface) { | ||
47 | return; | ||
48 | } | ||
49 | |||
50 | /* @var FormInterface $form */ | ||
51 | $config = $form->getConfig(); | ||
52 | |||
53 | if ($form->isSynchronized()) { | ||
54 | // Validate the form data only if transformation succeeded | ||
55 | $groups = self::getValidationGroups($form); | ||
56 | |||
57 | // Validate the data against its own constraints | ||
58 | if (self::allowDataWalking($form)) { | ||
59 | foreach ($groups as $group) { | ||
60 | $this->context->validate($form->getData(), 'data', $group, true); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | // Validate the data against the constraints defined | ||
65 | // in the form | ||
66 | $constraints = $config->getOption('constraints'); | ||
67 | foreach ($constraints as $constraint) { | ||
68 | foreach ($groups as $group) { | ||
69 | if (in_array($group, $constraint->groups)) { | ||
70 | $this->context->validateValue($form->getData(), $constraint, 'data', $group); | ||
71 | |||
72 | // Prevent duplicate validation | ||
73 | continue 2; | ||
74 | } | ||
75 | } | ||
76 | } | ||
77 | } else { | ||
78 | $childrenSynchronized = true; | ||
79 | |||
80 | foreach ($form as $child) { | ||
81 | if (!$child->isSynchronized()) { | ||
82 | $childrenSynchronized = false; | ||
83 | break; | ||
84 | } | ||
85 | } | ||
86 | |||
87 | // Mark the form with an error if it is not synchronized BUT all | ||
88 | // of its children are synchronized. If any child is not | ||
89 | // synchronized, an error is displayed there already and showing | ||
90 | // a second error in its parent form is pointless, or worse, may | ||
91 | // lead to duplicate errors if error bubbling is enabled on the | ||
92 | // child. | ||
93 | // See also https://github.com/symfony/symfony/issues/4359 | ||
94 | if ($childrenSynchronized) { | ||
95 | $clientDataAsString = is_scalar($form->getViewData()) | ||
96 | ? (string) $form->getViewData() | ||
97 | : gettype($form->getViewData()); | ||
98 | |||
99 | $this->context->addViolation( | ||
100 | $config->getOption('invalid_message'), | ||
101 | array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters')), | ||
102 | $form->getViewData(), | ||
103 | null, | ||
104 | Form::ERR_INVALID | ||
105 | ); | ||
106 | } | ||
107 | } | ||
108 | |||
109 | // Mark the form with an error if it contains extra fields | ||
110 | if (count($form->getExtraData()) > 0) { | ||
111 | $this->context->addViolation( | ||
112 | $config->getOption('extra_fields_message'), | ||
113 | array('{{ extra_fields }}' => implode('", "', array_keys($form->getExtraData()))), | ||
114 | $form->getExtraData() | ||
115 | ); | ||
116 | } | ||
117 | |||
118 | // Mark the form with an error if the uploaded size was too large | ||
119 | $length = $this->serverParams->getContentLength(); | ||
120 | |||
121 | if ($form->isRoot() && null !== $length) { | ||
122 | $max = $this->serverParams->getPostMaxSize(); | ||
123 | |||
124 | if (!empty($max) && $length > $max) { | ||
125 | $this->context->addViolation( | ||
126 | $config->getOption('post_max_size_message'), | ||
127 | array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()), | ||
128 | $length | ||
129 | ); | ||
130 | } | ||
131 | } | ||
132 | } | ||
133 | |||
134 | /** | ||
135 | * Returns whether the data of a form may be walked. | ||
136 | * | ||
137 | * @param FormInterface $form The form to test. | ||
138 | * | ||
139 | * @return Boolean Whether the graph walker may walk the data. | ||
140 | */ | ||
141 | private static function allowDataWalking(FormInterface $form) | ||
142 | { | ||
143 | $data = $form->getData(); | ||
144 | |||
145 | // Scalar values cannot have mapped constraints | ||
146 | if (!is_object($data) && !is_array($data)) { | ||
147 | return false; | ||
148 | } | ||
149 | |||
150 | // Root forms are always validated | ||
151 | if ($form->isRoot()) { | ||
152 | return true; | ||
153 | } | ||
154 | |||
155 | // Non-root forms are validated if validation cascading | ||
156 | // is enabled in all ancestor forms | ||
157 | while (null !== ($form = $form->getParent())) { | ||
158 | if (!$form->getConfig()->getOption('cascade_validation')) { | ||
159 | return false; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | return true; | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * Returns the validation groups of the given form. | ||
168 | * | ||
169 | * @param FormInterface $form The form. | ||
170 | * | ||
171 | * @return array The validation groups. | ||
172 | */ | ||
173 | private static function getValidationGroups(FormInterface $form) | ||
174 | { | ||
175 | $button = self::findClickedButton($form->getRoot()); | ||
176 | |||
177 | if (null !== $button) { | ||
178 | $groups = $button->getConfig()->getOption('validation_groups'); | ||
179 | |||
180 | if (null !== $groups) { | ||
181 | return self::resolveValidationGroups($groups, $form); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | do { | ||
186 | $groups = $form->getConfig()->getOption('validation_groups'); | ||
187 | |||
188 | if (null !== $groups) { | ||
189 | return self::resolveValidationGroups($groups, $form); | ||
190 | } | ||
191 | |||
192 | $form = $form->getParent(); | ||
193 | } while (null !== $form); | ||
194 | |||
195 | return array(Constraint::DEFAULT_GROUP); | ||
196 | } | ||
197 | |||
198 | /** | ||
199 | * Extracts a clicked button from a form tree, if one exists. | ||
200 | * | ||
201 | * @param FormInterface $form The root form. | ||
202 | * | ||
203 | * @return ClickableInterface|null The clicked button or null. | ||
204 | */ | ||
205 | private static function findClickedButton(FormInterface $form) | ||
206 | { | ||
207 | if ($form instanceof ClickableInterface && $form->isClicked()) { | ||
208 | return $form; | ||
209 | } | ||
210 | |||
211 | foreach ($form as $child) { | ||
212 | if (null !== ($button = self::findClickedButton($child))) { | ||
213 | return $button; | ||
214 | } | ||
215 | } | ||
216 | |||
217 | return null; | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * Post-processes the validation groups option for a given form. | ||
222 | * | ||
223 | * @param array|callable $groups The validation groups. | ||
224 | * @param FormInterface $form The validated form. | ||
225 | * | ||
226 | * @return array The validation groups. | ||
227 | */ | ||
228 | private static function resolveValidationGroups($groups, FormInterface $form) | ||
229 | { | ||
230 | if (!is_string($groups) && is_callable($groups)) { | ||
231 | $groups = call_user_func($groups, $form); | ||
232 | } | ||
233 | |||
234 | return (array) $groups; | ||
235 | } | ||
236 | } | ||
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.php new file mode 100644 index 00000000..14147531 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.php | |||
@@ -0,0 +1,68 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
7 | * | ||
8 | * For the full copyright and license information, please view the LICENSE | ||
9 | * file that was distributed with this source code. | ||
10 | */ | ||
11 | |||
12 | namespace Symfony\Component\Form\Extension\Validator\EventListener; | ||
13 | |||
14 | use Symfony\Component\EventDispatcher\EventSubscriberInterface; | ||
15 | use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapperInterface; | ||
16 | use Symfony\Component\Validator\ValidatorInterface; | ||
17 | use Symfony\Component\Form\FormEvents; | ||
18 | use Symfony\Component\Form\FormEvent; | ||
19 | use Symfony\Component\Form\Extension\Validator\Constraints\Form; | ||
20 | |||
21 | /** | ||
22 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
23 | */ | ||
24 | class ValidationListener implements EventSubscriberInterface | ||
25 | { | ||
26 | private $validator; | ||
27 | |||
28 | private $violationMapper; | ||
29 | |||
30 | /** | ||
31 | * {@inheritdoc} | ||
32 | */ | ||
33 | public static function getSubscribedEvents() | ||
34 | { | ||
35 | return array(FormEvents::POST_SUBMIT => 'validateForm'); | ||
36 | } | ||
37 | |||
38 | public function __construct(ValidatorInterface $validator, ViolationMapperInterface $violationMapper) | ||
39 | { | ||
40 | $this->validator = $validator; | ||
41 | $this->violationMapper = $violationMapper; | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * Validates the form and its domain object. | ||
46 | * | ||
47 | * @param FormEvent $event The event object | ||
48 | */ | ||
49 | public function validateForm(FormEvent $event) | ||
50 | { | ||
51 | $form = $event->getForm(); | ||
52 | |||
53 | if ($form->isRoot()) { | ||
54 | // Validate the form in group "Default" | ||
55 | $violations = $this->validator->validate($form); | ||
56 | |||
57 | if (count($violations) > 0) { | ||
58 | foreach ($violations as $violation) { | ||
59 | // Allow the "invalid" constraint to be put onto | ||
60 | // non-synchronized forms | ||
61 | $allowNonSynchronized = Form::ERR_INVALID === $violation->getCode(); | ||
62 | |||
63 | $this->violationMapper->mapViolation($violation, $form, $allowNonSynchronized); | ||
64 | } | ||
65 | } | ||
66 | } | ||
67 | } | ||
68 | } | ||
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Type/BaseValidatorExtension.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Type/BaseValidatorExtension.php new file mode 100644 index 00000000..7c5e6784 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Type/BaseValidatorExtension.php | |||
@@ -0,0 +1,56 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
7 | * | ||
8 | * For the full copyright and license information, please view the LICENSE | ||
9 | * file that was distributed with this source code. | ||
10 | */ | ||
11 | |||
12 | namespace Symfony\Component\Form\Extension\Validator\Type; | ||
13 | |||
14 | use Symfony\Component\Form\AbstractTypeExtension; | ||
15 | use Symfony\Component\OptionsResolver\Options; | ||
16 | use Symfony\Component\OptionsResolver\OptionsResolverInterface; | ||
17 | |||
18 | /** | ||
19 | * Encapsulates common logic of {@link FormTypeValidatorExtension} and | ||
20 | * {@link SubmitTypeValidatorExtension}. | ||
21 | * | ||
22 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
23 | */ | ||
24 | abstract class BaseValidatorExtension extends AbstractTypeExtension | ||
25 | { | ||
26 | /** | ||
27 | * {@inheritdoc} | ||
28 | */ | ||
29 | public function setDefaultOptions(OptionsResolverInterface $resolver) | ||
30 | { | ||
31 | // Make sure that validation groups end up as null, closure or array | ||
32 | $validationGroupsNormalizer = function (Options $options, $groups) { | ||
33 | if (false === $groups) { | ||
34 | return array(); | ||
35 | } | ||
36 | |||
37 | if (empty($groups)) { | ||
38 | return null; | ||
39 | } | ||
40 | |||
41 | if (is_callable($groups)) { | ||
42 | return $groups; | ||
43 | } | ||
44 | |||
45 | return (array) $groups; | ||
46 | }; | ||
47 | |||
48 | $resolver->setDefaults(array( | ||
49 | 'validation_groups' => null, | ||
50 | )); | ||
51 | |||
52 | $resolver->setNormalizers(array( | ||
53 | 'validation_groups' => $validationGroupsNormalizer, | ||
54 | )); | ||
55 | } | ||
56 | } | ||
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.php new file mode 100644 index 00000000..344bddad --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.php | |||
@@ -0,0 +1,84 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
7 | * | ||
8 | * For the full copyright and license information, please view the LICENSE | ||
9 | * file that was distributed with this source code. | ||
10 | */ | ||
11 | |||
12 | namespace Symfony\Component\Form\Extension\Validator\Type; | ||
13 | |||
14 | use Symfony\Component\Form\FormBuilderInterface; | ||
15 | use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper; | ||
16 | use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; | ||
17 | use Symfony\Component\Validator\ValidatorInterface; | ||
18 | use Symfony\Component\OptionsResolver\Options; | ||
19 | use Symfony\Component\OptionsResolver\OptionsResolverInterface; | ||
20 | |||
21 | /** | ||
22 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
23 | */ | ||
24 | class FormTypeValidatorExtension extends BaseValidatorExtension | ||
25 | { | ||
26 | /** | ||
27 | * @var ValidatorInterface | ||
28 | */ | ||
29 | private $validator; | ||
30 | |||
31 | /** | ||
32 | * @var ViolationMapper | ||
33 | */ | ||
34 | private $violationMapper; | ||
35 | |||
36 | public function __construct(ValidatorInterface $validator) | ||
37 | { | ||
38 | $this->validator = $validator; | ||
39 | $this->violationMapper = new ViolationMapper(); | ||
40 | } | ||
41 | |||
42 | /** | ||
43 | * {@inheritdoc} | ||
44 | */ | ||
45 | public function buildForm(FormBuilderInterface $builder, array $options) | ||
46 | { | ||
47 | $builder->addEventSubscriber(new ValidationListener($this->validator, $this->violationMapper)); | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * {@inheritdoc} | ||
52 | */ | ||
53 | public function setDefaultOptions(OptionsResolverInterface $resolver) | ||
54 | { | ||
55 | parent::setDefaultOptions($resolver); | ||
56 | |||
57 | // Constraint should always be converted to an array | ||
58 | $constraintsNormalizer = function (Options $options, $constraints) { | ||
59 | return is_object($constraints) ? array($constraints) : (array) $constraints; | ||
60 | }; | ||
61 | |||
62 | $resolver->setDefaults(array( | ||
63 | 'error_mapping' => array(), | ||
64 | 'constraints' => array(), | ||
65 | 'cascade_validation' => false, | ||
66 | 'invalid_message' => 'This value is not valid.', | ||
67 | 'invalid_message_parameters' => array(), | ||
68 | 'extra_fields_message' => 'This form should not contain extra fields.', | ||
69 | 'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.', | ||
70 | )); | ||
71 | |||
72 | $resolver->setNormalizers(array( | ||
73 | 'constraints' => $constraintsNormalizer, | ||
74 | )); | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * {@inheritdoc} | ||
79 | */ | ||
80 | public function getExtendedType() | ||
81 | { | ||
82 | return 'form'; | ||
83 | } | ||
84 | } | ||
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Type/RepeatedTypeValidatorExtension.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Type/RepeatedTypeValidatorExtension.php new file mode 100644 index 00000000..858ff0fa --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Type/RepeatedTypeValidatorExtension.php | |||
@@ -0,0 +1,45 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
7 | * | ||
8 | * For the full copyright and license information, please view the LICENSE | ||
9 | * file that was distributed with this source code. | ||
10 | */ | ||
11 | |||
12 | namespace Symfony\Component\Form\Extension\Validator\Type; | ||
13 | |||
14 | use Symfony\Component\Form\AbstractTypeExtension; | ||
15 | use Symfony\Component\OptionsResolver\Options; | ||
16 | use Symfony\Component\OptionsResolver\OptionsResolverInterface; | ||
17 | |||
18 | /** | ||
19 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
20 | */ | ||
21 | class RepeatedTypeValidatorExtension extends AbstractTypeExtension | ||
22 | { | ||
23 | /** | ||
24 | * {@inheritdoc} | ||
25 | */ | ||
26 | public function setDefaultOptions(OptionsResolverInterface $resolver) | ||
27 | { | ||
28 | // Map errors to the first field | ||
29 | $errorMapping = function (Options $options) { | ||
30 | return array('.' => $options['first_name']); | ||
31 | }; | ||
32 | |||
33 | $resolver->setDefaults(array( | ||
34 | 'error_mapping' => $errorMapping, | ||
35 | )); | ||
36 | } | ||
37 | |||
38 | /** | ||
39 | * {@inheritdoc} | ||
40 | */ | ||
41 | public function getExtendedType() | ||
42 | { | ||
43 | return 'repeated'; | ||
44 | } | ||
45 | } | ||
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Type/SubmitTypeValidatorExtension.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Type/SubmitTypeValidatorExtension.php new file mode 100644 index 00000000..5aad67fb --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Type/SubmitTypeValidatorExtension.php | |||
@@ -0,0 +1,28 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
7 | * | ||
8 | * For the full copyright and license information, please view the LICENSE | ||
9 | * file that was distributed with this source code. | ||
10 | */ | ||
11 | |||
12 | namespace Symfony\Component\Form\Extension\Validator\Type; | ||
13 | |||
14 | use Symfony\Component\Form\AbstractTypeExtension; | ||
15 | |||
16 | /** | ||
17 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
18 | */ | ||
19 | class SubmitTypeValidatorExtension extends AbstractTypeExtension | ||
20 | { | ||
21 | /** | ||
22 | * {@inheritdoc} | ||
23 | */ | ||
24 | public function getExtendedType() | ||
25 | { | ||
26 | return 'submit'; | ||
27 | } | ||
28 | } | ||
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Util/ServerParams.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Util/ServerParams.php new file mode 100644 index 00000000..fab6ac2a --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/Util/ServerParams.php | |||
@@ -0,0 +1,64 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
7 | * | ||
8 | * For the full copyright and license information, please view the LICENSE | ||
9 | * file that was distributed with this source code. | ||
10 | */ | ||
11 | |||
12 | namespace Symfony\Component\Form\Extension\Validator\Util; | ||
13 | |||
14 | /** | ||
15 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
16 | */ | ||
17 | class ServerParams | ||
18 | { | ||
19 | /** | ||
20 | * Returns maximum post size in bytes. | ||
21 | * | ||
22 | * @return null|integer The maximum post size in bytes | ||
23 | */ | ||
24 | public function getPostMaxSize() | ||
25 | { | ||
26 | $iniMax = $this->getNormalizedIniPostMaxSize(); | ||
27 | |||
28 | if ('' === $iniMax) { | ||
29 | return null; | ||
30 | } | ||
31 | |||
32 | if (preg_match('#^\+?(0X?)?(.*?)([KMG]?)$#', $iniMax, $match)) { | ||
33 | $shifts = array('' => 0, 'K' => 10, 'M' => 20, 'G' => 30); | ||
34 | $bases = array('' => 10, '0' => 8, '0X' => 16); | ||
35 | |||
36 | return intval($match[2], $bases[$match[1]]) << $shifts[$match[3]]; | ||
37 | } | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | /** | ||
43 | * Returns the normalized "post_max_size" ini setting. | ||
44 | * | ||
45 | * @return string | ||
46 | */ | ||
47 | public function getNormalizedIniPostMaxSize() | ||
48 | { | ||
49 | return strtoupper(trim(ini_get('post_max_size'))); | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * Returns the content length of the request. | ||
54 | * | ||
55 | * @return mixed The request content length. | ||
56 | */ | ||
57 | public function getContentLength() | ||
58 | { | ||
59 | return isset($_SERVER['CONTENT_LENGTH']) | ||
60 | ? (int) $_SERVER['CONTENT_LENGTH'] | ||
61 | : null; | ||
62 | } | ||
63 | |||
64 | } | ||
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php new file mode 100644 index 00000000..9cff22a2 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php | |||
@@ -0,0 +1,57 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
7 | * | ||
8 | * For the full copyright and license information, please view the LICENSE | ||
9 | * file that was distributed with this source code. | ||
10 | */ | ||
11 | |||
12 | namespace Symfony\Component\Form\Extension\Validator; | ||
13 | |||
14 | use Symfony\Component\Form\Extension\Validator\Type; | ||
15 | use Symfony\Component\Form\Extension\Validator\Constraints\Form; | ||
16 | use Symfony\Component\Form\AbstractExtension; | ||
17 | use Symfony\Component\Validator\ValidatorInterface; | ||
18 | use Symfony\Component\Validator\Constraints\Valid; | ||
19 | |||
20 | /** | ||
21 | * Extension supporting the Symfony2 Validator component in forms. | ||
22 | * | ||
23 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
24 | */ | ||
25 | class ValidatorExtension extends AbstractExtension | ||
26 | { | ||
27 | private $validator; | ||
28 | |||
29 | public function __construct(ValidatorInterface $validator) | ||
30 | { | ||
31 | $this->validator = $validator; | ||
32 | |||
33 | // Register the form constraints in the validator programmatically. | ||
34 | // This functionality is required when using the Form component without | ||
35 | // the DIC, where the XML file is loaded automatically. Thus the following | ||
36 | // code must be kept synchronized with validation.xml | ||
37 | |||
38 | /** @var \Symfony\Component\Validator\Mapping\ClassMetadata $metadata */ | ||
39 | $metadata = $this->validator->getMetadataFactory()->getMetadataFor('Symfony\Component\Form\Form'); | ||
40 | $metadata->addConstraint(new Form()); | ||
41 | $metadata->addPropertyConstraint('children', new Valid()); | ||
42 | } | ||
43 | |||
44 | public function loadTypeGuesser() | ||
45 | { | ||
46 | return new ValidatorTypeGuesser($this->validator->getMetadataFactory()); | ||
47 | } | ||
48 | |||
49 | protected function loadTypeExtensions() | ||
50 | { | ||
51 | return array( | ||
52 | new Type\FormTypeValidatorExtension($this->validator), | ||
53 | new Type\RepeatedTypeValidatorExtension(), | ||
54 | new Type\SubmitTypeValidatorExtension(), | ||
55 | ); | ||
56 | } | ||
57 | } | ||
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php new file mode 100644 index 00000000..dcd9cc55 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php | |||
@@ -0,0 +1,286 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
7 | * | ||
8 | * For the full copyright and license information, please view the LICENSE | ||
9 | * file that was distributed with this source code. | ||
10 | */ | ||
11 | |||
12 | namespace Symfony\Component\Form\Extension\Validator; | ||
13 | |||
14 | use Symfony\Component\Form\FormTypeGuesserInterface; | ||
15 | use Symfony\Component\Form\Guess\Guess; | ||
16 | use Symfony\Component\Form\Guess\TypeGuess; | ||
17 | use Symfony\Component\Form\Guess\ValueGuess; | ||
18 | use Symfony\Component\Validator\MetadataFactoryInterface; | ||
19 | use Symfony\Component\Validator\Constraint; | ||
20 | |||
21 | class ValidatorTypeGuesser implements FormTypeGuesserInterface | ||
22 | { | ||
23 | private $metadataFactory; | ||
24 | |||
25 | public function __construct(MetadataFactoryInterface $metadataFactory) | ||
26 | { | ||
27 | $this->metadataFactory = $metadataFactory; | ||
28 | } | ||
29 | |||
30 | /** | ||
31 | * {@inheritDoc} | ||
32 | */ | ||
33 | public function guessType($class, $property) | ||
34 | { | ||
35 | $guesser = $this; | ||
36 | |||
37 | return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) { | ||
38 | return $guesser->guessTypeForConstraint($constraint); | ||
39 | }); | ||
40 | } | ||
41 | |||
42 | /** | ||
43 | * {@inheritDoc} | ||
44 | */ | ||
45 | public function guessRequired($class, $property) | ||
46 | { | ||
47 | $guesser = $this; | ||
48 | |||
49 | return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) { | ||
50 | return $guesser->guessRequiredForConstraint($constraint); | ||
51 | // If we don't find any constraint telling otherwise, we can assume | ||
52 | // that a field is not required (with LOW_CONFIDENCE) | ||
53 | }, false); | ||
54 | } | ||
55 | |||
56 | /** | ||
57 | * {@inheritDoc} | ||
58 | */ | ||
59 | public function guessMaxLength($class, $property) | ||
60 | { | ||
61 | $guesser = $this; | ||
62 | |||
63 | return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) { | ||
64 | return $guesser->guessMaxLengthForConstraint($constraint); | ||
65 | }); | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * {@inheritDoc} | ||
70 | */ | ||
71 | public function guessPattern($class, $property) | ||
72 | { | ||
73 | $guesser = $this; | ||
74 | |||
75 | return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) { | ||
76 | return $guesser->guessPatternForConstraint($constraint); | ||
77 | }); | ||
78 | } | ||
79 | |||
80 | /** | ||
81 | * Guesses a field class name for a given constraint | ||
82 | * | ||
83 | * @param Constraint $constraint The constraint to guess for | ||
84 | * | ||
85 | * @return TypeGuess The guessed field class and options | ||
86 | */ | ||
87 | public function guessTypeForConstraint(Constraint $constraint) | ||
88 | { | ||
89 | switch (get_class($constraint)) { | ||
90 | case 'Symfony\Component\Validator\Constraints\Type': | ||
91 | switch ($constraint->type) { | ||
92 | case 'array': | ||
93 | return new TypeGuess('collection', array(), Guess::MEDIUM_CONFIDENCE); | ||
94 | case 'boolean': | ||
95 | case 'bool': | ||
96 | return new TypeGuess('checkbox', array(), Guess::MEDIUM_CONFIDENCE); | ||
97 | |||
98 | case 'double': | ||
99 | case 'float': | ||
100 | case 'numeric': | ||
101 | case 'real': | ||
102 | return new TypeGuess('number', array(), Guess::MEDIUM_CONFIDENCE); | ||
103 | |||
104 | case 'integer': | ||
105 | case 'int': | ||
106 | case 'long': | ||
107 | return new TypeGuess('integer', array(), Guess::MEDIUM_CONFIDENCE); | ||
108 | |||
109 | case '\DateTime': | ||
110 | return new TypeGuess('date', array(), Guess::MEDIUM_CONFIDENCE); | ||
111 | |||
112 | case 'string': | ||
113 | return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE); | ||
114 | } | ||
115 | break; | ||
116 | |||
117 | case 'Symfony\Component\Validator\Constraints\Country': | ||
118 | return new TypeGuess('country', array(), Guess::HIGH_CONFIDENCE); | ||
119 | |||
120 | case 'Symfony\Component\Validator\Constraints\Date': | ||
121 | return new TypeGuess('date', array('input' => 'string'), Guess::HIGH_CONFIDENCE); | ||
122 | |||
123 | case 'Symfony\Component\Validator\Constraints\DateTime': | ||
124 | return new TypeGuess('datetime', array('input' => 'string'), Guess::HIGH_CONFIDENCE); | ||
125 | |||
126 | case 'Symfony\Component\Validator\Constraints\Email': | ||
127 | return new TypeGuess('email', array(), Guess::HIGH_CONFIDENCE); | ||
128 | |||
129 | case 'Symfony\Component\Validator\Constraints\File': | ||
130 | case 'Symfony\Component\Validator\Constraints\Image': | ||
131 | return new TypeGuess('file', array(), Guess::HIGH_CONFIDENCE); | ||
132 | |||
133 | case 'Symfony\Component\Validator\Constraints\Language': | ||
134 | return new TypeGuess('language', array(), Guess::HIGH_CONFIDENCE); | ||
135 | |||
136 | case 'Symfony\Component\Validator\Constraints\Locale': | ||
137 | return new TypeGuess('locale', array(), Guess::HIGH_CONFIDENCE); | ||
138 | |||
139 | case 'Symfony\Component\Validator\Constraints\Time': | ||
140 | return new TypeGuess('time', array('input' => 'string'), Guess::HIGH_CONFIDENCE); | ||
141 | |||
142 | case 'Symfony\Component\Validator\Constraints\Url': | ||
143 | return new TypeGuess('url', array(), Guess::HIGH_CONFIDENCE); | ||
144 | |||
145 | case 'Symfony\Component\Validator\Constraints\Ip': | ||
146 | return new TypeGuess('text', array(), Guess::MEDIUM_CONFIDENCE); | ||
147 | |||
148 | case 'Symfony\Component\Validator\Constraints\MaxLength': | ||
149 | case 'Symfony\Component\Validator\Constraints\MinLength': | ||
150 | case 'Symfony\Component\Validator\Constraints\Regex': | ||
151 | return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE); | ||
152 | |||
153 | case 'Symfony\Component\Validator\Constraints\Min': | ||
154 | case 'Symfony\Component\Validator\Constraints\Max': | ||
155 | return new TypeGuess('number', array(), Guess::LOW_CONFIDENCE); | ||
156 | |||
157 | case 'Symfony\Component\Validator\Constraints\MinCount': | ||
158 | case 'Symfony\Component\Validator\Constraints\MaxCount': | ||
159 | return new TypeGuess('collection', array(), Guess::LOW_CONFIDENCE); | ||
160 | |||
161 | case 'Symfony\Component\Validator\Constraints\True': | ||
162 | case 'Symfony\Component\Validator\Constraints\False': | ||
163 | return new TypeGuess('checkbox', array(), Guess::MEDIUM_CONFIDENCE); | ||
164 | } | ||
165 | |||
166 | return null; | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * Guesses whether a field is required based on the given constraint | ||
171 | * | ||
172 | * @param Constraint $constraint The constraint to guess for | ||
173 | * | ||
174 | * @return Guess The guess whether the field is required | ||
175 | */ | ||
176 | public function guessRequiredForConstraint(Constraint $constraint) | ||
177 | { | ||
178 | switch (get_class($constraint)) { | ||
179 | case 'Symfony\Component\Validator\Constraints\NotNull': | ||
180 | case 'Symfony\Component\Validator\Constraints\NotBlank': | ||
181 | case 'Symfony\Component\Validator\Constraints\True': | ||
182 | return new ValueGuess(true, Guess::HIGH_CONFIDENCE); | ||
183 | } | ||
184 | |||
185 | return null; | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * Guesses a field's maximum length based on the given constraint | ||
190 | * | ||
191 | * @param Constraint $constraint The constraint to guess for | ||
192 | * | ||
193 | * @return Guess The guess for the maximum length | ||
194 | */ | ||
195 | public function guessMaxLengthForConstraint(Constraint $constraint) | ||
196 | { | ||
197 | switch (get_class($constraint)) { | ||
198 | case 'Symfony\Component\Validator\Constraints\MaxLength': | ||
199 | return new ValueGuess($constraint->limit, Guess::HIGH_CONFIDENCE); | ||
200 | |||
201 | case 'Symfony\Component\Validator\Constraints\Type': | ||
202 | if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) { | ||
203 | return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); | ||
204 | } | ||
205 | break; | ||
206 | |||
207 | case 'Symfony\Component\Validator\Constraints\Max': | ||
208 | return new ValueGuess(strlen((string) $constraint->limit), Guess::LOW_CONFIDENCE); | ||
209 | } | ||
210 | |||
211 | return null; | ||
212 | } | ||
213 | |||
214 | /** | ||
215 | * Guesses a field's pattern based on the given constraint | ||
216 | * | ||
217 | * @param Constraint $constraint The constraint to guess for | ||
218 | * | ||
219 | * @return Guess The guess for the pattern | ||
220 | */ | ||
221 | public function guessPatternForConstraint(Constraint $constraint) | ||
222 | { | ||
223 | switch (get_class($constraint)) { | ||
224 | case 'Symfony\Component\Validator\Constraints\MinLength': | ||
225 | return new ValueGuess(sprintf('.{%s,}', (string) $constraint->limit), Guess::LOW_CONFIDENCE); | ||
226 | |||
227 | case 'Symfony\Component\Validator\Constraints\Regex': | ||
228 | $htmlPattern = $constraint->getHtmlPattern(); | ||
229 | |||
230 | if (null !== $htmlPattern) { | ||
231 | return new ValueGuess($htmlPattern, Guess::HIGH_CONFIDENCE); | ||
232 | } | ||
233 | break; | ||
234 | |||
235 | case 'Symfony\Component\Validator\Constraints\Min': | ||
236 | return new ValueGuess(sprintf('.{%s,}', strlen((string) $constraint->limit)), Guess::LOW_CONFIDENCE); | ||
237 | |||
238 | case 'Symfony\Component\Validator\Constraints\Type': | ||
239 | if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) { | ||
240 | return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); | ||
241 | } | ||
242 | break; | ||
243 | } | ||
244 | |||
245 | return null; | ||
246 | } | ||
247 | |||
248 | /** | ||
249 | * Iterates over the constraints of a property, executes a constraints on | ||
250 | * them and returns the best guess | ||
251 | * | ||
252 | * @param string $class The class to read the constraints from | ||
253 | * @param string $property The property for which to find constraints | ||
254 | * @param \Closure $closure The closure that returns a guess | ||
255 | * for a given constraint | ||
256 | * @param mixed $defaultValue The default value assumed if no other value | ||
257 | * can be guessed. | ||
258 | * | ||
259 | * @return Guess The guessed value with the highest confidence | ||
260 | */ | ||
261 | protected function guess($class, $property, \Closure $closure, $defaultValue = null) | ||
262 | { | ||
263 | $guesses = array(); | ||
264 | $classMetadata = $this->metadataFactory->getMetadataFor($class); | ||
265 | |||
266 | if ($classMetadata->hasMemberMetadatas($property)) { | ||
267 | $memberMetadatas = $classMetadata->getMemberMetadatas($property); | ||
268 | |||
269 | foreach ($memberMetadatas as $memberMetadata) { | ||
270 | $constraints = $memberMetadata->getConstraints(); | ||
271 | |||
272 | foreach ($constraints as $constraint) { | ||
273 | if ($guess = $closure($constraint)) { | ||
274 | $guesses[] = $guess; | ||
275 | } | ||
276 | } | ||
277 | } | ||
278 | |||
279 | if (null !== $defaultValue) { | ||
280 | $guesses[] = new ValueGuess($defaultValue, Guess::LOW_CONFIDENCE); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | return Guess::getBestGuess($guesses); | ||
285 | } | ||
286 | } | ||
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.php new file mode 100644 index 00000000..7b96efb4 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.php | |||
@@ -0,0 +1,106 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
7 | * | ||
8 | * For the full copyright and license information, please view the LICENSE | ||
9 | * file that was distributed with this source code. | ||
10 | */ | ||
11 | |||
12 | namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; | ||
13 | |||
14 | use Symfony\Component\Form\FormInterface; | ||
15 | use Symfony\Component\Form\Exception\ErrorMappingException; | ||
16 | |||
17 | /** | ||
18 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
19 | */ | ||
20 | class MappingRule | ||
21 | { | ||
22 | /** | ||
23 | * @var FormInterface | ||
24 | */ | ||
25 | private $origin; | ||
26 | |||
27 | /** | ||
28 | * @var string | ||
29 | */ | ||
30 | private $propertyPath; | ||
31 | |||
32 | /** | ||
33 | * @var string | ||
34 | */ | ||
35 | private $targetPath; | ||
36 | |||
37 | public function __construct(FormInterface $origin, $propertyPath, $targetPath) | ||
38 | { | ||
39 | $this->origin = $origin; | ||
40 | $this->propertyPath = $propertyPath; | ||
41 | $this->targetPath = $targetPath; | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * @return FormInterface | ||
46 | */ | ||
47 | public function getOrigin() | ||
48 | { | ||
49 | return $this->origin; | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * Matches a property path against the rule path. | ||
54 | * | ||
55 | * If the rule matches, the form mapped by the rule is returned. | ||
56 | * Otherwise this method returns false. | ||
57 | * | ||
58 | * @param string $propertyPath The property path to match against the rule. | ||
59 | * | ||
60 | * @return null|FormInterface The mapped form or null. | ||
61 | */ | ||
62 | public function match($propertyPath) | ||
63 | { | ||
64 | if ($propertyPath === (string) $this->propertyPath) { | ||
65 | return $this->getTarget(); | ||
66 | } | ||
67 | |||
68 | return null; | ||
69 | } | ||
70 | |||
71 | /** | ||
72 | * Matches a property path against a prefix of the rule path. | ||
73 | * | ||
74 | * @param string $propertyPath The property path to match against the rule. | ||
75 | * | ||
76 | * @return Boolean Whether the property path is a prefix of the rule or not. | ||
77 | */ | ||
78 | public function isPrefix($propertyPath) | ||
79 | { | ||
80 | $length = strlen($propertyPath); | ||
81 | $prefix = substr($this->propertyPath, 0, $length); | ||
82 | $next = isset($this->propertyPath[$length]) ? $this->propertyPath[$length] : null; | ||
83 | |||
84 | return $prefix === $propertyPath && ('[' === $next || '.' === $next); | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * @return FormInterface | ||
89 | * | ||
90 | * @throws ErrorMappingException | ||
91 | */ | ||
92 | public function getTarget() | ||
93 | { | ||
94 | $childNames = explode('.', $this->targetPath); | ||
95 | $target = $this->origin; | ||
96 | |||
97 | foreach ($childNames as $childName) { | ||
98 | if (!$target->has($childName)) { | ||
99 | throw new ErrorMappingException(sprintf('The child "%s" of "%s" mapped by the rule "%s" in "%s" does not exist.', $childName, $target->getName(), $this->targetPath, $this->origin->getName())); | ||
100 | } | ||
101 | $target = $target->get($childName); | ||
102 | } | ||
103 | |||
104 | return $target; | ||
105 | } | ||
106 | } | ||
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/RelativePath.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/RelativePath.php new file mode 100644 index 00000000..ef5c9fad --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/RelativePath.php | |||
@@ -0,0 +1,45 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
7 | * | ||
8 | * For the full copyright and license information, please view the LICENSE | ||
9 | * file that was distributed with this source code. | ||
10 | */ | ||
11 | |||
12 | namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; | ||
13 | |||
14 | use Symfony\Component\Form\FormInterface; | ||
15 | use Symfony\Component\PropertyAccess\PropertyPath; | ||
16 | |||
17 | /** | ||
18 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
19 | */ | ||
20 | class RelativePath extends PropertyPath | ||
21 | { | ||
22 | /** | ||
23 | * @var FormInterface | ||
24 | */ | ||
25 | private $root; | ||
26 | |||
27 | /** | ||
28 | * @param FormInterface $root | ||
29 | * @param string $propertyPath | ||
30 | */ | ||
31 | public function __construct(FormInterface $root, $propertyPath) | ||
32 | { | ||
33 | parent::__construct($propertyPath); | ||
34 | |||
35 | $this->root = $root; | ||
36 | } | ||
37 | |||
38 | /** | ||
39 | * @return FormInterface | ||
40 | */ | ||
41 | public function getRoot() | ||
42 | { | ||
43 | return $this->root; | ||
44 | } | ||
45 | } | ||
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php new file mode 100644 index 00000000..8a7636c7 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php | |||
@@ -0,0 +1,299 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
7 | * | ||
8 | * For the full copyright and license information, please view the LICENSE | ||
9 | * file that was distributed with this source code. | ||
10 | */ | ||
11 | |||
12 | namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; | ||
13 | |||
14 | use Symfony\Component\Form\FormInterface; | ||
15 | use Symfony\Component\Form\Util\InheritDataAwareIterator; | ||
16 | use Symfony\Component\PropertyAccess\PropertyPathIterator; | ||
17 | use Symfony\Component\PropertyAccess\PropertyPathBuilder; | ||
18 | use Symfony\Component\PropertyAccess\PropertyPathIteratorInterface; | ||
19 | use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationPathIterator; | ||
20 | use Symfony\Component\Form\FormError; | ||
21 | use Symfony\Component\Validator\ConstraintViolation; | ||
22 | |||
23 | /** | ||
24 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
25 | */ | ||
26 | class ViolationMapper implements ViolationMapperInterface | ||
27 | { | ||
28 | /** | ||
29 | * @var Boolean | ||
30 | */ | ||
31 | private $allowNonSynchronized; | ||
32 | |||
33 | /** | ||
34 | * {@inheritdoc} | ||
35 | */ | ||
36 | public function mapViolation(ConstraintViolation $violation, FormInterface $form, $allowNonSynchronized = false) | ||
37 | { | ||
38 | $this->allowNonSynchronized = $allowNonSynchronized; | ||
39 | |||
40 | // The scope is the currently found most specific form that | ||
41 | // an error should be mapped to. After setting the scope, the | ||
42 | // mapper will try to continue to find more specific matches in | ||
43 | // the children of scope. If it cannot, the error will be | ||
44 | // mapped to this scope. | ||
45 | $scope = null; | ||
46 | |||
47 | $violationPath = null; | ||
48 | $relativePath = null; | ||
49 | $match = false; | ||
50 | |||
51 | // Don't create a ViolationPath instance for empty property paths | ||
52 | if (strlen($violation->getPropertyPath()) > 0) { | ||
53 | $violationPath = new ViolationPath($violation->getPropertyPath()); | ||
54 | $relativePath = $this->reconstructPath($violationPath, $form); | ||
55 | } | ||
56 | |||
57 | // This case happens if the violation path is empty and thus | ||
58 | // the violation should be mapped to the root form | ||
59 | if (null === $violationPath) { | ||
60 | $scope = $form; | ||
61 | } | ||
62 | |||
63 | // In general, mapping happens from the root form to the leaf forms | ||
64 | // First, the rules of the root form are applied to determine | ||
65 | // the subsequent descendant. The rules of this descendant are then | ||
66 | // applied to find the next and so on, until we have found the | ||
67 | // most specific form that matches the violation. | ||
68 | |||
69 | // If any of the forms found in this process is not synchronized, | ||
70 | // mapping is aborted. Non-synchronized forms could not reverse | ||
71 | // transform the value entered by the user, thus any further violations | ||
72 | // caused by the (invalid) reverse transformed value should be | ||
73 | // ignored. | ||
74 | |||
75 | if (null !== $relativePath) { | ||
76 | // Set the scope to the root of the relative path | ||
77 | // This root will usually be $form. If the path contains | ||
78 | // an unmapped form though, the last unmapped form found | ||
79 | // will be the root of the path. | ||
80 | $scope = $relativePath->getRoot(); | ||
81 | $it = new PropertyPathIterator($relativePath); | ||
82 | |||
83 | while ($this->acceptsErrors($scope) && null !== ($child = $this->matchChild($scope, $it))) { | ||
84 | $scope = $child; | ||
85 | $it->next(); | ||
86 | $match = true; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | // This case happens if an error happened in the data under a | ||
91 | // form inheriting its parent data that does not match any of the | ||
92 | // children of that form. | ||
93 | if (null !== $violationPath && !$match) { | ||
94 | // If we could not map the error to anything more specific | ||
95 | // than the root element, map it to the innermost directly | ||
96 | // mapped form of the violation path | ||
97 | // e.g. "children[foo].children[bar].data.baz" | ||
98 | // Here the innermost directly mapped child is "bar" | ||
99 | |||
100 | $scope = $form; | ||
101 | $it = new ViolationPathIterator($violationPath); | ||
102 | |||
103 | // Note: acceptsErrors() will always return true for forms inheriting | ||
104 | // their parent data, because these forms can never be non-synchronized | ||
105 | // (they don't do any data transformation on their own) | ||
106 | while ($this->acceptsErrors($scope) && $it->valid() && $it->mapsForm()) { | ||
107 | if (!$scope->has($it->current())) { | ||
108 | // Break if we find a reference to a non-existing child | ||
109 | break; | ||
110 | } | ||
111 | |||
112 | $scope = $scope->get($it->current()); | ||
113 | $it->next(); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | // Follow dot rules until we have the final target | ||
118 | $mapping = $scope->getConfig()->getOption('error_mapping'); | ||
119 | |||
120 | while ($this->acceptsErrors($scope) && isset($mapping['.'])) { | ||
121 | $dotRule = new MappingRule($scope, '.', $mapping['.']); | ||
122 | $scope = $dotRule->getTarget(); | ||
123 | $mapping = $scope->getConfig()->getOption('error_mapping'); | ||
124 | } | ||
125 | |||
126 | // Only add the error if the form is synchronized | ||
127 | if ($this->acceptsErrors($scope)) { | ||
128 | $scope->addError(new FormError( | ||
129 | $violation->getMessage(), | ||
130 | $violation->getMessageTemplate(), | ||
131 | $violation->getMessageParameters(), | ||
132 | $violation->getMessagePluralization() | ||
133 | )); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * Tries to match the beginning of the property path at the | ||
139 | * current position against the children of the scope. | ||
140 | * | ||
141 | * If a matching child is found, it is returned. Otherwise | ||
142 | * null is returned. | ||
143 | * | ||
144 | * @param FormInterface $form The form to search. | ||
145 | * @param PropertyPathIteratorInterface $it The iterator at its current position. | ||
146 | * | ||
147 | * @return null|FormInterface The found match or null. | ||
148 | */ | ||
149 | private function matchChild(FormInterface $form, PropertyPathIteratorInterface $it) | ||
150 | { | ||
151 | // Remember at what property path underneath "data" | ||
152 | // we are looking. Check if there is a child with that | ||
153 | // path, otherwise increase path by one more piece | ||
154 | $chunk = ''; | ||
155 | $foundChild = null; | ||
156 | $foundAtIndex = 0; | ||
157 | |||
158 | // Construct mapping rules for the given form | ||
159 | $rules = array(); | ||
160 | |||
161 | foreach ($form->getConfig()->getOption('error_mapping') as $propertyPath => $targetPath) { | ||
162 | // Dot rules are considered at the very end | ||
163 | if ('.' !== $propertyPath) { | ||
164 | $rules[] = new MappingRule($form, $propertyPath, $targetPath); | ||
165 | } | ||
166 | } | ||
167 | |||
168 | // Skip forms inheriting their parent data when iterating the children | ||
169 | $childIterator = new \RecursiveIteratorIterator( | ||
170 | new InheritDataAwareIterator($form->all()) | ||
171 | ); | ||
172 | |||
173 | // Make the path longer until we find a matching child | ||
174 | while (true) { | ||
175 | if (!$it->valid()) { | ||
176 | return null; | ||
177 | } | ||
178 | |||
179 | if ($it->isIndex()) { | ||
180 | $chunk .= '['.$it->current().']'; | ||
181 | } else { | ||
182 | $chunk .= ('' === $chunk ? '' : '.').$it->current(); | ||
183 | } | ||
184 | |||
185 | // Test mapping rules as long as we have any | ||
186 | foreach ($rules as $key => $rule) { | ||
187 | /* @var MappingRule $rule */ | ||
188 | |||
189 | // Mapping rule matches completely, terminate. | ||
190 | if (null !== ($form = $rule->match($chunk))) { | ||
191 | return $form; | ||
192 | } | ||
193 | |||
194 | // Keep only rules that have $chunk as prefix | ||
195 | if (!$rule->isPrefix($chunk)) { | ||
196 | unset($rules[$key]); | ||
197 | } | ||
198 | } | ||
199 | |||
200 | // Test children unless we already found one | ||
201 | if (null === $foundChild) { | ||
202 | foreach ($childIterator as $child) { | ||
203 | /* @var FormInterface $child */ | ||
204 | $childPath = (string) $child->getPropertyPath(); | ||
205 | |||
206 | // Child found, mark as return value | ||
207 | if ($chunk === $childPath) { | ||
208 | $foundChild = $child; | ||
209 | $foundAtIndex = $it->key(); | ||
210 | } | ||
211 | } | ||
212 | } | ||
213 | |||
214 | // Add element to the chunk | ||
215 | $it->next(); | ||
216 | |||
217 | // If we reached the end of the path or if there are no | ||
218 | // more matching mapping rules, return the found child | ||
219 | if (null !== $foundChild && (!$it->valid() || count($rules) === 0)) { | ||
220 | // Reset index in case we tried to find mapping | ||
221 | // rules further down the path | ||
222 | $it->seek($foundAtIndex); | ||
223 | |||
224 | return $foundChild; | ||
225 | } | ||
226 | } | ||
227 | |||
228 | return null; | ||
229 | } | ||
230 | |||
231 | /** | ||
232 | * Reconstructs a property path from a violation path and a form tree. | ||
233 | * | ||
234 | * @param ViolationPath $violationPath The violation path. | ||
235 | * @param FormInterface $origin The root form of the tree. | ||
236 | * | ||
237 | * @return RelativePath The reconstructed path. | ||
238 | */ | ||
239 | private function reconstructPath(ViolationPath $violationPath, FormInterface $origin) | ||
240 | { | ||
241 | $propertyPathBuilder = new PropertyPathBuilder($violationPath); | ||
242 | $it = $violationPath->getIterator(); | ||
243 | $scope = $origin; | ||
244 | |||
245 | // Remember the current index in the builder | ||
246 | $i = 0; | ||
247 | |||
248 | // Expand elements that map to a form (like "children[address]") | ||
249 | for ($it->rewind(); $it->valid() && $it->mapsForm(); $it->next()) { | ||
250 | if (!$scope->has($it->current())) { | ||
251 | // Scope relates to a form that does not exist | ||
252 | // Bail out | ||
253 | break; | ||
254 | } | ||
255 | |||
256 | // Process child form | ||
257 | $scope = $scope->get($it->current()); | ||
258 | |||
259 | if ($scope->getConfig()->getInheritData()) { | ||
260 | // Form inherits its parent data | ||
261 | // Cut the piece out of the property path and proceed | ||
262 | $propertyPathBuilder->remove($i); | ||
263 | } elseif (!$scope->getConfig()->getMapped()) { | ||
264 | // Form is not mapped | ||
265 | // Set the form as new origin and strip everything | ||
266 | // we have so far in the path | ||
267 | $origin = $scope; | ||
268 | $propertyPathBuilder->remove(0, $i + 1); | ||
269 | $i = 0; | ||
270 | } else { | ||
271 | /* @var \Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath */ | ||
272 | $propertyPath = $scope->getPropertyPath(); | ||
273 | |||
274 | if (null === $propertyPath) { | ||
275 | // Property path of a mapped form is null | ||
276 | // Should not happen, bail out | ||
277 | break; | ||
278 | } | ||
279 | |||
280 | $propertyPathBuilder->replace($i, 1, $propertyPath); | ||
281 | $i += $propertyPath->getLength(); | ||
282 | } | ||
283 | } | ||
284 | |||
285 | $finalPath = $propertyPathBuilder->getPropertyPath(); | ||
286 | |||
287 | return null !== $finalPath ? new RelativePath($origin, $finalPath) : null; | ||
288 | } | ||
289 | |||
290 | /** | ||
291 | * @param FormInterface $form | ||
292 | * | ||
293 | * @return Boolean | ||
294 | */ | ||
295 | private function acceptsErrors(FormInterface $form) | ||
296 | { | ||
297 | return $this->allowNonSynchronized || $form->isSynchronized(); | ||
298 | } | ||
299 | } | ||
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.php new file mode 100644 index 00000000..eb8907f1 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.php | |||
@@ -0,0 +1,33 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
7 | * | ||
8 | * For the full copyright and license information, please view the LICENSE | ||
9 | * file that was distributed with this source code. | ||
10 | */ | ||
11 | |||
12 | namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; | ||
13 | |||
14 | use Symfony\Component\Form\FormInterface; | ||
15 | use Symfony\Component\Validator\ConstraintViolation; | ||
16 | |||
17 | /** | ||
18 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
19 | */ | ||
20 | interface ViolationMapperInterface | ||
21 | { | ||
22 | /** | ||
23 | * Maps a constraint violation to a form in the form tree under | ||
24 | * the given form. | ||
25 | * | ||
26 | * @param ConstraintViolation $violation The violation to map. | ||
27 | * @param FormInterface $form The root form of the tree | ||
28 | * to map it to. | ||
29 | * @param Boolean $allowNonSynchronized Whether to allow | ||
30 | * mapping to non-synchronized forms. | ||
31 | */ | ||
32 | public function mapViolation(ConstraintViolation $violation, FormInterface $form, $allowNonSynchronized = false); | ||
33 | } | ||
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php new file mode 100644 index 00000000..06d09195 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php | |||
@@ -0,0 +1,250 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
7 | * | ||
8 | * For the full copyright and license information, please view the LICENSE | ||
9 | * file that was distributed with this source code. | ||
10 | */ | ||
11 | |||
12 | namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; | ||
13 | |||
14 | use Symfony\Component\Form\Exception\OutOfBoundsException; | ||
15 | use Symfony\Component\PropertyAccess\PropertyPath; | ||
16 | use Symfony\Component\PropertyAccess\PropertyPathInterface; | ||
17 | |||
18 | /** | ||
19 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
20 | */ | ||
21 | class ViolationPath implements \IteratorAggregate, PropertyPathInterface | ||
22 | { | ||
23 | /** | ||
24 | * @var array | ||
25 | */ | ||
26 | private $elements = array(); | ||
27 | |||
28 | /** | ||
29 | * @var array | ||
30 | */ | ||
31 | private $isIndex = array(); | ||
32 | |||
33 | /** | ||
34 | * @var array | ||
35 | */ | ||
36 | private $mapsForm = array(); | ||
37 | |||
38 | /** | ||
39 | * @var string | ||
40 | */ | ||
41 | private $pathAsString = ''; | ||
42 | |||
43 | /** | ||
44 | * @var integer | ||
45 | */ | ||
46 | private $length = 0; | ||
47 | |||
48 | /** | ||
49 | * Creates a new violation path from a string. | ||
50 | * | ||
51 | * @param string $violationPath The property path of a {@link ConstraintViolation} | ||
52 | * object. | ||
53 | */ | ||
54 | public function __construct($violationPath) | ||
55 | { | ||
56 | $path = new PropertyPath($violationPath); | ||
57 | $elements = $path->getElements(); | ||
58 | $data = false; | ||
59 | |||
60 | for ($i = 0, $l = count($elements); $i < $l; ++$i) { | ||
61 | if (!$data) { | ||
62 | // The element "data" has not yet been passed | ||
63 | if ('children' === $elements[$i] && $path->isProperty($i)) { | ||
64 | // Skip element "children" | ||
65 | ++$i; | ||
66 | |||
67 | // Next element must exist and must be an index | ||
68 | // Otherwise consider this the end of the path | ||
69 | if ($i >= $l || !$path->isIndex($i)) { | ||
70 | break; | ||
71 | } | ||
72 | |||
73 | $this->elements[] = $elements[$i]; | ||
74 | $this->isIndex[] = true; | ||
75 | $this->mapsForm[] = true; | ||
76 | } elseif ('data' === $elements[$i] && $path->isProperty($i)) { | ||
77 | // Skip element "data" | ||
78 | ++$i; | ||
79 | |||
80 | // End of path | ||
81 | if ($i >= $l) { | ||
82 | break; | ||
83 | } | ||
84 | |||
85 | $this->elements[] = $elements[$i]; | ||
86 | $this->isIndex[] = $path->isIndex($i); | ||
87 | $this->mapsForm[] = false; | ||
88 | $data = true; | ||
89 | } else { | ||
90 | // Neither "children" nor "data" property found | ||
91 | // Consider this the end of the path | ||
92 | break; | ||
93 | } | ||
94 | } else { | ||
95 | // Already after the "data" element | ||
96 | // Pick everything as is | ||
97 | $this->elements[] = $elements[$i]; | ||
98 | $this->isIndex[] = $path->isIndex($i); | ||
99 | $this->mapsForm[] = false; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | $this->length = count($this->elements); | ||
104 | |||
105 | $this->buildString(); | ||
106 | } | ||
107 | |||
108 | /** | ||
109 | * {@inheritdoc} | ||
110 | */ | ||
111 | public function __toString() | ||
112 | { | ||
113 | return $this->pathAsString; | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * {@inheritdoc} | ||
118 | */ | ||
119 | public function getLength() | ||
120 | { | ||
121 | return $this->length; | ||
122 | } | ||
123 | |||
124 | /** | ||
125 | * {@inheritdoc} | ||
126 | */ | ||
127 | public function getParent() | ||
128 | { | ||
129 | if ($this->length <= 1) { | ||
130 | return null; | ||
131 | } | ||
132 | |||
133 | $parent = clone $this; | ||
134 | |||
135 | --$parent->length; | ||
136 | array_pop($parent->elements); | ||
137 | array_pop($parent->isIndex); | ||
138 | array_pop($parent->mapsForm); | ||
139 | |||
140 | $parent->buildString(); | ||
141 | |||
142 | return $parent; | ||
143 | } | ||
144 | |||
145 | /** | ||
146 | * {@inheritdoc} | ||
147 | */ | ||
148 | public function getElements() | ||
149 | { | ||
150 | return $this->elements; | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * {@inheritdoc} | ||
155 | */ | ||
156 | public function getElement($index) | ||
157 | { | ||
158 | if (!isset($this->elements[$index])) { | ||
159 | throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); | ||
160 | } | ||
161 | |||
162 | return $this->elements[$index]; | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * {@inheritdoc} | ||
167 | */ | ||
168 | public function isProperty($index) | ||
169 | { | ||
170 | if (!isset($this->isIndex[$index])) { | ||
171 | throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); | ||
172 | } | ||
173 | |||
174 | return !$this->isIndex[$index]; | ||
175 | } | ||
176 | |||
177 | /** | ||
178 | * {@inheritdoc} | ||
179 | */ | ||
180 | public function isIndex($index) | ||
181 | { | ||
182 | if (!isset($this->isIndex[$index])) { | ||
183 | throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); | ||
184 | } | ||
185 | |||
186 | return $this->isIndex[$index]; | ||
187 | } | ||
188 | |||
189 | /** | ||
190 | * Returns whether an element maps directly to a form. | ||
191 | * | ||
192 | * Consider the following violation path: | ||
193 | * | ||
194 | * <code> | ||
195 | * children[address].children[office].data.street | ||
196 | * </code> | ||
197 | * | ||
198 | * In this example, "address" and "office" map to forms, while | ||
199 | * "street does not. | ||
200 | * | ||
201 | * @param integer $index The element index. | ||
202 | * | ||
203 | * @return Boolean Whether the element maps to a form. | ||
204 | * | ||
205 | * @throws OutOfBoundsException If the offset is invalid. | ||
206 | */ | ||
207 | public function mapsForm($index) | ||
208 | { | ||
209 | if (!isset($this->mapsForm[$index])) { | ||
210 | throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); | ||
211 | } | ||
212 | |||
213 | return $this->mapsForm[$index]; | ||
214 | } | ||
215 | |||
216 | /** | ||
217 | * Returns a new iterator for this path | ||
218 | * | ||
219 | * @return ViolationPathIterator | ||
220 | */ | ||
221 | public function getIterator() | ||
222 | { | ||
223 | return new ViolationPathIterator($this); | ||
224 | } | ||
225 | |||
226 | /** | ||
227 | * Builds the string representation from the elements. | ||
228 | */ | ||
229 | private function buildString() | ||
230 | { | ||
231 | $this->pathAsString = ''; | ||
232 | $data = false; | ||
233 | |||
234 | foreach ($this->elements as $index => $element) { | ||
235 | if ($this->mapsForm[$index]) { | ||
236 | $this->pathAsString .= ".children[$element]"; | ||
237 | } elseif (!$data) { | ||
238 | $this->pathAsString .= '.data'.($this->isIndex[$index] ? "[$element]" : ".$element"); | ||
239 | $data = true; | ||
240 | } else { | ||
241 | $this->pathAsString .= $this->isIndex[$index] ? "[$element]" : ".$element"; | ||
242 | } | ||
243 | } | ||
244 | |||
245 | if ('' !== $this->pathAsString) { | ||
246 | // remove leading dot | ||
247 | $this->pathAsString = substr($this->pathAsString, 1); | ||
248 | } | ||
249 | } | ||
250 | } | ||
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPathIterator.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPathIterator.php new file mode 100644 index 00000000..50baa453 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPathIterator.php | |||
@@ -0,0 +1,30 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
7 | * | ||
8 | * For the full copyright and license information, please view the LICENSE | ||
9 | * file that was distributed with this source code. | ||
10 | */ | ||
11 | |||
12 | namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; | ||
13 | |||
14 | use Symfony\Component\PropertyAccess\PropertyPathIterator; | ||
15 | |||
16 | /** | ||
17 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
18 | */ | ||
19 | class ViolationPathIterator extends PropertyPathIterator | ||
20 | { | ||
21 | public function __construct(ViolationPath $violationPath) | ||
22 | { | ||
23 | parent::__construct($violationPath); | ||
24 | } | ||
25 | |||
26 | public function mapsForm() | ||
27 | { | ||
28 | return $this->path->mapsForm($this->key()); | ||
29 | } | ||
30 | } | ||