custom/plugins/WebcellentInternalLinks/src/Subscriber/StorefrontSubscriber.php line 43

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Webcellent\InternalLinks\Subscriber;
  3. use Shopware\Core\Content\Cms\CmsPageEntity;
  4. use Shopware\Core\Content\Cms\Events\CmsPageLoadedEvent;
  5. use Shopware\Core\Content\Cms\SalesChannel\Struct\TextStruct;
  6. use Shopware\Core\Content\Cms\SalesChannel\Struct\ProductDescriptionReviewsStruct;
  7. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
  11. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  12. use Webcellent\InternalLinks\Entity\InternalLinksEntity;
  13. class StorefrontSubscriber implements EventSubscriberInterface {
  14.     private EntityRepository $linkRepository;
  15.     public function __construct(EntityRepository $linkRepository) {
  16.         $this->linkRepository $linkRepository;
  17.     }
  18.     public static function getSubscribedEvents(): array {
  19.         return [
  20.             CmsPageLoadedEvent::class => 'onPageLoadedEvent'
  21.         ];
  22.     }
  23.     public function onPageLoadedEvent(CmsPageLoadedEvent $event) {
  24.         $cmsCollection $event->getResult();
  25.         $salesChannel $event->getSalesChannelContext()->getSalesChannelId();
  26.         $criteria = new Criteria();
  27.         $criteria->addFilter(new EqualsFilter('salesChannelId'$salesChannel))->addSorting(new FieldSorting('updatedAt'FieldSorting::ASCENDING));
  28.         $internalLinks $this->linkRepository->search($criteria$event->getContext());
  29.         /**
  30.          * Convert $internalLinks to array,
  31.          * sort it by keyword length so longer keywords are processed first
  32.          */
  33.         $internalLinks iterator_to_array($internalLinks);
  34.         usort($internalLinks, function($link1$link2) {
  35.             return strlen($link2->getKeyword()) >= strlen($link1->getKeyword());
  36.         });
  37.         $alreadyReplaced = array();
  38.         /** @var CmsPageEntity $cmsEntity */
  39.         foreach ($cmsCollection as $cmsEntity) {
  40.             $sections $cmsEntity->getSections();
  41.             foreach ($sections as $section) {
  42.                 $blocks $section->getBlocks();
  43.                 foreach ($blocks as $block) {
  44.                     $slots $block->getSlots();
  45.                     foreach ($slots as $slot) {
  46.                         $data $slot->getData();
  47.                         if ($data instanceof TextStruct) {
  48.                             $content $data->getContent();
  49.                             /** @var InternalLinksEntity $keyword */
  50.                             foreach ($internalLinks as $internalLink) {
  51.                                 $keyword strtolower($internalLink->getKeyword());
  52.                                 $linkInHeadings $internalLink->getLinkInHeadings();
  53.                                 $currentURLs = [
  54.                                     ((array_key_exists('HTTPS'$_SERVER) && $_SERVER['HTTPS'] == 'on') ? 'https://' 'http://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
  55.                                     str_replace('www.''', ((array_key_exists('HTTPS'$_SERVER) && $_SERVER['HTTPS'] == 'on') ? 'https://' 'http://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']),
  56.                                     $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
  57.                                     str_replace('www.'''$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'])
  58.                                 ];
  59.                                 // skip internal link if currently on to be linked page
  60.                                 if (in_array($internalLink->getLink(), $currentURLs)) {
  61.                                     continue;
  62.                                 }
  63.                                 $limit $internalLink->getMaxLinks();
  64.                                 if (!is_int($limit) || $limit < -1) {
  65.                                     $limit 1;
  66.                                 }
  67.                                 if ($limit <= 0) {
  68.                                     $limit 10000;
  69.                                 }
  70.                                 if (!in_array($keyword$alreadyReplaced)) {
  71.                                     $content preg_replace('/\b(' $keyword ')(?![^<]*<\/a>)' . ($linkInHeadings '' '(?![^<]*<\/h1>)(?![^<]*<\/h2>)(?![^<]*<\/h3>)(?![^<]*<\/h4>)') . '\b/i'$this->generateReplacement($internalLink"$1"), $content$limit$count);
  72.                                     if ($count >= $limit) {
  73.                                         $alreadyReplaced[] = $keyword;
  74.                                     }
  75.                                 }
  76.                             }
  77.                             $content str_replace(['&wctlt;''&wctgt;'], ['<''>'], $content);
  78.                             $data->setContent($content);
  79.                         } elseif ($data instanceof ProductDescriptionReviewsStruct) {
  80.                             $product $data->getProduct();
  81.                             $content $product->getTranslation('description');
  82.                             foreach ($internalLinks as $internalLink) {
  83.                                 $keyword strtolower($internalLink->getKeyword());
  84.                                 $linkInHeadings $internalLink->getLinkInHeadings();
  85.                                 $currentURLs = [
  86.                                     ((array_key_exists('HTTPS'$_SERVER) && $_SERVER['HTTPS'] == 'on') ? 'https://' 'http://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
  87.                                     str_replace('www.''', ((array_key_exists('HTTPS'$_SERVER) && $_SERVER['HTTPS'] == 'on') ? 'https://' 'http://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']),
  88.                                     $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
  89.                                     str_replace('www.'''$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'])
  90.                                 ];
  91.                                 // skip internal link if currently on to be linked page
  92.                                 if (in_array($internalLink->getLink(), $currentURLs)) {
  93.                                     continue;
  94.                                 }
  95.                                 $limit $internalLink->getMaxLinks();
  96.                                 if (!is_int($limit) || $limit < -1) {
  97.                                     $limit 1;
  98.                                 }
  99.                                 if ($limit <= 0) {
  100.                                     $limit 10000;
  101.                                 }
  102.                                 $content preg_replace('/\b(' $keyword ')(?![^<]*<\/a>)' . ($linkInHeadings '' '(?![^<]*<\/h1>)(?![^<]*<\/h2>)(?![^<]*<\/h3>)(?![^<]*<\/h4>)') . '\b/i'$this->generateReplacement($internalLink"$1"), $content$limit$count);
  103.                                 if ($count >= $limit) {
  104.                                     $alreadyReplaced[] = $keyword;
  105.                                 }
  106.                             }
  107.                             $content str_replace(['&wctlt;''&wctgt;'], ['<''>'], $content);
  108.                             $product->setDescription($content);
  109.                             $product->addTranslated('description'$content);
  110.                             $data->setProduct($product);
  111.                         }
  112.                     }
  113.                 }
  114.             }
  115.         }
  116.     }
  117.     private function generateReplacement(InternalLinksEntity $internalLinkstring $originalContent) {
  118.         $tag '&wctlt;a href="' $internalLink->getLink() . '" id=' $internalLink->getId() . ' webcellent-internal-link=true class="internal-link ' $internalLink->getClasses() . '"';
  119.         if ($internalLink->isOpenInNewTab()) {
  120.             $tag .= ' target="_blank" rel="noreferrer"';
  121.         }
  122.         if ($internalLink->getTitle()) {
  123.             $tag .= ' title="' $internalLink->getTitle() . '"&wctgt;' $originalContent '&wctlt;/a&wctgt;';
  124.         } else {
  125.             $tag .= '&wctgt;' $originalContent '&wctlt;/a&wctgt;';
  126.         }
  127.         return $tag;
  128.     }
  129. }