custom/plugins/MageWorxSeoCrosslinks/src/Subscriber/LandingPageSubscriber.php line 54

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace MageWorx\SeoCrosslinks\Subscriber;
  3. use MageWorx\SeoCrosslinks\Core\Content\Crosslink\Service\SalesChannelContextProvider;
  4. use Shopware\Core\Content\Cms\Aggregate\CmsBlock\CmsBlockEntity;
  5. use Shopware\Core\Content\Cms\CmsPageEntity;
  6. use Shopware\Core\Framework\Context;
  7. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  9. use Shopware\Storefront\Page\LandingPage\LandingPage;
  10. use Shopware\Storefront\Page\LandingPage\LandingPageLoadedEvent;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
  14. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  15. use Symfony\Component\HttpFoundation\RequestStack;
  16. use Shopware\Core\System\SystemConfig\SystemConfigService;
  17. use MageWorx\SeoCrosslinks\Core\Content\Crosslink\Service\CrosslinkReplacer;
  18. class LandingPageSubscriber implements EventSubscriberInterface
  19. {
  20.     protected RequestStack $requestStack;
  21.     protected SystemConfigService $systemConfig;
  22.     protected EntityRepositoryInterface $crosslinkRepository;
  23.     protected CrosslinkReplacer $replacer;
  24.     private SalesChannelContextProvider $salesChannelContextProvider;
  25.     public function __construct(
  26.         EntityRepositoryInterface $crosslinkRepository,
  27.         SystemConfigService $systemConfigService,
  28.         RequestStack $requestStack,
  29.         CrosslinkReplacer $replacer,
  30.         SalesChannelContextProvider $salesChannelContextProvider
  31.     ) {
  32.         $this->crosslinkRepository $crosslinkRepository;
  33.         $this->requestStack $requestStack;
  34.         $this->systemConfig $systemConfigService;
  35.         $this->replacer $replacer;
  36.         $this->salesChannelContextProvider $salesChannelContextProvider;
  37.     }
  38.     public static function getSubscribedEvents(): array
  39.     {
  40.         return [
  41.             LandingPageLoadedEvent::class => 'onLandingPagesLoaded'
  42.         ];
  43.     }
  44.     public function onLandingPagesLoaded($event)
  45.     {
  46.         if (!$this->isAllow()) {
  47.             return;
  48.         }
  49.         $maxReplaceCount $this->systemConfig->getInt('MageWorxSeoCrosslinks.config.pageMaxReplacementCount');
  50.         if ($maxReplaceCount === 0) {
  51.             return;
  52.         }
  53.         $landingPageId $this->requestStack->getMainRequest()->attributes->get('landingPageId');
  54.         /** @var LandingPage $page */
  55.         $page $event->getPage();
  56.         if ($page) {
  57.             $cmsPage $page->getCmsPage();
  58.             if ($cmsPage) {
  59.                 $pairs $this->composePairs($cmsPage);
  60.                 if ($pairs) {
  61.                     $content $this->compactParts($pairs);
  62.                     $modContent $this->getModifiedContent(
  63.                         $content,
  64.                         $landingPageId,
  65.                         $event->getContext(),
  66.                         $maxReplaceCount
  67.                     );
  68.                     if ($modContent) {
  69.                         $pairs $this->extractParts($modContent$pairs);
  70.                         $this->applyPairs($cmsPage$pairs);
  71.                     }
  72.                 }
  73.             }
  74.         }
  75.     }
  76.     protected function composePairs($cmsPage): array
  77.     {
  78.         $pairs = [];
  79.         if ($cmsPage->getSections()) {
  80.             foreach ($cmsPage->getSections()->getElements() as $cmsSectionEntity) {
  81.                 if ($cmsSectionEntity->getBlocks()) {
  82.                     /** @var CmsBlockEntity $cmsBlock */
  83.                     foreach ($cmsSectionEntity->getBlocks()->getElements() as $cmsBlock) {
  84.                         if ($cmsBlock->getSlots()) {
  85.                             foreach ($cmsBlock->getSlots() as $slotId => $slot) {
  86.                                 if ($slot->getData() && $slot->getData()->getContent()) {
  87.                                     $pairs[$slotId] = $slot->getData()->getContent();
  88.                                 }
  89.                             }
  90.                         }
  91.                     }
  92.                 }
  93.             }
  94.         }
  95.         return $pairs;
  96.     }
  97.     protected function applyPairs(CmsPageEntity $cmsPage, array $pairs): void
  98.     {
  99.         if ($cmsPage->getSections()) {
  100.             foreach ($cmsPage->getSections()->getElements() as $cmsSectionEntity) {
  101.                 if ($cmsSectionEntity->getBlocks()) {
  102.                     /** @var CmsBlockEntity $cmsBlock */
  103.                     foreach ($cmsSectionEntity->getBlocks()->getElements() as $cmsBlock) {
  104.                         if ($cmsBlock->getSlots()) {
  105.                             foreach ($cmsBlock->getSlots() as $slotId => $slot) {
  106.                                 if (!array_key_exists($slotId$pairs)) {
  107.                                     continue;
  108.                                 }
  109.                                 $slot->getData()->setContent($pairs[$slotId]);
  110.                             }
  111.                         }
  112.                     }
  113.                 }
  114.             }
  115.         }
  116.     }
  117.     /**
  118.      * @param array $pairs
  119.      * @return string
  120.      */
  121.     protected function compactParts(array $pairs): string
  122.     {
  123.         $result '';
  124.         $firstFlag true;
  125.         foreach ($pairs as $id => $content) {
  126.             if (!$firstFlag) {
  127.                 $result .= $id;
  128.             }
  129.             $result .= $content;
  130.             $firstFlag false;
  131.         }
  132.         return $result;
  133.     }
  134.     protected function extractParts(string $content, array $pairs): array
  135.     {
  136.         $regexp "/" implode('|'array_keys($pairs)) . "/";
  137.         $parts preg_split($regexp$content);
  138.         return array_combine(array_keys($pairs), $parts);
  139.     }
  140.     protected function isAllow(): bool
  141.     {
  142.         if ($this->systemConfig->getBool('MageWorxSeoCrosslinks.config.enable')) {
  143.             $request $this->requestStack->getMainRequest();
  144.             if ($request) {
  145.                 $route $request->attributes->get('_route');
  146.                 $landingPageId $request->attributes->get('landingPageId');
  147.                 if ($route === 'frontend.landing.page' && $landingPageId) {
  148.                     return true;
  149.                 }
  150.             }
  151.         }
  152.         return false;
  153.     }
  154.     /**
  155.      * @param string $content
  156.      * @param string $entityId
  157.      * @param Context $context
  158.      * @param int $maxCount
  159.      * @return false|string
  160.      */
  161.     protected function getModifiedContent(
  162.         string $content,
  163.         string $entityId,
  164.         Context $context,
  165.         int $maxCount
  166.     ) {
  167.         $criteria = new Criteria();
  168.         $criteria->addFilter(
  169.             new EqualsFilter('isActive'true),
  170.             new EqualsFilter('inCmsPage'true),
  171.             new EqualsFilter('languageId'$context->getLanguageId()),
  172.             new EqualsFilter(
  173.                 'salesChannels.salesChannelId',
  174.                 $this->salesChannelContextProvider->getSalesChannelContext($context)->getSalesChannelId()
  175.             ),
  176.             new NotFilter('AND', [
  177.                 new EqualsFilter('internalLink'$entityId),
  178.             ]),
  179.         );
  180.         $criteria->addSorting(new FieldSorting('priority''DESC'));
  181.         $crosslinkCollection $this->crosslinkRepository->search($criteria$context)->getEntities();
  182.         return $this->replacer->replace($context$crosslinkCollection$content$maxCount);
  183.     }
  184. }