custom/plugins/VirginCustomElement/src/Storefront/Subscriber/StorefrontSubscriber.php line 155

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Virgin\VirginCustomElement\Storefront\Subscriber;
  3. use DateInterval;
  4. use DateTimeImmutable;
  5. use Doctrine\DBAL\Connection;
  6. use Exception;
  7. use PDO;
  8. use Shopware\Core\Checkout\Promotion\Gateway\Template\ActiveDateRange;
  9. use Shopware\Core\Checkout\Promotion\PromotionEntity;
  10. use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotEntity;
  11. use Shopware\Core\Content\Cms\CmsPageEvents;
  12. use Shopware\Core\Content\Product\ProductEntity;
  13. use Shopware\Core\Defaults;
  14. use Shopware\Core\Framework\Api\Context\AdminApiSource;
  15. use Shopware\Core\Framework\Context;
  16. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  17. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEvent;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Pricing\Price;
  19. use Shopware\Core\Framework\DataAbstractionLayer\Pricing\PriceCollection;
  20. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  21. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\ContainsFilter;
  22. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  23. use Shopware\Core\Framework\Uuid\Uuid;
  24. use Shopware\Core\System\SalesChannel\Context\CachedSalesChannelContextFactory;
  25. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  26. use Shopware\Core\System\Tag\TagCollection;
  27. use Shopware\Core\System\Tag\TagEntity;
  28. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  29. use Symfony\Component\HttpFoundation\RequestStack;
  30. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  31. use Virgin\ProductModelExtension\Custom\Club\ClubEntity;
  32. use Virgin\ProductModelExtension\Services\ClubService;
  33. use Virgin\ProductModelExtension\Services\ProductService;
  34. use Virgin\SubscriptionsConfigurator\Utils\Services\SubscriptionsConfiguratorService;
  35. use Virgin\SystemIntegration\Exception\VirginApiException;
  36. use Virgin\SystemIntegration\Services\RestApiClient;
  37. class StorefrontSubscriber implements EventSubscriberInterface
  38. {
  39. const string VIRGIN_CMS_SLOT_ENTITY_TYPE_PRODUCT_BOX = 'virgin-product-box';
  40. const string VIRGIN_CMS_SLOT_ENTITY_TYPE_REGISTRATION_FORM = 'virgin-registration-form';
  41. const string VIRGIN_CMS_SLOT_ENTITY_TYPE_CLUB_SELECT_FORM = 'virgin-club-select-form';
  42. const string SPECIAL_PROMO_PREFIX = 'promo_';
  43. const string SPECIAL_PROMO_TAG = 'special_promo';
  44. const string CONFIG_LANDING_TAG = 'config';
  45. const string VIRGIN_CMS_SLOT_ENTITY_TYPE_LANDING_CONFIG = 'virgin-landing-config';
  46. /**
  47. * @var ClubService
  48. */
  49. private ClubService $clubService;
  50. /**
  51. * @var SessionInterface
  52. */
  53. private SessionInterface $session;
  54. /**
  55. * @var EntityRepository
  56. */
  57. private EntityRepository $promotionRepository;
  58. /**
  59. * @var EntityRepository
  60. */
  61. private EntityRepository $salesChannelRepository;
  62. /**
  63. * @var CachedSalesChannelContextFactory
  64. */
  65. private CachedSalesChannelContextFactory $cachedSalesChannelContextFactory;
  66. /**
  67. * @var SubscriptionsConfiguratorService
  68. */
  69. private SubscriptionsConfiguratorService $subscriptionsConfigurationService;
  70. /**
  71. * @var RestApiClient
  72. */
  73. private RestApiClient $restApiClient;
  74. /**
  75. * @var EntityRepository
  76. */
  77. private EntityRepository $tagRepository;
  78. /**
  79. * @var EntityRepository
  80. */
  81. private EntityRepository $categoryRepository;
  82. /**
  83. * @var EntityRepository
  84. */
  85. private EntityRepository $cmsSlotTranslationRepository;
  86. /** @var Connection */
  87. private Connection $connection;
  88. /**
  89. * @var RequestStack
  90. */
  91. private RequestStack $requestStack;
  92. /**
  93. * @var ProductService
  94. */
  95. private ProductService $productService;
  96. public function __construct(
  97. ClubService $clubService,
  98. EntityRepository $promotionRepository,
  99. EntityRepository $salesChannelRepository,
  100. CachedSalesChannelContextFactory $cachedSalesChannelContextFactory,
  101. SubscriptionsConfiguratorService $subscriptionsConfigurationService,
  102. SessionInterface $session,
  103. EntityRepository $tagRepository,
  104. RestApiClient $restApiClient,
  105. EntityRepository $categoryRepository,
  106. EntityRepository $cmsSlotTranslationRepository,
  107. Connection $connection,
  108. RequestStack $requestStack,
  109. ProductService $productService
  110. ) {
  111. $this->clubService = $clubService;
  112. $this->promotionRepository = $promotionRepository;
  113. $this->salesChannelRepository = $salesChannelRepository;
  114. $this->cachedSalesChannelContextFactory = $cachedSalesChannelContextFactory;
  115. $this->subscriptionsConfigurationService = $subscriptionsConfigurationService;
  116. $this->session = $session;
  117. $this->tagRepository = $tagRepository;
  118. $this->restApiClient = $restApiClient;
  119. $this->categoryRepository = $categoryRepository;
  120. $this->cmsSlotTranslationRepository = $cmsSlotTranslationRepository;
  121. $this->connection = $connection;
  122. $this->requestStack = $requestStack;
  123. $this->productService = $productService;
  124. }
  125. public static function getSubscribedEvents(): array
  126. {
  127. return [
  128. CmsPageEvents::SLOT_LOADED_EVENT => 'addProductInfo',
  129. ];
  130. }
  131. /**
  132. * @param EntityLoadedEvent $event
  133. * @throws VirginApiException
  134. * @throws Exception
  135. */
  136. public function addProductInfo(EntityLoadedEvent $event): void
  137. {
  138. $context = $event->getContext();
  139. if ($context->getSource() instanceof AdminApiSource && $context->getSource()->isAdmin() || $this->requestStack->getCurrentRequest()->attributes->get('_route') !== 'frontend.navigation.page')
  140. return;
  141. $salesChannelContext = $this->getSalesChannelContext($context);
  142. //get landing config if there's any
  143. $landingConfig = $this->getLandingConfig($event);
  144. $virginCustomEntities = $this->getVirginCustomEntities($event);
  145. if (!$virginCustomEntities){
  146. return;
  147. }
  148. //expiration date check
  149. //todo spostare nel context
  150. if ($landingConfig && $landingConfig['expirationDate']) {
  151. $isExpired = new \DateTime($landingConfig['expirationDate']) < new \DateTime();
  152. if ($isExpired) {
  153. foreach ($virginCustomEntities as $entity){
  154. $entity->setCustomFields([
  155. 'isExpired' => true,
  156. 'redirectUrl' => $landingConfig['redirectUrl'] ?? 'https://www.virginactive.it/'
  157. ]);
  158. }
  159. }
  160. }
  161. $selectedClubGuids = !empty($landingConfig) && array_key_exists('clubArray', $landingConfig) && $landingConfig['clubArray'] ? $landingConfig['clubArray'] : [];
  162. /** @var ClubEntity[] $clubs */
  163. $clubs = $this->clubService->getClubList($salesChannelContext, $selectedClubGuids, empty($selectedClubGuids));
  164. switch ($virginCustomEntities[0]->getType()){
  165. case self::VIRGIN_CMS_SLOT_ENTITY_TYPE_PRODUCT_BOX:
  166. //get promotion
  167. $promotionCriteria = new Criteria();
  168. $promotionCriteria->addAssociation('virginPromotionAttributes');
  169. $promotionCriteria->addFilter(new EqualsFilter('virginPromotionAttributes.isSpecialPromoFlow', true));
  170. $promotionCriteria->addFilter(new EqualsFilter('virginPromotionAttributes.isExerpPromotion', true));
  171. $promotionCriteria->addFilter(new ActiveDateRange());
  172. $promotionCriteria->addFilter(new EqualsFilter('active', true));
  173. /** @var PromotionEntity $specialFlowPromotion */
  174. $specialFlowPromotion = $this->promotionRepository->search(
  175. $promotionCriteria,
  176. $context
  177. )->first();
  178. $isSpecialPromoFlow = false;
  179. $isDigitalProds = true;
  180. $clubId = null;
  181. $realProductEntities = [];
  182. $tagIds = [];
  183. $landingPagePromoTagName = $this::SPECIAL_PROMO_PREFIX;
  184. if ($specialFlowPromotion instanceof PromotionEntity) {
  185. $isSpecialPromoFlow = true;
  186. $isLandingConsultant = $landingConfig && array_key_exists('landingType', $landingConfig) && $landingConfig['landingType'] == 'consultant';
  187. $isLandingBocconi = $landingConfig && array_key_exists('landingType', $landingConfig) && $landingConfig['landingType'] == 'bocconi';
  188. $isLandingSaltafila = $landingConfig && array_key_exists('landingType', $landingConfig) && $landingConfig['landingType'] == 'saltafila';
  189. if ($isLandingConsultant){
  190. $consultantId = $this->getConsultantId();
  191. if (!$consultantId){
  192. $this->redirectToHomepage();
  193. }
  194. list($centerId, $userId)= explode("p", $consultantId);
  195. $selectedClub = $this->clubService->getClubByExerpId($centerId, $salesChannelContext);
  196. $clubId = $selectedClub->getId();
  197. if ($clubId == null){
  198. $this->redirectToHomepage();
  199. }
  200. $this->session->set("consultantId", $consultantId);
  201. } else if ($isLandingSaltafila){
  202. $appointmentId = $this->getAppointmentId();
  203. $clubId = $this->getClubId();
  204. if (!$clubId){
  205. $this->redirectToHomepage();
  206. }
  207. $selectedClub = $this->clubService->getClubByExerpId($clubId, $salesChannelContext);
  208. $clubId = $selectedClub->getId();
  209. if ($clubId == null){
  210. $this->redirectToHomepage();
  211. }
  212. if ($appointmentId){
  213. $this->session->set("appointmentId", $appointmentId);
  214. }
  215. }
  216. else if (!empty($this->session->get('clubId'))) {
  217. //chatbot only
  218. $clubId = $this->session->get('clubId');
  219. $selectedClub = $this->clubService->getClubById($clubId, $salesChannelContext);
  220. } else {
  221. $selectedClub = $clubs ? reset($clubs) : $this->clubService->getDefaultClub($salesChannelContext);
  222. $clubId = $selectedClub->getId();
  223. }
  224. $clubName = $selectedClub->getName();
  225. $this->session->set('clubName', $clubName);
  226. $context->assign(["selectedClub" => $selectedClub]);
  227. $context->assign(["clubName" => $clubName]);
  228. $context->assign(["clubList" => $this->subscriptionsConfigurationService->getClubFacet($salesChannelContext)]);
  229. $context->assign(["showClubName" => $landingConfig && isset($landingConfig['showClubName']) ? $landingConfig['showClubName'] : false]);
  230. $landingPagePromoTagName = $this->getCurrentLandingPageSpecialPromoTagName();
  231. $tagIds = $this->getLandingPagePromoTagIds($context, $landingPagePromoTagName);
  232. if ($isLandingBocconi){
  233. $bocconiToken = $this->getBocconiToken();
  234. if (!$bocconiToken){
  235. $this->redirectToHomepage();
  236. }
  237. $bocconiUser = $this->getBocconiUserInfo($bocconiToken);
  238. if (!$bocconiUser){
  239. $this->redirectToHomepage();
  240. }
  241. $bocconiTagName = $bocconiUser['campaignCode'];
  242. if ($bocconiTagName){
  243. $criteria = new Criteria();
  244. $criteria->addFilter(new ContainsFilter('name', $bocconiTagName));
  245. $idTag = $this->tagRepository->searchIds($criteria, $context)->firstId();
  246. if ($idTag){
  247. array_unshift($tagIds, $idTag);
  248. }
  249. }
  250. }
  251. }
  252. if ($landingConfig && isset($landingConfig['landingSelectClubUrl'])){
  253. $context->assign(["landingSelectClubUrl" => $landingConfig['landingSelectClubUrl']]);
  254. }
  255. foreach ($virginCustomEntities as $entity){
  256. //get products assigned via editor
  257. // 1:1 relation entity:product
  258. // can be fake or real
  259. $productEntity = $this->productService->getProductById($entity->getConfig()['product']['value'], $salesChannelContext);
  260. if ($productEntity) {
  261. $productTagsArray = $productEntity->getTags()->getElements();
  262. if (count($productTagsArray) > 0) {
  263. $specialPromoFakeProductTag = reset($productTagsArray);
  264. $isDigitalProds = strpos($specialPromoFakeProductTag->getName(), self::SPECIAL_PROMO_TAG) === false;
  265. }
  266. if ($isDigitalProds) {
  267. $realProductEntities[] = $productEntity;
  268. }
  269. }
  270. }
  271. if ($isDigitalProds) {
  272. $this->session->set("isDigital", true);
  273. } else {
  274. $this->session->set("isDigital", false);
  275. }
  276. // i prodotti digitali non hanno tagsIds quindi è in or
  277. if (empty($realProductEntities) && $isSpecialPromoFlow) {
  278. $realProductEntities = $this->productService->getProductsByTags($clubId, $tagIds, $salesChannelContext);
  279. }
  280. $this->getProductBoxProducts(
  281. $realProductEntities,
  282. $landingPagePromoTagName,
  283. $salesChannelContext,
  284. $isSpecialPromoFlow,
  285. $specialFlowPromotion,
  286. $virginCustomEntities,
  287. $isDigitalProds
  288. );
  289. break;
  290. case self::VIRGIN_CMS_SLOT_ENTITY_TYPE_CLUB_SELECT_FORM:
  291. case self::VIRGIN_CMS_SLOT_ENTITY_TYPE_REGISTRATION_FORM:
  292. $entity = $virginCustomEntities[0];
  293. $entity->setCustomFields([
  294. 'clubs' => $clubs,
  295. 'landingCardsUrl' => $landingConfig['landingCardsUrl'] ?? '',
  296. 'landingSelectClubUrl' => $landingConfig['landingSelectClubUrl'] ?? '',
  297. ]);
  298. break;
  299. default:
  300. }
  301. }
  302. /**
  303. * @param Context $context
  304. * @return SalesChannelContext
  305. * @throws \JsonException
  306. */
  307. private function getSalesChannelContext(Context $context): SalesChannelContext
  308. {
  309. $criteria = new Criteria();
  310. $criteria
  311. ->addFilter(new EqualsFilter('typeId', Defaults::SALES_CHANNEL_TYPE_STOREFRONT))
  312. ->addFilter(new EqualsFilter('active', true));
  313. $salesChannelId = $this->salesChannelRepository->searchIds($criteria, $context)->firstId();
  314. return $this->cachedSalesChannelContextFactory->create(Uuid::randomHex(), $salesChannelId);
  315. }
  316. /**
  317. * @return string
  318. */
  319. private function getCurrentLandingPageSpecialPromoTagName(): string
  320. {
  321. if ($currentNavigationPageTags = $this->session->get('currentNavigationPageTags')) {
  322. /** @var TagEntity $landingPageTag */
  323. foreach ($currentNavigationPageTags->getElements() as $landingPageTag) {
  324. if (str_contains($landingPageTagName = $landingPageTag->getName(), self::SPECIAL_PROMO_PREFIX)) {
  325. return $landingPageTagName;
  326. }
  327. }
  328. }
  329. return "";
  330. }
  331. /**
  332. * ritorna true se la landing page ha il tag che la identifica per avere il blocco di configurazione
  333. * @return bool
  334. */
  335. public function isConfigLanding(): bool
  336. {
  337. if ($currentNavigationPageTags = $this->session->get('currentNavigationPageTags')) {
  338. /** @var TagEntity $tag */
  339. foreach ($currentNavigationPageTags->getElements() as $tag) {
  340. if (strcmp($tag->getName(), self::CONFIG_LANDING_TAG)===0) {
  341. return true;
  342. }
  343. }
  344. }
  345. return false;
  346. }
  347. /**
  348. * @param Context $context
  349. * @param string $landingPagePromoTagName
  350. * @return array
  351. */
  352. private function getLandingPagePromoTagIds(Context $context, string $landingPagePromoTagName): array
  353. {
  354. if (!$landingPagePromoTagName) return [];
  355. $criteria = new Criteria();
  356. $criteria->addFilter(new ContainsFilter('name', $landingPagePromoTagName . "_"));
  357. return $this->tagRepository->searchIds($criteria, $context)->getIds();
  358. }
  359. /**
  360. * @param string $landingPagePromoTagName
  361. * @param TagCollection $tags
  362. * @return int
  363. */
  364. private function getLandingPagePromoTagIndex(string $landingPagePromoTagName, TagCollection $tags): int
  365. {
  366. if ($landingPagePromoTagName) {
  367. foreach ($tags as $tag) {
  368. if (str_contains($tag->getName(), $landingPagePromoTagName) && count(explode('_', $tag->getName())) == 3)
  369. return (int)explode('_', $tag->getName())[2];
  370. }
  371. }
  372. return 0;
  373. }
  374. /**
  375. * @param array $realProductEntities
  376. * @param string $landingPagePromoTagName
  377. * @param SalesChannelContext $salesChannelContext
  378. * @param bool $isSpecialPromoFlow
  379. * @param PromotionEntity|null $specialFlowPromotion
  380. * @param $entities
  381. * @param bool $isDigitalProds
  382. * @throws Exception
  383. */
  384. public function getProductBoxProducts(array $realProductEntities, string $landingPagePromoTagName, SalesChannelContext $salesChannelContext, bool $isSpecialPromoFlow, ?PromotionEntity $specialFlowPromotion, $entities, $isDigitalProds): void
  385. {
  386. $products = [];
  387. /** @var ProductEntity $realProductEntity */
  388. foreach ($realProductEntities as $realProductEntity) {
  389. $index = $this->getLandingPagePromoTagIndex($landingPagePromoTagName, $realProductEntity->getTags());
  390. try {
  391. $type = $realProductEntity->getCustomFields()['virgin_exerp_type'];
  392. $prorataDate = (new DateTimeImmutable())->add(new DateInterval('PT0H'))->format('Y-m-d');
  393. if (array_key_exists("free_trial_days", $realProductEntity->getCustomFields())) {
  394. $prorataDate = (new DateTimeImmutable())->add(new DateInterval('PT' . ($realProductEntity->getCustomFields()['free_trial_days'] * 24) . 'H'))->format('Y-m-d');
  395. }
  396. $subReq = [
  397. 'campainCode' => '',
  398. 'centerId' => $realProductEntity->getCustomFields()['virgin_exerp_centerid'],
  399. 'clearingHouseType' => $this->restApiClient::CLEARING_HOUSE_EFT,
  400. 'personType' => $this->restApiClient::PERSONTYPE_PRIVATE,
  401. 'starDate' => $prorataDate,
  402. 'subscriptionId' => $realProductEntity->getCustomFields()['virgin_exerp_productid'],
  403. ];
  404. $response = $this->restApiClient->getSubscritionContractDetails($subReq);
  405. if ($type == "EFT") {
  406. $exerpPrice = $response->normalPeriodPrice ?? $realProductEntity->getPrice()->first()->getGross();
  407. }
  408. if ($type == "CASH") {
  409. $exerpPrice = $response->totalAmount ?? $realProductEntity->getPrice()->first()->getGross();
  410. }
  411. if ($type == "GIFTCARD") {
  412. $exerpPrice = $realProductEntity->getPrice()->first()->getGross();
  413. }
  414. $priceCollection = new PriceCollection();
  415. $priceEntity = new Price(
  416. Defaults::CURRENCY,
  417. (float) $exerpPrice,
  418. (float) $exerpPrice,
  419. $realProductEntity->getPrice()->getCurrencyPrice(Defaults::CURRENCY)->getLinked()
  420. );
  421. $priceCollection->add($priceEntity);
  422. $realProductEntity->setPrice($priceCollection);
  423. } catch (VirginApiException $e) {
  424. $isExerpDown = true;
  425. }
  426. $productCardInformation = $this->productService->getProductCardInformation($realProductEntity, $salesChannelContext);
  427. $products[] = [
  428. 'product' => $realProductEntity,
  429. 'position' => $index,
  430. 'config' => [
  431. 'promotion' => $isSpecialPromoFlow ? current($specialFlowPromotion->getExtension('virginPromotionAttributes')->getElements()) : null,
  432. 'prices' => $productCardInformation['prices'],
  433. 'productCardInformation' => $productCardInformation,
  434. 'workouts' => $productCardInformation['workouts'],
  435. 'services' => $productCardInformation['services'],
  436. 'directFlow' => isset($_SESSION['isDirectFlow']),
  437. 'exerpDown' => $isExerpDown ?? null
  438. ],
  439. 'productCardInformation' => $productCardInformation,
  440. ];
  441. }
  442. usort($products, static function (array $a, array $b) {
  443. return $a['position'] <=> $b['position'];
  444. });
  445. if ($isDigitalProds) {
  446. // se $isDigitalProds ogni entity avrà un solo array contente un solo product
  447. $products = array_values($products);
  448. foreach ($entities as $index => $entity) {
  449. $entity->getCustomFields() ? $entity->setCustomFields(
  450. array_merge(
  451. $entity->getCustomFields(),
  452. ['products' => [$products[$index]]])
  453. ) : $entity->setCustomFields(['products' => [$products[$index]]]);
  454. }
  455. } else {
  456. // altrimenti ogni entity avrà lo stesso array di prodotti
  457. foreach ($entities as $entity) {
  458. $entity->getCustomFields() ? $entity->setCustomFields(
  459. array_merge(
  460. $entity->getCustomFields(),
  461. ['products' => $products])
  462. ) : $entity->setCustomFields(['products' => $products]);
  463. }
  464. }
  465. }
  466. /**
  467. * @param $entities
  468. * @return array
  469. */
  470. public function getProductBoxEntities($entities): array
  471. {
  472. $prodBoxEntities = [];
  473. foreach ($entities as $entity) {
  474. if ($entity->getType() === self::VIRGIN_CMS_SLOT_ENTITY_TYPE_PRODUCT_BOX) {
  475. $prodBoxEntities[] = $entity;
  476. }
  477. }
  478. return $prodBoxEntities;
  479. }
  480. private function getConsultantId(){
  481. if (isset($_GET['id'])){
  482. $pattern = '/^\d{3}p[0-9]+$/i';
  483. if (preg_match($pattern, $_GET['id'])){
  484. return $_GET['id'];
  485. }
  486. }
  487. return null;
  488. }
  489. /**
  490. * @return mixed|null
  491. */
  492. private function getBocconiToken(): mixed
  493. {
  494. if ($this->session->has("bocconiToken")){
  495. $token = $this->session->get("bocconiToken");
  496. $pattern = '/[A-Za-z0-9]+/i';
  497. if (preg_match($pattern, $token)){
  498. return $token;
  499. }
  500. }
  501. return null;
  502. }
  503. /**
  504. * @param string $bocconiToken
  505. * @throws VirginApiException
  506. */
  507. public function getBocconiUserInfo(string $bocconiToken)
  508. {
  509. return $this->restApiClient->getBocconiLead($bocconiToken);
  510. }
  511. /**
  512. * @return mixed|null
  513. */
  514. private function getAppointmentId(){
  515. if (isset($_GET['appointmentId'])){
  516. return $_GET['appointmentId'];
  517. }
  518. return null;
  519. }
  520. /**
  521. * @return mixed|null
  522. */
  523. private function getClubId(){
  524. if (isset($_GET['clubId'])){
  525. $pattern = '/^\d{3}+$/i';
  526. if (preg_match($pattern, $_GET['clubId'])){
  527. return $_GET['clubId'];
  528. }
  529. }
  530. return null;
  531. }
  532. /**
  533. * @param EntityLoadedEvent $event
  534. * @return array|null
  535. */
  536. private function getLandingConfig(EntityLoadedEvent $event): ? array
  537. {
  538. $context = $event->getContext();
  539. $mapCallbackFunction = function ($el){
  540. return $el['value'];
  541. };
  542. //vedere su quale landing siamo tramite tag "config/cards"
  543. if ($this->isConfigLanding()){
  544. //retrieve della config
  545. foreach ($event->getEntities() as $entity){
  546. /** @var CmsSlotEntity $entity */
  547. if ($entity->getType()==="virgin-landing-config"){
  548. return array_map($mapCallbackFunction, $entity->getConfig());
  549. }
  550. }
  551. } else {
  552. //retrieve del tag della promo
  553. $landingPagePromoTagName = $this->getCurrentLandingPageSpecialPromoTagName();
  554. //tramite tag promo prendere trio di landing
  555. $cmsPageId = $this->getConfigCmsPageIdFromTag($landingPagePromoTagName, $context);
  556. //recuperare la config
  557. if ($cmsPageId){
  558. $slotId = $this->getConfigSlotId($cmsPageId);
  559. if ($slotId){
  560. return array_map($mapCallbackFunction, $this->cmsSlotTranslationRepository->search(
  561. (new Criteria())->addFilter(new EqualsFilter('cmsSlotId', $slotId), new EqualsFilter('languageId', $context->getLanguageId())),
  562. $context
  563. )->first()->getConfig());
  564. }
  565. }
  566. }
  567. return null;
  568. }
  569. /**
  570. * @return void
  571. */
  572. private function redirectToHomepage(): void
  573. {
  574. echo '
  575. <script type="text/javascript">
  576. window.location = "https://www.virginactive.it/"
  577. </script>';
  578. }
  579. /**
  580. * @param string $tag
  581. * @param Context $context
  582. * @return string|null
  583. */
  584. public function getConfigCmsPageIdFromTag(string $tag, Context $context): ? string
  585. {
  586. $criteria = new Criteria();
  587. $criteria->addFilter(new EqualsFilter('tags.name', $tag));
  588. $criteria->addFilter(new EqualsFilter('tags.name', self::CONFIG_LANDING_TAG));
  589. $category = $this->categoryRepository->search($criteria, $context)->first();
  590. return $category ? $category->getCmsPageId() : null;
  591. }
  592. /**
  593. * @param string $cmsPageId
  594. * @return string|boolean
  595. * @throws \Doctrine\DBAL\Exception
  596. * @throws \Doctrine\DBAL\Driver\Exception
  597. */
  598. private function getConfigSlotId(string $cmsPageId): bool|string
  599. {
  600. $builder = $this->connection->createQueryBuilder();
  601. return $builder->select(['LOWER(HEX(slot.id))'])
  602. ->from('cms_slot', 'slot')
  603. ->leftJoin('slot','cms_block','block','slot.cms_block_id = block.id')
  604. ->leftJoin('block','cms_section','section','block.cms_section_id = section.id')
  605. ->where('LOWER(HEX(section.cms_page_id)) = :cmsPageId')
  606. ->andWhere('slot.type = :type')
  607. ->setParameter('cmsPageId', $cmsPageId)
  608. ->setParameter('type', self::VIRGIN_CMS_SLOT_ENTITY_TYPE_LANDING_CONFIG)
  609. ->execute()
  610. ->fetchOne();
  611. }
  612. /**
  613. * @param EntityLoadedEvent $event
  614. * @return CmsSlotEntity[]
  615. */
  616. private function getVirginCustomEntities(EntityLoadedEvent $event): array
  617. {
  618. $entities = [];
  619. /** @var CmsSlotEntity $entity */
  620. foreach ($event->getEntities() as $entity) {
  621. if ($entity->getType() === self::VIRGIN_CMS_SLOT_ENTITY_TYPE_REGISTRATION_FORM ||
  622. $entity->getType() === self::VIRGIN_CMS_SLOT_ENTITY_TYPE_CLUB_SELECT_FORM ||
  623. $entity->getType() === self::VIRGIN_CMS_SLOT_ENTITY_TYPE_PRODUCT_BOX
  624. ) {
  625. $entities[] = $entity;
  626. }
  627. }
  628. return $entities;
  629. }
  630. }