src/Form/UserType.php line 56

  1. <?php
  2. namespace App\Form;
  3. use App\Entity\User;
  4. use Symfony\Component\Form\FormError;
  5. use Symfony\Component\Form\FormEvent;
  6. use Symfony\Component\Form\FormEvents;
  7. use Symfony\Component\Form\AbstractType;
  8. use Vich\UploaderBundle\Form\Type\VichFileType;
  9. use Symfony\Component\Form\FormBuilderInterface;
  10. use Symfony\Component\Validator\Constraints\File;
  11. use Symfony\Component\Validator\Constraints\Email;
  12. use Symfony\Component\Validator\Constraints\Regex;
  13. use Symfony\Component\Validator\Constraints\NotBlank;
  14. use Symfony\Component\OptionsResolver\OptionsResolver;
  15. use Symfony\Component\Validator\Constraints as Assert;
  16. use Symfony\Component\Form\Extension\Core\Type\TelType;
  17. use Symfony\Component\Form\Extension\Core\Type\FileType;
  18. use Symfony\Component\Form\Extension\Core\Type\TextType;
  19. use Symfony\Component\Form\Extension\Core\Type\EmailType;
  20. use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
  21. use Symfony\Component\Form\Extension\Core\Type\PasswordType;
  22. use Symfony\Component\Form\Extension\Core\Type\TextareaType;
  23. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  24. class UserFormSubscriber implements EventSubscriberInterface
  25. {
  26.     public static function getSubscribedEvents()
  27.     {
  28.         return [
  29.             FormEvents::SUBMIT => 'onSubmit',
  30.         ];
  31.     }
  32.     public function onSubmit(FormEvent $event)
  33.     {
  34.         $data $event->getData();
  35.         $form $event->getForm();
  36.         
  37.         $user $form->getData();
  38.         
  39.         $password $form->get('password')->getData();
  40.         $passwordConfirmed $form->get('password_confirmed')->getData();
  41.         if ($password && $password === $passwordConfirmed) {
  42.             $user->setPassword($password);
  43.         } else {
  44.             $form->get('password')->addError(new FormError('Les mots de passe ne correspondent pas'));
  45.         }
  46.         $event->setData($data);
  47.     }
  48. }
  49. class UserType extends AbstractType
  50. {
  51.     public function buildForm(FormBuilderInterface $builder, array $options): void
  52.     {
  53.         $builder
  54.         ->add('email'EmailType::class, [
  55.             'attr' => [
  56.                 'placeholder' => "exemple@domaine.com",
  57.                 'class' => 'border border-gray-200 dark:border-gray-800 dark:text-gray-300 rounded-lg pl-4 dark:bg-foreground py-[15px] shadow-input hover:border hover:border-blue-200 focus:border-blue-200 focus:outline-none w-full mb-1'
  58.             ],
  59.             'label' => 'Adresse email*',
  60.             'label_attr' => [
  61.                 'class' => 'text-base text-gray-700 dark:text-gray-200 block mb-3'
  62.             ],
  63.             'error_bubbling' => false,
  64.             'constraints' => [
  65.                 new Email(['mode' => 'strict']),
  66.                 new NotBlank([
  67.                     'message' => 'L\'adresse email est obligatoire'
  68.                 ]),
  69.             ]
  70.         ]) 
  71.             ->add('roles'ChoiceType::class, [
  72.                 "choices" => [
  73.                     "ADMIN" => "ROLE_ADMIN",
  74.                     "COMMERCE" => "ROLE_COMMERCE",
  75.                     "USER" => "ROLE_USER"
  76.                 ],
  77.                 'multiple' => true,
  78.                 'expanded' => true,
  79.                 'attr' => ['hidden' => true],
  80.                 'data' => ['ROLE_COMMERCE']
  81.             ])
  82.             ->add('password'PasswordType::class, [
  83.                 "attr" => [
  84.                     "placeholder" => "votre mot de passe",
  85.                     'class' => 'border border-gray-200 dark:border-gray-800 dark:text-gray-300 rounded-lg pl-4 dark:bg-foreground py-[15px] shadow-input hover:border hover:border-blue-200 focus:border-blue-200 focus:outline-none w-full mb-1'
  86.                 ],
  87.                 'label' => 'Mot de passe*',
  88.                 'label_attr' => [
  89.                     'class' => 'text-base text-gray-700 dark:text-gray-200 block mb-3'
  90.                 ],
  91.                 "mapped" => false,
  92.                 'constraints' => [
  93.                     new NotBlank(),
  94.                     new Regex(
  95.                         "/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/",
  96.                         "Le mot de passe doit contenir au minimum 8 caractères, une majuscule, un chiffre et un caractère spécial"
  97.                     ),
  98.                 ]
  99.             ])
  100.             ->add('password_confirmed'PasswordType::class, [
  101.                 "attr" => [
  102.                     "placeholder" => "veuillez confirmer le mot de passe",
  103.                     'class' => 'border border-gray-200 dark:border-gray-800 dark:text-gray-300 rounded-lg pl-4 dark:bg-foreground py-[15px] shadow-input hover:border hover:border-blue-200 focus:border-blue-200 focus:outline-none w-full mb-1'
  104.                 ],
  105.                 'label' => 'Confirmez le mot de passe*',
  106.                 'label_attr' => [
  107.                     'class' => 'text-base text-gray-700 dark:text-gray-200 block mb-3'
  108.                 ],
  109.                 "mapped" => false,
  110.                 'constraints' => [
  111.                     new NotBlank(),
  112.                     new Regex(
  113.                         "/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/",
  114.                         "Le mot de passe doit contenir au minimum 8 caractères, une majuscule, un chiffre et un caractère spécial"
  115.                     ),
  116.                 ]
  117.             ])
  118.             ->add('firstName'TextType::class, [
  119.                 'attr' => [
  120.                     'placeholder' => "votre prénom",
  121.                     'class' => 'border border-gray-200 dark:border-gray-800 dark:text-gray-300 rounded-lg pl-4 dark:bg-foreground py-[15px] shadow-input hover:border hover:border-blue-200 focus:border-blue-200 focus:outline-none w-full mb-1'
  122.                 ],
  123.                 'label' => 'Prénom*',
  124.                 'label_attr' => [
  125.                     'class' => 'text-base text-gray-700 dark:text-gray-200 block mb-3'
  126.                 ],
  127.                 'constraints' => [
  128.                     new NotBlank([
  129.                         'message' => 'Le prénom est obligatoire'
  130.                     ])
  131.                 ]
  132.             ])
  133.             ->add('lastName'TextType::class, [
  134.                 'attr' => [
  135.                     'placeholder' => "votre nom",
  136.                     'class' => 'border border-gray-200 dark:border-gray-800 dark:text-gray-300 rounded-lg pl-4 dark:bg-foreground py-[15px] shadow-input hover:border hover:border-blue-200 focus:border-blue-200 focus:outline-none w-full mb-1'
  137.                 ],
  138.                 'label' => 'Nom*',
  139.                 'label_attr' => [
  140.                     'class' => 'text-base text-gray-700 dark:text-gray-200 block mb-3'
  141.                 ],
  142.                 'constraints' => [
  143.                     new NotBlank([
  144.                         'message' => 'Le nom est obligatoire'
  145.                     ])
  146.                 ]
  147.             ])
  148.             ->add('picture'VichFileType::class, [
  149.                 'attr' => [
  150.                     'class' => 'hidden'
  151.                 ],
  152.                 'label' => 'Photo de profil',
  153.                 'label_attr' => [
  154.                     'class' => 'text-base text-gray-700 dark:text-gray-200 block mb-3'
  155.                 ],
  156.                 'mapped' => false,
  157.                 'required' => false,
  158.                 'constraints' => [
  159.                     new Assert\Image([
  160.                         'maxSize' => '5M',
  161.                         'mimeTypes' => [
  162.                             'image/jpeg',
  163.                             'image/png',
  164.                             'image/webp',
  165.                         ],
  166.                         'mimeTypesMessage' => 'Veuillez uploader une image valide (jpeg, png ou webp)',
  167.                     ])
  168.                 ]
  169.             ])
  170.             ->add('phoneNumber'TelType::class, [
  171.                 'attr' => [
  172.                     'placeholder' => "06 00 00 00 00",
  173.                     'class' => 'border border-gray-200 dark:border-gray-800 dark:text-gray-300 rounded-lg pl-4 dark:bg-foreground py-[15px] shadow-input hover:border hover:border-blue-200 focus:border-blue-200 focus:outline-none w-full mb-1'
  174.                 ],
  175.                 'label' => 'Numéro de téléphone*',
  176.                 'label_attr' => [
  177.                     'class' => 'text-base text-gray-700 dark:text-gray-200 block mb-3'
  178.                 ],
  179.                 'constraints' => [
  180.                     new Assert\Regex([
  181.                         'pattern' => '/^\+?\d{1,3}[- ]?\d{2,4}[- ]?\d{2,4}[- ]?\d{2,4}$/',
  182.                         'message' => 'Le numéro de téléphone n\'est pas valide.'
  183.                     ]),
  184.                     new NotBlank([
  185.                         'message' => 'Le numéro de téléphone est obligatoire'
  186.                     ]),
  187.                 ]
  188.             ])            
  189.             ->add('about'TextareaType::class, [
  190.                 'attr' => [
  191.                     'placeholder' => "parlez-nous de vous...",
  192.                     'class' => 'border border-gray-200 dark:border-gray-800 dark:text-gray-300 rounded-lg pl-4 dark:bg-foreground py-[15px] shadow-input hover:border hover:border-blue-200 focus:border-blue-200 focus:outline-none w-full mb-1'
  193.                 ],
  194.                 'label' => 'Présentation',
  195.                 'label_attr' => [
  196.                     'class' => 'text-base text-gray-700 dark:text-gray-200 block mb-3'
  197.                 ],
  198.                 'required' => false
  199.             ])
  200.         ;
  201.                 // Ajouter l'abonnement à l'événement FormEvents::SUBMIT
  202.                 $builder->addEventSubscriber(new UserFormSubscriber());
  203.     }
  204.     public function configureOptions(OptionsResolver $resolver): void
  205.     {
  206.         $resolver->setDefaults([
  207.             'data_class' => User::class,
  208.         ]);
  209.     }
  210. }