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

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