<?php declare(strict_types=1);
namespace CioRedirectWriter\Subscriber;
use Shopware\Core\Content\Product\ProductEntity;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Event\BeforeSendResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
class RedirectSubscriber implements EventSubscriberInterface
{
private EntityRepositoryInterface $productRepository;
private EntityRepositoryInterface $scopRedirectRepository;
private Context $context;
public function __construct
(
EntityRepositoryInterface $productRepository,
EntityRepositoryInterface $scopRedirectRepository
)
{
$this->productRepository = $productRepository;
$this->scopRedirectRepository = $scopRedirectRepository;
$this->context = Context::createDefaultContext();
}
public static function getSubscribedEvents(): array
{
return [
BeforeSendResponseEvent::class => 'onCmsPageLoaded'
];
}
public function onCmsPageLoaded(BeforeSendResponseEvent $event): void
{
if ($event->getResponse()->getStatusCode() != 404) {
return;
}
$requestUrl = $event->getRequest()->attributes->get('sw-original-request-uri');
$storefrontUrl = $event->getRequest()->attributes->get('sw-storefront-uri');
$urlParts = explode('/', trim($requestUrl, '/'));
$locale = $urlParts[0];
$productNumber = end($urlParts);
$product = $this->getProductByProductNumber($productNumber);
if ($locale == 'en') {
$language = 'English';
} else {
$language = 'Deutsch';
}
$newUrl = null;
if ($product) {
$seoUrls = $product->getSeoUrls();
foreach ($seoUrls as $seoUrl) {
if ($seoUrl->getLanguage()->getName() == $language) {
$newUrl = $seoUrl->getSeoPathInfo();
}
}
} else {
return;
}
if (is_null($newUrl)) {
return;
}
if ($locale == 'en') {
$newUrl = "/en/$newUrl";
}
if ($requestUrl === $newUrl) {
return;
}
$this->handleRedirect($requestUrl, $newUrl, $storefrontUrl, $event);
}
public function handleRedirect($requestUrl, $newUrl, $host, $event)
{
$this->saveNewRedirect($requestUrl, $newUrl);
$redirectUrl = $host . $newUrl;
$event->setResponse(new RedirectResponse($redirectUrl, 301));
}
/**
* @param string $productNumber
* @return ProductEntity|null
*/
private function getProductByProductNumber(string $productNumber): ?ProductEntity
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('productNumber', $productNumber));
$criteria->addAssociation('seoUrls');
$criteria->addAssociation('seoUrls.language');
$res = $this->productRepository->search($criteria, $this->context);
return $res->first() instanceof ProductEntity ?
$res->first() :
null;
}
private function saveNewRedirect(string $requestUrl, string $newUrl): void
{
$data = [];
$data[] = [
'sourceURL' => $requestUrl,
'targetURL' => $newUrl,
'httpCode' => 301,
'enabled' => true,
'ignoreQueryParams' => true
];
$this->scopRedirectRepository->create($data, $this->context);
}
}