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

Skip to content

Commit a7608d9

Browse files
committed
merged branch bschussek/issue7642 (PR #7903)
This PR was merged into the master branch. Discussion ---------- [Form] Fixed CSRF error messages to be translated and added "csrf_message" option | Q | A | ------------- | --- | Bug fix? | yes | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #7642 | License | MIT | Doc PR | TODO Commits ------- 549a308 [Form] Fixed CSRF error messages to be translated and added "csrf_message" option
2 parents 2d9154f + 549a308 commit a7608d9

File tree

6 files changed

+133
-8
lines changed

6 files changed

+133
-8
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
<argument type="service" id="form.csrf_provider" />
2020
<argument>%form.type_extension.csrf.enabled%</argument>
2121
<argument>%form.type_extension.csrf.field_name%</argument>
22+
<argument type="service" id="translator.default" />
23+
<argument>%validator.translation_domain%</argument>
2224
</service>
2325
</services>
2426
</container>

src/Symfony/Component/Form/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ CHANGELOG
3131
* [BC BREAK] initialization for Form instances added to a form tree must be manually disabled
3232
* PRE_SET_DATA is now guaranteed to be called after children were added by the form builder,
3333
unless FormInterface::setData() is called manually
34+
* fixed CSRF error message to be translated
35+
* custom CSRF error messages can now be set through the "csrf_message" option
3436

3537
2.2.0
3638
-----

src/Symfony/Component/Form/Extension/Csrf/CsrfExtension.php

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,42 @@
1414
use Symfony\Component\Form\Extension\Csrf\Type;
1515
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
1616
use Symfony\Component\Form\AbstractExtension;
17+
use Symfony\Component\Translation\TranslatorInterface;
1718

1819
/**
1920
* This extension protects forms by using a CSRF token.
21+
*
22+
* @author Bernhard Schussek <[email protected]>
2023
*/
2124
class CsrfExtension extends AbstractExtension
2225
{
26+
/**
27+
* @var CsrfProviderInterface
28+
*/
2329
private $csrfProvider;
2430

31+
/**
32+
* @var TranslatorInterface
33+
*/
34+
private $translator;
35+
36+
/**
37+
* @var null|string
38+
*/
39+
private $translationDomain;
40+
2541
/**
2642
* Constructor.
2743
*
28-
* @param CsrfProviderInterface $csrfProvider The CSRF provider
44+
* @param CsrfProviderInterface $csrfProvider The CSRF provider
45+
* @param TranslatorInterface $translator The translator for translating error messages.
46+
* @param null|string $translationDomain The translation domain for translating.
2947
*/
30-
public function __construct(CsrfProviderInterface $csrfProvider)
48+
public function __construct(CsrfProviderInterface $csrfProvider, TranslatorInterface $translator = null, $translationDomain = null)
3149
{
3250
$this->csrfProvider = $csrfProvider;
51+
$this->translator = $translator;
52+
$this->translationDomain = $translationDomain;
3353
}
3454

3555
/**
@@ -38,7 +58,7 @@ public function __construct(CsrfProviderInterface $csrfProvider)
3858
protected function loadTypeExtensions()
3959
{
4060
return array(
41-
new Type\FormTypeCsrfExtension($this->csrfProvider),
61+
new Type\FormTypeCsrfExtension($this->csrfProvider, true, '_token', $this->translator, $this->translationDomain),
4262
);
4363
}
4464
}

src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\Form\FormError;
1717
use Symfony\Component\Form\FormEvent;
1818
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
19+
use Symfony\Component\Translation\TranslatorInterface;
1920

2021
/**
2122
* @author Bernhard Schussek <[email protected]>
@@ -44,18 +45,37 @@ class CsrfValidationListener implements EventSubscriberInterface
4445
*/
4546
private $intention;
4647

48+
/**
49+
* The message displayed in case of an error.
50+
* @var string
51+
*/
52+
private $errorMessage;
53+
54+
/**
55+
* @var TranslatorInterface
56+
*/
57+
private $translator;
58+
59+
/**
60+
* @var null|string
61+
*/
62+
private $translationDomain;
63+
4764
public static function getSubscribedEvents()
4865
{
4966
return array(
5067
FormEvents::PRE_SUBMIT => 'preSubmit',
5168
);
5269
}
5370

54-
public function __construct($fieldName, CsrfProviderInterface $csrfProvider, $intention)
71+
public function __construct($fieldName, CsrfProviderInterface $csrfProvider, $intention, $errorMessage, TranslatorInterface $translator = null, $translationDomain = null)
5572
{
5673
$this->fieldName = $fieldName;
5774
$this->csrfProvider = $csrfProvider;
5875
$this->intention = $intention;
76+
$this->errorMessage = $errorMessage;
77+
$this->translator = $translator;
78+
$this->translationDomain = $translationDomain;
5979
}
6080

6181
public function preSubmit(FormEvent $event)
@@ -65,7 +85,13 @@ public function preSubmit(FormEvent $event)
6585

6686
if ($form->isRoot() && $form->getConfig()->getOption('compound')) {
6787
if (!isset($data[$this->fieldName]) || !$this->csrfProvider->isCsrfTokenValid($this->intention, $data[$this->fieldName])) {
68-
$form->addError(new FormError('The CSRF token is invalid. Please try to resubmit the form.'));
88+
$errorMessage = $this->errorMessage;
89+
90+
if (null !== $this->translator) {
91+
$errorMessage = $this->translator->trans($errorMessage, array(), $this->translationDomain);
92+
}
93+
94+
$form->addError(new FormError($errorMessage));
6995
}
7096

7197
if (is_array($data)) {

src/Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.php

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,45 @@
1818
use Symfony\Component\Form\FormView;
1919
use Symfony\Component\Form\FormInterface;
2020
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
21+
use Symfony\Component\Translation\TranslatorInterface;
2122

2223
/**
2324
* @author Bernhard Schussek <[email protected]>
2425
*/
2526
class FormTypeCsrfExtension extends AbstractTypeExtension
2627
{
28+
/**
29+
* @var CsrfProviderInterface
30+
*/
2731
private $defaultCsrfProvider;
32+
33+
/**
34+
* @var Boolean
35+
*/
2836
private $defaultEnabled;
37+
38+
/**
39+
* @var string
40+
*/
2941
private $defaultFieldName;
3042

31-
public function __construct(CsrfProviderInterface $defaultCsrfProvider, $defaultEnabled = true, $defaultFieldName = '_token')
43+
/**
44+
* @var TranslatorInterface
45+
*/
46+
private $translator;
47+
48+
/**
49+
* @var null|string
50+
*/
51+
private $translationDomain;
52+
53+
public function __construct(CsrfProviderInterface $defaultCsrfProvider, $defaultEnabled = true, $defaultFieldName = '_token', TranslatorInterface $translator = null, $translationDomain = null)
3254
{
3355
$this->defaultCsrfProvider = $defaultCsrfProvider;
3456
$this->defaultEnabled = $defaultEnabled;
3557
$this->defaultFieldName = $defaultFieldName;
58+
$this->translator = $translator;
59+
$this->translationDomain = $translationDomain;
3660
}
3761

3862
/**
@@ -49,7 +73,14 @@ public function buildForm(FormBuilderInterface $builder, array $options)
4973

5074
$builder
5175
->setAttribute('csrf_factory', $builder->getFormFactory())
52-
->addEventSubscriber(new CsrfValidationListener($options['csrf_field_name'], $options['csrf_provider'], $options['intention']))
76+
->addEventSubscriber(new CsrfValidationListener(
77+
$options['csrf_field_name'],
78+
$options['csrf_provider'],
79+
$options['intention'],
80+
$options['csrf_message'],
81+
$this->translator,
82+
$this->translationDomain
83+
))
5384
;
5485
}
5586

@@ -83,6 +114,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
83114
'csrf_protection' => $this->defaultEnabled,
84115
'csrf_field_name' => $this->defaultFieldName,
85116
'csrf_provider' => $this->defaultCsrfProvider,
117+
'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.',
86118
'intention' => 'unknown',
87119
));
88120
}

src/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\Form\AbstractType;
1515
use Symfony\Component\Form\FormBuilderInterface;
16+
use Symfony\Component\Form\FormError;
1617
use Symfony\Component\Form\Test\TypeTestCase;
1718
use Symfony\Component\Form\Extension\Csrf\CsrfExtension;
1819

@@ -33,26 +34,36 @@ public function getName()
3334

3435
class FormTypeCsrfExtensionTest extends TypeTestCase
3536
{
37+
/**
38+
* @var \PHPUnit_Framework_MockObject_MockObject
39+
*/
3640
protected $csrfProvider;
3741

42+
/**
43+
* @var \PHPUnit_Framework_MockObject_MockObject
44+
*/
45+
protected $translator;
46+
3847
protected function setUp()
3948
{
4049
$this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface');
50+
$this->translator = $this->getMock('Symfony\Component\Translation\TranslatorInterface');
4151

4252
parent::setUp();
4353
}
4454

4555
protected function tearDown()
4656
{
4757
$this->csrfProvider = null;
58+
$this->translator = null;
4859

4960
parent::tearDown();
5061
}
5162

5263
protected function getExtensions()
5364
{
5465
return array_merge(parent::getExtensions(), array(
55-
new CsrfExtension($this->csrfProvider),
66+
new CsrfExtension($this->csrfProvider, $this->translator),
5667
));
5768
}
5869

@@ -255,4 +266,36 @@ public function testNoCsrfProtectionOnPrototype()
255266
$this->assertFalse(isset($prototypeView['csrf']));
256267
$this->assertCount(1, $prototypeView);
257268
}
269+
270+
public function testsTranslateCustomErrorMessage()
271+
{
272+
$this->csrfProvider->expects($this->once())
273+
->method('isCsrfTokenValid')
274+
->with('%INTENTION%', 'token')
275+
->will($this->returnValue(false));
276+
277+
$this->translator->expects($this->once())
278+
->method('trans')
279+
->with('Foobar')
280+
->will($this->returnValue('[trans]Foobar[/trans]'));
281+
282+
$form = $this->factory
283+
->createBuilder('form', null, array(
284+
'csrf_field_name' => 'csrf',
285+
'csrf_provider' => $this->csrfProvider,
286+
'csrf_message' => 'Foobar',
287+
'intention' => '%INTENTION%',
288+
'compound' => true,
289+
))
290+
->getForm();
291+
292+
$form->submit(array(
293+
'csrf' => 'token',
294+
));
295+
296+
$errors = $form->getErrors();
297+
298+
$this->assertGreaterThan(0, count($errors));
299+
$this->assertEquals(new FormError('[trans]Foobar[/trans]'), $errors[0]);
300+
}
258301
}

0 commit comments

Comments
 (0)