<?php
namespace App\Controller;
use App\Constant\RegisterTypeConstant;
use App\Entity\CommonInformation;
use App\Entity\User;
use App\Form\RegistrationType;
use App\Repository\UserRepository;
use App\Security\EmailVerifier;
use App\Services\CurlHttpClient;
use App\Services\SeoManager;
use App\Services\WebhookManager;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mime\Address;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
use SymfonyCasts\Bundle\VerifyEmail\Exception\VerifyEmailExceptionInterface;
const SESSION = 'session';
class RegistrationController extends WhiplayController
{
private EmailVerifier $emailVerifier;
public function __construct(
WebhookManager $webhookManager,
EmailVerifier $emailVerifier
) {
parent::__construct($webhookManager);
$this->emailVerifier = $emailVerifier;
}
/**
* Show register page or process form if data was sent
*
* @param Request $request
* @param TranslatorInterface $translator
* @param SeoManager $seoManager
* @param WebhookManager $webhookManager
* @param CurlHttpClient $httpClient
* @param UserPasswordHasherInterface $userPasswordHasher
* @param EntityManagerInterface $entityManager
* @param string $registerType
* @return Response
*/
public function register(
Request $request,
TranslatorInterface $translator,
SeoManager $seoManager,
WebhookManager $webhookManager,
CurlHttpClient $httpClient,
UserPasswordHasherInterface $userPasswordHasher,
EntityManagerInterface $entityManager,
string $registerType = RegisterTypeConstant::REGISTER_TYPE_USER
): Response {
$title = 'registration.user.seo.title';
$description = 'registration.user.seo.description';
if ($registerType === RegisterTypeConstant::REGISTER_TYPE_BAND) {
$title = 'registration.band.seo.title';
$description = 'registration.band.seo.description';
}
$seoManager
->setTitleAndDescription($title, $description)
->useLogo();
$user = new User();
if ($request->query->get('email')) {
$user->setEmail($request->query->get('email'));
}
if ($request->query->get('first_name')) {
$user->setFirstName($request->query->get('first_name'));
}
if ($request->query->get('last_name')) {
$user->setLastName($request->query->get('last_name'));
}
if ($request->query->get('user_name')) {
$user->setUsername($request->query->get('user_name'));
}
$birthDayKey = 'birthday';
if ($request->query->get($birthDayKey)) {
$birthDay = DateTime::createFromFormat('Y-m-d', $request->query->get($birthDayKey));
$user->setBirthday($birthDay);
}
$form = $this->createForm(RegistrationType::class, $user);
$form->setData($user);
$formData = $request->request->get('registration');
if (is_array($formData) && isset($formData[$birthDayKey]) && !empty($formData[$birthDayKey])) {
$form->handleRequest($request);
}
if ($request->query->get('external') && !$form->isSubmitted()) {
$form->get('external')->setData('true');
}
$birthDay = $form->get($birthDayKey)->getData();
if ($birthDay) {
$interval = $birthDay->diff(new DateTime());
if ($interval->y < 13) {
$form->get($birthDayKey)->addError(
new FormError($translator->trans('registration.errors.minimum_age'))
);
}
if ($interval->y > 130) {
$form->get($birthDayKey)->addError(
new FormError($translator->trans('registration.errors.maximum_age'))
);
}
}
if ($form->isSubmitted() && $form->isValid() && $request->get('contra') == 'true') {
$data = array(
'secret' => $this->getParameter('hcaptcha_secret_key'),
'response' => $request->request->get('h-captcha-response')
);
$response = $httpClient->post("https://hcaptcha.com/siteverify", $data, false);
$captchaData = json_decode($response);
if ($captchaData->success) {
$commonInformation = new CommonInformation();
$commonInformation->setInscriptionDate(new DateTime());
$user->setCommonInformation($commonInformation);
$user->setPassword(
$userPasswordHasher->hashPassword(
$user,
$form->get('plainPassword')->getData()
)
);
$entityManager->persist($user);
$entityManager->flush();
// generate a signed url and email it to the user
$this->emailVerifier->sendEmailConfirmation('registration_verify_email', $user,
(new TemplatedEmail())
->from(new Address('no-reply@whiplay.fr', $translator->trans('band.mail.email_verification.from')))
->to($user->getEmail())
->subject($translator->trans('band.mail.email_verification.subject'))
->htmlTemplate('Registration/confirmation_email.html.twig')
);
$url = $this->generateUrl('registration_check_email');
$response = new RedirectResponse($url);
$webhookManager->sendNewUserOnDiscord($user);
return $response;
} else {
$form->addError(new FormError(
$translator->trans('registration.errors.captcha')
));
}
}
return $this->render('Registration/register.html.twig', array(
'form' => $form->createView(),
'registerType' => $registerType,
));
}
/**
* Tell the user to check their email provider.
*/
public function checkEmail(): Response
{
return $this->render('Registration/check_email.html.twig');
}
public function verifyUserEmail(Request $request, UserRepository $userRepository): Response
{
$id = $request->get('id');
if (null === $id) {
return $this->redirectToRoute('app_register');
}
$user = $userRepository->find($id);
if (null === $user) {
return $this->redirectToRoute('app_register');
}
// validate email confirmation link, sets User::isVerified=true and persists
try {
$this->emailVerifier->handleEmailConfirmation($request, $user);
} catch (VerifyEmailExceptionInterface $exception) {
$this->addFlash('verify_email_error', $exception->getReason());
return $this->redirectToRoute('app_register');
}
// @TODO Change the redirect on success and handle or remove the flash message in your templates
$this->addFlash('success', 'Your email address has been verified.');
return $this->redirectToRoute('app_register');
}
}