<?php declare(strict_types=1);
namespace MageWorx\SeoCrosslinks\Subscriber;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\Content\Product\ProductEvents;
use Symfony\Component\HttpFoundation\RequestStack;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use MageWorx\SeoCrosslinks\Core\Content\Crosslink\Service\CrosslinkReplacer;
use MageWorx\SeoCrosslinks\Core\Content\Crosslink\Service\SalesChannelContextProvider;
class ProductSubscriber implements EventSubscriberInterface
{
protected RequestStack $requestStack;
protected SystemConfigService $systemConfig;
protected EntityRepositoryInterface $crosslinkRepository;
protected CrosslinkReplacer $replacer;
protected SalesChannelContextProvider $salesChannelContextProvider;
public function __construct(
EntityRepositoryInterface $crosslinkRepository,
SystemConfigService $systemConfigService,
RequestStack $requestStack,
CrosslinkReplacer $replacer,
SalesChannelContextProvider $salesChannelContextProvider
) {
$this->crosslinkRepository = $crosslinkRepository;
$this->requestStack = $requestStack;
$this->systemConfig = $systemConfigService;
$this->replacer = $replacer;
$this->salesChannelContextProvider = $salesChannelContextProvider;
}
public static function getSubscribedEvents(): array
{
return [
ProductEvents::PRODUCT_LOADED_EVENT => 'onProductsLoaded'
];
}
public function onProductsLoaded(EntityLoadedEvent $event)
{
if ($this->isAllow()) {
$id = $this->requestStack->getMainRequest()->attributes->get('productId');
$maxReplaceCount = (int)$this->systemConfig->get('MageWorxSeoCrosslinks.config.productMaxReplacementCount');
if ($maxReplaceCount) {
$product = current($event->getEntities());
if ($product && $product->getId() === $id) {
$translated = $product->getTranslated();
if ($translated) {
$description = $translated['description'];
$modifiedDescription = $this->getModifiedContent(
$description,
$product->getId(),
$event->getContext(),
$maxReplaceCount
);
if ($modifiedDescription) {
$translated['description'] = $modifiedDescription;
$product->setTranslated($translated);
}
}
}
}
}
}
protected function isAllow(): bool
{
if ($this->systemConfig->getBool('MageWorxSeoCrosslinks.config.enable')) {
$request = $this->requestStack->getMainRequest();
if ($request) {
$route = $request->attributes->get('_route');
$productId = $request->attributes->get('productId');
if ($route === 'frontend.detail.page' && $productId) {
return true;
}
}
}
return false;
}
/**
* @param string|null $content
* @param string $entityId
* @param Context $context
* @param int $maxCount
* @return false|string
*/
protected function getModifiedContent(
?string $content,
string $entityId,
Context $context,
int $maxCount
) {
if ($content === null) {
return $content;
}
$criteria = new Criteria();
$criteria->addFilter(
new EqualsFilter('isActive', true),
new EqualsFilter('inProduct', true),
new EqualsFilter('languageId', $context->getLanguageId()),
new EqualsFilter(
'salesChannels.salesChannelId',
$this->salesChannelContextProvider->getSalesChannelContext($context)->getSalesChannelId()
),
new NotFilter('AND', [
new EqualsFilter('internalLink', $entityId),
])
);
$criteria->addSorting(new FieldSorting('priority', 'DESC'));
$crosslinkCollection = $this->crosslinkRepository->search($criteria, $context)->getEntities();
return $this->replacer->replace($context, $crosslinkCollection, $content, $maxCount);
}
}