diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml
index 72442bcbba..57cad204aa 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml
@@ -19,6 +19,8 @@
%form.type_extension.csrf.enabled%
%form.type_extension.csrf.field_name%
+
+ %validator.translation_domain%
diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md
index 88a5714053..6cc800d0af 100644
--- a/src/Symfony/Component/Form/CHANGELOG.md
+++ b/src/Symfony/Component/Form/CHANGELOG.md
@@ -31,6 +31,8 @@ CHANGELOG
* [BC BREAK] initialization for Form instances added to a form tree must be manually disabled
* PRE_SET_DATA is now guaranteed to be called after children were added by the form builder,
unless FormInterface::setData() is called manually
+ * fixed CSRF error message to be translated
+ * custom CSRF error messages can now be set through the "csrf_message" option
2.2.0
-----
diff --git a/src/Symfony/Component/Form/Extension/Csrf/CsrfExtension.php b/src/Symfony/Component/Form/Extension/Csrf/CsrfExtension.php
index 71d06381ad..f9d9e40aa8 100644
--- a/src/Symfony/Component/Form/Extension/Csrf/CsrfExtension.php
+++ b/src/Symfony/Component/Form/Extension/Csrf/CsrfExtension.php
@@ -14,22 +14,42 @@ namespace Symfony\Component\Form\Extension\Csrf;
use Symfony\Component\Form\Extension\Csrf\Type;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
use Symfony\Component\Form\AbstractExtension;
+use Symfony\Component\Translation\TranslatorInterface;
/**
* This extension protects forms by using a CSRF token.
+ *
+ * @author Bernhard Schussek
*/
class CsrfExtension extends AbstractExtension
{
+ /**
+ * @var CsrfProviderInterface
+ */
private $csrfProvider;
+ /**
+ * @var TranslatorInterface
+ */
+ private $translator;
+
+ /**
+ * @var null|string
+ */
+ private $translationDomain;
+
/**
* Constructor.
*
- * @param CsrfProviderInterface $csrfProvider The CSRF provider
+ * @param CsrfProviderInterface $csrfProvider The CSRF provider
+ * @param TranslatorInterface $translator The translator for translating error messages.
+ * @param null|string $translationDomain The translation domain for translating.
*/
- public function __construct(CsrfProviderInterface $csrfProvider)
+ public function __construct(CsrfProviderInterface $csrfProvider, TranslatorInterface $translator = null, $translationDomain = null)
{
$this->csrfProvider = $csrfProvider;
+ $this->translator = $translator;
+ $this->translationDomain = $translationDomain;
}
/**
@@ -38,7 +58,7 @@ class CsrfExtension extends AbstractExtension
protected function loadTypeExtensions()
{
return array(
- new Type\FormTypeCsrfExtension($this->csrfProvider),
+ new Type\FormTypeCsrfExtension($this->csrfProvider, true, '_token', $this->translator, $this->translationDomain),
);
}
}
diff --git a/src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php b/src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php
index 9d062f9546..547e9d756c 100644
--- a/src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php
+++ b/src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php
@@ -16,6 +16,7 @@ use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
+use Symfony\Component\Translation\TranslatorInterface;
/**
* @author Bernhard Schussek
@@ -44,6 +45,22 @@ class CsrfValidationListener implements EventSubscriberInterface
*/
private $intention;
+ /**
+ * The message displayed in case of an error.
+ * @var string
+ */
+ private $errorMessage;
+
+ /**
+ * @var TranslatorInterface
+ */
+ private $translator;
+
+ /**
+ * @var null|string
+ */
+ private $translationDomain;
+
public static function getSubscribedEvents()
{
return array(
@@ -51,11 +68,14 @@ class CsrfValidationListener implements EventSubscriberInterface
);
}
- public function __construct($fieldName, CsrfProviderInterface $csrfProvider, $intention)
+ public function __construct($fieldName, CsrfProviderInterface $csrfProvider, $intention, $errorMessage, TranslatorInterface $translator = null, $translationDomain = null)
{
$this->fieldName = $fieldName;
$this->csrfProvider = $csrfProvider;
$this->intention = $intention;
+ $this->errorMessage = $errorMessage;
+ $this->translator = $translator;
+ $this->translationDomain = $translationDomain;
}
public function preSubmit(FormEvent $event)
@@ -65,7 +85,13 @@ class CsrfValidationListener implements EventSubscriberInterface
if ($form->isRoot() && $form->getConfig()->getOption('compound')) {
if (!isset($data[$this->fieldName]) || !$this->csrfProvider->isCsrfTokenValid($this->intention, $data[$this->fieldName])) {
- $form->addError(new FormError('The CSRF token is invalid. Please try to resubmit the form.'));
+ $errorMessage = $this->errorMessage;
+
+ if (null !== $this->translator) {
+ $errorMessage = $this->translator->trans($errorMessage, array(), $this->translationDomain);
+ }
+
+ $form->addError(new FormError($errorMessage));
}
if (is_array($data)) {
diff --git a/src/Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.php b/src/Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.php
index ea13056c86..336cf04756 100644
--- a/src/Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.php
+++ b/src/Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.php
@@ -18,21 +18,45 @@ use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
+use Symfony\Component\Translation\TranslatorInterface;
/**
* @author Bernhard Schussek
*/
class FormTypeCsrfExtension extends AbstractTypeExtension
{
+ /**
+ * @var CsrfProviderInterface
+ */
private $defaultCsrfProvider;
+
+ /**
+ * @var Boolean
+ */
private $defaultEnabled;
+
+ /**
+ * @var string
+ */
private $defaultFieldName;
- public function __construct(CsrfProviderInterface $defaultCsrfProvider, $defaultEnabled = true, $defaultFieldName = '_token')
+ /**
+ * @var TranslatorInterface
+ */
+ private $translator;
+
+ /**
+ * @var null|string
+ */
+ private $translationDomain;
+
+ public function __construct(CsrfProviderInterface $defaultCsrfProvider, $defaultEnabled = true, $defaultFieldName = '_token', TranslatorInterface $translator = null, $translationDomain = null)
{
$this->defaultCsrfProvider = $defaultCsrfProvider;
$this->defaultEnabled = $defaultEnabled;
$this->defaultFieldName = $defaultFieldName;
+ $this->translator = $translator;
+ $this->translationDomain = $translationDomain;
}
/**
@@ -49,7 +73,14 @@ class FormTypeCsrfExtension extends AbstractTypeExtension
$builder
->setAttribute('csrf_factory', $builder->getFormFactory())
- ->addEventSubscriber(new CsrfValidationListener($options['csrf_field_name'], $options['csrf_provider'], $options['intention']))
+ ->addEventSubscriber(new CsrfValidationListener(
+ $options['csrf_field_name'],
+ $options['csrf_provider'],
+ $options['intention'],
+ $options['csrf_message'],
+ $this->translator,
+ $this->translationDomain
+ ))
;
}
@@ -83,6 +114,7 @@ class FormTypeCsrfExtension extends AbstractTypeExtension
'csrf_protection' => $this->defaultEnabled,
'csrf_field_name' => $this->defaultFieldName,
'csrf_provider' => $this->defaultCsrfProvider,
+ 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.',
'intention' => 'unknown',
));
}
diff --git a/src/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php
index 13b305fe4b..0a1f0dc481 100644
--- a/src/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php
+++ b/src/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php
@@ -13,6 +13,7 @@ namespace Symfony\Component\Form\Tests\Extension\Csrf\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\Form\FormError;
use Symfony\Component\Form\Test\TypeTestCase;
use Symfony\Component\Form\Extension\Csrf\CsrfExtension;
@@ -33,11 +34,20 @@ class FormTypeCsrfExtensionTest_ChildType extends AbstractType
class FormTypeCsrfExtensionTest extends TypeTestCase
{
+ /**
+ * @var \PHPUnit_Framework_MockObject_MockObject
+ */
protected $csrfProvider;
+ /**
+ * @var \PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $translator;
+
protected function setUp()
{
$this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface');
+ $this->translator = $this->getMock('Symfony\Component\Translation\TranslatorInterface');
parent::setUp();
}
@@ -45,6 +55,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase
protected function tearDown()
{
$this->csrfProvider = null;
+ $this->translator = null;
parent::tearDown();
}
@@ -52,7 +63,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase
protected function getExtensions()
{
return array_merge(parent::getExtensions(), array(
- new CsrfExtension($this->csrfProvider),
+ new CsrfExtension($this->csrfProvider, $this->translator),
));
}
@@ -255,4 +266,36 @@ class FormTypeCsrfExtensionTest extends TypeTestCase
$this->assertFalse(isset($prototypeView['csrf']));
$this->assertCount(1, $prototypeView);
}
+
+ public function testsTranslateCustomErrorMessage()
+ {
+ $this->csrfProvider->expects($this->once())
+ ->method('isCsrfTokenValid')
+ ->with('%INTENTION%', 'token')
+ ->will($this->returnValue(false));
+
+ $this->translator->expects($this->once())
+ ->method('trans')
+ ->with('Foobar')
+ ->will($this->returnValue('[trans]Foobar[/trans]'));
+
+ $form = $this->factory
+ ->createBuilder('form', null, array(
+ 'csrf_field_name' => 'csrf',
+ 'csrf_provider' => $this->csrfProvider,
+ 'csrf_message' => 'Foobar',
+ 'intention' => '%INTENTION%',
+ 'compound' => true,
+ ))
+ ->getForm();
+
+ $form->submit(array(
+ 'csrf' => 'token',
+ ));
+
+ $errors = $form->getErrors();
+
+ $this->assertGreaterThan(0, count($errors));
+ $this->assertEquals(new FormError('[trans]Foobar[/trans]'), $errors[0]);
+ }
}