<?php declare(strict_types=1);
namespace Webcellent\InternalLinks\Subscriber;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Webcellent\InternalLinks\Entity\InternalLinksEntity;
class ProductDetailPageSubscriber implements EventSubscriberInterface
{
private EntityRepository $linkRepository;
public function __construct(EntityRepository $linkRepository) {
$this->linkRepository = $linkRepository;
}
public static function getSubscribedEvents(): array {
return [
ProductPageLoadedEvent::class => "onProductPageLoaded"
];
}
public function onProductPageLoaded(ProductPageLoadedEvent $event) {
$salesChannel = $event->getSalesChannelContext()->getSalesChannelId();
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('salesChannelId', $salesChannel));
$internalLinks = $this->linkRepository->search($criteria, $event->getContext());
/**
* Convert $internalLinks to array,
* sort it by keyword length so longer keywords are processed first
*/
$internalLinks = iterator_to_array($internalLinks);
usort($internalLinks, function($link1, $link2) {
return strlen($link2->getKeyword()) >= strlen($link1->getKeyword());
});
$content = $event->getPage()->getProduct()->getTranslation('description');
foreach ($internalLinks as $internalLink) {
$keyword = strtolower($internalLink->getKeyword());
$linkInHeadings = $internalLink->getLinkInHeadings();
$currentURLs = [
((array_key_exists('HTTPS', $_SERVER) && $_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
str_replace('www.', '', ((array_key_exists('HTTPS', $_SERVER) && $_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']),
$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
str_replace('www.', '', $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'])
];
// skip internal link if currently on to be linked page
if (in_array($internalLink->getLink(), $currentURLs)) {
continue;
}
$limit = $internalLink->getMaxLinks();
if (!is_int($limit) || $limit < -1) {
$limit = 1;
}
if ($limit <= 0) {
$limit = 10000;
}
$content = preg_replace('/\b(' . $keyword . ')(?![^<]*<\/a>)' . ($linkInHeadings ? '' : '(?![^<]*<\/h1>)(?![^<]*<\/h2>)(?![^<]*<\/h3>)(?![^<]*<\/h4>)') . '\b/i', $this->generateReplacement($internalLink, "$1"), $content, $limit, $count);
}
$content = str_replace(['&wctlt;', '&wctgt;'], ['<', '>'], $content);
$event->getPage()->getProduct()->setDescription($content);
}
private function generateReplacement(InternalLinksEntity $internalLink, string $originalContent) {
$tag = '&wctlt;a href="' . $internalLink->getLink() . '" id=' . $internalLink->getId() . ' webcellent-internal-link=true class="internal-link ' . $internalLink->getClasses() . '"';
if ($internalLink->isOpenInNewTab()) {
$tag .= 'target="_blank" rel="noreferrer"';
}
if ($internalLink->getTitle()) {
$tag .= ' title="' . $internalLink->getTitle(). '"&wctgt;' . $originalContent . '&wctlt;/a&wctgt;';
} else {
$tag .= '&wctgt;' . $originalContent . '&wctlt;/a&wctgt;';
}
return $tag;
}
}