<?php declare(strict_types=1);
namespace Acris\ShopSwitch\Subscriber;
use Acris\ShopSwitch\Components\ShopSwitch\AbstractShopSwitchRoute;
use Acris\ShopSwitch\Components\ShopSwitch\ShopSwitchResult;
use Acris\ShopSwitch\Components\ShopSwitchCookieService;
use Acris\ShopSwitch\Custom\ShopSwitchRuleDefinition;
use Acris\ShopSwitch\Custom\ShopSwitchRuleEntity;
use Shopware\Core\Framework\Adapter\Cache\AbstractCacheTracer;
use Shopware\Core\Framework\Adapter\Cache\CacheValueCompressor;
use Shopware\Core\Framework\Struct\ArrayEntity;
use Shopware\Core\SalesChannelRequest;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Storefront\Pagelet\Header\HeaderPageletLoadedEvent;
use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Contracts\Cache\ItemInterface;
use Shopware\Core\Framework\Context;
use Symfony\Component\HttpFoundation\Request;
class ShopSwitchModalDataSubscriber implements EventSubscriberInterface
{
public const SHOP_SWITCH_MODAL_LOADED_AFTER = 'shopSwitchModalLoadedAfter';
private AbstractShopSwitchRoute $shopSwitchRoute;
private TagAwareAdapterInterface $cache;
private AbstractCacheTracer $tracer;
private SystemConfigService $configService;
private ShopSwitchCookieService $shopSwitchCookieService;
public function __construct(AbstractShopSwitchRoute $shopSwitchRoute, TagAwareAdapterInterface $cache, AbstractCacheTracer $tracer, SystemConfigService $configService, ShopSwitchCookieService $shopSwitchCookieService)
{
$this->shopSwitchRoute = $shopSwitchRoute;
$this->cache = $cache;
$this->tracer = $tracer;
$this->configService = $configService;
$this->shopSwitchCookieService = $shopSwitchCookieService;
}
public static function getSubscribedEvents()
{
return [
HeaderPageletLoadedEvent::class => 'onHeaderPageletLoaded',
];
}
public function onHeaderPageletLoaded(HeaderPageletLoadedEvent $event): void
{
if($this->configService->get('AcrisShopSwitchCS.config.loadShopSwitchModal', $event->getSalesChannelContext()->getSalesChannelId()) !== 'enableJs') {
return;
}
$salesChannelContext = $event->getSalesChannelContext();
if($salesChannelContext->hasExtension(ShopSwitchResult::MODAL_EXTENSION_KEY)) {
return;
}
$request = $event->getRequest();
$context = $event->getContext();
$activeDomainId = $request->get(SalesChannelRequest::ATTRIBUTE_DOMAIN_ID);
// do only if at the page the modal window is not loaded anymore
if($this->shopSwitchCookieService->isAlreadyConfigured($request, $activeDomainId) === false) {
return;
}
$currentShippingCountryIso = $salesChannelContext->getShippingLocation()->getCountry()->getIso();
$currentLanguageId = $salesChannelContext->getLanguageId();
$key = $this->generateKey($activeDomainId, $currentShippingCountryIso);
$shopSwitchResult = $this->getFromCache($key, $activeDomainId, $currentShippingCountryIso, $currentLanguageId, $request, $context);
if ($shopSwitchResult instanceof ShopSwitchResult) {
$shopSwitchResult->setLoadImmediately(false);
if($shopSwitchResult->getShopSwitchRuleEntity() instanceof ShopSwitchRuleEntity) {
$salesChannelContext->addExtension(ShopSwitchResult::MODAL_EXTENSION_KEY, $shopSwitchResult);
$salesChannelContext->addExtension(self::SHOP_SWITCH_MODAL_LOADED_AFTER, new ArrayEntity([]));
}
}
}
private function getFromCache($key, string $activeDomainId, string $currentShippingCountryIso, string $currentLanguageId, Request $request, Context $context): ?ShopSwitchResult
{
$value = $this->cache->get($key, function (ItemInterface $item) use ($activeDomainId, $currentShippingCountryIso, $currentLanguageId, $request, $context) {
$name = self::buildName($activeDomainId, $currentShippingCountryIso);
/** @var ShopSwitchResult $shopSwitchResult */
$shopSwitchResult = $this->tracer->trace($name, function () use ($activeDomainId, $currentShippingCountryIso, $currentLanguageId, $request, $context) {
return $this->shopSwitchRoute->load($activeDomainId, $request, $context, $currentLanguageId, $currentLanguageId, $currentShippingCountryIso)->getResult();
});
// only load configurations with switch type is modal
if($shopSwitchResult->getShopSwitchRuleEntity() instanceof ShopSwitchRuleEntity) {
if($shopSwitchResult->getShopSwitchRuleEntity()->getSwitchType() !== ShopSwitchRuleDefinition::SWITCH_TYPE_MODAL) {
$shopSwitchResult = null;
}
}
$item->tag($this->generateTags($activeDomainId, $currentShippingCountryIso));
return CacheValueCompressor::compress($shopSwitchResult);
});
return CacheValueCompressor::uncompress($value);
}
public static function buildName(string $activeDomainId, string $shippingCountryIso): string
{
return 'shop-switch-modal-data-' . $activeDomainId . '-' . $shippingCountryIso;
}
private function generateKey(string $activeDomainId, string $shippingCountryIso) {
return 'shop-switch-modal-data-' . $activeDomainId . '-' . $shippingCountryIso;
}
private function generateTags(string $activeDomainId, string $shippingCountryIso): array
{
$tags = array_merge(
$this->tracer->get(self::buildName($activeDomainId, $shippingCountryIso)),
[self::buildName($activeDomainId, $shippingCountryIso)],
[ShopSwitchCacheSubscriber::HEADER_CACHE_TAG],
['sales-channel'],
['sales-channel-context'],
['navigation']
);
return array_unique($tags);
}
}