src/Actimage/CaptchaBundle/Form/Type/ActimageCaptchaType.php line 44

Open in your IDE?
  1. <?php 
  2. namespace App\Actimage\CaptchaBundle\Form\Type;
  3. use Symfony\Component\Form\AbstractType;
  4. use Symfony\Component\Form\FormBuilderInterface;
  5. use Symfony\Component\Form\Extension\Core\Type\TextType;
  6. use Symfony\Component\Form\FormView;
  7. use Symfony\Component\Form\FormInterface;
  8. use Symfony\Component\Validator\Constraints\Expression;
  9. use Symfony\Component\Form\CallbackTransformer;
  10. use App\Actimage\CaptchaBundle\Service\ActimageCaptchaService;
  11. use Symfony\Component\HttpFoundation\RequestStack;
  12. use Symfony\Component\Form\FormEvent;
  13. use Symfony\Component\Form\FormEvents;
  14. /**
  15.  * @author Actimage - Marc Dornier
  16.  */
  17.  
  18. class ActimageCaptchaType extends AbstractType
  19. {
  20.     protected $requestStack;
  21.     protected $session;
  22.     protected $actimageCaptchaService;
  23.     protected $captchaText;
  24.     protected $cipherCaptcha;
  25.     
  26.     public function __construct(RequestStack $requestStackActimageCaptchaService $actimageCaptchaService)
  27.     {   
  28.         $this->requestStack $requestStack;
  29.         $this->session $this->requestStack->getSession();
  30.         $this->session->start();
  31.         $this->actimageCaptchaService $actimageCaptchaService;
  32.         // Génération du captcha et encodage de ce dernier pour appeler les services de génération d'image et de son
  33.         // depuis le JS sans divulguer le code dans les URLs
  34.         $this->captchaText $this->actimageCaptchaService->secure_generate_string();
  35.         $this->cipherCaptcha $this->actimageCaptchaService->cipherCaptcha($this->captchaText);
  36.         if($this->session->get('allCaptcha', []) == []){
  37.             $arrayAllCaptcha = [];
  38.             array_push($arrayAllCaptchastrtolower($this->captchaText));
  39.             $this->session->set('allCaptcha'$arrayAllCaptcha);
  40.         }
  41.     }
  42.     public function buildForm(FormBuilderInterface $builder, array $options)
  43.     {
  44.         $encodedCaptcha $this->cipherCaptcha;
  45.         $builder
  46.         ->add('captcha'TextType::class, [
  47.             'attr' => ['autocomplete' => 'off''encodedCaptcha' => $this->cipherCaptcha],
  48.             'label_attr' => ['class' => 'mb-0'],
  49.             'help_attr' => ['class' => 'mb-1'],
  50.             'help' => '(les lettres peuvent être retranscrites indifféremment en minuscule ou en majuscule)',
  51.             'required' => true
  52.         ])
  53.         ->addEventListener(FormEvents::PRE_SUBMIT , function (FormEvent $event) use ($encodedCaptcha) {
  54.             $data $event->getData();
  55.             $form $event->getForm();
  56.             if (!$data) {
  57.                 return;
  58.             }
  59.             if (isset($data['captcha'])) {
  60.                 // On stock plusieurs captcha en session et on les comparent tous avec la saisie utilisateur
  61.                 // pour éviter les problème de mauvais captcha comparé lors du double chargement du formulaire
  62.                 // (formulaire chargé 2 fois à cause de Symfony, et donc session écrasée lors du 2eme chargement)
  63.                 $storedCaptcha $this->actimageCaptchaService->decipherCaptcha($encodedCaptcha);
  64.                 $allCaptcha $this->session->get('allCaptcha', []);
  65.                 array_push($allCaptchastrtolower($storedCaptcha));
  66.                 if(count($allCaptcha) > 3){
  67.                     array_shift($allCaptcha);
  68.                 }
  69.                 $this->session->set('allCaptcha'$allCaptcha);
  70.                 // On stock la saisie utilisateur en session pour la comparer aux captchas stockées
  71.                 $this->session->set('captchaSent'$data['captcha']);
  72.             }
  73.             // Ajout de la contrainte de validation lors du PRE_SUBMIT pour avoir la valeur de saisie utilisateur captcha déclarée en session lors du submit d'avant
  74.             foreach($event->getForm()->all() as $child){
  75.                 $childName $child->getName();
  76.                 $type get_class($child->getConfig()->getType()->getInnerType());
  77.                 $options $child->getConfig()->getOptions();
  78.             
  79.                 $options['constraints'] =  [
  80.                     new Expression([
  81.                         'expression' => "'ok' == captcha_text",
  82.                         'values' => ['captcha_text' => $this->isCaptchaValid()],
  83.                         'message' => 'Le captcha doit être valide '
  84.                     ])
  85.                 ];
  86.             
  87.                 $form->add($childName,$type,$options);
  88.             }
  89.         })
  90.         ->get('captcha')
  91.         ->addModelTransformer(new CallbackTransformer(
  92.             function ($data) {
  93.                 return $data;
  94.             },
  95.             function ($data) {
  96.                 // met la saisie utilisateur en lowercase pour faire la comparaison avec le code captcha sans se soucier de la casse
  97.                 $data strtolower($data);
  98.                 return $data;
  99.             }
  100.         ))
  101.         ;
  102.     }
  103.     /**
  104.      * Vérification de la saisie utilisateur captcha
  105.      */
  106.     public function isCaptchaValid(){
  107.         // Si le captcha est valide = OK, si le captcha n'est pas valide ou non submit alors NULL
  108.         $allCaptcha $this->session->get('allCaptcha');
  109.         $captchaSent $this->session->get('captchaSent'null);
  110.         if($captchaSent != null && in_array(strtolower($captchaSent), $allCaptcha)){
  111.             return 'ok';
  112.         }
  113.         return null;
  114.     }
  115.     public function buildView(FormView $viewFormInterface $form, array $options): void
  116.     {
  117.         // $view->vars['captcha_text'] = $this->cipherCaptcha.' '.$this->captchaText;
  118.     }
  119. }