custom/plugins/NetiNextAccessManager/src/Subscriber/StorefrontSubscriber.php line 103

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace NetInventors\NetiNextAccessManager\Subscriber;
  4. use NetInventors\NetiNextAccessManager\Components\StringHelper;
  5. use NetInventors\NetiNextAccessManager\Events\Subscriber\ExtendControllerWhitelist;
  6. use NetInventors\NetiNextAccessManager\Events\Subscriber\ExtendTemplatesEvent;
  7. use NetInventors\NetiNextAccessManager\Service\PluginConfig;
  8. use NetInventors\NetiNextAccessManager\Service\RouteScopeHandler\RouteScopeHandlerInterface;
  9. use Shopware\Core\Checkout\Cart\Event\AfterLineItemAddedEvent;
  10. use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
  11. use Shopware\Core\Checkout\Customer\CustomerEntity;
  12. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  13. use Shopware\Core\Framework\Routing\Event\SalesChannelContextResolvedEvent;
  14. use Shopware\Core\System\SalesChannel\SalesChannelEntity;
  15. use Shopware\Storefront\Controller\AuthController;
  16. use Shopware\Storefront\Controller\CartLineItemController;
  17. use Shopware\Storefront\Controller\CheckoutController;
  18. use Shopware\Storefront\Controller\CmsController;
  19. use Shopware\Storefront\Controller\ContextController;
  20. use Shopware\Storefront\Controller\CookieController;
  21. use Shopware\Storefront\Controller\CountryStateController;
  22. use Shopware\Storefront\Controller\FormController;
  23. use Shopware\Storefront\Controller\RegisterController;
  24. use Shopware\Storefront\Controller\SearchController;
  25. use Symfony\Bundle\FrameworkBundle\Controller\TemplateController;
  26. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  27. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  28. use Symfony\Component\HttpFoundation\RedirectResponse;
  29. use Symfony\Component\HttpFoundation\Request;
  30. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  31. use Symfony\Component\HttpKernel\KernelEvents;
  32. use Symfony\Component\Routing\RouterInterface;
  33. class StorefrontSubscriber implements EventSubscriberInterface
  34. {
  35.     /**
  36.      * @var CustomerEntity|null
  37.      */
  38.     private $customer;
  39.     /**
  40.      * @var ?SalesChannelEntity
  41.      */
  42.     private $salesChannel;
  43.     /**
  44.      * @var PluginConfig
  45.      */
  46.     private $pluginConfig;
  47.     /**
  48.      * @var RouterInterface
  49.      */
  50.     private $router;
  51.     /**
  52.      * @var TemplateController
  53.      */
  54.     private $templateController;
  55.     /**
  56.      * @var EventDispatcherInterface
  57.      */
  58.     private $eventDispatcher;
  59.     /**
  60.      * @var CartService
  61.      */
  62.     private $cartService;
  63.     public function __construct(
  64.         PluginConfig             $pluginConfig,
  65.         RouterInterface          $router,
  66.         TemplateController       $templateController,
  67.         EventDispatcherInterface $eventDispatcher,
  68.         CartService              $cartService
  69.     ) {
  70.         $this->pluginConfig       $pluginConfig;
  71.         $this->router             $router;
  72.         $this->templateController $templateController;
  73.         $this->eventDispatcher    $eventDispatcher;
  74.         $this->cartService        $cartService;
  75.     }
  76.     /**
  77.      * @return array|string[]
  78.      */
  79.     public static function getSubscribedEvents(): array
  80.     {
  81.         return [
  82.             SalesChannelContextResolvedEvent::class => 'onSalesChannelResolved',
  83.             KernelEvents::RESPONSE                  => 'onResponse',
  84.             AfterLineItemAddedEvent::class          => 'onItemAdded',
  85.         ];
  86.     }
  87.     /**
  88.      * @param SalesChannelContextResolvedEvent $event
  89.      */
  90.     public function onSalesChannelResolved(SalesChannelContextResolvedEvent $event): void
  91.     {
  92.         if (!$this->pluginConfig->isActive()) {
  93.             return;
  94.         }
  95.         $this->salesChannel $event->getSalesChannelContext()->getSalesChannel();
  96.         $this->customer     $event->getSalesChannelContext()->getCustomer();
  97.     }
  98.     /**
  99.      * @param ResponseEvent $event
  100.      */
  101.     public function onResponse(ResponseEvent $event): void
  102.     {
  103.         if (!$this->pluginConfig->isActive() || (null !== $this->salesChannel && $this->salesChannel->isMaintenance())) {
  104.             return;
  105.         }
  106.         $request  $event->getRequest();
  107.         $response null;
  108.         if ($this->isShopHidden($request)) {
  109.             $message['type'] = 'danger';
  110.             $message['text'] = 'login-first';
  111.             if ($request->isXmlHttpRequest()) {
  112.                 /**
  113.                  * @psalm-suppress DeprecatedClass
  114.                  * These classes will be internal since SW 6.5.0.0.
  115.                  */
  116.                 $templates = [
  117.                     CartLineItemController::class => '@NetiNextAccessManager/storefront/access-manager/blocked/search.html.twig',
  118.                     SearchController::class       => '@NetiNextAccessManager/storefront/access-manager/blocked/search.html.twig',
  119.                     CheckoutController::class     => '@NetiNextAccessManager/storefront/access-manager/blocked/cart-offcanvas.html.twig',
  120.                 ];
  121.                 $extendTemplatesEvent = new ExtendTemplatesEvent($this$templates);
  122.                 $this->eventDispatcher->dispatch($extendTemplatesEventExtendTemplatesEvent::NAME);
  123.                 $currentController $request->attributes->get('_controller');
  124.                 $currentController substr($currentController0strpos($currentController'::'));
  125.                 if (isset($templates[$currentController]) && $request->attributes->get('_route') !== 'frontend.checkout.info') {
  126.                     $response $this->templateController->templateAction($templates[$currentController]);
  127.                 }
  128.             } elseif ('' !== $this->pluginConfig->getRedirectCategory()) {
  129.                 $response = new RedirectResponse(
  130.                     $this->router->generate(
  131.                         'frontend.navigation.page',
  132.                         [ 'navigationId' => $this->pluginConfig->getRedirectCategory() ]
  133.                     )
  134.                 );
  135.             } else {
  136.                 $response = new RedirectResponse(
  137.                     $this->router->generate('frontend.account.login.page', [ 'amMessage' => $message ])
  138.                 );
  139.             }
  140.             if (null !== $response) {
  141.                 $event->setResponse($response);
  142.             }
  143.         }
  144.     }
  145.     /**
  146.      * @param Request $request
  147.      *
  148.      * @return bool
  149.      */
  150.     public function isShopHidden(Request $request): bool
  151.     {
  152.         /**
  153.          * @var RouteScope|array
  154.          *
  155.          * RouteScope will be removed in SW 6.5 and this Subscriber will be adjusted
  156.          * It is not possible to only rely on array because custom Controller can still use RouteScope
  157.          *
  158.          * @psalm-suppress DeprecatedClass
  159.          */
  160.         $routeScope $request->attributes->get('_routeScope');
  161.         if (null === $routeScope) {
  162.             return false;
  163.         }
  164.         if ($routeScope instanceof RouteScope) {
  165.             if (
  166.                 $routeScope->hasScope('administration')
  167.                 || $routeScope->hasScope('api')
  168.                 || $routeScope->hasScope('store-api')
  169.             ) {
  170.                 return false;
  171.             }
  172.         }
  173.         if (\is_array($routeScope)) {
  174.             if (
  175.                 \in_array('administration'$routeScopetrue)
  176.                 || \in_array('api'$routeScopetrue)
  177.                 || \in_array('store-api'$routeScopetrue)
  178.             ) {
  179.                 return false;
  180.             }
  181.         }
  182.         if (null !== $this->customer || false === $this->pluginConfig->isHideShop() || !$this->salesChannel instanceof SalesChannelEntity) {
  183.             return false;
  184.         }
  185.         $navigationId $request->attributes->get('navigationId');
  186.         if (
  187.             \in_array($navigationId$this->pluginConfig->getAllowedCategories(), true)
  188.             || $navigationId === $this->pluginConfig->getRedirectCategory()
  189.             || ($request->getRequestUri() === '/'
  190.                 && \in_array(
  191.                     $this->salesChannel->getNavigationCategoryId(),
  192.                     $this->pluginConfig->getAllowedCategories(),
  193.                     true
  194.                 ))
  195.             || \in_array($request->getRequestUri(), $this->pluginConfig->getWhitelistedPaths())
  196.         ) {
  197.             return false;
  198.         }
  199.         foreach ($this->pluginConfig->getWhitelistedPaths() as $path) {
  200.             /** @var ?string $originRequestUri */
  201.             $originRequestUri $request->attributes->get('sw-original-request-uri');
  202.             if (
  203.                 StringHelper::stringMatchWithWildcard($request->getRequestUri(), $path)
  204.                 || (
  205.                     \is_string($originRequestUri)
  206.                     && StringHelper::stringMatchWithWildcard($originRequestUri$path)
  207.                 )
  208.             ) {
  209.                 return false;
  210.             }
  211.         }
  212.         /**
  213.          * @psalm-suppress DeprecatedClass
  214.          * These classes will be internal since SW 6.5.0.0.
  215.          */
  216.         $accessList array_merge([
  217.             AuthController::class,
  218.             ContextController::class,
  219.             CmsController::class,
  220.             FormController::class,
  221.             CountryStateController::class,
  222.             RegisterController::class,
  223.             CookieController::class,
  224.         ], $this->pluginConfig->getWhitelistedControllers());
  225.         $extendWhitelistControllerEvent = new ExtendControllerWhitelist($this$accessList);
  226.         $this->eventDispatcher->dispatch($extendWhitelistControllerEventExtendControllerWhitelist::NAME);
  227.         $currentController $request->attributes->get('_controller');
  228.         if (null === $currentController) {
  229.             return false;
  230.         }
  231.         foreach ($accessList as $controller) {
  232.             if (=== strpos($currentController"{$controller}::")) {
  233.                 return false;
  234.             }
  235.             if (StringHelper::stringMatchWithWildcard($currentController$controller)) {
  236.                 return false;
  237.             }
  238.         }
  239.         return true;
  240.     }
  241.     /**
  242.      * @param AfterLineItemAddedEvent $event
  243.      */
  244.     public function onItemAdded(AfterLineItemAddedEvent $event): void
  245.     {
  246.         if (
  247.             !$this->pluginConfig->isHideShop()
  248.             || !$this->pluginConfig->isActive()
  249.             || $event->getSalesChannelContext()->getCustomer() !== null
  250.         ) {
  251.             return;
  252.         }
  253.         $this->cartService->deleteCart($event->getSalesChannelContext());
  254.     }
  255. }