<?php
declare(strict_types=1);
namespace Abap\ApplicationContextBundle\EventSubscriber;
use Abap\ApplicationContextBundle\ConfigurationLoader\ConfigurationLoaderRegistry;
use Abap\ApplicationContextBundle\Context\ApplicationContext;
use Abap\ApplicationContextBundle\Context\ApplicationContextInterface;
use Abap\ApplicationContextBundle\Context\ApplicationContextRegistry;
use Abap\ThemeBundle\Context\ThemeContextInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
final class ApplicationContextSubscriber implements EventSubscriberInterface
{
private ThemeContextInterface $currentThemeContext;
private ConfigurationLoaderRegistry $configurationLoaderRegistry;
private ApplicationContextRegistry $applicationContextRegistry;
public function __construct(ThemeContextInterface $themeContext, ConfigurationLoaderRegistry $configurationLoaderRegistry, ApplicationContextRegistry $applicationContextRegistry)
{
$this->currentThemeContext = $themeContext;
$this->configurationLoaderRegistry = $configurationLoaderRegistry;
$this->applicationContextRegistry = $applicationContextRegistry;
}
public static function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => [
['loadApplicationContext', 50],
],
];
}
public function loadApplicationContext(RequestEvent $event): void
{
$request = $event->getRequest();
if (!$event->isMainRequest()) {
return;
}
$this->applicationContextRegistry->unsetCurrent();
foreach ($this->configurationLoaderRegistry->all() as $configurationLoader) {
if (null === $availableContexts = $configurationLoader->load()) {
continue;
}
foreach ($availableContexts as $contextCode=>$contextData) {
$applicationContext = new ApplicationContext();
$applicationContext->loadData($contextCode, $contextData);
$this->applicationContextRegistry->addContext($applicationContext);
if (!$this->applicationContextRegistry->hasCurrent() && $this->isApplicable($request, $applicationContext)) {
$this->applicationContextRegistry->setCurrent($applicationContext->getCode());
$this->currentThemeContext->loadTheme($applicationContext->getTheme());
}
}
}
}
private function isApplicable(Request $request, ApplicationContext $applicationContext): bool
{
if ($this->isExcludedPath($request, $applicationContext)) {
return false;
}
$path = $applicationContext->getPath();
if (empty($path) || '/' === $path) {
return true;
}
$reg = '/^' . preg_quote($path, '/') . '($|\/|\?)/';
$requestUri = $request->getRequestUri();
return (bool) preg_match($reg, $requestUri);
}
public function isExcludedPath(Request $request, ApplicationContext $applicationContext): bool
{
$requestUri = $request->getRequestUri();
foreach ($applicationContext->getExcludedPaths() as $excludedPath) {
$reg = '/^' . preg_quote($excludedPath, '/') . '($|\/|\?)/';
if ((bool)preg_match($reg, $requestUri)) {
return true;
}
}
return false;
}
}