src/Controller/Page/User/UserController.php line 327

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Page\User;
  3. use App\Decorator\CompanyDecorator;
  4. use App\Entity\Booking;
  5. use App\Entity\Company;
  6. use App\Entity\MainBooker;
  7. use App\Entity\Page;
  8. use App\Entity\Route as RouteEntity;
  9. use App\Entity\SiteUserData;
  10. use App\Entity\Subscription;
  11. use App\Entity\User;
  12. use App\Entity\Vacancy;
  13. use App\Event\CompanyCreatedEvent;
  14. use App\EventListener\FeatureFlagListener;
  15. use App\Form\CompanyType;
  16. use App\Form\MainBookerType;
  17. use App\Form\RegisterUserType;
  18. use App\Renderer\Page as PageRenderer;
  19. use App\Templating\Decorator;
  20. use App\Translation\RuntimeTranslator;
  21. use App\Widget\UserDashboard\UserDashboardWidgetCollection;
  22. use Doctrine\ORM\EntityManagerInterface;
  23. use Flagception\Manager\FeatureManagerInterface;
  24. use FOS\UserBundle\Controller\ResettingController;
  25. use FOS\UserBundle\Event\FilterUserResponseEvent;
  26. use FOS\UserBundle\Event\FormEvent;
  27. use FOS\UserBundle\Event\GetResponseUserEvent;
  28. use FOS\UserBundle\Form\Factory\FactoryInterface;
  29. use FOS\UserBundle\FOSUserEvents;
  30. use FOS\UserBundle\Model\UserInterface;
  31. use FOS\UserBundle\Model\UserManagerInterface;
  32. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  33. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  34. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  35. use Symfony\Component\HttpFoundation\JsonResponse;
  36. use Symfony\Component\HttpFoundation\RedirectResponse;
  37. use Symfony\Component\HttpFoundation\Request;
  38. use Symfony\Component\HttpFoundation\Response;
  39. use Symfony\Component\Routing\Annotation\Route;
  40. use Symfony\Component\Routing\RouterInterface;
  41. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  42. use Symfony\Contracts\Translation\TranslatorInterface;
  43. use Twig\Error\LoaderError as Twig_Error_Loader;
  44. use Twig\Error\RuntimeError as Twig_Error_Runtime;
  45. use Twig\Error\SyntaxError as Twig_Error_Syntax;
  46. class UserController extends AbstractController
  47. {
  48.     public const ROLE_MAPPING = [
  49.         'user' => 'ROLE_SITE_USER',
  50.         'company' => 'ROLE_SITE_COMPANY_USER',
  51.         'mobility' => 'ROLE_SITE_MOBILITY_USER',
  52.     ];
  53.     /** @param RuntimeTranslator $translator */
  54.     public function __construct(
  55.         private readonly UserManagerInterface $userManager,
  56.         private readonly EventDispatcherInterface $eventDispatcher,
  57.         private readonly FactoryInterface $registrationFormFactory,
  58.         private readonly TranslatorInterface $translator,
  59.         private readonly PageRenderer $pageRenderer,
  60.         private readonly ResettingController $resettingController,
  61.         private readonly CompanyDecorator $companyDecorator,
  62.         private readonly FeatureManagerInterface $featureManager,
  63.         private readonly RouterInterface $router,
  64.         private readonly ParameterBagInterface $parameterBag,
  65.         private readonly EntityManagerInterface $entityManager,
  66.         private readonly UserDashboardWidgetCollection $widgetCollection,
  67.         private readonly Decorator $decorator,
  68.     ) {
  69.     }
  70.     /**
  71.      * @throws Twig_Error_Loader
  72.      * @throws Twig_Error_Runtime
  73.      * @throws Twig_Error_Syntax
  74.      */
  75.     #[Route(path'/'name'pages_user_dashboard')]
  76.     public function defaultAction(): Response
  77.     {
  78.         /** @var User $user */
  79.         $user $this->getUser();
  80.         if (
  81.             $this->featureManager->isActive(FeatureFlagListener::FEATURE_MOBILITY_PLATFORM) &&
  82.             $user->hasRole(self::ROLE_MAPPING['mobility'])
  83.         ) {
  84.             return $this->renderMobilityDashboard();
  85.         }
  86.         if ($user->hasRole(self::ROLE_MAPPING['company'])) {
  87.             return $this->getCompanyDashboard();
  88.         }
  89.         if ($user->hasRole(self::ROLE_MAPPING['user'])) {
  90.             if (!$this->parameterBag->get('site_user_active')) {
  91.                 return $this->redirectToRoute('homepage');
  92.             }
  93.             return $this->getUserDashboard();
  94.         }
  95.         throw new AccessDeniedException();
  96.     }
  97.     /**
  98.      * @throws Twig_Error_Loader
  99.      * @throws Twig_Error_Runtime
  100.      * @throws Twig_Error_Syntax
  101.      */
  102.     #[Route(path'/register/{type}'name'pages_user_register'requirements: ['type' => 'user|company'])]
  103.     public function registerAction(Request $requeststring $type): Response
  104.     {
  105.         if ('company' === $type && !$this->parameterBag->get('site_user_enable_company_registration')) {
  106.             $this->addFlash('error'$this->translator->trans('This action is not permitted'));
  107.             return $this->redirectToRoute('user_login');
  108.         }
  109.         $route $this->getDoctrine()->getRepository(RouteEntity::class)
  110.             ->findOneBy(['name' => 'user_register']);
  111.         /** @var User $user */
  112.         $user $this->userManager->createUser();
  113.         $user->setEnabled(true);
  114.         $event = new GetResponseUserEvent($user$request);
  115.         $this->eventDispatcher->dispatch($eventFOSUserEvents::REGISTRATION_INITIALIZE);
  116.         if (null !== $event->getResponse()) {
  117.             return $event->getResponse();
  118.         }
  119.         $form $this->createForm(RegisterUserType::class, $user);
  120.         $form->remove('username');
  121.         $form->handleRequest($request);
  122.         if ($form->isSubmitted() && $form->isValid()) {
  123.             $event = new FormEvent($form$request);
  124.             $this->eventDispatcher->dispatch($eventFOSUserEvents::REGISTRATION_SUCCESS);
  125.             $user->setRoles([self::ROLE_MAPPING[$type]]);
  126.             $this->userManager->updateUser($user);
  127.             if (null === $response $event->getResponse()) {
  128.                 $url $this->generateUrl('fos_user_registration_confirmed');
  129.                 $response = new RedirectResponse($url);
  130.             }
  131.             $this->eventDispatcher->dispatch(
  132.                 new FilterUserResponseEvent($user$request$response),
  133.                 FOSUserEvents::REGISTRATION_COMPLETED
  134.             );
  135.             if ('company' === $type) {
  136.                 $response = new RedirectResponse($this->generateUrl('user_login'));
  137.             }
  138.             $this->addFlash(
  139.                 'success',
  140.                 str_replace(
  141.                     '%email%',
  142.                     $user->getEmail(),
  143.                     $this->translator->getCatalogue()->get('registration.check_email''FOSUserBundle')
  144.                 )
  145.             );
  146.             return $response;
  147.         }
  148.         $response $this
  149.             ->pageRenderer
  150.             ->renderPage(
  151.                 '{user_register}',
  152.                 $this->decorator->getTemplate('pages/user_register.html.twig'),
  153.                 ['form' => $form->createView(), 'type' => $type],
  154.                 route$route
  155.             );
  156.         $response->setPrivate()->setMaxAge(0)->setSharedMaxAge(0);
  157.         return $response;
  158.     }
  159.     #[Route('register_headless/{type}'name'register_user_headless')]
  160.     public function headless(Request $requeststring $type): Response
  161.     {
  162.         /** @var User $user */
  163.         $user $this->userManager->createUser();
  164.         $user->setEnabled(true);
  165.         $event = new GetResponseUserEvent($user$request);
  166.         $this->eventDispatcher->dispatch($eventFOSUserEvents::REGISTRATION_INITIALIZE);
  167.         if (null !== $event->getResponse()) {
  168.             return $event->getResponse();
  169.         }
  170.         $form $this->createForm(RegisterUserType::class, $user);
  171.         $form->remove('username');
  172.         $form->handleRequest($request);
  173.         if ($form->isSubmitted() && $form->isValid()) {
  174.             $event = new FormEvent($form$request);
  175.             $this->eventDispatcher->dispatch($eventFOSUserEvents::REGISTRATION_SUCCESS);
  176.             $user->setRoles([self::ROLE_MAPPING[$type]]);
  177.             $this->userManager->updateUser($user);
  178.             $this->eventDispatcher->dispatch(
  179.                 new FilterUserResponseEvent($user$request$event->getResponse()),
  180.                 FOSUserEvents::REGISTRATION_COMPLETED
  181.             );
  182.             $response null;
  183.             if ('company' === $type) {
  184.                 $response = new JsonResponse([
  185.                     'redirect' => $this->generateUrl('user_login'),
  186.                 ]);
  187.             }
  188.             $this->addFlash('success'str_replace(
  189.                 '%email%',
  190.                 $user->getEmail(),
  191.                 $this->translator->getCatalogue()->get('registration.check_email''FOSUserBundle')
  192.             ));
  193.             if ($request->isXmlHttpRequest() && $response instanceof Response) {
  194.                 return $response;
  195.             }
  196.         }
  197.         return $this->render('@default/pages/form/register_user_form_headless.html.twig', [
  198.             'form' => $form->createView(),
  199.         ]);
  200.     }
  201.     #[Route(path'/reset/{token}'name'fos_user_resetting_reset')]
  202.     public function resetAction(Request $request$token): Response
  203.     {
  204.         if (!$user $this->userManager->findUserByConfirmationToken($token)) {
  205.             return new RedirectResponse($this->router->generate('user_login'));
  206.         }
  207.         $event = new GetResponseUserEvent($user$request);
  208.         $this->eventDispatcher->dispatch($eventFOSUserEvents::RESETTING_RESET_INITIALIZE);
  209.         if (null !== $event->getResponse()) {
  210.             return $event->getResponse();
  211.         }
  212.         $form $this->registrationFormFactory->createForm();
  213.         $form->remove('username');
  214.         $form->setData($user);
  215.         $form->handleRequest($request);
  216.         if ($form->isSubmitted() && $form->isValid()) {
  217.             $event = new FormEvent($form$request);
  218.             $this->eventDispatcher->dispatch($eventFOSUserEvents::RESETTING_RESET_SUCCESS);
  219.             $this->userManager->updateUser($user);
  220.             if (null === $response $event->getResponse()) {
  221.                 $url $this->generateUrl('pages_user_dashboard');
  222.                 $response = new RedirectResponse($url);
  223.             }
  224.             $this->eventDispatcher->dispatch(
  225.                 new FilterUserResponseEvent($user$request$response),
  226.                 FOSUserEvents::RESETTING_RESET_COMPLETED
  227.             );
  228.             return $response;
  229.         }
  230.         $page = (new Page())
  231.             ->setTitle('Check your email')
  232.             ->setBody($this->renderView('@default/pages/user_reset.html.twig', [
  233.                 'token' => $token,
  234.                 'form' => $form->createView(),
  235.             ]))
  236.         ;
  237.         return $this->render('@default/pages/pages_index.html.twig', [
  238.             'header' => $this->pageRenderer->getHeader(),
  239.             'footer' => $this->pageRenderer->getFooter(),
  240.             'page' => $page,
  241.         ]);
  242.     }
  243.     #[Route(path'/check-email'name'fos_user_resetting_check_email')]
  244.     public function checkMailAction(): Response
  245.     {
  246.         $page = (new Page())
  247.             ->setTitle('Check you email')
  248.             ->setBody($this->renderView('@default/pages/check_email.html.twig', [
  249.                 'tokenLifetime' => ceil($this->parameterBag->get('fos_user.resetting.retry_ttl') / 3600),
  250.             ]))
  251.         ;
  252.         return $this->render('@default/pages/pages_index.html.twig', [
  253.             'header' => $this->pageRenderer->getHeader(),
  254.             'footer' => $this->pageRenderer->getFooter(),
  255.             'page' => $page,
  256.         ]);
  257.     }
  258.     #[Route(path'/forgot-password'name'pages_user_forgot_password')]
  259.     public function forgotPasswordAction(Request $request): Response
  260.     {
  261.         if ($request->get('username')) {
  262.             $response $this->resettingController->sendEmailAction($request);
  263.             if ($response instanceof RedirectResponse) {
  264.                 return $response;
  265.             }
  266.         }
  267.         $page = (new Page())
  268.             ->setTitle('Forgot password')
  269.             ->setBody($this->renderView('@default/pages/forgot_password.html.twig'))
  270.         ;
  271.         return $this->render('@default/pages/pages_index.html.twig', [
  272.             'header' => $this->pageRenderer->getHeader(),
  273.             'footer' => $this->pageRenderer->getFooter(),
  274.             'page' => $page,
  275.         ]);
  276.     }
  277.     /**
  278.      * @throws Twig_Error_Loader
  279.      * @throws Twig_Error_Runtime
  280.      * @throws Twig_Error_Syntax
  281.      */
  282.     #[Route(path'/company/create'name'pages_users_create_company')]
  283.     public function createCompanyAction(Request $request): Response
  284.     {
  285.         if ($this->getUser()?->getCompanies()->count() > 0) {
  286.             $this->addFlash('info'$this->translator->trans('A company is already registered for your account', [], 'company'));
  287.             return $this->redirectToRoute('pages_user_dashboard');
  288.         }
  289.         $company = new Company();
  290.         $form $this->createForm(
  291.             CompanyType::class,
  292.             $company,
  293.             ['decorator' => $this->companyDecorator]
  294.         );
  295.         $form->remove('canonicalUrl');
  296.         $form->remove('hero');
  297.         $form->remove('overviewImage');
  298.         $form->remove('optionValues');
  299.         $form->remove('metaTitle');
  300.         $form->remove('metaDescription');
  301.         $form->get('logo')->remove('metaInformation');
  302.         $form->handleRequest($request);
  303.         if ($form->isSubmitted()) {
  304.             if ($form->isValid()) {
  305.                 $this->entityManager->persist($company);
  306.                 $this->entityManager->flush();
  307.                 /** @var User $user */
  308.                 $user $this->getUser();
  309.                 $user->addCompany($company);
  310.                 $this->entityManager->persist($user);
  311.                 $this->entityManager->flush();
  312.                 $this->addFlash('success'$this->translator->trans('Company is created', [], 'company'));
  313.                 $this->eventDispatcher->dispatch(new CompanyCreatedEvent($company), CompanyCreatedEvent::CREATED_BY_USER);
  314.                 return $this->redirectToRoute('pages_user_dashboard');
  315.             }
  316.             $this->addFlash('danger'$this->translator->trans('Form is not valid', [], 'company'));
  317.         }
  318.         $page = (new Page())
  319.             ->setTitle('register')
  320.             ->setBody($this->renderView('@default/pages/company_form.html.twig', [
  321.                 'form' => $form->createView(),
  322.             ]))
  323.         ;
  324.         return $this->render('@default/pages/pages_index.html.twig', [
  325.             'header' => $this->pageRenderer->getHeader(),
  326.             'footer' => $this->pageRenderer->getFooter(),
  327.             'page' => $page,
  328.         ]);
  329.     }
  330.     #[Route(path'/user/delete'name'pages_users_user_delete')]
  331.     public function deleteUserAction(): Response
  332.     {
  333.         if (!$user $this->getUser()) {
  334.             throw $this->createNotFoundException();
  335.         }
  336.         $userSiteData $this->entityManager
  337.             ->getRepository(SiteUserData::class)->findOneBy(['user' => $user]);
  338.         if ($userSiteData) {
  339.             $this->entityManager->remove($userSiteData);
  340.         }
  341.         $this->entityManager->remove($user);
  342.         $this->entityManager->flush();
  343.         $this->addFlash('success''Your account has been deleted!');
  344.         return $this->redirectToRoute('user_login');
  345.     }
  346.     /**
  347.      * @throws Twig_Error_Loader
  348.      * @throws Twig_Error_Runtime
  349.      * @throws Twig_Error_Syntax
  350.      */
  351.     private function getCompanyDashboard(): Response
  352.     {
  353.         $companyIds $this->getUser()?->getCompanies()->map(function (Company $company) {
  354.             return $company->getId();
  355.         })->toArray();
  356.         if (empty($companyIds)) {
  357.             $this->addFlash(
  358.                 'info',
  359.                 $this->translator->trans('Register your company before adding vacancies', [], 'company')
  360.             );
  361.             return $this->redirectToRoute('pages_users_create_company');
  362.         }
  363.         $latestVacancies $this->entityManager->getRepository(Vacancy::class)->findBy([
  364.             'company' => $companyIds,
  365.         ], ['created' => 'desc'], 5);
  366.         $page = (new Page())
  367.             ->setTitle('User dashboard')
  368.             ->setBody($this->renderView('@default/pages/company_dashboard.html.twig', [
  369.                 'latest_vacancies' => $latestVacancies,
  370.                 'company' => $this->getUser()?->getCompanies()->first(),
  371.             ]))
  372.         ;
  373.         return $this->render('@default/pages/pages_index.html.twig', [
  374.             'header' => $this->pageRenderer->getHeader(),
  375.             'footer' => $this->pageRenderer->getFooter(),
  376.             'page' => $page,
  377.         ]);
  378.     }
  379.     private function getUserDashboard(): Response
  380.     {
  381.         $siteUserData $this->entityManager->getRepository(SiteUserData::class)->findOneBy(['user' => $this->getUser()]
  382.         );
  383.         $bookings $this->entityManager->getRepository(Booking::class)->findBy(['user' => $this->getUser()]);
  384.         $can_delete true;
  385.         foreach ($bookings as $booking) {
  386.             if ($booking->getReturnDate()->getTimestamp() > strtotime('NOW')) {
  387.                 $can_delete false;
  388.             }
  389.         }
  390.         $page = (new Page())
  391.             ->setTitle('User dashboard')
  392.             ->setBody(
  393.                 $this->renderView('@default/pages/user_dashboard.html.twig', [
  394.                     'siteUserData' => $siteUserData// Legacy
  395.                     'widgets' => $this->widgetCollection->getActiveWidgets(),
  396.                     'bookings' => $bookings,
  397.                     'candelete' => $can_delete,
  398.                 ])
  399.             );
  400.         return $this->render('@default/pages/pages_index.html.twig', [
  401.             'header' => $this->pageRenderer->getHeader(),
  402.             'footer' => $this->pageRenderer->getFooter(),
  403.             'page' => $page,
  404.         ]);
  405.     }
  406.     #[Route(path'/register/confirm/{token}'name'fos_user_registration_confirm')]
  407.     public function confirmAction(Request $request): Response
  408.     {
  409.         return $this->forward(
  410.             'fos_user.registration.controller:confirmAction',
  411.             $request->get('_route_params')
  412.         );
  413.     }
  414.     #[Route(path'register/confirmed'name'fos_user_registration_confirmed')]
  415.     public function confirmedAction(): Response
  416.     {
  417.         $user $this->getUser();
  418.         if (!\is_object($user) || !$user instanceof UserInterface) {
  419.             throw new AccessDeniedException('This user does not have access to this section.');
  420.         }
  421.         $page = (new Page())
  422.             ->setTitle('User dashboard')
  423.             ->setBody($this->renderView('@default/pages/confirmed.html.twig', [
  424.                 'user' => $user,
  425.             ]))
  426.         ;
  427.         return $this->render('@default/pages/pages_index.html.twig', [
  428.             'header' => $this->pageRenderer->getHeader(),
  429.             'footer' => $this->pageRenderer->getFooter(),
  430.             'page' => $page,
  431.         ]);
  432.     }
  433.     #[Route(path'/validate_email'name'user_validate_email'options: ['expose' => true])]
  434.     public function validateEmailAddress(Request $request): Response
  435.     {
  436.         if (!$email $request->get('email')) {
  437.             return new JsonResponse([
  438.                 'success' => false,
  439.                 'message' => 'No email address was provided',
  440.             ], 400);
  441.         }
  442.         $user $this->entityManager->getRepository(User::class)->findOneBy(['email' => $email]);
  443.         return new JsonResponse([
  444.             'success' => true,
  445.             'exists' => !empty($user),
  446.         ]);
  447.     }
  448.     private function renderMobilityDashboard(): Response
  449.     {
  450.         $user $this->getUser();
  451.         $page = (new Page())
  452.             ->setTitle('Mobility dashboard')
  453.             ->setBody($this->renderView('@default/pages/mobility_dashboard.html.twig', ['user' => $user]));
  454.         return $this->render('@default/pages/pages_index.html.twig', [
  455.             'header' => $this->pageRenderer->getHeader(),
  456.             'footer' => $this->pageRenderer->getFooter(),
  457.             'page' => $page,
  458.         ]);
  459.     }
  460.     #[Route('/personal_information'name'user_personal_information')]
  461.     public function personalinformationAction(Request $request): Response
  462.     {
  463.         if (!$mainBooker $this->entityManager->getRepository(MainBooker::class)->findOneBy([
  464.             'user' => $this->getUser(),
  465.         ])) {
  466.             $mainBooker = (new MainBooker())
  467.                 ->setUser($this->getUser());
  468.         }
  469.         $form $this->createForm(MainBookerType::class, $mainBooker);
  470.         $form->handleRequest($request);
  471.         if ($form->isSubmitted() && $form->isValid()) {
  472.             $this->entityManager->persist($mainBooker);
  473.             $this->entityManager->flush();
  474.         }
  475.         $newsletter $this->getDoctrine()->getRepository(Subscription::class)->findBy(
  476.             ['email' => $this->getUser()->getEmail()]
  477.         );
  478.         $page = (new Page())
  479.             ->setTitle('Contact Information')
  480.             ->setBody(
  481.                 $this->renderView($this->decorator->getTemplate('pages/user_personal_information.html.twig'), [
  482.                     'user' => $this->getUser(),
  483.                     'newsletter' => $newsletter,
  484.                     'form' => $form->createView(),
  485.                 ])
  486.             );
  487.         $response $this->render(
  488.             $this->decorator->getTemplate('pages/pages_index.html.twig'),
  489.             [
  490.                 'header' => $this->pageRenderer->getHeader(),
  491.                 'footer' => $this->pageRenderer->getFooter(),
  492.                 'page' => $page,
  493.             ]
  494.         );
  495.         $response->setPrivate()->setMaxAge(0)->setSharedMaxAge(0);
  496.         return $response;
  497.     }
  498. }