src/Controller/GuardianRegister/GuardianShortRegisterV3Controller.php line 102

Open in your IDE?
  1. <?php
  2. namespace App\Controller\GuardianRegister;
  3. use App\Entity\Consent;
  4. use App\Entity\Guardian;
  5. use App\Entity\GuardianRegister\GuardianRegister;
  6. use App\Entity\GuardianRegister\GuardianRegisterChild;
  7. use App\Entity\GuardianRegister\GuardianRegisterVerification;
  8. use App\Form\GuardianShortRegister\GuardianShortRegisterCodeConfirmType;
  9. use App\Form\GuardianShortRegister\GuardianShortRegisterContactStepType;
  10. use App\Form\GuardianShortRegister\GuardianShortRegisterGuardianInfoType;
  11. use App\Message\SendMailMessage;
  12. use App\Repository\ChildRepository;
  13. use App\Repository\ConfigurationRepository;
  14. use App\Repository\DiscountCouponRepository;
  15. use App\Repository\GuardianRegister\GuardianRegisterRepository;
  16. use App\Repository\GuardianRegister\GuardianRegisterVerificationRepository;
  17. use App\Repository\GuardianRepository;
  18. use App\Repository\ReminderConfigurationRepository;
  19. use App\Repository\TeacherRepository;
  20. use App\Repository\UserBlacklistRepository;
  21. use App\Service\GuardianRegisterDuplicateReconciliationService;
  22. use App\Service\OmnisendService;
  23. use App\Service\RefererService;
  24. use App\Service\SmsService;
  25. use App\Utils\HelperUtils;
  26. use Doctrine\ORM\EntityManagerInterface;
  27. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  28. use Symfony\Component\Form\FormError;
  29. use Symfony\Component\Form\FormInterface;
  30. use Symfony\Component\HttpFoundation\Request;
  31. use Symfony\Component\HttpFoundation\RequestStack;
  32. use Symfony\Component\HttpFoundation\Response;
  33. use Symfony\Component\Messenger\MessageBusInterface;
  34. use Symfony\Component\Routing\Annotation\Route;
  35. /**
  36. * @Route("/registracija")
  37. */
  38. class GuardianShortRegisterV3Controller extends AbstractController
  39. {
  40. private const TYPE_GUARDIAN = 'tevams';
  41. private const TYPE_STUDENT = 'mokiniai';
  42. private const LEGACY_TYPE_STUDENT = 'mokiniams';
  43. private const EXISTING_EMAIL_ERROR = 'Šiuo el.pašto adresu jau yra paskyra sistemoje. Prisijunkite <a href="https://app.corepetitus.lt">app.corepetitus.lt</a> arba susisiekite su administracija. +370 610 40 856';
  44. private const EXISTING_PHONE_ERROR = 'Šiuo telefono numeriu jau yra paskyra sistemoje. Prisijunkite <a href="https://app.corepetitus.lt">app.corepetitus.lt</a> arba susisiekite su administracija. +370 610 40 856';
  45. private const BLACKLIST_ERROR = 'Registracija negalima. Jūsų duomenys sutampa su platformos apribotų vartotojų sąrašu. Prašome susisiekti su administracija dėl tolimesnės informacijos +370 610 40 856.';
  46. private SmsService $smsService;
  47. private EntityManagerInterface $entityManager;
  48. private ReminderConfigurationRepository $reminderConfigurationRepository;
  49. private GuardianRepository $guardianRepository;
  50. private GuardianRegisterRepository $guardianRegisterRepository;
  51. private ConfigurationRepository $configurationRepository;
  52. private ChildRepository $childRepository;
  53. private MessageBusInterface $messageBus;
  54. private GuardianRegisterVerificationRepository $guardianRegisterVerificationRepository;
  55. private OmnisendService $omnisendService;
  56. private DiscountCouponRepository $discountCouponRepository;
  57. private TeacherRepository $teacherRepository;
  58. private UserBlacklistRepository $userBlacklistRepository;
  59. private GuardianRegisterDuplicateReconciliationService $guardianRegisterDuplicateReconciliationService;
  60. public function __construct(
  61. SmsService $smsService,
  62. UserBlacklistRepository $userBlacklistRepository,
  63. ChildRepository $childRepository,
  64. EntityManagerInterface $entityManager,
  65. ConfigurationRepository $configurationRepository,
  66. GuardianRepository $guardianRepository,
  67. GuardianRegisterRepository $guardianRegisterRepository,
  68. ReminderConfigurationRepository $reminderConfigurationRepository,
  69. MessageBusInterface $messageBus,
  70. GuardianRegisterVerificationRepository $guardianRegisterVerificationRepository,
  71. OmnisendService $omnisendService,
  72. DiscountCouponRepository $discountCouponRepository,
  73. TeacherRepository $teacherRepository,
  74. GuardianRegisterDuplicateReconciliationService $guardianRegisterDuplicateReconciliationService
  75. ) {
  76. $this->smsService = $smsService;
  77. $this->entityManager = $entityManager;
  78. $this->reminderConfigurationRepository = $reminderConfigurationRepository;
  79. $this->guardianRepository = $guardianRepository;
  80. $this->guardianRegisterRepository = $guardianRegisterRepository;
  81. $this->configurationRepository = $configurationRepository;
  82. $this->childRepository = $childRepository;
  83. $this->messageBus = $messageBus;
  84. $this->guardianRegisterVerificationRepository = $guardianRegisterVerificationRepository;
  85. $this->omnisendService = $omnisendService;
  86. $this->discountCouponRepository = $discountCouponRepository;
  87. $this->teacherRepository = $teacherRepository;
  88. $this->userBlacklistRepository = $userBlacklistRepository;
  89. $this->guardianRegisterDuplicateReconciliationService = $guardianRegisterDuplicateReconciliationService;
  90. }
  91. /**
  92. * @Route("/", name="guardian_short_register_v2", methods={"GET", "POST"})
  93. * @Route("/{type}/{step}", name="guardian_short_register_v2_type", methods={"GET", "POST"})
  94. */
  95. public function register(Request $request, RefererService $refererService, RequestStack $requestStack, $type = null, $step = null): Response
  96. {
  97. $refererService->setReferer();
  98. if ($redirect = $this->getRedirectType($request, $type)) {
  99. return $this->redirectToStep($redirect, 1);
  100. }
  101. if (!$type) {
  102. return $this->renderStart();
  103. }
  104. if ($step === 'end') {
  105. return $this->renderSuccess($requestStack, $type);
  106. }
  107. if ((int) $step === 0) {
  108. return $this->redirectToRoute('guardian_short_register_v2');
  109. }
  110. $guardianRegister = $this->getGuardianRegisterFromSession($requestStack);
  111. if ((int) $step === 1) {
  112. return $this->handleContactStep($request, $requestStack, $guardianRegister, $type);
  113. }
  114. if ((int) $step === 2 && $this->isStudentType($type)) {
  115. return $this->handleGuardianInfoStep($request, $requestStack, $guardianRegister, $type);
  116. }
  117. if ($this->isCodeConfirmStep($type, (int) $step)) {
  118. return $this->handleCodeConfirmStep($request, $requestStack, $guardianRegister, $type);
  119. }
  120. return $this->redirectToStep($type, 1);
  121. }
  122. private function handleContactStep(Request $request, RequestStack $requestStack, GuardianRegister $guardianRegister, string $type): Response
  123. {
  124. $form = $this->createForm(GuardianShortRegisterContactStepType::class, $guardianRegister, [
  125. 'type' => $this->getFormType($type),
  126. ]);
  127. $form->handleRequest($request);
  128. if ($form->isSubmitted()) {
  129. $email = $this->normalizeEmail($guardianRegister->getEmail());
  130. $guardianRegister->setEmail($email);
  131. $this->saveStudentClass($form, $requestStack);
  132. $phone = $this->normalizePhoneForCountry($guardianRegister->getPhone(), $form->get('country')->getData());
  133. $guardianRegister->setPhone($phone);
  134. $phoneForSearch = $this->normalizeLithuanianPhone($phone);
  135. $this->validateContactEmail($form, $email, $phoneForSearch);
  136. $this->validateContactPhone($form, $email, $phoneForSearch);
  137. $this->validateReferralCode($form, $guardianRegister->getReferralCode());
  138. if ($form->isValid()) {
  139. $requestStack->getSession()->set('guardianRegister', serialize($guardianRegister));
  140. $this->saveConsent($guardianRegister, $type);
  141. return $this->redirectToStep($type, 2);
  142. }
  143. }
  144. return $this->renderStep($form, 1, $this->getTemplateType($type), $guardianRegister);
  145. }
  146. private function handleGuardianInfoStep(Request $request, RequestStack $requestStack, GuardianRegister $guardianRegister, string $type): Response
  147. {
  148. $studentEmail = $this->normalizeEmail($guardianRegister->getEmail());
  149. $form = $this->createForm(GuardianShortRegisterGuardianInfoType::class, $guardianRegister);
  150. $form->handleRequest($request);
  151. if ($form->isSubmitted()) {
  152. $email = $this->normalizeEmail($guardianRegister->getGuardianEmail());
  153. $guardianRegister->setGuardianEmail($email);
  154. $phone = $this->normalizePhoneForCountry($guardianRegister->getGuardianPhone(), $form->get('country')->getData());
  155. $guardianRegister->setGuardianPhone($phone);
  156. $phoneForSearch = $this->normalizeLithuanianPhone($phone);
  157. $this->validateGuardianContact($form, $email, $phoneForSearch);
  158. $emailsMatch = $email && $email === $studentEmail;
  159. if ($emailsMatch) {
  160. $errorMessage = 'Mokinio ir tėvo el. pašto adresai negali sutapti';
  161. $form->get('guardianEmail')->addError(new FormError($errorMessage));
  162. }
  163. if ($guardianRegister->getPhone() === $guardianRegister->getGuardianPhone()) {
  164. $form->get('guardianPhone')->addError(new FormError('Telefono numeriai negali sutapti.'));
  165. }
  166. if ($form->isValid() && !$emailsMatch) {
  167. $requestStack->getSession()->set('guardianRegister', serialize($guardianRegister));
  168. return $this->redirectToStep($type, 3);
  169. }
  170. }
  171. return $this->renderStep($form, 2, $this->getTemplateType($type), $guardianRegister);
  172. }
  173. private function handleCodeConfirmStep(Request $request, RequestStack $requestStack, GuardianRegister $guardianRegister, string $type): Response
  174. {
  175. $form = $this->createForm(GuardianShortRegisterCodeConfirmType::class, $guardianRegister);
  176. $form->handleRequest($request);
  177. $phone = (string) $this->normalizeLithuanianPhone($guardianRegister->getPhone());
  178. $verification = $this->getOrCreateVerification($phone);
  179. $this->sendVerificationSMS($verification);
  180. $code = $form->get('code')->getData();
  181. if ($code) {
  182. $this->validateVerificationCode($form, $phone, $code);
  183. if ($form->isSubmitted() && $form->isValid()) {
  184. $requestStack->getSession()->set('guardianRegister', serialize($guardianRegister));
  185. $this->finishRegistration($request, $requestStack, $guardianRegister, $type);
  186. return $this->redirectToStep($type, 'end');
  187. }
  188. }
  189. return $this->renderStep($form, $this->getCodeConfirmStep($type), $this->getTemplateType($type), $guardianRegister);
  190. }
  191. private function validateContactEmail(FormInterface $form, ?string $email, ?string $phone): void
  192. {
  193. if (!$email) {
  194. return;
  195. }
  196. $leftGuardians = $this->findGuardians($email, null, Guardian::FORMER_CLIENT_STATUSES);
  197. $guardians = $leftGuardians ? [] : $this->findGuardians($email);
  198. $children = $this->findChildren($email);
  199. if ($guardians || $children) {
  200. $form->get('email')->addError(new FormError(self::EXISTING_EMAIL_ERROR));
  201. }
  202. if ($this->checkBlackList($email, $phone)) {
  203. $form->get('email')->addError(new FormError(self::BLACKLIST_ERROR));
  204. }
  205. }
  206. private function validateContactPhone(FormInterface $form, ?string $email, ?string $phone): void
  207. {
  208. $leftGuardians = $this->findGuardians($email, $phone, Guardian::FORMER_CLIENT_STATUSES);
  209. $guardians = $leftGuardians ? [] : $this->findGuardians($email, $phone);
  210. $children = $this->findChildren($email, $phone);
  211. if ($guardians || $children) {
  212. $form->get('phone')->addError(new FormError(self::EXISTING_PHONE_ERROR));
  213. }
  214. }
  215. private function validateGuardianContact(FormInterface $form, ?string $email, ?string $phone): void
  216. {
  217. $leftGuardians = $this->findGuardians($email, $phone, [Guardian::STATUS_LEFT['value'], Guardian::STATUS_OVERPAID['value']]);
  218. $guardians = $leftGuardians ? [] : $this->findGuardians($email, $phone);
  219. $children = $this->findChildren($email, $phone);
  220. if ($guardians || $children) {
  221. $form->get('guardianEmail')->addError(new FormError(self::EXISTING_EMAIL_ERROR));
  222. }
  223. if ($this->checkBlackList($email, $phone)) {
  224. $form->get('guardianEmail')->addError(new FormError(self::BLACKLIST_ERROR));
  225. }
  226. }
  227. private function validateReferralCode(FormInterface $form, ?string $referralCode): void
  228. {
  229. if (!$referralCode) {
  230. return;
  231. }
  232. $discountCoupon = $this->discountCouponRepository->findOneByCodeValidAt($referralCode, new \DateTime());
  233. $teacher = $this->teacherRepository->findOneBy(['referralCode' => $referralCode]);
  234. $guardian = $this->guardianRepository->findOneBy(['referralCode' => $referralCode]);
  235. if (!$discountCoupon && !$teacher && !$guardian) {
  236. $form->get('referralCode')->addError(new FormError('Toks nuolaidos kodas neegzistuoja.'));
  237. }
  238. if ($discountCoupon && $discountCoupon->getValidFrom() > new \DateTime() && !$teacher && !$guardian) {
  239. $form->get('referralCode')->addError(new FormError('Toks nuolaidos kodas neegzistuoja.'));
  240. }
  241. if ($discountCoupon && $discountCoupon->getValidTo() < new \DateTime() && !$teacher && !$guardian) {
  242. $form->get('referralCode')->addError(new FormError('Nuolaidos kodo galiojimo laikas pasibaigė.22'));
  243. }
  244. }
  245. private function findGuardians(?string $email = null, ?string $phone = null, array $statuses = []): array
  246. {
  247. $query = $this->guardianRepository->createQueryBuilder('g');
  248. $this->addEmailOrPhoneFilter($query, 'g.email', 'g.phoneNumber', $email, $phone);
  249. if ($statuses) {
  250. $query
  251. ->andWhere('g.status IN (:statuses)')
  252. ->setParameter('statuses', $statuses);
  253. }
  254. return $query->getQuery()->getResult();
  255. }
  256. private function findChildren(?string $email = null, ?string $phone = null): array
  257. {
  258. $query = $this->childRepository->createQueryBuilder('c');
  259. $this->addEmailOrPhoneFilter($query, 'c.email', 'c.phoneNumber', $email, $phone);
  260. return $query->getQuery()->getResult();
  261. }
  262. private function addEmailOrPhoneFilter($query, string $emailField, string $phoneField, ?string $email, ?string $phone, ?string $secondaryPhoneField = null): void
  263. {
  264. $conditions = [];
  265. if ($email) {
  266. $conditions[] = "{$emailField} = :email";
  267. $query->setParameter('email', $email);
  268. }
  269. if ($phone) {
  270. $conditions[] = "{$phoneField} LIKE :phone";
  271. $query->setParameter('phone', "%{$phone}%");
  272. if ($secondaryPhoneField) {
  273. $conditions[] = "{$secondaryPhoneField} LIKE :phone";
  274. }
  275. }
  276. if (!$conditions) {
  277. $query->andWhere('1 = 0');
  278. return;
  279. }
  280. $query->andWhere($query->expr()->orX(...$conditions));
  281. }
  282. private function finishRegistration(Request $request, RequestStack $requestStack, GuardianRegister $guardianRegister, string $type): void
  283. {
  284. $guardianRegister->setIsGuardian($this->isGuardianType($type));
  285. $guardianRegister->setPriceChange($this->getDefaultGuardianPriceChange());
  286. $this->setCurrentGuardianFoundBy($guardianRegister);
  287. $this->saveGoogleTracking($request, $guardianRegister);
  288. $this->saveSessionTracking($requestStack, $guardianRegister);
  289. $guardianRegister->setCreatedAt(new \DateTime());
  290. $this->entityManager->persist($guardianRegister);
  291. $this->entityManager->flush();
  292. $this->guardianRegisterDuplicateReconciliationService->markIfDuplicate($guardianRegister);
  293. $this->addStudentClassChild($requestStack, $guardianRegister);
  294. $this->sendSuccessEmail($guardianRegister);
  295. $this->trackSignup($guardianRegister);
  296. }
  297. private function getDefaultGuardianPriceChange()
  298. {
  299. $configuration = $this->configurationRepository->findOneBy(['name' => 'DEFAULT_GUARDIAN_PRICE_CHANGE']);
  300. return $configuration ? $configuration->getValue() : null;
  301. }
  302. private function setCurrentGuardianFoundBy(GuardianRegister $guardianRegister): void
  303. {
  304. $foundByEmail = false;
  305. $foundByPhone = false;
  306. if ($guardianRegister->getEmail() && $this->guardianRepository->findOneBy(['email' => $guardianRegister->getEmail()])) {
  307. $foundByEmail = true;
  308. }
  309. if ($guardianRegister->getGuardianEmail() && $this->guardianRepository->findOneBy(['email' => $guardianRegister->getGuardianEmail()])) {
  310. $foundByEmail = true;
  311. }
  312. foreach ([$guardianRegister->getPhone(), $guardianRegister->getGuardianPhone()] as $phone) {
  313. if ($this->hasExistingPhone($phone)) {
  314. $foundByPhone = true;
  315. }
  316. }
  317. if ($foundByEmail && $foundByPhone) {
  318. $guardianRegister->setCurrentGuardianFoundBy('EMAIL&TEL');
  319. } elseif ($foundByEmail) {
  320. $guardianRegister->setCurrentGuardianFoundBy('EMAIL');
  321. } elseif ($foundByPhone) {
  322. $guardianRegister->setCurrentGuardianFoundBy('TEL');
  323. }
  324. }
  325. private function hasExistingPhone(?string $phone): bool
  326. {
  327. $phoneToSearch = $this->phoneToSearch($phone);
  328. if (!$phoneToSearch) {
  329. return false;
  330. }
  331. return $this->findGuardians(null, $phoneToSearch) || $this->findChildren(null, $phoneToSearch);
  332. }
  333. private function saveGoogleTracking(Request $request, GuardianRegister $guardianRegister): void
  334. {
  335. $gaCookie = $request->cookies->get('_ga');
  336. if ($gaCookie) {
  337. $guardianRegister->setGoogleClientId(str_replace('GA1.1.', '', $gaCookie));
  338. }
  339. $gaSessionCookie = $request->cookies->get('_ga_T59GXEEM42');
  340. if (!$gaSessionCookie) {
  341. return;
  342. }
  343. if (str_starts_with($gaSessionCookie, 'GA1.1.')) {
  344. $guardianRegister->setGoogleSessionId(explode('.', str_replace('GS1.1.', '', $gaSessionCookie))[0]);
  345. }
  346. if (str_starts_with($gaSessionCookie, 'GS2.1.')) {
  347. $guardianRegister->setGoogleSessionId(explode('.', str_replace('GS2.1.', '', $gaSessionCookie))[0]);
  348. }
  349. }
  350. private function saveSessionTracking(RequestStack $requestStack, GuardianRegister $guardianRegister): void
  351. {
  352. $sessionMap = [
  353. 'referer' => 'setReferer',
  354. 'refererCategory' => 'setRefererCategory',
  355. 'ad' => 'setAd',
  356. 'utm_source' => 'setUtmSource',
  357. 'utm_medium' => 'setUtmMedium',
  358. 'utm_campaign' => 'setUtmCampaign',
  359. 'handl_landing_page' => 'setLandingPage',
  360. ];
  361. foreach ($sessionMap as $sessionKey => $setter) {
  362. if ($value = $requestStack->getSession()->get($sessionKey)) {
  363. $guardianRegister->{$setter}($value);
  364. }
  365. }
  366. }
  367. private function addStudentClassChild(RequestStack $requestStack, GuardianRegister $guardianRegister): void
  368. {
  369. $guardianRegisterClass = $requestStack->getSession()->get('guardianRegisterClass');
  370. if (!$guardianRegisterClass) {
  371. return;
  372. }
  373. $guardianRegisterChild = (new GuardianRegisterChild())
  374. ->setName('Vardas1')
  375. ->setClass($guardianRegisterClass)
  376. ->setGuardianRegister($guardianRegister);
  377. $guardianRegister->addGuardianRegisterChild($guardianRegisterChild);
  378. $this->entityManager->persist($guardianRegister);
  379. $this->entityManager->persist($guardianRegisterChild);
  380. $this->entityManager->flush();
  381. }
  382. private function trackSignup(GuardianRegister $guardianRegister): void
  383. {
  384. $emailToSend = $guardianRegister->getIsGuardian()
  385. ? $guardianRegister->getEmail()
  386. : $guardianRegister->getGuardianEmail();
  387. if (!$emailToSend) {
  388. return;
  389. }
  390. $this->omnisendService->trackEvent($emailToSend, 'UserSignedUp', [
  391. 'email' => $guardianRegister->getEmail(),
  392. 'phone' => $guardianRegister->getPhone(),
  393. 'type' => $guardianRegister->getIsGuardian() ? 'parent' : 'child',
  394. ]);
  395. }
  396. private function saveConsent(GuardianRegister $guardianRegister, string $type): void
  397. {
  398. $email = $guardianRegister->getEmail();
  399. $consent = (new Consent())
  400. ->setEmail($email)
  401. ->setType($type)
  402. ->setPhone($guardianRegister->getPhone())
  403. ->setHttpRef($this->getHttpData());
  404. $this->entityManager->persist($consent);
  405. $this->entityManager->flush();
  406. if (!$email) {
  407. return;
  408. }
  409. $this->omnisendService->trackEvent($email, 'ConsentGiven', [
  410. 'email' => $email,
  411. 'type' => 'parent',
  412. ]);
  413. }
  414. private function getHttpData(): string
  415. {
  416. return json_encode([
  417. 'HTTP_USER_AGENT' => $_SERVER['HTTP_USER_AGENT'] ?? '',
  418. 'HTTP_ACCEPT' => $_SERVER['HTTP_ACCEPT'] ?? '',
  419. 'HTTP_ACCEPT_LANGUAGE' => $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '',
  420. 'HTTP_ACCEPT_ENCODING' => $_SERVER['HTTP_ACCEPT_ENCODING'] ?? '',
  421. 'HTTP_SEC_CH_UA' => $_SERVER['HTTP_SEC_CH_UA'] ?? '',
  422. 'HTTP_SEC_CH_UA_MOBILE' => $_SERVER['HTTP_SEC_CH_UA_MOBILE'] ?? '',
  423. 'HTTP_SEC_CH_UA_PLATFORM' => $_SERVER['HTTP_SEC_CH_UA_PLATFORM'] ?? '',
  424. 'HTTP_CONNECTION' => $_SERVER['HTTP_CONNECTION'] ?? '',
  425. 'HTTP_UPGRADE_INSECURE_REQUESTS' => $_SERVER['HTTP_UPGRADE_INSECURE_REQUESTS'] ?? '',
  426. 'REMOTE_ADDR' => $_SERVER['REMOTE_ADDR'] ?? '',
  427. 'REQUEST_METHOD' => $_SERVER['REQUEST_METHOD'] ?? '',
  428. 'REQUEST_URI' => $_SERVER['REQUEST_URI'] ?? '',
  429. 'REQUEST_TIME' => $_SERVER['REQUEST_TIME'] ?? time(),
  430. ]);
  431. }
  432. private function validateVerificationCode(FormInterface $form, string $phone, string $code): void
  433. {
  434. $verification = $this->guardianRegisterVerificationRepository->findOneBy(['phone' => $phone, 'status' => null]);
  435. if ($verification && $verification->getCode() === $code) {
  436. $verification->setStatus('success');
  437. $this->entityManager->persist($verification);
  438. $this->entityManager->flush();
  439. } else {
  440. $form->get('code')->addError(new FormError('Neteisingas patvirtinimo kodas. Bandykite dar kartą.'));
  441. }
  442. }
  443. private function getOrCreateVerification(string $phone): GuardianRegisterVerification
  444. {
  445. $verification = $this->guardianRegisterVerificationRepository->findOneBy(['phone' => $phone, 'status' => null]);
  446. if ($verification) {
  447. return $verification;
  448. }
  449. $verification = new GuardianRegisterVerification();
  450. $verification->setPhone($phone);
  451. $this->entityManager->persist($verification);
  452. $this->entityManager->flush();
  453. return $verification;
  454. }
  455. public function sendVerificationSMS(GuardianRegisterVerification $guardianRegisterVerification): array
  456. {
  457. $randomNumber = rand(1000, 9999);
  458. $dateNow = new \DateTime();
  459. $dateNow->modify('-3 hours');
  460. if ($guardianRegisterVerification->getSmsVerificationSentAt() && $guardianRegisterVerification->getSmsVerificationSentAt() >= $dateNow) {
  461. return [
  462. 'message' => 'Šiuo numeriu jau siuntėme patvirtinimo kodą, jis vis dar galioja. Prašome įvesti gautą kodą, į laukelį žemiau.',
  463. 'status' => true,
  464. ];
  465. }
  466. $guardianRegisterVerification->setCode($randomNumber);
  467. $guardianRegisterVerification->setSmsVerificationSentAt(new \DateTime());
  468. $this->entityManager->persist($guardianRegisterVerification);
  469. $this->entityManager->flush();
  470. $reminderObject = $this->reminderConfigurationRepository->findOneBy(['reminder_key' => 'REGISTER_PHONE_VERIFICATION']);
  471. $content = str_replace('[CODE]', $randomNumber, $reminderObject->getSmsTemplate());
  472. $phoneNumber = $guardianRegisterVerification->getPhone();
  473. $this->smsService->send($phoneNumber, $content, true);
  474. return [
  475. 'message' => "Išsiuntėme aktyvavimo kodą SMS žinute nurodytu numeriu {$phoneNumber}",
  476. 'status' => true,
  477. ];
  478. }
  479. public function checkBlackList(?string $email, ?string $phoneNumber)
  480. {
  481. if (!$email) {
  482. return false;
  483. }
  484. $phoneNumber = preg_replace('/^\+370/i', '', (string) $phoneNumber);
  485. $blackListed = $this->userBlacklistRepository->createQueryBuilder('u')
  486. ->andWhere('u.email = :email OR u.phoneNumber LIKE :phoneNumber')
  487. ->setParameter('email', $email)
  488. ->setParameter('phoneNumber', "%{$phoneNumber}")
  489. ->andWhere('u.userType = :userType')
  490. ->setParameter('userType', 'guardian')
  491. ->getQuery()
  492. ->getResult();
  493. return $blackListed ? 'Toks el. paštas jau yra sistemoje..' : false;
  494. }
  495. public function sendSuccessEmail(GuardianRegister $guardianRegister): void
  496. {
  497. $this->messageBus->dispatch(new SendMailMessage($guardianRegister->getEmail(), '', '', [], 'REGISTER_NOTIF_0'));
  498. }
  499. private function normalizePhoneForCountry(?string $phone, ?string $country): ?string
  500. {
  501. if (!$phone || !$country) {
  502. return $phone;
  503. }
  504. $countryData = HelperUtils::countryData();
  505. if (!isset($countryData[$country])) {
  506. return $phone;
  507. }
  508. $dialCode = $countryData[$country]['dialCode'];
  509. if (!str_starts_with($phone, $dialCode)) {
  510. $phone = $dialCode . $phone;
  511. }
  512. return str_replace('+370+370', '+370', $phone);
  513. }
  514. private function normalizeLithuanianPhone(?string $phone): ?string
  515. {
  516. if (!$phone) {
  517. return null;
  518. }
  519. $phone = preg_replace('/^6/i', '+3706', $phone);
  520. return preg_replace('/^86/i', '+3706', $phone);
  521. }
  522. private function phoneToSearch(?string $phone): ?string
  523. {
  524. if (!$phone || strlen($phone) <= 5) {
  525. return null;
  526. }
  527. $phone = str_replace('+3706', '', $phone);
  528. $phone = str_replace('3706', '', $phone);
  529. return preg_replace('/^86/i', '', $phone);
  530. }
  531. private function normalizeEmail(?string $email): ?string
  532. {
  533. $email = trim((string) $email);
  534. return $email === '' ? null : strtolower($email);
  535. }
  536. private function saveStudentClass(FormInterface $form, RequestStack $requestStack): void
  537. {
  538. if ($form->has('class') && $form->get('class')->getData()) {
  539. $requestStack->getSession()->set('guardianRegisterClass', $form->get('class')->getData());
  540. return;
  541. }
  542. $requestStack->getSession()->set('guardianRegisterClass', null);
  543. }
  544. private function getGuardianRegisterFromSession(RequestStack $requestStack): GuardianRegister
  545. {
  546. $guardianRegister = $requestStack->getSession()->get('guardianRegister');
  547. if ($guardianRegister) {
  548. return unserialize($guardianRegister);
  549. }
  550. return (new GuardianRegister())
  551. ->setEmail(null)
  552. ->setPhone(null);
  553. }
  554. private function getRedirectType(Request $request, ?string $type): ?string
  555. {
  556. if ($type) {
  557. return null;
  558. }
  559. $redirect = $request->query->get('redirect');
  560. if ($redirect === self::TYPE_GUARDIAN) {
  561. return self::TYPE_GUARDIAN;
  562. }
  563. return $this->isStudentType($redirect) ? self::TYPE_STUDENT : null;
  564. }
  565. private function isCodeConfirmStep(string $type, int $step): bool
  566. {
  567. return ($this->isGuardianType($type) && $step === 2) || ($this->isStudentType($type) && $step === 3);
  568. }
  569. private function getCodeConfirmStep(string $type): int
  570. {
  571. return $this->isGuardianType($type) ? 2 : 3;
  572. }
  573. private function isGuardianType(string $type): bool
  574. {
  575. return $type === self::TYPE_GUARDIAN;
  576. }
  577. private function isStudentType(?string $type): bool
  578. {
  579. return in_array($type, [self::TYPE_STUDENT, self::LEGACY_TYPE_STUDENT], true);
  580. }
  581. private function getFormType(string $type): string
  582. {
  583. return $this->isStudentType($type) ? self::LEGACY_TYPE_STUDENT : $type;
  584. }
  585. private function getTemplateType(string $type): string
  586. {
  587. return $this->isStudentType($type) ? self::LEGACY_TYPE_STUDENT : $type;
  588. }
  589. private function redirectToStep(string $type, $step): Response
  590. {
  591. return $this->redirectToRoute('guardian_short_register_v2_type', [
  592. 'type' => $this->isStudentType($type) ? self::TYPE_STUDENT : $type,
  593. 'step' => $step,
  594. ]);
  595. }
  596. private function renderStep(?FormInterface $form, $step, ?string $type, ?GuardianRegister $guardianRegister = null): Response
  597. {
  598. return $this->renderForm('guardian_register/frontend/short_registration_steps_v2.html.twig', [
  599. 'form' => $form,
  600. 'step' => $step,
  601. 'type' => $type,
  602. 'guardianRegister' => $guardianRegister,
  603. ]);
  604. }
  605. private function renderStart(): Response
  606. {
  607. return $this->render('guardian_register/frontend/short_registration_steps_v2.html.twig', [
  608. 'form' => null,
  609. 'step' => 'start',
  610. 'type' => null,
  611. ]);
  612. }
  613. private function renderSuccess(RequestStack $requestStack, string $type): Response
  614. {
  615. $guardianRegister = $requestStack->getSession()->get('guardianRegister');
  616. if ($guardianRegister) {
  617. $guardianRegister = unserialize($guardianRegister);
  618. }
  619. return $this->render('guardian_register/frontend/short_registration_success.html.twig', [
  620. 'guardianRegister' => $guardianRegister,
  621. 'step' => 'end',
  622. 'type' => $this->getTemplateType($type),
  623. ]);
  624. }
  625. }