vendor/contao/manager-bundle/src/HttpKernel/ContaoKernel.php line 312

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4.  * This file is part of Contao.
  5.  *
  6.  * (c) Leo Feyer
  7.  *
  8.  * @license LGPL-3.0-or-later
  9.  */
  10. namespace Contao\ManagerBundle\HttpKernel;
  11. use AppBundle\AppBundle;
  12. use Contao\ManagerBundle\Api\ManagerConfig;
  13. use Contao\ManagerBundle\ContaoManager\Plugin;
  14. use Contao\ManagerPlugin\Bundle\BundleLoader;
  15. use Contao\ManagerPlugin\Bundle\Config\ConfigResolverFactory;
  16. use Contao\ManagerPlugin\Bundle\Parser\DelegatingParser;
  17. use Contao\ManagerPlugin\Bundle\Parser\IniParser;
  18. use Contao\ManagerPlugin\Bundle\Parser\JsonParser;
  19. use Contao\ManagerPlugin\Config\ConfigPluginInterface;
  20. use Contao\ManagerPlugin\Config\ContainerBuilder as PluginContainerBuilder;
  21. use Contao\ManagerPlugin\HttpKernel\HttpCacheSubscriberPluginInterface;
  22. use Contao\ManagerPlugin\PluginLoader;
  23. use FOS\HttpCache\SymfonyCache\HttpCacheProvider;
  24. use ProxyManager\Configuration;
  25. use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator;
  26. use Symfony\Component\Config\Loader\LoaderInterface;
  27. use Symfony\Component\Console\Input\InputInterface;
  28. use Symfony\Component\Dotenv\Dotenv;
  29. use Symfony\Component\ErrorHandler\Debug;
  30. use Symfony\Component\HttpFoundation\Request;
  31. use Symfony\Component\HttpKernel\HttpKernelInterface;
  32. use Symfony\Component\HttpKernel\Kernel;
  33. class ContaoKernel extends Kernel implements HttpCacheProvider
  34. {
  35.     /**
  36.      * @var string
  37.      */
  38.     protected static $projectDir;
  39.     /**
  40.      * @var PluginLoader
  41.      */
  42.     private $pluginLoader;
  43.     /**
  44.      * @var BundleLoader
  45.      */
  46.     private $bundleLoader;
  47.     /**
  48.      * @var JwtManager
  49.      */
  50.     private $jwtManager;
  51.     /**
  52.      * @var ManagerConfig
  53.      */
  54.     private $managerConfig;
  55.     /**
  56.      * @var ContaoCache
  57.      */
  58.     private $httpCache;
  59.     public function registerBundles(): array
  60.     {
  61.         $bundles = [];
  62.         $this->addBundlesFromPlugins($bundles);
  63.         return $bundles;
  64.     }
  65.     public function getProjectDir(): string
  66.     {
  67.         if (null === self::$projectDir) {
  68.             throw new \LogicException('ContaoKernel::setProjectDir() must be called to initialize the Contao kernel');
  69.         }
  70.         return self::$projectDir;
  71.     }
  72.     /**
  73.      * @deprecated since Symfony 4.2, use getProjectDir() instead
  74.      */
  75.     public function getRootDir(): string
  76.     {
  77.         if (null === $this->rootDir) {
  78.             $this->rootDir $this->getProjectDir().'/app';
  79.         }
  80.         return $this->rootDir;
  81.     }
  82.     public function getCacheDir(): string
  83.     {
  84.         return $this->getProjectDir().'/var/cache/'.$this->getEnvironment();
  85.     }
  86.     public function getLogDir(): string
  87.     {
  88.         return $this->getProjectDir().'/var/logs';
  89.     }
  90.     public function getPluginLoader(): PluginLoader
  91.     {
  92.         if (null === $this->pluginLoader) {
  93.             $this->pluginLoader = new PluginLoader();
  94.             $config $this->getManagerConfig()->all();
  95.             if (
  96.                 isset($config['contao_manager']['disabled_packages'])
  97.                 && \is_array($config['contao_manager']['disabled_packages'])
  98.             ) {
  99.                 $this->pluginLoader->setDisabledPackages($config['contao_manager']['disabled_packages']);
  100.             }
  101.         }
  102.         return $this->pluginLoader;
  103.     }
  104.     public function setPluginLoader(PluginLoader $pluginLoader): void
  105.     {
  106.         $this->pluginLoader $pluginLoader;
  107.     }
  108.     public function getBundleLoader(): BundleLoader
  109.     {
  110.         if (null === $this->bundleLoader) {
  111.             $parser = new DelegatingParser();
  112.             $parser->addParser(new JsonParser());
  113.             $parser->addParser(new IniParser($this->getProjectDir().'/system/modules'));
  114.             $this->bundleLoader = new BundleLoader($this->getPluginLoader(), new ConfigResolverFactory(), $parser);
  115.         }
  116.         return $this->bundleLoader;
  117.     }
  118.     public function setBundleLoader(BundleLoader $bundleLoader): void
  119.     {
  120.         $this->bundleLoader $bundleLoader;
  121.     }
  122.     public function getJwtManager(): ?JwtManager
  123.     {
  124.         return $this->jwtManager;
  125.     }
  126.     public function setJwtManager(JwtManager $jwtManager): void
  127.     {
  128.         $this->jwtManager $jwtManager;
  129.     }
  130.     public function getManagerConfig(): ManagerConfig
  131.     {
  132.         if (null === $this->managerConfig) {
  133.             $this->managerConfig = new ManagerConfig($this->getProjectDir());
  134.         }
  135.         return $this->managerConfig;
  136.     }
  137.     public function setManagerConfig(ManagerConfig $managerConfig): void
  138.     {
  139.         $this->managerConfig $managerConfig;
  140.     }
  141.     public function registerContainerConfiguration(LoaderInterface $loader): void
  142.     {
  143.         if ($parametersFile $this->getConfigFile('parameters')) {
  144.             $loader->load($parametersFile);
  145.         }
  146.         $config $this->getManagerConfig()->all();
  147.         $plugins $this->getPluginLoader()->getInstancesOf(PluginLoader::CONFIG_PLUGINS);
  148.         /** @var array<ConfigPluginInterface> $plugins */
  149.         foreach ($plugins as $plugin) {
  150.             $plugin->registerContainerConfiguration($loader$config);
  151.         }
  152.         // Reload the parameters.yml file
  153.         if ($parametersFile) {
  154.             $loader->load($parametersFile);
  155.         }
  156.         if ($configFile $this->getConfigFile('config_'.$this->getEnvironment())) {
  157.             $loader->load($configFile);
  158.         } elseif ($configFile $this->getConfigFile('config')) {
  159.             $loader->load($configFile);
  160.         }
  161.         // Automatically load the services.yml file if it exists
  162.         if ($servicesFile $this->getConfigFile('services')) {
  163.             $loader->load($servicesFile);
  164.         }
  165.         if (is_dir($this->getProjectDir().'/src')) {
  166.             $loader->load(__DIR__.'/../Resources/skeleton/config/services.php');
  167.         }
  168.     }
  169.     public function getHttpCache(): ContaoCache
  170.     {
  171.         if (null !== $this->httpCache) {
  172.             return $this->httpCache;
  173.         }
  174.         $this->httpCache = new ContaoCache($this$this->getProjectDir().'/var/cache/prod/http_cache');
  175.         /** @var array<HttpCacheSubscriberPluginInterface> $plugins */
  176.         $plugins $this->getPluginLoader()->getInstancesOf(HttpCacheSubscriberPluginInterface::class);
  177.         foreach ($plugins as $plugin) {
  178.             foreach ($plugin->getHttpCacheSubscribers() as $subscriber) {
  179.                 $this->httpCache->addSubscriber($subscriber);
  180.             }
  181.         }
  182.         return $this->httpCache;
  183.     }
  184.     /**
  185.      * Sets the project directory (the Contao kernel does not know its location).
  186.      */
  187.     public static function setProjectDir(string $projectDir): void
  188.     {
  189.         self::$projectDir realpath($projectDir) ?: $projectDir;
  190.     }
  191.     /**
  192.      * @return ContaoKernel|ContaoCache
  193.      */
  194.     public static function fromRequest(string $projectDirRequest $request): HttpKernelInterface
  195.     {
  196.         self::loadEnv($projectDir'jwt');
  197.         // See https://github.com/symfony/recipes/blob/master/symfony/framework-bundle/4.2/public/index.php
  198.         if ($trustedProxies $_SERVER['TRUSTED_PROXIES'] ?? null) {
  199.             Request::setTrustedProxies(explode(','$trustedProxies), Request::HEADER_X_FORWARDED_ALL Request::HEADER_X_FORWARDED_HOST);
  200.         }
  201.         if ($trustedHosts $_SERVER['TRUSTED_HOSTS'] ?? null) {
  202.             Request::setTrustedHosts(explode(','$trustedHosts));
  203.         }
  204.         Request::enableHttpMethodParameterOverride();
  205.         $jwtManager null;
  206.         $env null;
  207.         $parseJwt 'jwt' === $_SERVER['APP_ENV'];
  208.         if ($parseJwt) {
  209.             $env 'prod';
  210.             $jwtManager = new JwtManager($projectDir);
  211.             $jwt $jwtManager->parseRequest($request);
  212.             if (\is_array($jwt) && ($jwt['debug'] ?? false)) {
  213.                 $env 'dev';
  214.             }
  215.             $_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $env;
  216.         }
  217.         $kernel = static::create($projectDir$env);
  218.         if ($parseJwt) {
  219.             $kernel->setJwtManager($jwtManager);
  220.         }
  221.         if (!$kernel->isDebug()) {
  222.             $cache $kernel->getHttpCache();
  223.             // Enable the Symfony reverse proxy if request has no surrogate capability
  224.             if (($surrogate $cache->getSurrogate()) && !$surrogate->hasSurrogateCapability($request)) {
  225.                 return $cache;
  226.             }
  227.         }
  228.         return $kernel;
  229.     }
  230.     public static function fromInput(string $projectDirInputInterface $input): self
  231.     {
  232.         $env $input->getParameterOption(['--env''-e'], null);
  233.         self::loadEnv($projectDir$env ?: 'prod');
  234.         return static::create($projectDir$env);
  235.     }
  236.     protected function getContainerBuilder(): PluginContainerBuilder
  237.     {
  238.         $container = new PluginContainerBuilder($this->getPluginLoader(), []);
  239.         $container->getParameterBag()->add($this->getKernelParameters());
  240.         if (class_exists(Configuration::class) && class_exists(RuntimeInstantiator::class)) {
  241.             $container->setProxyInstantiator(new RuntimeInstantiator());
  242.         }
  243.         return $container;
  244.     }
  245.     protected function initializeContainer(): void
  246.     {
  247.         parent::initializeContainer();
  248.         if (null === ($container $this->getContainer())) {
  249.             return;
  250.         }
  251.         // Set the plugin loader again so it is available at runtime (synthetic service)
  252.         $container->set('contao_manager.plugin_loader'$this->getPluginLoader());
  253.         // Set the JWT manager only if the debug mode has not been configured in env variables
  254.         if ($jwtManager $this->getJwtManager()) {
  255.             $container->set('contao_manager.jwt_manager'$jwtManager);
  256.         }
  257.     }
  258.     private function getConfigFile(string $file): ?string
  259.     {
  260.         $projectDir $this->getProjectDir();
  261.         foreach (['.yaml''.yml'] as $ext) {
  262.             if (file_exists($projectDir.'/config/'.$file.$ext)) {
  263.                 return $projectDir.'/config/'.$file.$ext;
  264.             }
  265.         }
  266.         // Fallback to the legacy config file (see #566)
  267.         foreach (['.yaml''.yml'] as $ext) {
  268.             if (file_exists($projectDir.'/app/config/'.$file.$ext)) {
  269.                 @trigger_error(sprintf('Storing the "%s" file in the "app/config" folder has been deprecated and will no longer work in Contao 5.0. Move it to the "config" folder instead.'$file.$ext), E_USER_DEPRECATED);
  270.                 return $projectDir.'/app/config/'.$file.$ext;
  271.             }
  272.         }
  273.         return null;
  274.     }
  275.     private function addBundlesFromPlugins(array &$bundles): void
  276.     {
  277.         $configs $this->getBundleLoader()->getBundleConfigs(
  278.             'dev' === $this->getEnvironment(),
  279.             $this->debug null $this->getCacheDir().'/bundles.map'
  280.         );
  281.         foreach ($configs as $config) {
  282.             $bundles[$config->getName()] = $config->getBundleInstance($this);
  283.         }
  284.         // Autoload AppBundle for convenience
  285.         $appBundle AppBundle::class;
  286.         if (!isset($bundles[$appBundle]) && class_exists($appBundle)) {
  287.             $bundles[$appBundle] = new $appBundle();
  288.         }
  289.     }
  290.     private static function create(string $projectDirstring $env null): self
  291.     {
  292.         if (null === $env) {
  293.             $env $_SERVER['APP_ENV'] ?? 'prod';
  294.         }
  295.         if ('dev' !== $env && 'prod' !== $env) {
  296.             throw new \RuntimeException('The Contao Managed Edition only supports the "dev" and "prod" environments');
  297.         }
  298.         Plugin::autoloadModules($projectDir.'/system/modules');
  299.         static::setProjectDir($projectDir);
  300.         if ('dev' === $env) {
  301.             Debug::enable();
  302.         }
  303.         return new static($env'dev' === $env);
  304.     }
  305.     private static function loadEnv(string $projectDirstring $defaultEnv 'prod'): void
  306.     {
  307.         // Load cached env vars if the .env.local.php file exists
  308.         // See https://github.com/symfony/recipes/blob/master/symfony/framework-bundle/4.2/config/bootstrap.php
  309.         if (\is_array($env = @include $projectDir.'/.env.local.php')) {
  310.             foreach ($env as $k => $v) {
  311.                 $_ENV[$k] = $_ENV[$k] ?? (isset($_SERVER[$k]) && !== strpos($k'HTTP_') ? $_SERVER[$k] : $v);
  312.             }
  313.         } elseif (file_exists($projectDir.'/.env')) {
  314.             (new Dotenv(false))->loadEnv($projectDir.'/.env''APP_ENV'$defaultEnv);
  315.         }
  316.         $_SERVER += $_ENV;
  317.         $_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null ?: $defaultEnv;
  318.     }
  319. }