<?php
namespace App\Form;
use App\Entity\Location\City;
use App\Entity\User;
use App\Repository\CityRepository;
use App\Repository\UserRepository;
use App\Service\DefaultCityProvider;
use App\Service\Features;
use App\Validator\Constraints\EmailNotBlack;
use EWZ\Bundle\RecaptchaBundle\Form\Type\EWZRecaptchaType;
use EWZ\Bundle\RecaptchaBundle\Validator\Constraints\IsTrue;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Intl\Countries;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
class RegisterAccountForm extends AbstractType
{
public function __construct(
private Features $features,
private CityRepository $cityRepository,
private UserRepository $userRepository,
private DefaultCityProvider $defaultCityProvider,
) {}
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('accountType', HiddenType::class, [
'mapped' => false,
]);
$builder
->add('nickName', TextType::class)
->add('plainPassword', RepeatedType::class, [
'type' => PasswordType::class,
])
->add('email', EmailType::class, [
'constraints' => [
new NotBlank(),
new Length(['min' => 5]),
new Email(),
new EmailNotBlack(),
new Callback(function($object, ExecutionContextInterface $context, $payload): void {
if(!empty($object) && null != $this->userRepository->findOneBy(['email' => $object])) {
$context->buildViolation('Email already in use')
->atPath('email')
->addViolation()
;
}
}),
],
])
;
if ($this->features->multiple_cities()) {
$cityCountries = $this->cityRepository->cityCountries();
if (count($cityCountries) > 1) {
$builder
->add('country', ChoiceType::class, [
'placeholder' => 'Выберите страну',
'choices' => $cityCountries,
'choice_label' => function ($choice): string {
return Countries::getName($choice);
},
'required' => true,
]);
}
$builder
->add('city', EntityType::class, [
'class' => City::class,
'placeholder' => 'Выберите',
'choice_label' => 'name',
'choice_attr' => function (City $city): array {
return ['data-country' => $city->getCountryCode()];
},
'required' => true,
'constraints' => [
new NotBlank(),
],
]);
}
if (true === $options['use_captcha']) {
$builder->add($options['captcha_field_name'], EWZRecaptchaType::class, [
'mapped' => false,
'constraints' => [
new IsTrue(),
],
]);
}
$builder->addEventListener(FormEvents::POST_SUBMIT, [$this, 'onSubmit']);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => User::class,
'validation_groups' => ['Default', 'Registration'],
'use_captcha' => false,
'captcha_field_name' => 'captcha',
]);
$resolver->setAllowedTypes('use_captcha', 'boolean');
$resolver->setAllowedTypes('captcha_field_name', 'string');
}
public function onSubmit(FormEvent $event): void
{
$user = $event->getData();
if(null === $user) {
return;
}
/** @var User $user */
if(null === $user->getCity()) {
$user->setCity($this->defaultCityProvider->getDefaultCity());
}
}
}