Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 423460b

Browse files
committed
invalidate forms on transformation failures
1 parent 5c3d826 commit 423460b

File tree

5 files changed

+159
-1
lines changed

5 files changed

+159
-1
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@
166166
<tag name="form.type" alias="currency" />
167167
</service>
168168

169+
<service id="form.type_extension.form.transformation_failure_handling" class="Symfony\Component\Form\Extension\Core\Type\TransformationFailureExtension">
170+
<tag name="form.type_extension" extended-type="Symfony\Component\Form\Extension\Core\Type\FormType" />
171+
<argument type="service" id="translator" on-invalid="ignore" />
172+
</service>
173+
169174
<!-- FormTypeHttpFoundationExtension -->
170175
<service id="form.type_extension.form.http_foundation" class="Symfony\Component\Form\Extension\HttpFoundation\Type\FormTypeHttpFoundationExtension">
171176
<argument type="service" id="form.type_extension.form.request_handler" />

src/Symfony/Component/Form/Extension/Core/CoreExtension.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616
use Symfony\Component\Form\ChoiceList\Factory\ChoiceListFactoryInterface;
1717
use Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory;
1818
use Symfony\Component\Form\ChoiceList\Factory\PropertyAccessDecorator;
19+
use Symfony\Component\Form\Extension\Core\Type\TransformationFailureExtension;
1920
use Symfony\Component\PropertyAccess\PropertyAccess;
2021
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
22+
use Symfony\Component\Translation\TranslatorInterface;
2123

2224
/**
2325
* Represents the main form extension, which loads the core functionality.
@@ -28,11 +30,13 @@ class CoreExtension extends AbstractExtension
2830
{
2931
private $propertyAccessor;
3032
private $choiceListFactory;
33+
private $translator;
3134

32-
public function __construct(PropertyAccessorInterface $propertyAccessor = null, ChoiceListFactoryInterface $choiceListFactory = null)
35+
public function __construct(PropertyAccessorInterface $propertyAccessor = null, ChoiceListFactoryInterface $choiceListFactory = null, TranslatorInterface $translator = null)
3336
{
3437
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
3538
$this->choiceListFactory = $choiceListFactory ?: new CachingFactoryDecorator(new PropertyAccessDecorator(new DefaultChoiceListFactory(), $this->propertyAccessor));
39+
$this->translator = $translator;
3640
}
3741

3842
protected function loadTypes()
@@ -71,4 +75,11 @@ protected function loadTypes()
7175
new Type\CurrencyType(),
7276
);
7377
}
78+
79+
protected function loadTypeExtensions()
80+
{
81+
return array(
82+
new TransformationFailureExtension($this->translator),
83+
);
84+
}
7485
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Core\EventListener;
13+
14+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
15+
use Symfony\Component\Form\FormError;
16+
use Symfony\Component\Form\FormEvent;
17+
use Symfony\Component\Form\FormEvents;
18+
use Symfony\Component\Translation\TranslatorInterface;
19+
20+
/**
21+
* @author Christian Flothmann <[email protected]>
22+
*/
23+
class TransformationFailureListener implements EventSubscriberInterface
24+
{
25+
private $translator;
26+
27+
public function __construct(TranslatorInterface $translator = null)
28+
{
29+
$this->translator = $translator;
30+
}
31+
32+
public static function getSubscribedEvents()
33+
{
34+
return array(
35+
FormEvents::POST_SUBMIT => array('convertTransformationFailureToFormError', -1024),
36+
);
37+
}
38+
39+
public function convertTransformationFailureToFormError(FormEvent $event)
40+
{
41+
$form = $event->getForm();
42+
43+
if (null === $form->getTransformationFailure() || !$form->isValid()) {
44+
return;
45+
}
46+
47+
$childrenSynchronized = true;
48+
49+
foreach ($form as $child) {
50+
if (!$child->isSynchronized()) {
51+
$childrenSynchronized = false;
52+
break;
53+
}
54+
}
55+
56+
if ($childrenSynchronized) {
57+
$clientDataAsString = is_scalar($form->getViewData()) ? (string) $form->getViewData() : \gettype($form->getViewData());
58+
$message = 'This value is not valid.';
59+
60+
if (null !== $this->translator) {
61+
$message = $this->translator->trans($message, array('{{ value }}' => $clientDataAsString));
62+
}
63+
64+
$form->addError(new FormError($message, 'This value is not valid.', array('{{ value }}' => $clientDataAsString), null, $form->getTransformationFailure()));
65+
}
66+
}
67+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Core\Type;
13+
14+
use Symfony\Component\Form\AbstractTypeExtension;
15+
use Symfony\Component\Form\Extension\Core\EventListener\TransformationFailureListener;
16+
use Symfony\Component\Form\FormBuilderInterface;
17+
use Symfony\Component\Translation\TranslatorInterface;
18+
19+
/**
20+
* @author Christian Flothmann <[email protected]>
21+
*/
22+
class TransformationFailureExtension extends AbstractTypeExtension
23+
{
24+
private $translator;
25+
26+
public function __construct(TranslatorInterface $translator = null)
27+
{
28+
$this->translator = $translator;
29+
}
30+
31+
public function buildForm(FormBuilderInterface $builder, array $options)
32+
{
33+
if (!isset($options['invalid_message']) && !isset($options['invalid_message_parameters'])) {
34+
$builder->addEventSubscriber(new TransformationFailureListener($this->translator));
35+
}
36+
}
37+
38+
public function getExtendedType()
39+
{
40+
return 'Symfony\Component\Form\Extension\Core\Type\FormType';
41+
}
42+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Tests\Extension\Core;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Form\Extension\Core\CoreExtension;
16+
use Symfony\Component\Form\FormFactoryBuilder;
17+
18+
class CoreExtensionTest extends TestCase
19+
{
20+
public function testTransformationFailuresAreConvertedIntoFormErrors()
21+
{
22+
$formFactoryBuilder = new FormFactoryBuilder();
23+
$formFactory = $formFactoryBuilder->addExtension(new CoreExtension())
24+
->getFormFactory();
25+
26+
$form = $formFactory->createBuilder()
27+
->add('foo', 'Symfony\Component\Form\Extension\Core\Type\DateType')
28+
->getForm();
29+
$form->submit('foo');
30+
31+
$this->assertFalse($form->isValid());
32+
}
33+
}

0 commit comments

Comments
 (0)