<?php declare(strict_types=1); 
 
namespace Shopware\Storefront\Theme\Twig; 
 
use Shopware\Core\Checkout\Document\Event\DocumentTemplateRendererParameterEvent; 
use Shopware\Core\Framework\Adapter\Twig\NamespaceHierarchy\TemplateNamespaceHierarchyBuilderInterface; 
use Shopware\Core\SalesChannelRequest; 
use Shopware\Core\System\SalesChannel\SalesChannelContext; 
use Shopware\Storefront\Theme\SalesChannelThemeLoader; 
use Symfony\Component\EventDispatcher\EventSubscriberInterface; 
use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpKernel\Event\RequestEvent; 
use Symfony\Component\HttpKernel\KernelEvents; 
use Symfony\Contracts\Service\ResetInterface; 
 
class ThemeNamespaceHierarchyBuilder implements TemplateNamespaceHierarchyBuilderInterface, EventSubscriberInterface, ResetInterface 
{ 
    /** 
     * @var array<int|string, bool> 
     */ 
    private array $themes = []; 
 
    private ThemeInheritanceBuilderInterface $themeInheritanceBuilder; 
 
    private SalesChannelThemeLoader $salesChannelThemeLoader; 
 
    /** 
     * @internal 
     */ 
    public function __construct( 
        ThemeInheritanceBuilderInterface $themeInheritanceBuilder, 
        SalesChannelThemeLoader $salesChannelThemeLoader 
    ) { 
        $this->themeInheritanceBuilder = $themeInheritanceBuilder; 
        $this->salesChannelThemeLoader = $salesChannelThemeLoader; 
    } 
 
    /** 
     * @return array<string, string|array{0: string, 1: int}|list<array{0: string, 1?: int}>> 
     */ 
    public static function getSubscribedEvents() 
    { 
        return [ 
            KernelEvents::REQUEST => 'requestEvent', 
            KernelEvents::EXCEPTION => 'requestEvent', 
            DocumentTemplateRendererParameterEvent::class => 'onDocumentRendering', 
        ]; 
    } 
 
    public function requestEvent(RequestEvent $event): void 
    { 
        $request = $event->getRequest(); 
 
        $this->themes = $this->detectedThemes($request); 
    } 
 
    public function onDocumentRendering(DocumentTemplateRendererParameterEvent $event): void 
    { 
        $parameters = $event->getParameters(); 
 
        if (!\array_key_exists('context', $parameters)) { 
            return; 
        } 
 
        /** @var SalesChannelContext $context */ 
        $context = $parameters['context']; 
 
        $themes = []; 
 
        $theme = $this->salesChannelThemeLoader->load($context->getSalesChannelId()); 
 
        if (empty($theme['themeName'])) { 
            return; 
        } 
 
        $themes[$theme['themeName']] = true; 
        $themes['Storefront'] = true; 
 
        $this->themes = $themes; 
    } 
 
    public function buildNamespaceHierarchy(array $namespaceHierarchy): array 
    { 
        if (empty($this->themes)) { 
            return $namespaceHierarchy; 
        } 
 
        return $this->themeInheritanceBuilder->build($namespaceHierarchy, $this->themes); 
    } 
 
    public function reset(): void 
    { 
        $this->themes = []; 
    } 
 
    /** 
     * @return array<int|string, bool> 
     */ 
    private function detectedThemes(Request $request): array 
    { 
        // get name if theme is not inherited 
        $theme = $request->attributes->get(SalesChannelRequest::ATTRIBUTE_THEME_NAME); 
 
        if (!$theme) { 
            // get theme name from base theme because for inherited themes the name is always null 
            $theme = $request->attributes->get(SalesChannelRequest::ATTRIBUTE_THEME_BASE_NAME); 
        } 
 
        if (!$theme) { 
            return []; 
        } 
 
        $themes[$theme] = true; 
        $themes['Storefront'] = true; 
 
        return $themes; 
    } 
}