<?php declare(strict_types=1);
namespace Hemo\CustomerGroupRestriction\Subscriber;
use Shopware\Core\PlatformRequest;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Framework\Cache\Event\HttpCacheGenerateKeyEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* The storefront HTTP cache key only contains rule ids, currency, version and the logged-in
* state. Two logged-in customers from different customer groups would therefore share cached
* pages. This subscriber stores the customer group in a cookie and mixes it into the cache key.
*/
final class HttpCacheCustomerGroupSubscriber implements EventSubscriberInterface
{
public const COOKIE_NAME = 'hemo-customer-group';
public static function getSubscribedEvents(): array
{
return [
KernelEvents::RESPONSE => 'onResponse',
HttpCacheGenerateKeyEvent::class => 'onGenerateKey',
];
}
public function onResponse(ResponseEvent $event): void
{
if (!$event->isMainRequest()) {
return;
}
$request = $event->getRequest();
$scopes = $request->attributes->get(PlatformRequest::ATTRIBUTE_ROUTE_SCOPE, []);
if (!\is_array($scopes) || !\in_array('storefront', $scopes, true)) {
return;
}
$context = $request->attributes->get(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_CONTEXT_OBJECT);
if (!$context instanceof SalesChannelContext) {
return;
}
$customerGroupId = $context->getCurrentCustomerGroup()->getId();
if ($request->cookies->get(self::COOKIE_NAME) === $customerGroupId) {
return;
}
$cookie = Cookie::create(self::COOKIE_NAME, $customerGroupId);
$cookie->setSecureDefault($request->isSecure());
$event->getResponse()->headers->setCookie($cookie);
}
public function onGenerateKey(HttpCacheGenerateKeyEvent $event): void
{
$customerGroupId = $event->getRequest()->cookies->get(self::COOKIE_NAME);
if (!\is_string($customerGroupId) || $customerGroupId === '') {
return;
}
$event->setHash(hash('sha256', $event->getHash() . '-' . $customerGroupId));
}
}