src/App/Controller/RegistrationController.php line 158

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\AnonymousUserInfo;
  4. use App\Entity\User;
  5. use App\Event\UserRegisteredEvent;
  6. use App\Event\UserTermsAndConditionsAcceptedEvent;
  7. use App\Exception\InvalidEmailException;
  8. use App\Kernel;
  9. use App\Service\ConversionEventService;
  10. use App\Service\FeatureLimitationsService;
  11. use App\Service\MailService;
  12. use App\Service\RegistrationService;
  13. use App\Service\RouterHelperService;
  14. use App\Service\SessionService;
  15. use App\Service\SplittestingService;
  16. use App\Service\UserService;
  17. use Doctrine\ORM\EntityManagerInterface;
  18. use Exception;
  19. use FOS\ElasticaBundle\Persister\ObjectPersisterInterface;
  20. use FOS\UserBundle\Controller\RegistrationController as FOSUserBundleRegistrationController;
  21. use FOS\UserBundle\Event\FilterUserResponseEvent;
  22. use FOS\UserBundle\Event\FormEvent;
  23. use FOS\UserBundle\Form\Factory\FactoryInterface;
  24. use FOS\UserBundle\FOSUserEvents;
  25. use FOS\UserBundle\Model\UserManagerInterface;
  26. use FOS\UserBundle\Util\CanonicalFieldsUpdater;
  27. use JanusHercules\DatawarehouseIntegration\Domain\Entity\BusinessEvent;
  28. use JanusHercules\DatawarehouseIntegration\Domain\Service\BusinessEventDomainService;
  29. use JanusHercules\JoboffererOnboarding\SubverticalFacade\JoboffererOnboardingFacade;
  30. use Psr\Log\LoggerInterface;
  31. use Symfony\Component\HttpFoundation\RedirectResponse;
  32. use Symfony\Component\HttpFoundation\Request;
  33. use Symfony\Component\HttpFoundation\RequestStack;
  34. use Symfony\Component\HttpFoundation\Response;
  35. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  36. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  37. use Symfony\Contracts\Translation\TranslatorInterface;
  38. /**
  39. * The methods here are overrides of FOSUserBundle methods to extend their functionality as needed.
  40. */
  41. class RegistrationController extends FOSUserBundleRegistrationController
  42. {
  43. private EventDispatcherInterface $eventDispatcher;
  44. private FactoryInterface $formFactory;
  45. private UserManagerInterface $userManager;
  46. private BusinessEventDomainService $businessEventDomainService;
  47. private SplittestingService $splittestingService;
  48. private TranslatorInterface $translator;
  49. private EntityManagerInterface $entityManager;
  50. private RegistrationService $registrationService;
  51. private UserService $userService;
  52. private ConversionEventService $conversionEventService;
  53. private RequestStack $requestStack;
  54. private MailService $mailService;
  55. private SessionService $sessionService;
  56. private RouterHelperService $routerHelperService;
  57. private LoggerInterface $logger;
  58. private FeatureLimitationsService $featureLimitationsService;
  59. private CanonicalFieldsUpdater $canonicalFieldsUpdater;
  60. private ObjectPersisterInterface $wantedJobsPersister;
  61. private ObjectPersisterInterface $recurrentJobsPersister;
  62. private Kernel $kernel;
  63. public function __construct(
  64. EventDispatcherInterface $eventDispatcher,
  65. FactoryInterface $formFactory,
  66. UserManagerInterface $userManager,
  67. TokenStorageInterface $tokenStorage,
  68. BusinessEventDomainService $businessEventDomainService,
  69. SplittestingService $splittestingService,
  70. TranslatorInterface $translator,
  71. EntityManagerInterface $entityManager,
  72. RegistrationService $registrationService,
  73. UserService $userService,
  74. ConversionEventService $conversionEventService,
  75. RequestStack $requestStack,
  76. SessionService $sessionService,
  77. RouterHelperService $routerHelperService,
  78. LoggerInterface $logger,
  79. FeatureLimitationsService $featureLimitationsService,
  80. Kernel $kernel
  81. ) {
  82. parent::__construct($eventDispatcher, $formFactory, $userManager, $tokenStorage);
  83. $this->eventDispatcher = $eventDispatcher;
  84. $this->formFactory = $formFactory;
  85. $this->userManager = $userManager;
  86. $this->businessEventDomainService = $businessEventDomainService;
  87. $this->splittestingService = $splittestingService;
  88. $this->translator = $translator;
  89. $this->entityManager = $entityManager;
  90. $this->registrationService = $registrationService;
  91. $this->userService = $userService;
  92. $this->conversionEventService = $conversionEventService;
  93. $this->requestStack = $requestStack;
  94. $this->routerHelperService = $routerHelperService;
  95. $this->sessionService = $sessionService;
  96. $this->logger = $logger;
  97. $this->featureLimitationsService = $featureLimitationsService;
  98. $this->kernel = $kernel;
  99. }
  100. public function changeEmailAddressAction(Request $request): Response
  101. {
  102. $newEmailAddress = $request->get('newEmailAddress');
  103. $userId = $request->get('userId');
  104. $response = new Response();
  105. $handleResult = $this->userService->handleNewUserEmailAddressConfirmation(
  106. $this->getUser()->getId(),
  107. $userId,
  108. $newEmailAddress
  109. );
  110. if ($handleResult > UserService::CHANGE_EMAIL_RESULT_SUCCESSFUL) {
  111. $response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR);
  112. if ($handleResult === UserService::CHANGE_EMAIL_RESULT_ALREADY_IN_USE) {
  113. $alertMessage = $this->translator->trans('errors.email_address_already_in_use.alert');
  114. $mainContent = $this->translator->trans('errors.email_address_already_in_use.main_content');
  115. } else {
  116. $alertMessage = $this->translator->trans('errors.general.alert');
  117. $mainContent = $this->translator->trans('errors.general.main_content');
  118. }
  119. return $this->render(
  120. 'errors/general_error.html.twig',
  121. [
  122. 'alert_message' => $alertMessage,
  123. 'main_content_message' => $mainContent
  124. ], $response
  125. );
  126. }
  127. $response->setStatusCode(Response::HTTP_OK);
  128. return $this->render('default/new_email_confirmation.html.twig', [], $response);
  129. }
  130. /** @throws Exception */
  131. public function registerAction(Request $request): Response
  132. {
  133. /** @var User $user */
  134. $user = $this->getUser();
  135. if ($user instanceof User) {
  136. $response = new Response();
  137. $response->setStatusCode(Response::HTTP_FORBIDDEN);
  138. return $this->render('errors/already_logged_in.html.twig', [], $response);
  139. }
  140. $assignedRegistrationSplittestingBucket = 0;
  141. $user = $this->registrationService->createRudimentaryUser();
  142. $response = $this->registrationService->dispatchRegistrationInitializedEvent($request, $user);
  143. if (!is_null($response)) {
  144. return $response;
  145. }
  146. $form = $this->formFactory->createForm();
  147. $form->setData($user);
  148. try {
  149. $form->handleRequest($request);
  150. } catch (InvalidEmailException $e) {
  151. $this->addFlash('danger', $this->translator->trans('registration.flash.email_invalid'));
  152. $response = $this->registrationService->handleRegistrationFailure($request, $form);
  153. if (!is_null($response)) {
  154. return $response;
  155. }
  156. }
  157. $role = $request->get('createWithRole');
  158. if ($form->isSubmitted()) {
  159. $captchaIsValid = $this->registrationService->captchaIsValid($request);
  160. if (!$captchaIsValid) {
  161. $this->addFlash('danger', $this->translator->trans('registration.flash.captcha_invalid'));
  162. } else {
  163. if (!$form->isValid()) {
  164. if (count($form->getErrors()) > 0) {
  165. foreach ($form->getErrors() as $error) {
  166. if ($error->getMessageTemplate() === 'fos_user.username.already_used') {
  167. if (!is_null($user)) {
  168. /** @var User $foundUser */
  169. if (!empty($foundUser = $this->entityManager->getRepository(User::class)->findOneBy(['email' => $user->getEmail()]))) {
  170. if (!$foundUser->isEnabled()) {
  171. if ($foundUser->getRoles()[0] === $role) {
  172. $this->registrationService->checkEmailAddressValidity($user);
  173. $user = $foundUser;
  174. if ($role === User::ROLE_NAME_JOBSEEKER) {
  175. $this->registrationService->addRequestProfileDataToJobseekerProfile($request, $user);
  176. }
  177. $event = new FormEvent($form, $request);
  178. $createWithRole = $form['createWithRole']->getData();
  179. if ($createWithRole !== User::ROLE_NAME_JOBSEEKER && $createWithRole !== User::ROLE_NAME_JOBOFFERER) {
  180. $this->logger->warning("Invalid createWithRole {$createWithRole}, falling back to '" . User::ROLE_NAME_JOBSEEKER . "'.");
  181. $createWithRole = User::ROLE_NAME_JOBSEEKER;
  182. }
  183. $user->addRole($createWithRole);
  184. $user->setEnabled(false);
  185. $token = $user->getConfirmationToken();
  186. if ($this->sessionService->hasSessionAnonymousUserInfo($this->requestStack->getSession())) {
  187. $anonymousUserInfo = $this->entityManager->find(AnonymousUserInfo::class, $this->sessionService->getAnonymousUserInfo($this->requestStack->getSession()));
  188. $anonymousUserInfo->setToken($token);
  189. $this->entityManager->persist($anonymousUserInfo);
  190. $this->entityManager->flush();
  191. }
  192. $this->registrationService->sendConfirmationMailAndGetMessage($user);
  193. $this->requestStack->getSession()->set(
  194. 'fos_user_send_confirmation_email/email',
  195. $user->getEmail()
  196. );
  197. if ($user->hasRole(User::ROLE_NAME_JOBOFFERER)) {
  198. if (JoboffererOnboardingFacade::userMustUseNewOnboardingFlow($user)) {
  199. $url = $this->routerHelperService->generate(
  200. 'janus_aurora.jobofferer_onboarding.wait_for_activation',
  201. ['email' => $user->getEmail()],
  202. );
  203. } else {
  204. $url = $this->routerHelperService->generate(
  205. 'fos_user_registration_check_email_jobofferer'
  206. );
  207. }
  208. } elseif ($user->hasRole(User::ROLE_NAME_JOBSEEKER)) {
  209. $url = $this->routerHelperService->generate('fos_user_registration_check_email_jobseeker');
  210. } else {
  211. $url = $this->routerHelperService->generate('fos_user_registration_check_email');
  212. }
  213. $event->setResponse(new RedirectResponse($url));
  214. $this->eventDispatcher->dispatch(new FilterUserResponseEvent($user, $request, $event->getResponse()), FOSUserEvents::REGISTRATION_COMPLETED);
  215. if ($role === User::ROLE_NAME_JOBSEEKER) {
  216. $this->splittestingService->handleGoalReached(
  217. SplittestingService::TEST_ID_JOBSEEKER_REGISTRATION_FORM_ORDER,
  218. $event->getResponse(),
  219. $request,
  220. $user
  221. );
  222. }
  223. return $event->getResponse();
  224. }
  225. $response = $this->registrationService->handleRegistrationFailure($request, $form, null);
  226. if (!is_null($response)) {
  227. return $response;
  228. }
  229. }
  230. }
  231. }
  232. }
  233. }
  234. }
  235. }
  236. if ($form->isValid()) {
  237. $this->registrationService->checkEmailAddressValidity($user);
  238. if ($role === User::ROLE_NAME_JOBSEEKER) {
  239. $this->registrationService->addRequestProfileDataToJobseekerProfile($request, $user);
  240. }
  241. $event = new FormEvent($form, $request);
  242. $this->eventDispatcher->dispatch($event, FOSUserEvents::REGISTRATION_SUCCESS);
  243. $this->userManager->updateUser($user);
  244. if (null === $response = $event->getResponse()) {
  245. $url = $this->generateUrl('fos_user_registration_confirmed');
  246. $response = new RedirectResponse($url);
  247. }
  248. $this->eventDispatcher->dispatch(new FilterUserResponseEvent($user, $request, $response), FOSUserEvents::REGISTRATION_COMPLETED);
  249. if ($form->get('acceptedTermsAndConditions')) {
  250. $this->eventDispatcher->dispatch(
  251. new UserTermsAndConditionsAcceptedEvent(
  252. $user
  253. )
  254. );
  255. }
  256. $this->eventDispatcher->dispatch(
  257. new UserRegisteredEvent($user),
  258. UserRegisteredEvent::class
  259. );
  260. if ($role === User::ROLE_NAME_JOBSEEKER) {
  261. $this->splittestingService->handleGoalReached(
  262. SplittestingService::TEST_ID_JOBSEEKER_REGISTRATION_FORM_ORDER,
  263. $response,
  264. $request,
  265. $user
  266. );
  267. }
  268. return $response;
  269. }
  270. $response = $this->registrationService->handleRegistrationFailure($request, $form, null);
  271. if (!is_null($response)) {
  272. return $response;
  273. }
  274. }
  275. }
  276. $response = new Response();
  277. if ($role !== User::ROLE_NAME_JOBOFFERER) {
  278. $assignedRegistrationSplittestingBucket = $this->splittestingService->initiateSplittesting(
  279. SplittestingService::TEST_ID_JOBSEEKER_REGISTRATION_FORM_ORDER,
  280. $response
  281. );
  282. }
  283. if ($request->get('away') === 'true') {
  284. $this->businessEventDomainService->writeNewEvent(BusinessEvent::EVENT_TYPE_LINK_FROM_EBAY_AWAY_MESSAGE_CLICKED, $user);
  285. }
  286. if ($role === User::ROLE_NAME_JOBOFFERER) {
  287. $this->conversionEventService->initiateGoalReachedConversionTracking(null, ConversionEventService::CAMPAIGN_ID_REGISTRATION_REFERER, 0, null, $request, null, json_encode(['referer' => $request->headers->get('referer')]));
  288. }
  289. if ($role === User::ROLE_NAME_JOBSEEKER) {
  290. $this->conversionEventService->initiateGoalReachedConversionTracking(null, ConversionEventService::CAMPAIGN_ID_REGISTRATION_REFERER, 1, null, $request, null, json_encode(['referer' => $request->headers->get('referer')]));
  291. }
  292. $this->conversionEventService->initiateGoalReachedConversionTrackingBasedOnRequest($request);
  293. return $this->render(
  294. '@FOSUser/Registration/register.html.twig',
  295. [
  296. 'form' => $form->createView(),
  297. 'createWithRole' => $role,
  298. 'assignedRegistrationSplittestingBucket' => $assignedRegistrationSplittestingBucket
  299. ],
  300. $response
  301. );
  302. }
  303. /** @throws Exception */
  304. public function confirmedAction(Request $request): Response
  305. {
  306. $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
  307. /** @var User $user */
  308. $user = $this->getUser();
  309. $this->registrationService->handleUserAccountConfirmation($request, $user);
  310. if ($this->featureLimitationsService->userMustBeForwardedToDataImport($user) !== -1) {
  311. return $this->redirectToRoute('account.profiles.check_recruit_dl', ['usersId' => $user->getId()]);
  312. } else {
  313. if ($user->isJobofferer()) {
  314. // Because our test setup currently depends on a very specific process to create a jobofferer test actor
  315. // (see Tests\Application\TestCase::getActivatedJoboffererActor), we do not (yet) send the client to the
  316. // new Jobofferer Onboarding flow.
  317. if ($this->kernel->getEnvironment() === 'test') {
  318. return $this->redirectToRoute('account.profiles.index', ['isFirstEdit' => true]);
  319. }
  320. if (JoboffererOnboardingFacade::userMustUseNewOnboardingFlow($user)) {
  321. return $this->redirectToRoute('janus_aurora.jobofferer_onboarding.start');
  322. } else {
  323. return $this->redirectToRoute('account.profiles.index', ['isFirstEdit' => true]);
  324. }
  325. }
  326. return $this->redirectToRoute('janus_hercules.jobseeker_registration.presentation.index', ['step' => 0, 'firstEdit' => true]);
  327. }
  328. }
  329. public function confirmAction(Request $request, $token): Response
  330. {
  331. $userManager = $this->userManager;
  332. $user = $userManager->findUserByConfirmationToken($token);
  333. // User not found? Instead of showing an error, redirect to homepage.
  334. if (is_null($user)) {
  335. $url = $this->generateUrl('homepage');
  336. return new RedirectResponse($url);
  337. }
  338. // User found and already enabled - aka the user has repeatedly clicked on the activation link.
  339. // In this case, log the user in.
  340. if ($user->isEnabled()) {
  341. $this->userService->login($request, $user);
  342. return new RedirectResponse($this->generateUrl('account.conversations.index_router'));
  343. }
  344. // None of the above? That's the default case and we activate the account.
  345. return $this->registrationService->confirmUserRegistration($request, $user);
  346. }
  347. }