src/Controller/GuardianRegister/GuardianShortRegisterV3Controller.php line 111

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->createQueryBuilder('dc')
  233. ->where('dc.code = :code')
  234. ->andWhere('dc.validTo > :now and dc.validFrom < :now')
  235. ->setParameter('code', $referralCode)
  236. ->setParameter('now', new \DateTime())
  237. ->getQuery()
  238. ->setMaxResults(1)
  239. ->getOneOrNullResult();
  240. $teacher = $this->teacherRepository->findOneBy(['referralCode' => $referralCode]);
  241. $guardian = $this->guardianRepository->findOneBy(['referralCode' => $referralCode]);
  242. if (!$discountCoupon && !$teacher && !$guardian) {
  243. $form->get('referralCode')->addError(new FormError('Toks nuolaidos kodas neegzistuoja.'));
  244. }
  245. if ($discountCoupon && $discountCoupon->getValidFrom() > new \DateTime() && !$teacher && !$guardian) {
  246. $form->get('referralCode')->addError(new FormError('Toks nuolaidos kodas neegzistuoja.'));
  247. }
  248. if ($discountCoupon && $discountCoupon->getValidTo() < new \DateTime() && !$teacher && !$guardian) {
  249. $form->get('referralCode')->addError(new FormError('Nuolaidos kodo galiojimo laikas pasibaigė.22'));
  250. }
  251. }
  252. private function findGuardians(?string $email = null, ?string $phone = null, array $statuses = []): array
  253. {
  254. $query = $this->guardianRepository->createQueryBuilder('g');
  255. $this->addEmailOrPhoneFilter($query, 'g.email', 'g.phoneNumber', $email, $phone);
  256. if ($statuses) {
  257. $query
  258. ->andWhere('g.status IN (:statuses)')
  259. ->setParameter('statuses', $statuses);
  260. }
  261. return $query->getQuery()->getResult();
  262. }
  263. private function findChildren(?string $email = null, ?string $phone = null): array
  264. {
  265. $query = $this->childRepository->createQueryBuilder('c');
  266. $this->addEmailOrPhoneFilter($query, 'c.email', 'c.phoneNumber', $email, $phone);
  267. return $query->getQuery()->getResult();
  268. }
  269. private function addEmailOrPhoneFilter($query, string $emailField, string $phoneField, ?string $email, ?string $phone, ?string $secondaryPhoneField = null): void
  270. {
  271. $conditions = [];
  272. if ($email) {
  273. $conditions[] = "{$emailField} = :email";
  274. $query->setParameter('email', $email);
  275. }
  276. if ($phone) {
  277. $conditions[] = "{$phoneField} LIKE :phone";
  278. $query->setParameter('phone', "%{$phone}%");
  279. if ($secondaryPhoneField) {
  280. $conditions[] = "{$secondaryPhoneField} LIKE :phone";
  281. }
  282. }
  283. if (!$conditions) {
  284. $query->andWhere('1 = 0');
  285. return;
  286. }
  287. $query->andWhere($query->expr()->orX(...$conditions));
  288. }
  289. private function finishRegistration(Request $request, RequestStack $requestStack, GuardianRegister $guardianRegister, string $type): void
  290. {
  291. $guardianRegister->setIsGuardian($this->isGuardianType($type));
  292. $guardianRegister->setPriceChange($this->getDefaultGuardianPriceChange());
  293. $this->setCurrentGuardianFoundBy($guardianRegister);
  294. $this->saveGoogleTracking($request, $guardianRegister);
  295. $this->saveSessionTracking($requestStack, $guardianRegister);
  296. $guardianRegister->setCreatedAt(new \DateTime());
  297. $this->entityManager->persist($guardianRegister);
  298. $this->entityManager->flush();
  299. $this->guardianRegisterDuplicateReconciliationService->markIfDuplicate($guardianRegister);
  300. $this->addStudentClassChild($requestStack, $guardianRegister);
  301. $this->sendSuccessEmail($guardianRegister);
  302. $this->trackSignup($guardianRegister);
  303. }
  304. private function getDefaultGuardianPriceChange()
  305. {
  306. $configuration = $this->configurationRepository->findOneBy(['name' => 'DEFAULT_GUARDIAN_PRICE_CHANGE']);
  307. return $configuration ? $configuration->getValue() : null;
  308. }
  309. private function setCurrentGuardianFoundBy(GuardianRegister $guardianRegister): void
  310. {
  311. $foundByEmail = false;
  312. $foundByPhone = false;
  313. if ($guardianRegister->getEmail() && $this->guardianRepository->findOneBy(['email' => $guardianRegister->getEmail()])) {
  314. $foundByEmail = true;
  315. }
  316. if ($guardianRegister->getGuardianEmail() && $this->guardianRepository->findOneBy(['email' => $guardianRegister->getGuardianEmail()])) {
  317. $foundByEmail = true;
  318. }
  319. foreach ([$guardianRegister->getPhone(), $guardianRegister->getGuardianPhone()] as $phone) {
  320. if ($this->hasExistingPhone($phone)) {
  321. $foundByPhone = true;
  322. }
  323. }
  324. if ($foundByEmail && $foundByPhone) {
  325. $guardianRegister->setCurrentGuardianFoundBy('EMAIL&TEL');
  326. } elseif ($foundByEmail) {
  327. $guardianRegister->setCurrentGuardianFoundBy('EMAIL');
  328. } elseif ($foundByPhone) {
  329. $guardianRegister->setCurrentGuardianFoundBy('TEL');
  330. }
  331. }
  332. private function hasExistingPhone(?string $phone): bool
  333. {
  334. $phoneToSearch = $this->phoneToSearch($phone);
  335. if (!$phoneToSearch) {
  336. return false;
  337. }
  338. return $this->findGuardians(null, $phoneToSearch) || $this->findChildren(null, $phoneToSearch);
  339. }
  340. private function saveGoogleTracking(Request $request, GuardianRegister $guardianRegister): void
  341. {
  342. $gaCookie = $request->cookies->get('_ga');
  343. if ($gaCookie) {
  344. $guardianRegister->setGoogleClientId(str_replace('GA1.1.', '', $gaCookie));
  345. }
  346. $gaSessionCookie = $request->cookies->get('_ga_T59GXEEM42');
  347. if (!$gaSessionCookie) {
  348. return;
  349. }
  350. if (str_starts_with($gaSessionCookie, 'GA1.1.')) {
  351. $guardianRegister->setGoogleSessionId(explode('.', str_replace('GS1.1.', '', $gaSessionCookie))[0]);
  352. }
  353. if (str_starts_with($gaSessionCookie, 'GS2.1.')) {
  354. $guardianRegister->setGoogleSessionId(explode('.', str_replace('GS2.1.', '', $gaSessionCookie))[0]);
  355. }
  356. }
  357. private function saveSessionTracking(RequestStack $requestStack, GuardianRegister $guardianRegister): void
  358. {
  359. $sessionMap = [
  360. 'referer' => 'setReferer',
  361. 'refererCategory' => 'setRefererCategory',
  362. 'ad' => 'setAd',
  363. 'utm_source' => 'setUtmSource',
  364. 'utm_medium' => 'setUtmMedium',
  365. 'utm_campaign' => 'setUtmCampaign',
  366. 'handl_landing_page' => 'setLandingPage',
  367. ];
  368. foreach ($sessionMap as $sessionKey => $setter) {
  369. if ($value = $requestStack->getSession()->get($sessionKey)) {
  370. $guardianRegister->{$setter}($value);
  371. }
  372. }
  373. }
  374. private function addStudentClassChild(RequestStack $requestStack, GuardianRegister $guardianRegister): void
  375. {
  376. $guardianRegisterClass = $requestStack->getSession()->get('guardianRegisterClass');
  377. if (!$guardianRegisterClass) {
  378. return;
  379. }
  380. $guardianRegisterChild = (new GuardianRegisterChild())
  381. ->setName('Vardas1')
  382. ->setClass($guardianRegisterClass)
  383. ->setGuardianRegister($guardianRegister);
  384. $guardianRegister->addGuardianRegisterChild($guardianRegisterChild);
  385. $this->entityManager->persist($guardianRegister);
  386. $this->entityManager->persist($guardianRegisterChild);
  387. $this->entityManager->flush();
  388. }
  389. private function trackSignup(GuardianRegister $guardianRegister): void
  390. {
  391. $emailToSend = $guardianRegister->getIsGuardian()
  392. ? $guardianRegister->getEmail()
  393. : $guardianRegister->getGuardianEmail();
  394. if (!$emailToSend) {
  395. return;
  396. }
  397. $this->omnisendService->trackEvent($emailToSend, 'UserSignedUp', [
  398. 'email' => $guardianRegister->getEmail(),
  399. 'phone' => $guardianRegister->getPhone(),
  400. 'type' => $guardianRegister->getIsGuardian() ? 'parent' : 'child',
  401. ]);
  402. }
  403. private function saveConsent(GuardianRegister $guardianRegister, string $type): void
  404. {
  405. $email = $guardianRegister->getEmail();
  406. $consent = (new Consent())
  407. ->setEmail($email)
  408. ->setType($type)
  409. ->setPhone($guardianRegister->getPhone())
  410. ->setHttpRef($this->getHttpData());
  411. $this->entityManager->persist($consent);
  412. $this->entityManager->flush();
  413. if (!$email) {
  414. return;
  415. }
  416. $this->omnisendService->trackEvent($email, 'ConsentGiven', [
  417. 'email' => $email,
  418. 'type' => 'parent',
  419. ]);
  420. }
  421. private function getHttpData(): string
  422. {
  423. return json_encode([
  424. 'HTTP_USER_AGENT' => $_SERVER['HTTP_USER_AGENT'] ?? '',
  425. 'HTTP_ACCEPT' => $_SERVER['HTTP_ACCEPT'] ?? '',
  426. 'HTTP_ACCEPT_LANGUAGE' => $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '',
  427. 'HTTP_ACCEPT_ENCODING' => $_SERVER['HTTP_ACCEPT_ENCODING'] ?? '',
  428. 'HTTP_SEC_CH_UA' => $_SERVER['HTTP_SEC_CH_UA'] ?? '',
  429. 'HTTP_SEC_CH_UA_MOBILE' => $_SERVER['HTTP_SEC_CH_UA_MOBILE'] ?? '',
  430. 'HTTP_SEC_CH_UA_PLATFORM' => $_SERVER['HTTP_SEC_CH_UA_PLATFORM'] ?? '',
  431. 'HTTP_CONNECTION' => $_SERVER['HTTP_CONNECTION'] ?? '',
  432. 'HTTP_UPGRADE_INSECURE_REQUESTS' => $_SERVER['HTTP_UPGRADE_INSECURE_REQUESTS'] ?? '',
  433. 'REMOTE_ADDR' => $_SERVER['REMOTE_ADDR'] ?? '',
  434. 'REQUEST_METHOD' => $_SERVER['REQUEST_METHOD'] ?? '',
  435. 'REQUEST_URI' => $_SERVER['REQUEST_URI'] ?? '',
  436. 'REQUEST_TIME' => $_SERVER['REQUEST_TIME'] ?? time(),
  437. ]);
  438. }
  439. private function validateVerificationCode(FormInterface $form, string $phone, string $code): void
  440. {
  441. $verification = $this->guardianRegisterVerificationRepository->findOneBy(['phone' => $phone, 'status' => null]);
  442. if ($verification && $verification->getCode() === $code) {
  443. $verification->setStatus('success');
  444. $this->entityManager->persist($verification);
  445. $this->entityManager->flush();
  446. } else {
  447. $form->get('code')->addError(new FormError('Neteisingas patvirtinimo kodas. Bandykite dar kartą.'));
  448. }
  449. }
  450. private function getOrCreateVerification(string $phone): GuardianRegisterVerification
  451. {
  452. $verification = $this->guardianRegisterVerificationRepository->findOneBy(['phone' => $phone, 'status' => null]);
  453. if ($verification) {
  454. return $verification;
  455. }
  456. $verification = new GuardianRegisterVerification();
  457. $verification->setPhone($phone);
  458. $this->entityManager->persist($verification);
  459. $this->entityManager->flush();
  460. return $verification;
  461. }
  462. public function sendVerificationSMS(GuardianRegisterVerification $guardianRegisterVerification): array
  463. {
  464. $randomNumber = rand(1000, 9999);
  465. $dateNow = new \DateTime();
  466. $dateNow->modify('-3 hours');
  467. if ($guardianRegisterVerification->getSmsVerificationSentAt() && $guardianRegisterVerification->getSmsVerificationSentAt() >= $dateNow) {
  468. return [
  469. 'message' => 'Šiuo numeriu jau siuntėme patvirtinimo kodą, jis vis dar galioja. Prašome įvesti gautą kodą, į laukelį žemiau.',
  470. 'status' => true,
  471. ];
  472. }
  473. $guardianRegisterVerification->setCode($randomNumber);
  474. $guardianRegisterVerification->setSmsVerificationSentAt(new \DateTime());
  475. $this->entityManager->persist($guardianRegisterVerification);
  476. $this->entityManager->flush();
  477. $reminderObject = $this->reminderConfigurationRepository->findOneBy(['reminder_key' => 'REGISTER_PHONE_VERIFICATION']);
  478. $content = str_replace('[CODE]', $randomNumber, $reminderObject->getSmsTemplate());
  479. $phoneNumber = $guardianRegisterVerification->getPhone();
  480. $this->smsService->send($phoneNumber, $content, true);
  481. return [
  482. 'message' => "Išsiuntėme aktyvavimo kodą SMS žinute nurodytu numeriu {$phoneNumber}",
  483. 'status' => true,
  484. ];
  485. }
  486. public function checkBlackList(?string $email, ?string $phoneNumber)
  487. {
  488. if (!$email) {
  489. return false;
  490. }
  491. $phoneNumber = preg_replace('/^\+370/i', '', (string) $phoneNumber);
  492. $blackListed = $this->userBlacklistRepository->createQueryBuilder('u')
  493. ->andWhere('u.email = :email OR u.phoneNumber LIKE :phoneNumber')
  494. ->setParameter('email', $email)
  495. ->setParameter('phoneNumber', "%{$phoneNumber}")
  496. ->andWhere('u.userType = :userType')
  497. ->setParameter('userType', 'guardian')
  498. ->getQuery()
  499. ->getResult();
  500. return $blackListed ? 'Toks el. paštas jau yra sistemoje..' : false;
  501. }
  502. public function sendSuccessEmail(GuardianRegister $guardianRegister): void
  503. {
  504. $this->messageBus->dispatch(new SendMailMessage($guardianRegister->getEmail(), '', '', [], 'REGISTER_NOTIF_0'));
  505. }
  506. private function normalizePhoneForCountry(?string $phone, ?string $country): ?string
  507. {
  508. if (!$phone || !$country) {
  509. return $phone;
  510. }
  511. $countryData = HelperUtils::countryData();
  512. if (!isset($countryData[$country])) {
  513. return $phone;
  514. }
  515. $dialCode = $countryData[$country]['dialCode'];
  516. if (!str_starts_with($phone, $dialCode)) {
  517. $phone = $dialCode . $phone;
  518. }
  519. return str_replace('+370+370', '+370', $phone);
  520. }
  521. private function normalizeLithuanianPhone(?string $phone): ?string
  522. {
  523. if (!$phone) {
  524. return null;
  525. }
  526. $phone = preg_replace('/^6/i', '+3706', $phone);
  527. return preg_replace('/^86/i', '+3706', $phone);
  528. }
  529. private function phoneToSearch(?string $phone): ?string
  530. {
  531. if (!$phone || strlen($phone) <= 5) {
  532. return null;
  533. }
  534. $phone = str_replace('+3706', '', $phone);
  535. $phone = str_replace('3706', '', $phone);
  536. return preg_replace('/^86/i', '', $phone);
  537. }
  538. private function normalizeEmail(?string $email): ?string
  539. {
  540. $email = trim((string) $email);
  541. return $email === '' ? null : strtolower($email);
  542. }
  543. private function saveStudentClass(FormInterface $form, RequestStack $requestStack): void
  544. {
  545. if ($form->has('class') && $form->get('class')->getData()) {
  546. $requestStack->getSession()->set('guardianRegisterClass', $form->get('class')->getData());
  547. return;
  548. }
  549. $requestStack->getSession()->set('guardianRegisterClass', null);
  550. }
  551. private function getGuardianRegisterFromSession(RequestStack $requestStack): GuardianRegister
  552. {
  553. $guardianRegister = $requestStack->getSession()->get('guardianRegister');
  554. if ($guardianRegister) {
  555. return unserialize($guardianRegister);
  556. }
  557. return (new GuardianRegister())
  558. ->setEmail(null)
  559. ->setPhone(null);
  560. }
  561. private function getRedirectType(Request $request, ?string $type): ?string
  562. {
  563. if ($type) {
  564. return null;
  565. }
  566. $redirect = $request->query->get('redirect');
  567. if ($redirect === self::TYPE_GUARDIAN) {
  568. return self::TYPE_GUARDIAN;
  569. }
  570. return $this->isStudentType($redirect) ? self::TYPE_STUDENT : null;
  571. }
  572. private function isCodeConfirmStep(string $type, int $step): bool
  573. {
  574. return ($this->isGuardianType($type) && $step === 2) || ($this->isStudentType($type) && $step === 3);
  575. }
  576. private function getCodeConfirmStep(string $type): int
  577. {
  578. return $this->isGuardianType($type) ? 2 : 3;
  579. }
  580. private function isGuardianType(string $type): bool
  581. {
  582. return $type === self::TYPE_GUARDIAN;
  583. }
  584. private function isStudentType(?string $type): bool
  585. {
  586. return in_array($type, [self::TYPE_STUDENT, self::LEGACY_TYPE_STUDENT], true);
  587. }
  588. private function getFormType(string $type): string
  589. {
  590. return $this->isStudentType($type) ? self::LEGACY_TYPE_STUDENT : $type;
  591. }
  592. private function getTemplateType(string $type): string
  593. {
  594. return $this->isStudentType($type) ? self::LEGACY_TYPE_STUDENT : $type;
  595. }
  596. private function redirectToStep(string $type, $step): Response
  597. {
  598. return $this->redirectToRoute('guardian_short_register_v2_type', [
  599. 'type' => $this->isStudentType($type) ? self::TYPE_STUDENT : $type,
  600. 'step' => $step,
  601. ]);
  602. }
  603. private function renderStep(?FormInterface $form, $step, ?string $type, ?GuardianRegister $guardianRegister = null): Response
  604. {
  605. return $this->renderForm('guardian_register/frontend/short_registration_steps_v2.html.twig', [
  606. 'form' => $form,
  607. 'step' => $step,
  608. 'type' => $type,
  609. 'guardianRegister' => $guardianRegister,
  610. ]);
  611. }
  612. private function renderStart(): Response
  613. {
  614. return $this->render('guardian_register/frontend/short_registration_steps_v2.html.twig', [
  615. 'form' => null,
  616. 'step' => 'start',
  617. 'type' => null,
  618. ]);
  619. }
  620. private function renderSuccess(RequestStack $requestStack, string $type): Response
  621. {
  622. $guardianRegister = $requestStack->getSession()->get('guardianRegister');
  623. if ($guardianRegister) {
  624. $guardianRegister = unserialize($guardianRegister);
  625. }
  626. return $this->render('guardian_register/frontend/short_registration_success.html.twig', [
  627. 'guardianRegister' => $guardianRegister,
  628. 'step' => 'end',
  629. 'type' => $this->getTemplateType($type),
  630. ]);
  631. }
  632. }