<?php declare(strict_types=1);
namespace Ott\MerchantShops\Subscriber;
use Ott\MerchantShops\Gateway\MerchantGateway;
use Shopware\Core\Checkout\Order\SalesChannel\OrderService;
use Shopware\Core\Content\Seo\SeoUrlPlaceholderHandlerInterface;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\Struct\ArrayEntity;
use Shopware\Core\Framework\Struct\ArrayStruct;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Framework\Routing\RequestTransformer;
use Shopware\Storefront\Page\GenericPageLoadedEvent;
use Shopware\Storefront\Page\Navigation\NavigationPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class PageSubscriber implements EventSubscriberInterface
{
private MerchantGateway $merchantGateway;
private SeoUrlPlaceholderHandlerInterface $seoUrlPlaceholderHandler;
private EntityRepositoryInterface $mediaRepository;
public function __construct(
MerchantGateway $merchantGateway,
SeoUrlPlaceholderHandlerInterface $seoUrlPlaceholderHandler,
EntityRepositoryInterface $mediaRepository
)
{
$this->merchantGateway = $merchantGateway;
$this->seoUrlPlaceholderHandler = $seoUrlPlaceholderHandler;
$this->mediaRepository = $mediaRepository;
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::RESPONSE => 'onResponse',
NavigationPageLoadedEvent::class => 'onNavigationPageLoadedEvent',
GenericPageLoadedEvent::class => 'onGenericPageLoadedEvent',
];
}
public function onResponse(ResponseEvent $event): void
{
$allowedAncestors = [
'staging.taschen24.de',
'stackoverflow.com',
];
$event->getResponse()->headers->set('x-frame-options', 'ALLOW-FROM *');
$event->getResponse()->headers->set(
'Content-Security-Policy',
'frame-ancestors *'
);
}
public function onNavigationPageLoadedEvent(NavigationPageLoadedEvent $event): void
{
$affiliateCode = $event->getRequest()->get('affiliateCode', null);
if (!empty($affiliateCode)) {
return;
}
$navigationId = $event->getPage()->getNavigationId();
$merchantId = $this->merchantGateway->getCategoryMerchantId(
$navigationId,
$event->getSalesChannelContext()->getLanguageId()
);
if (empty($merchantId)) {
return;
}
$merchantNumber = $this->merchantGateway->getMerchantNumber($merchantId);
if (empty($merchantNumber)) {
return;
}
$navigationUrl = $this->getNavigationUrlById(
$navigationId,
$event->getSalesChannelContext(),
$event->getRequest()->attributes->get(RequestTransformer::STOREFRONT_URL)
);
$navigationUrl .= '?affiliateCode=' . $merchantNumber;
$isIframe = $event->getRequest()->get('isIframe', null);
if (!empty($isIframe)) {
$navigationUrl .= '&isIframe=1';
}
$response = new RedirectResponse($navigationUrl);
$response->send();
}
public function onGenericPageLoadedEvent(GenericPageLoadedEvent $event): void
{
$route = $event->getRequest()->attributes->get('_route');
$merchantId = $event->getRequest()->getSession()->get(OrderService::AFFILIATE_CODE_KEY);
if (
'frontend.home.page' === $route
|| 'frontend.landing.page' === $route
|| 'frontend.navigation.page' === $route
|| 'frontend.detail.page' === $route
) {
$merchantId = $event->getRequest()->get('affiliateCode');
}
if (empty($merchantId)) {
$event->getRequest()->getSession()->remove(OrderService::AFFILIATE_CODE_KEY);
return;
}
$merchant = $this->merchantGateway->getMerchantByNumber($merchantId);
if (empty($merchant)) {
$event->getRequest()->getSession()->remove(OrderService::AFFILIATE_CODE_KEY);
return;
}
$merchantCategory = $this->merchantGateway->getMerchantCategory($merchant['id']);
if (!empty($merchantCategory)) {
$merchant['categoryId'] = $merchantCategory;
}
$mediaIds = [];
if (null !== $merchant['logo']) {
$mediaIds[] = $merchant['logo'];
}
if (null !== $merchant['contactImage']) {
$mediaIds[] = $merchant['contactImage'];
}
if (!empty($mediaIds)) {
$criteria = new Criteria($mediaIds);
$mediaCollection = $this->mediaRepository
->search($criteria, $event->getContext())
->getEntities()
;
foreach ($mediaCollection as $mediaId => $media) {
if ($mediaId === $merchant['logo']) {
$merchant['logo'] = $media->getUrl();
} elseif ($mediaId === $merchant['contactImage']) {
$merchant['contactImage'] = $media->getUrl();
}
}
}
$event->getPage()->addExtension('ottMerchantShopsData', new ArrayStruct([
'merchant' => new ArrayEntity($merchant),
]));
}
private function getNavigationUrlById(
string $navigationId,
SalesChannelContext $salesChannelContext,
string $host
): string
{
return $this->seoUrlPlaceholderHandler->replace(
$this->seoUrlPlaceholderHandler->generate('frontend.navigation.page', ['navigationId' => $navigationId]),
$host,
$salesChannelContext
);
}
}