1 <?php 
declare(strict_types
=1); 
   4  * This file is part of the Rapsys PackBundle package. 
   6  * (c) Raphaël Gertz <symfony@rapsys.eu> 
   8  * For the full copyright and license information, please view the LICENSE 
   9  * file that was distributed with this source code. 
  12 namespace Rapsys\PackBundle\Form
; 
  14 use Rapsys\PackBundle\RapsysPackBundle
; 
  15 use Rapsys\PackBundle\Util\ImageUtil
; 
  16 use Rapsys\PackBundle\Util\SluggerUtil
; 
  18 use Symfony\Component\Form\AbstractType
; 
  19 use Symfony\Component\Form\Extension\Core\Type\HiddenType
; 
  20 use Symfony\Component\Form\Extension\Core\Type\IntegerType
; 
  21 use Symfony\Component\Form\FormBuilderInterface
; 
  22 use Symfony\Component\Form\FormError
; 
  23 use Symfony\Component\Form\FormEvent
; 
  24 use Symfony\Component\Form\FormEvents
; 
  25 use Symfony\Component\OptionsResolver\OptionsResolver
; 
  26 use Symfony\Contracts\Translation\TranslatorInterface
; 
  29  * Captcha Type class definition 
  31  * @see https://symfony.com/doc/current/form/create_custom_field_type.html 
  33 class CaptchaType 
extends AbstractType 
{ 
  37          * @param ?ImageUtil $image The image instance 
  38          * @param ?SluggerUtil $slugger The slugger instance 
  39          * @param ?TranslatorInterface $translator The translator instance 
  40          * @param bool $enable Use captcha 
  42         public function __construct(protected ?ImageUtil 
$image = null, protected ?SluggerUtil 
$slugger = null, protected ?TranslatorInterface 
$translator = null, protected bool $enable = false) { 
  50         public function buildForm(FormBuilderInterface 
$builder, array $options): void { 
  51                 //With image, slugger and translator 
  52                 if (!empty($options['captcha']) && $this->image 
!== null && $this->slugger 
!== null && $this->translator 
!== null) { 
  54                         $captcha = $this->image
->getCaptcha(); 
  57                         $builder->add('_captcha_token', HiddenType
::class, ['data' => $captcha['token'], 'empty_data' => $captcha['token'], 'mapped' => false]); 
  60                         $builder->add('captcha', IntegerType
::class, ['label_attr' => ['class' => 'captcha'], 'label' => '<img src="'.htmlentities($captcha['src']).'" alt="'.htmlentities($captcha['equation']).'" />', 'label_html' => true, 'mapped' => false, 'translation_domain' => false]); 
  62                         //Add event listener on captcha 
  63                         $builder->addEventListener(FormEvents
::PRE_SUBMIT
, [$this, 'validateCaptcha']); 
  70         public function configureOptions(OptionsResolver 
$resolver): void { 
  71                 //Call parent configure options 
  72                 parent
::configureOptions($resolver); 
  75                 $resolver->setDefaults(['captcha' => $this->enable
, 'error_bubbling' => true, 'translation_domain' => RapsysPackBundle
::getAlias()]); 
  77                 //Add extra captcha option 
  78                 $resolver->setAllowedTypes('captcha', 'boolean'); 
  84          * @param FormEvent $event The form event 
  86         public function validateCaptcha(FormEvent 
$event): void { 
  88                 $form = $event->getForm(); 
  91                 $data = $event->getData(); 
  94                 $token = $form->get('_captcha_token')->getConfig()->getData(); 
  97                 if (empty($data['captcha'])) { 
  98                         //Add error on captcha 
  99                         $form->addError(new FormError($this->translator
->trans('Captcha is empty'))); 
 101                         //Reset captcha token 
 102                         $data['_captcha_token'] = $token; 
 105                         $event->setData($data); 
 106                 //With invalid captcha 
 107                 } elseif ($this->slugger
->hash($data['captcha']) !== $data['_captcha_token']) { 
 108                         //Add error on captcha 
 109                         $form->addError(new FormError($this->translator
->trans('Captcha is invalid'))); 
 111                         //Reset captcha token 
 112                         $data['_captcha_token'] = $token; 
 115                         $event->setData($data);