src/Social/UserBundle/Form/UserType.php line 37

Open in your IDE?
  1. <?php
  2. namespace Social\UserBundle\Form;
  3. use Gedmo\Sluggable\Util\Urlizer;
  4. use Social\UserBundle\Entity\User;
  5. use Symfony\Component\Form\AbstractType;
  6. use Symfony\Bridge\Doctrine\RegistryInterface;
  7. use Symfony\Component\Form\FormBuilderInterface;
  8. use Symfony\Component\OptionsResolver\OptionsResolver;
  9. use Symfony\Component\Translation\TranslatorInterface;
  10. use Symfony\Component\Form\Extension\Core\Type\TextType;
  11. use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
  12. use Symfony\Component\Form\Extension\Core\Type\HiddenType;
  13. use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
  14. use Symfony\Component\Form\Extension\Core\Type\TextareaType;
  15. use Symfony\Component\Form\Extension\Core\Type\BirthdayType;
  16. use Symfony\Component\Form\Extension\Core\Type\PasswordType;
  17. use Symfony\Component\Validator\Constraints\Callback;
  18. use Symfony\Component\Validator\Constraints\Email;
  19. use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
  20. use Symfony\Component\Validator\Constraints\LessThanOrEqual;
  21. use Symfony\Component\Validator\Constraints\NotBlank;
  22. use Symfony\Component\Validator\Constraints\NotNull;
  23. use Symfony\Component\Validator\Constraints\Regex;
  24. use Symfony\Component\Validator\Context\ExecutionContext;
  25. use Social\FrontendBundle\Form\DataTransformer\LocationToIdTransformer;
  26. use Social\FrontendBundle\Form\DataTransformer\LanguageToIdTransformer;
  27. use DateTime;
  28. use Doctrine\Persistence\ObjectManager;
  29. /**
  30.  * Class UserType
  31.  *
  32.  * @package Social\UserBundle\Form
  33.  */
  34. class UserType extends AbstractType
  35. {
  36.     /**
  37.      * @var ObjectManager $em
  38.      */
  39.     private $em;
  40.     /**
  41.      * @var TranslatorInterface $translator
  42.      */
  43.     private $translator;
  44.     /**
  45.      * @var string $locale
  46.      */
  47.     private $locale;
  48.     /**
  49.      * UserType constructor.
  50.      *
  51.      * @param RegistryInterface   $registry
  52.      * @param TranslatorInterface $translator
  53.      * @param string              $currentLocale
  54.      */
  55.     public function __construct(RegistryInterface $registryTranslatorInterface $translator,string $currentLocale)
  56.     {
  57.         $this->em $registry->getManager();
  58.         $this->translator $translator;
  59.         $this->locale $currentLocale;
  60.     }
  61.     /**
  62.      * @param FormBuilderInterface $builder
  63.      * @param array                $options
  64.      */
  65.     public function buildForm(FormBuilderInterface $builder, array $options)
  66.     {
  67.         $builder->remove('username');
  68.         $builder->remove('username_canonical');
  69.         $builder->remove('email');
  70.         if (in_array('step-1'$options['destination'])) {
  71.             $builder
  72.                 ->add(
  73.                     'username',
  74.                     TextType::class,
  75.                     [
  76.                         'attr'        => [
  77.                             'class'                                                 => 'label-over form-control bg-gray',
  78.                             'autocomplete'                                          => 'off',
  79.                             'readonly' . ($options['username_disabled'] ? '' '_') => 'readonly',
  80.                         ],
  81.                         'property_path' => 'username',
  82.                         'label_attr'  => [
  83.                             'class' => 'label-hide control-label',
  84.                         ],
  85.                         'label'       => $this->translator->trans('Nickname *'),
  86.                         'constraints' => new Regex([
  87.                             'pattern' => "/^(?!(?:[^\d\r\n]*\d){5})[a-zA-Z0-9]{4,15}$/",
  88.                             'message' => $this->translator->trans('Username invalid'),
  89.                         ]),
  90.                     ]
  91.                 )
  92.                 ->add(
  93.                     'email',
  94.                     TextType::class,
  95.                     [
  96.                         'attr'       => [
  97.                             'class'                                              => 'label-over form-control bg-gray ',
  98.                             'autocomplete'                                       => 'off',
  99.                             'readonly' . ($options['email_disabled'] ? '' '_') => 'readonly',
  100.                         ],
  101.                         'label'      => $this->translator->trans('Email *'),
  102.                         'label_attr' => [
  103.                             'class' => 'label-hide control-label',
  104.                         ],
  105.                     ]
  106.                 )
  107.                 ->add(
  108.                     'password',
  109.                     PasswordType::class,
  110.                     [
  111.                         'attr'          => [
  112.                             'class'        => 'label-over form-control bg-gray',
  113.                             'autocomplete' => 'off',
  114.                         ],
  115.                         'label_attr'    => [
  116.                             'class' => 'label-hide control-label',
  117.                         ],
  118.                         'label'         => $this->translator->trans('Password *'),
  119.                         'property_path' => 'plainPassword',
  120.                         'data'          => '',
  121.                     ]
  122.                 )
  123.                 ->add(
  124.                     'gender',
  125.                     ChoiceType::class,
  126.                     [
  127.                         'choices'     => User::$genderOptions,
  128.                         'required'    => true,
  129.                         'expanded'    => true,
  130.                         'multiple'    => false,
  131.                         'constraints' => [],
  132.                         'choice_attr' => function ($val$key$index) {
  133.                             return [
  134.                                 'data-toggle'         => 'tooltip',
  135.                                 'data-original-title' => User::$genderOptionsAlternative[$key],
  136.                                 'data-placement'      => 'top',
  137.                             ];
  138.                         },
  139.                     ]
  140.                 );
  141.             if ($options['email_repeat']) {
  142.                 $builder
  143.                     ->add(
  144.                         'email_repeat',
  145.                         TextType::class,
  146.                         [
  147.                             'attr'        => [
  148.                                 'class'        => 'label-over form-control bg-gray',
  149.                                 'autocomplete' => 'off',
  150.                             ],
  151.                             'label_attr'  => [
  152.                                 'class' => 'label-hide control-label',
  153.                             ],
  154.                             'label'       => 'Email Repeat *',
  155.                             'constraints' => [
  156.                                 new Email(['message' => $this->translator->trans('Re-Entered Email is not valid')]),
  157.                                 new NotBlank(['message' => $this->translator->trans('Re-Entered Email should not be blank')]),
  158.                             ],
  159.                         ]
  160.                     );
  161.             }
  162.             if ($options['password_repeat']) {
  163.                 $builder
  164.                     ->add(
  165.                         'password_repeat',
  166.                         PasswordType::class,
  167.                         [
  168.                             'attr'          => [
  169.                                 'class'        => 'label-over form-control bg-gray',
  170.                                 'autocomplete' => 'off',
  171.                             ],
  172.                             'label_attr'    => [
  173.                                 'class' => 'label-hide control-label ',
  174.                             ],
  175.                             'label'         => $this->translator->trans('Password Repeat *'),
  176.                             'property_path' => 'plainPasswordRepeat',
  177.                             'data'          => '',
  178.                         ]
  179.                     );
  180.             }
  181.         }
  182.         if (in_array('step-3'$options['destination'])) {
  183.             $builder
  184.                 ->add(
  185.                     'new_location',
  186.                     HiddenType::class,
  187.                     [
  188.                         'attr'        => [
  189.                             'class' => 'fake-location-input',
  190.                         ],
  191.                         'label'       => $this->translator->trans('Location *'),
  192.                         'constraints' => [
  193.                             new NotNull(['message' => $this->translator->trans('Location is not valid. Please select a valid location')]),
  194.                         ],
  195.                     ]
  196.                 )
  197.                 ->add(
  198.                     'fake_country',
  199.                     HiddenType::class,
  200.                     ['attr' => ['class' => 'fake-country-input']]
  201.                 )
  202.                 ->add(
  203.                     'country',
  204.                     TextType::class,
  205.                     [
  206.                         'attr' => [
  207.                             'class' => $this->getLocationClass('country'$options['data']),
  208.                             'autocomplete' => 'off',
  209.                             'placeholder' => 'Country',
  210.                         ]
  211.                     ]
  212.                 )
  213.                 ->add(
  214.                     'city',
  215.                     TextType::class,
  216.                     [
  217.                         'attr' => [
  218.                             'class' => $this->getLocationClass('city'$options['data']),
  219.                             'autocomplete' => 'off',
  220.                             'placeholder' => 'City',
  221.                         ]
  222.                     ]
  223.                 )
  224.                 ->add('delete_profile_picture_id'HiddenType::class)
  225.                 ->add(
  226.                     'relationship_status',
  227.                     ChoiceType::class,
  228.                     [
  229.                         'choices' => User::getRelationshipStatusOptions($options['locale']),
  230.                         'attr'    => ['class' => 'label-over form-control bg-gray select-fancy'],
  231.                     ]
  232.                 );
  233.             $builder->get('new_location')->addModelTransformer(new LocationToIdTransformer($this->em));
  234.         }
  235.         if (in_array('set-password'$options['destination'])) {
  236.             $builder->add(
  237.                 'password',
  238.                 PasswordType::class,
  239.                 [
  240.                     'attr'          => [
  241.                         'class'        => 'label-over form-control bg-gray',
  242.                         'autocomplete' => 'off',
  243.                     ],
  244.                     'label_attr'    => [
  245.                         'class' => 'label-hide control-label',
  246.                     ],
  247.                     'label'         => $this->translator->trans('Password *'),
  248.                     'property_path' => 'plainPassword',
  249.                     'data'          => '',
  250.                     'constraints'     => [
  251.                         new NotNull([
  252.                             'message' => $this->translator->trans('Password should not be empty'),
  253.                         ]),
  254.                     ],
  255.                 ])
  256.                 ->add(
  257.                 'password_repeat',
  258.                 PasswordType::class,
  259.                 [
  260.                     'attr'          => [
  261.                         'class'        => 'label-over form-control bg-gray',
  262.                         'autocomplete' => 'off',
  263.                     ],
  264.                     'label_attr'    => [
  265.                         'class' => 'label-hide control-label ',
  266.                     ],
  267.                     'label'         => $this->translator->trans('Password Repeat *'),
  268.                     'property_path' => 'plainPasswordRepeat',
  269.                     'data'          => '',
  270.                 ]
  271.             );
  272.         }
  273.         if ($options['include_birthday']) {
  274.             $builder
  275.                 ->add(
  276.                     'birthday',
  277.                     BirthdayType::class,
  278.                     [
  279.                         'widget'          => 'single_text',
  280.                         'format'          => 'dd/MM/yyyy',
  281.                         'attr'            => [
  282.                             'class'        => 'label-over form-control bg-gray birthday-datepicker',
  283.                             'autocomplete' => 'off',
  284.                         ],
  285.                         'label_attr'      => [
  286.                             'class' => 'label-hide control-label',
  287.                         ],
  288.                         'label'           => 'Birthday *',
  289.                         'invalid_message' => $this->translator->trans('Birthday is not valid.'),
  290.                         'constraints'     => [
  291.                             new NotNull([
  292.                                 'message' => $this->translator->trans('Birthday should not be blank'),
  293.                                 'groups'  => ['Default''Profile'],
  294.                             ]),
  295.                             new LessThanOrEqual(
  296.                                 [
  297.                                     'message' => $this->translator->trans('The minimum registration age is 18 years old'),
  298.                                     'groups'  => ['Default''Profile'],
  299.                                     'value'   => (new DateTime('@' strtotime('-18 years'))),
  300.                                 ]
  301.                             ),
  302.                             new GreaterThanOrEqual(
  303.                                 [
  304.                                     'message' => $this->translator->trans('The maximum registration age is 90 years old'),
  305.                                     'groups'  => ['Default''Profile'],
  306.                                     'value'   => (new DateTime('@' strtotime('-90 years'))),
  307.                                 ]
  308.                             ),
  309.                         ],
  310.                     ]
  311.                 );
  312.         }
  313.         if (in_array('personalize'$options['destination'])) {
  314.             $builder
  315.                 ->add('workplace'TextType::class, ['attr' => ['class' => 'label-over form-control bg-gray']])
  316.                 ->add('short_bio'TextareaType::class, ['attr' => ['class' => 'label-over form-control bg-gray']])
  317.                 ->add(
  318.                     'interested_in',
  319.                     ChoiceType::class,
  320.                     [
  321.                         'choices'  => User::getLookingFor($this->locale),
  322.                         'multiple' => true,
  323.                         'expanded' => true,
  324.                     ]
  325.                 )
  326.                 ->add('interested_in_long',
  327.                     TextareaType::class,
  328.                     ['attr' => ['class' => 'label-over form-control bg-gray interested-in']])
  329.                 ->add('motto'TextType::class, ['attr' => ['class' => 'label-over form-control bg-gray']])
  330.                 ->add('public_profile'CheckboxType::class);
  331.         }
  332.         if (in_array('notifications'$options['destination'])) {
  333.             $builder
  334.                 ->add('receive_email_notifications',
  335.                     CheckboxType::class,
  336.                     ['label' => $this->translator->trans('Receive email notifications entirely')]);
  337.         }
  338.         if (in_array('names'$options['destination'])) {
  339.             $builder
  340.                 ->add(
  341.                     'first_name',
  342.                     TextType::class,
  343.                     [
  344.                         'attr'        => [
  345.                             'class' => 'label-over form-control bg-gray',
  346.                         ],
  347.                         'label_attr'  => [
  348.                             'class' => 'label-hide control-label',
  349.                         ],
  350.                         'constraints' => [],
  351.                     ]
  352.                 )
  353.                 ->add(
  354.                     'last_name',
  355.                     TextType::class,
  356.                     [
  357.                         'attr'        => [
  358.                             'class' => 'label-over form-control bg-gray',
  359.                         ],
  360.                         'label_attr'  => [
  361.                             'class' => 'label-hide control-label',
  362.                         ],
  363.                         'constraints' => [],
  364.                     ]
  365.                 );
  366.         }
  367.         if (in_array('profile-confirmation'$options['destination'])) {
  368.             $builder
  369.                 ->add(
  370.                     'username',
  371.                     TextType::class,
  372.                     [
  373.                         'attr'        => [
  374.                             'class'                                                 => 'label-over form-control bg-gray',
  375.                             'autocomplete'                                          => 'off',
  376.                             'readonly' . ($options['username_disabled'] ? '' '_') => 'readonly',
  377.                         ],
  378.                         'label_attr'  => [
  379.                             'class' => 'label-hide control-label',
  380.                         ],
  381.                         'label'       => $this->translator->trans('Nickname *'),
  382.                         'constraints' => new Regex([
  383.                             'pattern' => "/^(?!(?:[^\d\r\n]*\d){5})[a-zA-Z0-9]{4,15}$/",
  384.                             'message' => $this->translator->trans('Username invalid'),
  385.                         ]),
  386.                         'property_path' => 'username',
  387.                     ]
  388.                 )
  389.                 ->add(
  390.                     'birthday',
  391.                     BirthdayType::class,
  392.                     [
  393.                         'widget'          => 'single_text',
  394.                         'format'          => 'dd/MM/yyyy',
  395.                         'attr'            => [
  396.                             'class'        => 'label-over form-control bg-gray birthday-datepicker',
  397.                             'autocomplete' => 'off',
  398.                         ],
  399.                         'label_attr'      => [
  400.                             'class' => 'label-hide control-label',
  401.                         ],
  402.                         'label'           => 'Birthday *',
  403.                         'invalid_message' => $this->translator->trans('Birthday is not valid.'),
  404.                         'constraints'     => [
  405.                             new NotNull([
  406.                                 'message' => $this->translator->trans('Birthday should not be blank'),
  407.                                 'groups'  => ['Default''Profile'],
  408.                             ]),
  409.                             new LessThanOrEqual(
  410.                                 [
  411.                                     'message' => $this->translator->trans('The minimum registration age is 18 years old'),
  412.                                     'groups'  => ['Default''Profile'],
  413.                                     'value'   => (new DateTime('@' strtotime('-18 years'))),
  414.                                 ]
  415.                             ),
  416.                             new GreaterThanOrEqual(
  417.                                 [
  418.                                     'message' => $this->translator->trans('The maximum registration age is 90 years old'),
  419.                                     'groups'  => ['Default''Profile'],
  420.                                     'value'   => (new DateTime('@' strtotime('-90 years'))),
  421.                                 ]
  422.                             ),
  423.                         ],
  424.                     ]
  425.                 );
  426.         }
  427.         if ($options['include_language']) {
  428.             $builder->add(
  429.                 'language',
  430.                 ChoiceType::class,
  431.                 [
  432.                     'choices'    => $options['languages'],
  433.                     'attr'       => ['class' => 'label-over form-control bg-gray select-fancy'],
  434.                 ]
  435.             );
  436.             $builder->get('language')->addModelTransformer(new LanguageToIdTransformer($this->em));
  437.         }
  438.     }
  439.     /**
  440.      * @param OptionsResolver $resolver
  441.      */
  442.     public function configureOptions(OptionsResolver $resolver)
  443.     {
  444.         $postDataValidation = new Callback(
  445.             function ($dataExecutionContext $context) {
  446.                 $password       $data->getPlainPassword();
  447.                 $passwordRepeat $data->getPlainPasswordRepeat();
  448.                 $gender         $data->getGender();
  449.                 if ($password != $passwordRepeat && !is_null($data->getId())) {
  450.                     $context
  451.                         ->buildViolation('Passwords should match')
  452.                         ->atPath('plainPassword')
  453.                         ->addViolation();
  454.                 }
  455.                 $username $data->getUsername();
  456.                 if (is_null($gender) || !in_array($genderarray_values(User::$genderOptions))) {
  457.                     $context->addViolation($this->translator->trans('Please select a gender'));
  458.                 }
  459.                 if ($data->getId() && count($data->getInterestedIn()) == 0) {
  460.                     $context->buildViolation('Please select at least 1 gender you are interested in.')
  461.                             ->atPath('interested_in')
  462.                             ->addViolation();
  463.                 }
  464.             }
  465.         );
  466.         $resolver->setDefaults([
  467.             'data_class'         => User::class,
  468.             'cascade_validation' => true,
  469.             'error_bubbling'     => true,
  470.             'constraints'        => [$postDataValidation],
  471.             'validation_groups'  => ['Default''Profile'],
  472.             'destination'        => ['step-1'],
  473.             'include_birthday'   => false,
  474.             'include_agree'      => false,
  475.             'email_repeat'       => true,
  476.             'password_repeat'    => false,
  477.             'email_disabled'     => false,
  478.             'username_disabled'  => false,
  479.             'include_language'   => false,
  480.             'locale'             => 'it',
  481.             'languages'          => []
  482.         ]);
  483.     }
  484.     /**
  485.      * @return string
  486.      */
  487.     public function getName(): string
  488.     {
  489.         return 'social_userbundle_usertype';
  490.     }
  491.     private function getLocationClass($field$value)
  492.     {
  493.         $class "form-control bg-gray location-autocomplete-{$field}";
  494.         $className "get".ucfirst($field);
  495.         if (empty($value->$className())) {
  496.             return $class;
  497.         }
  498.         return "$class valid-location";
  499.     }
  500. }