vendor/dachcom-digital/formbuilder/src/FormBuilderBundle/Form/Type/DynamicFormType.php line 18

Open in your IDE?
  1. <?php
  2. namespace FormBuilderBundle\Form\Type;
  3. use FormBuilderBundle\Configuration\Configuration;
  4. use FormBuilderBundle\Form\Data\FormData;
  5. use Symfony\Component\Form\AbstractType;
  6. use Symfony\Component\Form\CallbackTransformer;
  7. use Symfony\Component\Form\Extension\Core\Type\HiddenType;
  8. use Symfony\Component\Form\FormBuilderInterface;
  9. use Symfony\Component\Form\FormError;
  10. use Symfony\Component\Form\FormEvent;
  11. use Symfony\Component\Form\FormEvents;
  12. use Symfony\Component\OptionsResolver\OptionsResolver;
  13. use Symfony\Component\Security\Csrf\CsrfToken;
  14. use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
  15. class DynamicFormType extends AbstractType
  16. {
  17.     public const EMPTY_RUNTIME_DATA_KEY 'no-runtime-data';
  18.     protected CsrfTokenManagerInterface $defaultTokenManager;
  19.     protected Configuration $configuration;
  20.     public function __construct(
  21.         CsrfTokenManagerInterface $defaultTokenManager,
  22.         Configuration $configuration
  23.     ) {
  24.         $this->defaultTokenManager $defaultTokenManager;
  25.         $this->configuration $configuration;
  26.     }
  27.     public function buildForm(FormBuilderInterface $builder, array $options): void
  28.     {
  29.         $addHoneypot $this->configuration->getConfigFlag('use_honeypot_field');
  30.         $spamProtectionConfig $this->configuration->getConfig('spam_protection');
  31.         $honeyPotConfig $spamProtectionConfig['honeypot'];
  32.         $builder
  33.             ->add('formId'HiddenType::class, [
  34.                 'mapped' => false,
  35.                 'data'   => $options['current_form_id'],
  36.             ])
  37.             ->add('formCl'HiddenType::class, [
  38.                 'mapped' => false,
  39.                 'data'   => $options['conditional_logic'] ?? null,
  40.             ]);
  41.         if ($addHoneypot === true) {
  42.             $builder->add($honeyPotConfig['field_name'], HoneypotType::class, ['mapped' => false]);
  43.         }
  44.         $this->addRuntimeData($builder$options);
  45.         $builder->get('formCl')->addModelTransformer(new CallbackTransformer(
  46.             function ($conditionalLogic) {
  47.                 return is_array($conditionalLogic) ? json_encode($conditionalLogic) : null;
  48.             },
  49.             function ($conditionalLogic) {
  50.                 return empty($conditionalLogic) ? null json_decode($conditionalLogictrue);
  51.             }
  52.         ));
  53.         $builder->get('formRuntimeData')->addModelTransformer(new CallbackTransformer(
  54.             function ($runtimeData) {
  55.                 return is_array($runtimeData) ? json_encode($runtimeData) : null;
  56.             },
  57.             function ($runtimeData) {
  58.                 return empty($runtimeData) ? null json_decode($runtimeDatatrue);
  59.             }
  60.         ));
  61.     }
  62.     protected function addRuntimeData(FormBuilderInterface $builder, array $options): void
  63.     {
  64.         $runtimeData $options['runtime_data'] ?? null;
  65.         if (isset($runtimeData['email'], $runtimeData['email']['_deprecated_note'])) {
  66.             unset($runtimeData['email']['_deprecated_note']);
  67.         }
  68.         $token is_array($runtimeData) ? md5(json_encode($runtimeData)) : md5(self::EMPTY_RUNTIME_DATA_KEY);
  69.         $builder
  70.             ->add('formRuntimeData'HiddenType::class, [
  71.                 'mapped' => false,
  72.                 'data'   => $runtimeData,
  73.             ]);
  74.         $builder
  75.             ->add('formRuntimeDataToken'HiddenType::class, [
  76.                 'mapped' => false,
  77.                 'data'   => (string) $this->defaultTokenManager->getToken($token),
  78.             ]);
  79.         $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
  80.             $data $event->getData();
  81.             $runtimeData $data['formRuntimeData'] ?? null;
  82.             $tokenValue $data['formRuntimeDataToken'] ?? null;
  83.             if (empty($runtimeData)) {
  84.                 $runtimeData self::EMPTY_RUNTIME_DATA_KEY;
  85.             }
  86.             $rtCsrfToken = new CsrfToken(md5($runtimeData), $tokenValue);
  87.             if ($tokenValue === null || !$this->defaultTokenManager->isTokenValid($rtCsrfToken)) {
  88.                 $event->getForm()->addError(new FormError('Manipulated runtime token detected.''', [], null$rtCsrfToken));
  89.             }
  90.         });
  91.     }
  92.     public function configureOptions(OptionsResolver $resolver): void
  93.     {
  94.         $resolver->setDefaults([
  95.             'current_form_id'    => 0,
  96.             'conditional_logic'  => [],
  97.             'runtime_data'       => [],
  98.             'allow_extra_fields' => true,
  99.             'csrf_protection'    => true,
  100.             'data_class'         => FormData::class
  101.         ]);
  102.     }
  103. }