Skip to content

Commit b620dc6

Browse files
author
Bernhard Schussek
committed
[Form] Extracted validation logic of form. Fields can now contain multiple validators
1 parent 2d0096f commit b620dc6

File tree

9 files changed

+75
-64
lines changed

9 files changed

+75
-64
lines changed

Field.php

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class Field implements FieldInterface
6565
private $normTransformer;
6666
private $clientTransformer;
6767
private $transformationSuccessful = true;
68-
private $validator;
68+
private $validators;
6969
private $renderer;
7070
private $readOnly = false;
7171
private $dispatcher;
@@ -74,15 +74,21 @@ class Field implements FieldInterface
7474
public function __construct($name, EventDispatcherInterface $dispatcher,
7575
RendererInterface $renderer, DataTransformerInterface $clientTransformer = null,
7676
DataTransformerInterface $normTransformer = null,
77-
FieldValidatorInterface $validator = null, $required = false,
77+
array $validators = array(), $required = false,
7878
$readOnly = false, array $attributes = array())
7979
{
80+
foreach ($validators as $validator) {
81+
if (!$validator instanceof FieldValidatorInterface) {
82+
throw new UnexpectedTypeException($validator, 'Symfony\Component\Form\Validator\FieldValidatorInterface');
83+
}
84+
}
85+
8086
$this->name = (string)$name;
8187
$this->dispatcher = $dispatcher;
8288
$this->renderer = $renderer;
8389
$this->clientTransformer = $clientTransformer;
8490
$this->normTransformer = $normTransformer;
85-
$this->validator = $validator;
91+
$this->validators = $validators;
8692
$this->required = $required;
8793
$this->readOnly = $readOnly;
8894
$this->attributes = $attributes;
@@ -276,8 +282,8 @@ public function bind($clientData)
276282
$event = new DataEvent($this, $clientData);
277283
$this->dispatcher->dispatch(Events::postBind, $event);
278284

279-
if ($this->validator) {
280-
$this->validator->validate($this);
285+
foreach ($this->validators as $validator) {
286+
$validator->validate($this);
281287
}
282288
}
283289

FieldBuilder.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class FieldBuilder
4444

4545
private $theme;
4646

47-
private $validator;
47+
private $validators = array();
4848

4949
private $attributes = array();
5050

@@ -139,14 +139,16 @@ public function getRequired()
139139
return $this->required;
140140
}
141141

142-
public function setValidator(FieldValidatorInterface $validator)
142+
public function addValidator(FieldValidatorInterface $validator)
143143
{
144-
$this->validator = $validator;
144+
$this->validators[] = $validator;
145+
146+
return $this;
145147
}
146148

147-
public function getValidator()
149+
public function getValidators()
148150
{
149-
return $this->validator;
151+
return $this->validators;
150152
}
151153

152154
/**
@@ -286,7 +288,7 @@ public function getInstance()
286288
$this->buildRenderer(),
287289
$this->getClientTransformer(),
288290
$this->getNormTransformer(),
289-
$this->getValidator(),
291+
$this->getValidators(),
290292
$this->getRequired(),
291293
$this->getReadOnly(),
292294
$this->getAttributes()

Form.php

Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,14 @@ class Form extends Field implements \IteratorAggregate, FormInterface
5757
* Contains the names of bound values who don't belong to any fields
5858
* @var array
5959
*/
60-
private $extraFields = array();
60+
private $extraData = array();
6161

6262
private $dataMapper;
6363

6464
public function __construct($name, EventDispatcherInterface $dispatcher,
6565
RendererInterface $renderer, DataTransformerInterface $clientTransformer = null,
6666
DataTransformerInterface $normalizationTransformer = null,
67-
DataMapperInterface $dataMapper, FieldValidatorInterface $validator = null,
67+
DataMapperInterface $dataMapper, array $validators = null,
6868
$required = false, $readOnly = false, array $attributes = array())
6969
{
7070
$dispatcher->addListener(array(
@@ -76,7 +76,7 @@ public function __construct($name, EventDispatcherInterface $dispatcher,
7676
$this->dataMapper = $dataMapper;
7777

7878
parent::__construct($name, $dispatcher, $renderer, $clientTransformer,
79-
$normalizationTransformer, $validator, $required, $readOnly,
79+
$normalizationTransformer, $validators, $required, $readOnly,
8080
$attributes);
8181
}
8282

@@ -177,13 +177,13 @@ public function filterBoundClientData(FilterDataEvent $event)
177177
}
178178
}
179179

180-
$this->extraFields = array();
180+
$this->extraData = array();
181181

182182
foreach ($data as $name => $value) {
183183
if ($this->has($name)) {
184184
$this->fields[$name]->bind($value);
185185
} else {
186-
$this->extraFields[] = $name;
186+
$this->extraData[$name] = $value;
187187
}
188188
}
189189

@@ -195,15 +195,9 @@ public function filterBoundClientData(FilterDataEvent $event)
195195
$event->setData($data);
196196
}
197197

198-
/**
199-
* Returns whether this form was bound with extra fields
200-
*
201-
* @return Boolean
202-
*/
203-
public function isBoundWithExtraFields()
198+
public function getExtraData()
204199
{
205-
// TODO: integrate the field names in the error message
206-
return count($this->extraFields) > 0;
200+
return $this->extraData;
207201
}
208202

209203
/**
@@ -329,33 +323,6 @@ public function bindRequest(Request $request)
329323
$this->bind($data);
330324
}
331325

332-
/**
333-
* Returns whether the maximum POST size was reached in this request.
334-
*
335-
* @return Boolean
336-
*/
337-
public function isPostMaxSizeReached()
338-
{
339-
if ($this->isRoot() && isset($_SERVER['CONTENT_LENGTH'])) {
340-
$length = (int) $_SERVER['CONTENT_LENGTH'];
341-
$max = trim(ini_get('post_max_size'));
342-
343-
switch (strtolower(substr($max, -1))) {
344-
// The 'G' modifier is available since PHP 5.1.0
345-
case 'g':
346-
$max *= 1024;
347-
case 'm':
348-
$max *= 1024;
349-
case 'k':
350-
$max *= 1024;
351-
}
352-
353-
return $length > $max;
354-
}
355-
356-
return false;
357-
}
358-
359326
/**
360327
* Validates the data of this form
361328
*

FormBuilder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ public function getInstance()
249249
$this->getClientTransformer(),
250250
$this->getNormTransformer(),
251251
$this->getDataMapper(),
252-
$this->getValidator(),
252+
$this->getValidators(),
253253
$this->getRequired(),
254254
$this->getReadOnly(),
255255
$this->getAttributes()

Resources/config/validation.xml

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,6 @@
1717
<property name="fields">
1818
<constraint name="Valid" />
1919
</property>
20-
<getter property="boundWithExtraFields">
21-
<constraint name="AssertFalse">
22-
<option name="message">This form should not contain extra fields</option>
23-
</constraint>
24-
</getter>
25-
<getter property="postMaxSizeReached">
26-
<constraint name="AssertFalse">
27-
<option name="message">The uploaded file was too large. Please try to upload a smaller file</option>
28-
</constraint>
29-
</getter>
3020
</class>
3121

3222
<class name="Symfony\Component\Form\RepeatedField">

Type/CsrfType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public function configure(FieldBuilder $builder, array $options)
3333

3434
$builder
3535
->setData($csrfProvider->generateCsrfToken($pageId))
36-
->setValidator(new CallbackValidator(
36+
->addValidator(new CallbackValidator(
3737
function (FieldInterface $field) use ($csrfProvider, $pageId) {
3838
if (!$csrfProvider->isCsrfTokenValid($pageId, $field->getData())) {
3939
// FIXME this error is currently not displayed

Type/FieldType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public function configure(FieldBuilder $builder, array $options)
5959
->setData($options['data'])
6060
->setRenderer(new DefaultRenderer($this->theme, $options['template']))
6161
->addRendererPlugin(new FieldPlugin())
62-
->setValidator(new DelegatingValidator($this->validator));
62+
->addValidator(new DelegatingValidator($this->validator));
6363

6464
if ($options['trim']) {
6565
$builder->addEventSubscriber(new TrimListener());

Type/FormType.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\Form\CsrfProvider\CsrfProviderInterface;
1818
use Symfony\Component\Form\DataMapper\PropertyPathMapper;
1919
use Symfony\Component\Form\Renderer\Plugin\FormPlugin;
20+
use Symfony\Component\Form\Validator\FormValidator;
2021
use Symfony\Component\EventDispatcher\EventDispatcher;
2122

2223
class FormType extends AbstractType
@@ -32,6 +33,7 @@ public function configure(FieldBuilder $builder, array $options)
3233
{
3334
$builder->setAttribute('virtual', $options['virtual'])
3435
->addRendererPlugin(new FormPlugin())
36+
->addValidator(new FormValidator())
3537
->setDataClass($options['data_class'])
3638
->setDataMapper(new PropertyPathMapper(
3739
$options['data_class'],

Validator/FormValidator.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien.potencier@symfony-project.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\Validator;
13+
14+
use Symfony\Component\Form\FieldInterface;
15+
use Symfony\Component\Form\FieldError;
16+
17+
class FormValidator implements FieldValidatorInterface
18+
{
19+
public function validate(FieldInterface $form)
20+
{
21+
if (count($form->getExtraData()) > 0) {
22+
$form->addError(new FieldError('This form should not contain extra fields'));
23+
}
24+
25+
if ($form->isRoot() && isset($_SERVER['CONTENT_LENGTH'])) {
26+
$length = (int) $_SERVER['CONTENT_LENGTH'];
27+
$max = trim(ini_get('post_max_size'));
28+
29+
switch (strtolower(substr($max, -1))) {
30+
// The 'G' modifier is available since PHP 5.1.0
31+
case 'g':
32+
$max *= 1024;
33+
case 'm':
34+
$max *= 1024;
35+
case 'k':
36+
$max *= 1024;
37+
}
38+
39+
if ($length > $max) {
40+
$form->addError(new FieldError('The uploaded file was too large. Please try to upload a smaller file'));
41+
}
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)