]> Raphaël G. Git Repositories - packbundle/blob - Form/CaptchaType.php
Version 0.5.7
[packbundle] / Form / CaptchaType.php
1 <?php declare(strict_types=1);
2
3 /*
4 * This file is part of the Rapsys PackBundle package.
5 *
6 * (c) Raphaël Gertz <symfony@rapsys.eu>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 namespace Rapsys\PackBundle\Form;
13
14 use Rapsys\PackBundle\RapsysPackBundle;
15 use Rapsys\PackBundle\Util\ImageUtil;
16 use Rapsys\PackBundle\Util\SluggerUtil;
17
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;
27
28 /**
29 * Captcha Type class definition
30 *
31 * @see https://symfony.com/doc/current/form/create_custom_field_type.html
32 */
33 class CaptchaType extends AbstractType {
34 /**
35 * Constructor
36 *
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
41 */
42 public function __construct(protected ?ImageUtil $image = null, protected ?SluggerUtil $slugger = null, protected ?TranslatorInterface $translator = null, protected bool $enable = false) {
43 }
44
45 /**
46 * {@inheritdoc}
47 *
48 * Build form
49 */
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) {
53 //Set captcha
54 $captcha = $this->image->getCaptcha();
55
56 //Add captcha token
57 $builder->add('_captcha_token', HiddenType::class, ['data' => $captcha['token'], 'empty_data' => $captcha['token'], 'mapped' => false]);
58
59 //Add captcha
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, 'required' => true]);
61
62 //Add event listener on captcha
63 $builder->addEventListener(FormEvents::PRE_SUBMIT, [$this, 'validateCaptcha']);
64 }
65 }
66
67 /**
68 * {@inheritdoc}
69 */
70 public function configureOptions(OptionsResolver $resolver): void {
71 //Call parent configure options
72 parent::configureOptions($resolver);
73
74 //Set defaults
75 $resolver->setDefaults(['captcha' => $this->enable, 'error_bubbling' => true, 'translation_domain' => RapsysPackBundle::getAlias()]);
76
77 //Add extra captcha option
78 $resolver->setAllowedTypes('captcha', 'boolean');
79 }
80
81 /**
82 * Validate captcha
83 *
84 * @param FormEvent $event The form event
85 */
86 public function validateCaptcha(FormEvent $event): void {
87 //Get form
88 $form = $event->getForm();
89
90 //Get event data
91 $data = $event->getData();
92
93 //Set token
94 $token = $form->get('_captcha_token')->getConfig()->getData();
95
96 //Without captcha
97 if (empty($data['captcha'])) {
98 //Add error on captcha
99 //XXX: we need to add error on form
100 //XXX: see https://github.com/symfony/symfony/issues/35831
101 $form->addError(new FormError($this->translator->trans('Captcha is empty')));
102
103 //Reset captcha token
104 $data['_captcha_token'] = $token;
105
106 //Set event data
107 $event->setData($data);
108 //With invalid captcha
109 } elseif ($this->slugger->hash($data['captcha']) !== $data['_captcha_token']) {
110 //Add error on captcha
111 //XXX: we need to add error on form
112 //XXX: see https://github.com/symfony/symfony/issues/35831
113 $form->addError(new FormError($this->translator->trans('Captcha is invalid')));
114
115 //Reset captcha token
116 $data['_captcha_token'] = $token;
117
118 //Set event data
119 $event->setData($data);
120 }
121 }
122 }