vendor/symfony/form/Extension/Csrf/Type/FormTypeCsrfExtension.php line 73

Open in your IDE?
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Form\Extension\Csrf\Type;
  11. use Symfony\Component\Form\AbstractTypeExtension;
  12. use Symfony\Component\Form\Extension\Core\Type\FormType;
  13. use Symfony\Component\Form\Extension\Core\Type\HiddenType;
  14. use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener;
  15. use Symfony\Component\Form\FormBuilderInterface;
  16. use Symfony\Component\Form\FormInterface;
  17. use Symfony\Component\Form\FormView;
  18. use Symfony\Component\Form\Util\ServerParams;
  19. use Symfony\Component\OptionsResolver\OptionsResolver;
  20. use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
  21. use Symfony\Contracts\Translation\TranslatorInterface;
  22. /**
  23. * @author Bernhard Schussek <bschussek@gmail.com>
  24. */
  25. class FormTypeCsrfExtension extends AbstractTypeExtension
  26. {
  27. private $defaultTokenManager;
  28. private $defaultEnabled;
  29. private $defaultFieldName;
  30. private $translator;
  31. private $translationDomain;
  32. private $serverParams;
  33. public function __construct(CsrfTokenManagerInterface $defaultTokenManager, bool $defaultEnabled = true, string $defaultFieldName = '_token', ?TranslatorInterface $translator = null, ?string $translationDomain = null, ?ServerParams $serverParams = null)
  34. {
  35. $this->defaultTokenManager = $defaultTokenManager;
  36. $this->defaultEnabled = $defaultEnabled;
  37. $this->defaultFieldName = $defaultFieldName;
  38. $this->translator = $translator;
  39. $this->translationDomain = $translationDomain;
  40. $this->serverParams = $serverParams;
  41. }
  42. /**
  43. * Adds a CSRF field to the form when the CSRF protection is enabled.
  44. */
  45. public function buildForm(FormBuilderInterface $builder, array $options)
  46. {
  47. if (!$options['csrf_protection']) {
  48. return;
  49. }
  50. $builder
  51. ->addEventSubscriber(new CsrfValidationListener(
  52. $options['csrf_field_name'],
  53. $options['csrf_token_manager'],
  54. $options['csrf_token_id'] ?: ($builder->getName() ?: \get_class($builder->getType()->getInnerType())),
  55. $options['csrf_message'],
  56. $this->translator,
  57. $this->translationDomain,
  58. $this->serverParams
  59. ))
  60. ;
  61. }
  62. /**
  63. * Adds a CSRF field to the root form view.
  64. */
  65. public function finishView(FormView $view, FormInterface $form, array $options)
  66. {
  67. if ($options['csrf_protection'] && !$view->parent && $options['compound']) {
  68. $factory = $form->getConfig()->getFormFactory();
  69. $tokenId = $options['csrf_token_id'] ?: ($form->getName() ?: \get_class($form->getConfig()->getType()->getInnerType()));
  70. $data = (string) $options['csrf_token_manager']->getToken($tokenId);
  71. $csrfForm = $factory->createNamed($options['csrf_field_name'], HiddenType::class, $data, [
  72. 'block_prefix' => 'csrf_token',
  73. 'mapped' => false,
  74. ]);
  75. $view->children[$options['csrf_field_name']] = $csrfForm->createView($view);
  76. }
  77. }
  78. /**
  79. * {@inheritdoc}
  80. */
  81. public function configureOptions(OptionsResolver $resolver)
  82. {
  83. $resolver->setDefaults([
  84. 'csrf_protection' => $this->defaultEnabled,
  85. 'csrf_field_name' => $this->defaultFieldName,
  86. 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.',
  87. 'csrf_token_manager' => $this->defaultTokenManager,
  88. 'csrf_token_id' => null,
  89. ]);
  90. }
  91. /**
  92. * {@inheritdoc}
  93. */
  94. public static function getExtendedTypes(): iterable
  95. {
  96. return [FormType::class];
  97. }
  98. }