custom/plugins/LeadManager/src/Storefront/Subscriber/StorefrontSubscriber.php line 100

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Virgin\LeadManager\Storefront\Subscriber;
  3. use Doctrine\DBAL\Connection;
  4. use Doctrine\DBAL\Exception;
  5. use Doctrine\DBAL\Query\QueryBuilder;
  6. use Shopware\Core\Content\Category\CategoryEntity;
  7. use Shopware\Core\Content\Category\CategoryEvents;
  8. use Shopware\Core\Content\Category\Event\NavigationLoadedEvent;
  9. use Shopware\Core\Content\LandingPage\LandingPageEvents;
  10. use Shopware\Core\Framework\Context;
  11. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEvent;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  14. use Shopware\Core\Framework\Validation\BuildValidationEvent;
  15. use Shopware\Core\System\Language\LanguageCollection;
  16. use Shopware\Core\System\Tag\TagCollection;
  17. use Shopware\Core\System\Tag\TagEntity;
  18. use Shopware\Storefront\Event\StorefrontRenderEvent;
  19. use Shopware\Storefront\Page\LandingPage\LandingPage;
  20. use Symfony\Component\DependencyInjection\ContainerInterface;
  21. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  22. use Symfony\Component\HttpFoundation\RedirectResponse;
  23. use Symfony\Component\HttpFoundation\Session\Session;
  24. use Symfony\Component\HttpKernel\Event\RequestEvent;
  25. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  26. use Symfony\Component\HttpKernel\KernelEvents;
  27. use Symfony\Component\Validator\Constraints\Regex;
  28. use Virgin\LeadManager\Utils\Services\LeadGenerationService;
  29. use Virgin\SystemIntegration\Exception\VirginApiException;
  30. use Virgin\SystemIntegration\Services\RestApiClient;
  31. class StorefrontSubscriber implements EventSubscriberInterface
  32. {
  33. public const string TAG_DIRECT = 'direct';
  34. public const string TAG_FOOTER = 'footer';
  35. /**
  36. * @var LeadGenerationService
  37. */
  38. private LeadGenerationService $leadService;
  39. /** @var ContainerInterface */
  40. private ContainerInterface $container;
  41. /**
  42. * @var RestApiClient
  43. */
  44. private RestApiClient $restApiClient;
  45. /** @var Session */
  46. private Session $session;
  47. /** @var EntityRepository */
  48. private EntityRepository $languageRepository;
  49. /**
  50. * @param LeadGenerationService $leadService
  51. * @param ContainerInterface $container
  52. * @param RestApiClient $restApiClient
  53. * @param EntityRepository $languageRepository
  54. */
  55. public function __construct(
  56. LeadGenerationService $leadService,
  57. ContainerInterface $container,
  58. RestApiClient $restApiClient,
  59. EntityRepository $languageRepository
  60. ) {
  61. $this->leadService = $leadService;
  62. $this->container = $container;
  63. $this->restApiClient = $restApiClient;
  64. $session = $container->get('session');
  65. if ($session instanceof Session){
  66. $this->session = $session;
  67. }
  68. $this->languageRepository = $languageRepository;
  69. }
  70. /**
  71. * @return string[]
  72. */
  73. public static function getSubscribedEvents(): array
  74. {
  75. return [
  76. StorefrontRenderEvent::class => 'addCustomerInfo',
  77. KernelEvents::RESPONSE => 'onEventResponse',
  78. CategoryEvents::CATEGORY_LOADED_EVENT => 'onLoadCategory',
  79. LandingPageEvents::LANDING_PAGE_LOADED_EVENT => 'onLoadLandingPage',
  80. NavigationLoadedEvent::class => 'onLoadNavigation',
  81. KernelEvents::REQUEST => 'getUtmParams',
  82. 'framework.validation.customer.password.update' => 'validatePassword'
  83. ];
  84. }
  85. /**
  86. * @param BuildValidationEvent $event
  87. * @return void
  88. */
  89. public function validatePassword(BuildValidationEvent $event): void
  90. {
  91. error_log($event->getName());
  92. $event->getDefinition()->add('newPassword', new Regex($this->restApiClient::PASSWORD_REGEX));
  93. }
  94. /**
  95. * @param RequestEvent $event
  96. * @return void
  97. */
  98. public function getUtmParams(RequestEvent $event): void
  99. {
  100. $utmParams = [
  101. "utm_source" => $event->getRequest()->query->get('utm_source'),
  102. "utm_medium" => $event->getRequest()->query->get('utm_medium'),
  103. "utm_campaign" => $event->getRequest()->query->get('utm_campaign'),
  104. "utm_term" => $event->getRequest()->query->get('utm_term'),
  105. "utm_content" => $event->getRequest()->query->get('utm_content'),
  106. ];
  107. if(array_filter($utmParams)) {
  108. $_SESSION['utm_params'] = $utmParams;
  109. }
  110. }
  111. /**
  112. * @param StorefrontRenderEvent $event
  113. * @return void
  114. * @throws VirginApiException
  115. */
  116. public function addCustomerInfo(StorefrontRenderEvent $event): void
  117. {
  118. $salesChannelContext = $event->getSalesChannelContext();
  119. $tagCommanderVariablesArray = $this->getTagCommanderVariablesArray();
  120. $tagCommanderVariablesArray['envLanguage'] = $this->getLanguageIsoCode($salesChannelContext->getContext());
  121. $tagCommanderVariablesArray['envCurrency'] = $salesChannelContext->getCurrency()->getIsoCode();
  122. if ($customer = $event->getSalesChannelContext()->getCustomer()) {
  123. $customerEmail = $customer->getEmail();
  124. $checkPersonResponse = json_decode($this->restApiClient->checkPerson($customerEmail), false);
  125. if (null !== $checkPersonResponse && null !== $checkPersonResponse->exerp_User) {
  126. $tagCommanderVariablesArray['userId'] = $checkPersonResponse->exerp_User->id;
  127. }
  128. $tagCommanderVariablesArray['userEmail'] = $customerEmail;
  129. if(!empty($_SESSION['utm_params'])) {
  130. $this->restApiClient->insertUtmParams(
  131. $_SESSION['utm_params'],
  132. $customerEmail,
  133. $customer->getFirstName(),
  134. $customer->getLastName(),
  135. 'LOGGED_USER'
  136. );
  137. unset($_SESSION['utm_params']);
  138. }
  139. $privacyConsent = $customer->getCustomFields()['privacy_consent'] ?? null;
  140. $event->setParameter('privacy', $privacyConsent);
  141. if(!isset($customer->getCustomFields()['lead_implicit_registration']) || !$customer->getCustomFields()['lead_implicit_registration']) {
  142. $event->setParameter('isUserLoggedExplicit', true);
  143. }
  144. }else{
  145. if(isset($_COOKIE[LeadGenerationService::ECOMMERCE_COOKIE_NAME])){
  146. $decodedCookie = json_decode(base64_decode($_COOKIE[LeadGenerationService::ECOMMERCE_COOKIE_NAME]));
  147. if(isset($decodedCookie->email) && $this->leadService->checkIfMailExist($decodedCookie->email, $event->getSalesChannelContext())){
  148. $this->leadService->shadowLogin($decodedCookie->email, $event->getSalesChannelContext());
  149. }else{
  150. unset($_COOKIE[LeadGenerationService::ECOMMERCE_COOKIE_NAME]);
  151. setcookie(LeadGenerationService::ECOMMERCE_COOKIE_NAME, '', time() - 3600, '/');
  152. }
  153. }
  154. }
  155. $navId = $event->getRequest()->get('navigationId');
  156. if (null !== $navId) {
  157. /** @var CategoryEntity $categoryEntity */
  158. $categoryEntity = $this->leadService->checkPageCategoryWithDirectTag($navId);
  159. if (null !== $categoryEntity) {
  160. $tagCommanderVariablesArray['categoryId'] = $categoryEntity->getId();
  161. $tagCommanderVariablesArray['categoryName'] = $categoryEntity->getName();
  162. }
  163. }
  164. $revolutionDigitaleId = $this->leadService->getRevolutionDigitaleId($salesChannelContext);
  165. $event->setParameter('revolutionDigitaleId', $revolutionDigitaleId);
  166. $event->setParameter('navId', $navId);
  167. $event->setParameter('tagCommanderVariables', $tagCommanderVariablesArray);
  168. }
  169. /**
  170. * @param ResponseEvent $event
  171. * @return void
  172. */
  173. public function onEventResponse(ResponseEvent $event): void
  174. {
  175. $request = $event->getRequest();
  176. $attributes = $request->attributes;
  177. // $salesChannelContext = $attributes->get('sw-sales-channel-context');
  178. // if(isset($attributes->get('_route_params')['navigationId'])){
  179. // $navigationId = $attributes->get('_route_params')['navigationId'];
  180. // if (
  181. // !$this->leadService->checkPageCategoryWithDirectTag($navigationId)
  182. // && $this->session->has('isDirectFlow')
  183. // ) {
  184. // $this->session->remove('isDirectFlow');
  185. // }
  186. // if ($this->leadService->checkPageCategory($request, $navigationId)) {
  187. //// if (!$salesChannelContext->getCustomer()) {
  188. //// $url = $this->container->get('router')->generate('frontend.purchase');
  189. //// $event->setResponse(new RedirectResponse($url));
  190. //// }
  191. // }
  192. // } else {
  193. // if ($this->session->has('isDirectFlow')) {
  194. // $this->session->remove('isDirectFlow');
  195. // }
  196. // }
  197. if($attributes->get('_route') && $attributes->get('_route') == 'frontend.home.page'){
  198. $url = $this->container->get('router')->generate('frontend.account.register.page');
  199. $event->setResponse(new RedirectResponse($url));
  200. }
  201. }
  202. /**
  203. * @param EntityLoadedEvent $event
  204. * @return void
  205. */
  206. public function onLoadCategory(EntityLoadedEvent $event): void
  207. {
  208. $categories = $event->getEntities();
  209. foreach ($categories as $c) {
  210. $tagObjects = $this->getCategoryTag($c->getId());
  211. if (!empty($tagObjects)) {
  212. $tagEntities = [];
  213. foreach ($tagObjects as $tagObject) {
  214. $tag = new TagEntity();
  215. $tag->setName($tagObject['name']);
  216. $tag->setId($tagObject['id']);
  217. $tagEntities[] = $tag;
  218. }
  219. $c->setTags(new TagCollection($tagEntities));
  220. }
  221. }
  222. }
  223. /**
  224. * @param EntityLoadedEvent $event
  225. * @throws Exception
  226. * @throws \Doctrine\DBAL\Driver\Exception
  227. */
  228. public function onLoadLandingPage(EntityLoadedEvent $event): void
  229. {
  230. /** @var LandingPage $landingPages */
  231. $landingPages = $event->getEntities();
  232. foreach ($landingPages as $l) {
  233. $tagObjects = $this->getLandingPageTag($l->getId());
  234. if (!empty($tagObjects)) {
  235. $tagEntities = [];
  236. foreach ($tagObjects as $tagObject) {
  237. $tag = new TagEntity();
  238. $tag->setName($tagObject['name']);
  239. $tag->setId($tagObject['id']);
  240. $tagEntities[] = $tag;
  241. }
  242. $l->setTags(new TagCollection($tagEntities));
  243. $this->session->set('currentNavigationPageTags', $l->getTags());
  244. }
  245. }
  246. }
  247. /**
  248. * @param NavigationLoadedEvent $event
  249. * @return void
  250. */
  251. public function onLoadNavigation(NavigationLoadedEvent $event): void
  252. {
  253. $isDirect=false;
  254. $categoryActive = $event->getNavigation()->getActive();
  255. $this->session->set('currentNavigationPageId', $categoryActive->getId());
  256. $currentCategoryTags = $categoryActive->getTags();
  257. if ($currentCategoryTags) {
  258. $this->session->set('currentNavigationPageTags', $currentCategoryTags);
  259. foreach ($currentCategoryTags as $tagActive){
  260. if($tagActive != null){
  261. if(str_contains($tagActive->getName(), self::TAG_DIRECT)){
  262. $isDirect = true;
  263. $_SESSION['isDirectFlow']= true;
  264. $this->session->set('isDirectFlow', true);
  265. }else{
  266. if ($this->session->has('isDirectFlow')) {
  267. $this->session->remove('isDirectFlow');
  268. }
  269. }
  270. }
  271. }
  272. }
  273. $navTree = $event->getNavigation()->getTree();
  274. foreach ($navTree as $k=>$t){
  275. $tags= $t->getCategory()->getTags();
  276. if($tags != null){
  277. foreach ($tags as $tag){
  278. if(($isDirect && !str_contains($tag->getName(), self::TAG_DIRECT) && !str_contains($tag->getName(), self::TAG_FOOTER))
  279. ||(!$isDirect && str_contains($tag->getName(), self::TAG_DIRECT))){
  280. unset($navTree[$k]);
  281. }
  282. }
  283. }else{ //is club?
  284. if($isDirect){
  285. unset($navTree[$k]);
  286. }
  287. }
  288. }
  289. $event->getNavigation()->setTree($navTree);
  290. }
  291. /**
  292. * @param $categoryId
  293. * @return array
  294. * @throws Exception
  295. * @throws \Doctrine\DBAL\Driver\Exception
  296. */
  297. private function getCategoryTag($categoryId): array
  298. {
  299. $connection = $this->container->get(Connection::class);
  300. /** @var QueryBuilder $builder */
  301. $builder = $connection->createQueryBuilder();
  302. return $builder->select('LOWER(HEX(t.id)) id, t.name')
  303. ->from('tag', 't')
  304. ->leftJoin('t','category_tag','ct','t.id = ct.tag_id')
  305. ->where('ct.category_id = UNHEX( :categoryId)')
  306. ->setParameter('categoryId', $categoryId)
  307. ->execute()
  308. ->fetchAllAssociative();
  309. }
  310. /**
  311. * @param $landingPageId
  312. * @return array
  313. * @throws Exception
  314. * @throws \Doctrine\DBAL\Driver\Exception
  315. */
  316. private function getLandingPageTag($landingPageId): array
  317. {
  318. $connection = $this->container->get(Connection::class);
  319. /** @var QueryBuilder $builder */
  320. $builder = $connection->createQueryBuilder();
  321. return $builder->select('LOWER(HEX(t.id)) id, t.name')
  322. ->from('tag', 't')
  323. ->leftJoin('t','landing_page_tag','lt','t.id = lt.tag_id')
  324. ->where('lt.landing_page_id = UNHEX( :landingPageId)')
  325. ->setParameter('landingPageId', $landingPageId)
  326. ->execute()
  327. ->fetchAllAssociative();
  328. }
  329. /**
  330. * @param Context $context
  331. * @return false|string
  332. */
  333. private function getLanguageIsoCode(Context $context): false|string
  334. {
  335. $languageId = $context->getLanguageId();
  336. $criteria = new Criteria([$languageId]);
  337. $criteria->addAssociation('locale');
  338. /** @var LanguageCollection $languageCollection */
  339. $languageCollection = $this->languageRepository->search($criteria, $context)->getEntities();
  340. $language = $languageCollection->get($languageId);
  341. if ($language === null) {
  342. return 'en';
  343. }
  344. $locale = $language->getLocale();
  345. if (!$locale) {
  346. return 'en';
  347. }
  348. return substr($locale->getCode(), 0, 2);
  349. }
  350. /**
  351. * @return string[]
  352. */
  353. private function getTagCommanderVariablesArray(): array
  354. {
  355. return [
  356. 'envLanguage' => '',
  357. 'envCountry' => 'Italy',
  358. 'envCurrency' => '',
  359. 'userId' => '',
  360. 'userEmail' => '',
  361. 'categoryId' => '',
  362. 'categoryName' => '',
  363. ];
  364. }
  365. }