<?php
namespace App\Controller;
use App\Entity\Doctor;
use App\Entity\DoctorInterface;
use App\Entity\Patient;
use App\Event\MemberRegisteredEvent;
use App\Events;
use App\Exception\AppException;
use App\Form\CreatePasswordType;
use App\Form\RegisterType;
use App\Security\EmailVerifier;
use Boab\CmsBundle\Controller\BaseController;
use Boab\CmsBundle\Entity\UserInterface;
use Boab\CmsBundle\Exception\ApiException;
use Boab\CmsBundle\Repository\UserRepository;
use Boab\CmsBundle\Repository\UserRepositoryInterface;
use Boab\CmsBundle\Security\RandomGeneratorInterface;
use Boab\CmsBundle\View\ViewManagerInterface;
use Doctrine\Common\Cache\Psr6\InvalidArgument;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Annotation\Route;
use SymfonyCasts\Bundle\VerifyEmail\Exception\VerifyEmailExceptionInterface;
class RegisterController extends BaseController
{
public function __construct(
private RandomGeneratorInterface $generator,
private UserPasswordHasherInterface $passwordHasher,
private LoggerInterface $logger,
private EmailVerifier $emailVerifier,
private UserRepositoryInterface $userRepository)
{}
public function index(Request $request, ViewManagerInterface $view,$_route)
{
$form = $this->createForm(RegisterType::class, null,[
"action" => $this->router->generate($_route),
"method"=>'post'
]);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()){
$data = $form->getData();
$member = $this->getUserEntity($data);
try{
$this->entityManager->beginTransaction();
$this->save($member);
$event = new MemberRegisteredEvent($member);
$this->eventDispatcher->dispatch($event, Events::MEMBER_REGISTERED);
$this->entityManager->commit();
return $this->redirectToRoute('app.register_success', ['username'=>$member->getUsername()]);
}catch(\Exception $e){
//dump($e);
$this->logger->error($e->getMessage(), ['exception'=>$e]);
$this->entityManager->rollback();
$this->flash->setWarning('Something went wrong during procession of the form. Please try again.');
}
return $this->redirectToRoute($_route, ['username'=>$member->getUsername()]);
}elseif($form->isSubmitted() && !$form->isValid()) {
$this->flash->setWarning('Error! Please correct the errors on the form');
}
$view = $view->load('app/sign_up.html.twig');
$view->form = $form->createView();
$view->pageTitle = "Register";
return $view;
}
public function success(Request $request, ViewManagerInterface $view, $_route)
{
$username = $request->get('username');
if(!$username){
throw new AppException(400, 'Invalid Request! The resource you are accessing is invalid');
}
$user = $this->getUserByUsername($username);
//dump($user);
return $this->render('app/register_success.html.twig',[
'email' => $user->getEmail(),
'pageTitle' => "Thank you for registring"
]);
}
/**
* @Route("/verify", name="app.verify_registration")
*/
public function verify(Request $request)
{
$id = $request->get('id');
$user = $this->userRepository->findOneBy(['id'=>$id]);
if (!$user) {
throw new AppException(422, 'Invalid Request! Something went wrong and could not process your request');
}
// validate email confirmation link, sets User::isVerified=true and persists
try {
$this->emailVerifier->handleEmailConfirmation($request, $user);
$user->setIsVerified(true);
$this->save($user);
} catch (VerifyEmailExceptionInterface | \Exception $exception) {
throw new AppException(500, $exception->getMessage());
}
// @TODO Change the redirect on success and handle or remove the flash message in your templates
$this->flash->setWarning('success', 'Your email address has been verified.');
return $this->redirectToRoute('app.register_create_password', ['username'=>$user->getUsername()]);
}
/**
* @Route("/create-password/{username}", name="app.create_password")
*/
public function password(Request $request, UserPasswordHasherInterface $passwordHasher, string $username)
{
$user = $this->getUserByUsername($username);
$form = $this->createForm(CreatePasswordType::class, null, [
'action' => $this->router->generate('app.register_create_password', ["username"=>$username]),
'method' => 'POST',
]);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
//$data = $form->getData();
$data = $request->request->all()[$form->getName()];
try{
$hashedPassword = $passwordHasher->hashPassword($user, $data['plainPassword']['first']);
$user->setPassword($hashedPassword);
$role = $user instanceof DoctorInterface ? 'ROLE_DOCTOR':'ROLE_CLIENT';
$user->addRole($role);
$this->save($user);
}catch(\Exception $e){
$this->logger->error($e->getMessage(), ['exception'=>$e]);
throw new ApiException(500, 'Something went wrong with the data');
}
return new JsonResponse([
'status'=>'success',
'message' => 'Password updated successfully',
'redirectUrl' => $this->router->generate('app.login')
]);
}
$view = $this->viewManager->load('registration/password_form.html.twig');
$view->pageTitle = 'Email Verification';
$view->user = $user;
$view->form = $form->createView();
return $view;
}
private function getUserByUsername(string $username): UserInterface
{
$user = $this->userRepository->findOneBy(['username'=>$username]);
if (!$user) {
throw new InvalidArgument('Invalid Request! Something went wrong and could not process your request');
}
return $user;
}
private function getUserEntity(array $data)
{
$user = $data['registerAs'] == 'Client' ? new Patient : new Doctor;
//$password = $this->passwordHasher->hashPassword($user, $data['password']);
$username = $this->generator->generate(8);
$user->setFirstName($data['firstname'])
->setLastName($data['lastname'])
->setDob($data['dob'])
->setEmail($data['email'])
->setWhatsappNumber($data['whatsappNumber'])
->setAddress($data['address'])
->setCity($data['city'])
->setCountry($data['country'])
->setGender($data['gender'])
->setContactNumber($data['contactNumber'])
->setIsActivated(false)
->setUsername($username)
->setCreatedAt(new \DateTime('now'))
//->setPassword($password)
->setLongitude($data['longitude'])
->setLatitude($data['latitude'])
;
if($user instanceof Doctor){
$user->setPricing('Free');
$user->addRole('ROLE_START_MEETING');
}
return $user;
}
}