<?php declare(strict_types=1);
namespace Shopware\Core\Checkout\Customer\Subscriber;
use Shopware\Core\Checkout\Customer\CustomerEvents;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityDeletedEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Shopware\Core\PlatformRequest;
use Shopware\Core\System\SalesChannel\Context\SalesChannelContextPersister;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
class CustomerTokenSubscriber implements EventSubscriberInterface
{
/**
* @var SalesChannelContextPersister
*/
private $contextPersister;
/**
* @var RequestStack
*/
private $requestStack;
public function __construct(
SalesChannelContextPersister $contextPersister,
RequestStack $requestStack
) {
$this->contextPersister = $contextPersister;
$this->requestStack = $requestStack;
}
public static function getSubscribedEvents()
{
return [
CustomerEvents::CUSTOMER_WRITTEN_EVENT => 'onCustomerWritten',
CustomerEvents::CUSTOMER_DELETED_EVENT => 'onCustomerDeleted',
];
}
public function onCustomerWritten(EntityWrittenEvent $event): void
{
$master = $this->requestStack->getMasterRequest();
if (!$master) {
return;
}
if (!$master->attributes->has(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_CONTEXT_OBJECT)) {
return;
}
/** @var SalesChannelContext $context */
$context = $master->attributes->get(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_CONTEXT_OBJECT);
$token = $context->getToken();
$payloads = $event->getPayloads();
foreach ($payloads as $payload) {
if ($this->customerCredentialsChanged($payload)) {
$newToken = $this->contextPersister->replace($token, $context);
$context->assign([
'token' => $newToken,
]);
if (!$master->hasSession()) {
return;
}
$session = $master->getSession();
$session->migrate();
$session->set('sessionId', $session->getId());
$session->set(PlatformRequest::HEADER_CONTEXT_TOKEN, $newToken);
$master->headers->set(PlatformRequest::HEADER_CONTEXT_TOKEN, $newToken);
return;
}
}
}
public function onCustomerDeleted(EntityDeletedEvent $event): void
{
$master = $this->requestStack->getMasterRequest();
if (!$master) {
return;
}
$customerIds = $event->getIds();
foreach ($customerIds as $customerId) {
$this->contextPersister->revokeAllCustomerTokens($customerId);
}
}
private function customerCredentialsChanged(array $payload): bool
{
return isset($payload['password']);
}
}