<?php declare(strict_types=1);
/**
* dk communications
* Copyright (c) 2025.
*
* All rights reserved.
*
*/
namespace Valantic\Bundle\PentagastBundle\Subscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\RouterInterface;
use Shopware\Core\PlatformRequest;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\System\SalesChannel\Context\SalesChannelContextService;
use Shopware\Core\System\SalesChannel\Context\SalesChannelContextServiceParameters;
use Valantic\Bundle\PentagastBundle\Service\ShopFeaturesService;
class VatIdCheckoutSubscriber implements EventSubscriberInterface
{
public function __construct(
private readonly ShopFeaturesService $shopFeaturesService,
private readonly RouterInterface $router,
private readonly RequestStack $requestStack,
private readonly SalesChannelContextService $scContextService
) {}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::CONTROLLER => ['onController', 0],
];
}
public function onController(ControllerEvent $event): void
{
// nur Haupt-Request
if (method_exists($event, 'isMainRequest')) {
if (!$event->isMainRequest()) { return; }
} elseif (method_exists($event, 'isMasterRequest') && !$event->isMasterRequest()) {
return;
}
$request = $event->getRequest();
$route = (string) ($request->attributes->get('_route') ?? '');
// nur relevante Checkout-Routen
$guardedRoutes = [
'frontend.checkout.confirm.page',
'frontend.checkout.order.place',
];
if (!\in_array($route, $guardedRoutes, true)) {
return;
}
// SalesChannelContext aus Request oder via Fallback rekonstruieren
/** @var SalesChannelContext|null $scContext */
$scContext = $request->attributes->get(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_CONTEXT_OBJECT);
if (!$scContext instanceof SalesChannelContext) {
$salesChannelId = (string) ($request->attributes->get(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_ID) ?? '');
$token = (string) ($request->headers->get(PlatformRequest::HEADER_CONTEXT_TOKEN)
?? $request->cookies->get(PlatformRequest::COOKIE_CONTEXT_TOKEN)
?? '');
if ($salesChannelId && $token) {
try {
$params = new SalesChannelContextServiceParameters($salesChannelId, $token);
$scContext = $this->scContextService->get($params);
} catch (\Throwable) {
return;
}
} else {
return;
}
}
// Feature am Verkaufskanal aktiv?
if (!$this->shopFeaturesService->vatIdRequiredForCheckout($scContext)) {
return;
}
// Kunde & VAT-ID check
$customer = $scContext->getCustomer();
if (!$customer || $this->shopFeaturesService->customerHasVatId($customer)) {
return;
}
// blockieren & zum Profil leiten
$this->flash(
'danger',
'Für diesen Shop ist die Angabe einer Umsatzsteuer-ID für den Kauf verpflichtend. Bitte ergänzen Sie die Umsatzsteuer-ID in Ihrem Profil.'
);
$profileUrl = $this->router->generate('frontend.account.profile.page');
$event->setController(fn () => new RedirectResponse($profileUrl));
}
private function flash(string $type, string $message): void
{
if ($session = $this->requestStack->getSession()) {
$session->getFlashBag()->add($type, $message);
}
}
}