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

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