vendor/pimcore/pimcore/lib/Kernel.php line 323

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Commercial License (PCL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  *  @license    http://www.pimcore.org/license     GPLv3 and PCL
  13.  */
  14. namespace Pimcore;
  15. use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
  16. use Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle;
  17. use FOS\JsRoutingBundle\FOSJsRoutingBundle;
  18. use League\FlysystemBundle\FlysystemBundle;
  19. use Pimcore\Bundle\AdminBundle\PimcoreAdminBundle;
  20. use Pimcore\Bundle\CoreBundle\PimcoreCoreBundle;
  21. use Pimcore\Cache\RuntimeCache;
  22. use Pimcore\Config\BundleConfigLocator;
  23. use Pimcore\Event\SystemEvents;
  24. use Pimcore\Extension\Bundle\Config\StateConfig;
  25. use Pimcore\HttpKernel\BundleCollection\BundleCollection;
  26. use Pimcore\HttpKernel\BundleCollection\ItemInterface;
  27. use Pimcore\HttpKernel\BundleCollection\LazyLoadedItem;
  28. use Presta\SitemapBundle\PrestaSitemapBundle;
  29. use Scheb\TwoFactorBundle\SchebTwoFactorBundle;
  30. use Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle;
  31. use Symfony\Bundle\DebugBundle\DebugBundle;
  32. use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
  33. use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
  34. use Symfony\Bundle\MonologBundle\MonologBundle;
  35. use Symfony\Bundle\SecurityBundle\SecurityBundle;
  36. use Symfony\Bundle\TwigBundle\TwigBundle;
  37. use Symfony\Bundle\WebProfilerBundle\WebProfilerBundle;
  38. use Symfony\Cmf\Bundle\RoutingBundle\CmfRoutingBundle;
  39. use Symfony\Component\Config\Definition\Processor;
  40. use Symfony\Component\Config\Loader\LoaderInterface;
  41. use Symfony\Component\Config\Resource\FileExistenceResource;
  42. use Symfony\Component\Config\Resource\FileResource;
  43. use Symfony\Component\DependencyInjection\ContainerBuilder;
  44. use Symfony\Component\DependencyInjection\ContainerInterface;
  45. use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
  46. use Symfony\Component\EventDispatcher\GenericEvent;
  47. use Symfony\Component\HttpKernel\Bundle\BundleInterface;
  48. use Symfony\Component\HttpKernel\Kernel as SymfonyKernel;
  49. use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
  50. use Twig\Extra\TwigExtraBundle\TwigExtraBundle;
  51. abstract class Kernel extends SymfonyKernel
  52. {
  53.     use MicroKernelTrait {
  54.         registerContainerConfiguration as microKernelRegisterContainerConfiguration;
  55.         registerBundles as microKernelRegisterBundles;
  56.     }
  57.     private const CONFIG_LOCATION 'config_location';
  58.     /**
  59.      * @deprecated will be removed in Pimcore 11
  60.      *
  61.      * @var Extension\Config
  62.      */
  63.     protected $extensionConfig;
  64.     /**
  65.      * @var BundleCollection
  66.      */
  67.     private $bundleCollection;
  68.     /**
  69.      * @deprecated
  70.      */
  71.     public function getRootDir()
  72.     {
  73.         trigger_deprecation(
  74.             'pimcore/pimcore',
  75.             '10.3',
  76.             'Kernel::getRootDir() is deprecated and will be removed in Pimcore 11. Use Kernel::getProjectDir() instead.',
  77.         );
  78.         return PIMCORE_PROJECT_ROOT;
  79.     }
  80.     /**
  81.      * {@inheritdoc}
  82.      *
  83.      * @return string
  84.      */
  85.     #[\ReturnTypeWillChange]
  86.     public function getProjectDir()// : string
  87.     {
  88.         return PIMCORE_PROJECT_ROOT;
  89.     }
  90.     /**
  91.      * {@inheritdoc}
  92.      *
  93.      * @return string
  94.      */
  95.     #[\ReturnTypeWillChange]
  96.     public function getCacheDir()// : string
  97.     {
  98.         if (isset($_SERVER['APP_CACHE_DIR'])) {
  99.             return $_SERVER['APP_CACHE_DIR'].'/'.$this->environment;
  100.         }
  101.         return PIMCORE_SYMFONY_CACHE_DIRECTORY '/' $this->environment;
  102.     }
  103.     /**
  104.      * {@inheritdoc}
  105.      *
  106.      * @return string
  107.      */
  108.     #[\ReturnTypeWillChange]
  109.     public function getLogDir()// : string
  110.     {
  111.         return PIMCORE_LOG_DIRECTORY;
  112.     }
  113.     /**
  114.      * {@inheritdoc}
  115.      */
  116.     protected function configureContainer(ContainerConfigurator $container): void
  117.     {
  118.         $projectDir realpath($this->getProjectDir());
  119.         $container->import($projectDir '/config/{packages}/*.yaml');
  120.         $container->import($projectDir '/config/{packages}/'.$this->environment.'/*.yaml');
  121.         if (is_file($projectDir '/config/services.yaml')) {
  122.             $container->import($projectDir '/config/services.yaml');
  123.             $container->import($projectDir '/config/{services}_'.$this->environment.'.yaml');
  124.         } elseif (is_file($path $projectDir '/config/services.php')) {
  125.             (require $path)($container->withPath($path), $this);
  126.         }
  127.     }
  128.     /**
  129.      * {@inheritdoc}
  130.      */
  131.     protected function configureRoutes(RoutingConfigurator $routes): void
  132.     {
  133.         $projectDir realpath($this->getProjectDir());
  134.         $routes->import($projectDir '/config/{routes}/'.$this->environment.'/*.yaml');
  135.         $routes->import($projectDir '/config/{routes}/*.yaml');
  136.         if (is_file($projectDir '/config/routes.yaml')) {
  137.             $routes->import($projectDir '/config/routes.yaml');
  138.         } elseif (is_file($path $projectDir '/config/routes.php')) {
  139.             (require $path)($routes->withPath($path), $this);
  140.         }
  141.     }
  142.     /**
  143.      * {@inheritdoc}
  144.      */
  145.     public function registerContainerConfiguration(LoaderInterface $loader)
  146.     {
  147.         $loader->load(function (ContainerBuilder $container) {
  148.             $this->registerExtensionConfigFileResources($container);
  149.         });
  150.         $bundleConfigLocator = new BundleConfigLocator($this);
  151.         foreach ($bundleConfigLocator->locate('config') as $bundleConfig) {
  152.             $loader->load($bundleConfig);
  153.         }
  154.         $this->microKernelRegisterContainerConfiguration($loader);
  155.         //load system configuration
  156.         $systemConfigFile Config::locateConfigFile('system.yml');
  157.         if (file_exists($systemConfigFile)) {
  158.             $loader->load($systemConfigFile);
  159.         }
  160.         $configArray = [
  161.             [
  162.                 'storageDirectoryEnvVariableName' => 'PIMCORE_CONFIG_STORAGE_DIR_IMAGE_THUMBNAILS',
  163.                 'defaultStorageDirectoryName' => 'image-thumbnails',
  164.             ],
  165.             [
  166.                 'storageDirectoryEnvVariableName' => 'PIMCORE_CONFIG_STORAGE_DIR_VIDEO_THUMBNAILS',
  167.                 'defaultStorageDirectoryName' => 'video-thumbnails',
  168.             ],
  169.             [
  170.                 'storageDirectoryEnvVariableName' => 'PIMCORE_CONFIG_STORAGE_DIR_CUSTOM_REPORTS',
  171.                 'defaultStorageDirectoryName' => 'custom-reports',
  172.             ],
  173.             [
  174.                 'storageDirectoryEnvVariableName' => 'PIMCORE_CONFIG_STORAGE_DIR_DOCUMENT_TYPES',
  175.                 'defaultStorageDirectoryName' => 'document-types',
  176.             ],
  177.             [
  178.                 'storageDirectoryEnvVariableName' => 'PIMCORE_CONFIG_STORAGE_DIR_WEB_TO_PRINT',
  179.                 'defaultStorageDirectoryName' => 'web-to-print',
  180.             ],
  181.             [
  182.                 'storageDirectoryEnvVariableName' => 'PIMCORE_CONFIG_STORAGE_DIR_PREDEFINED_PROPERTIES',
  183.                 'defaultStorageDirectoryName' => 'predefined-properties',
  184.             ],
  185.             [
  186.                 'storageDirectoryEnvVariableName' => 'PIMCORE_CONFIG_STORAGE_DIR_PREDEFINED_ASSET_METADATA',
  187.                 'defaultStorageDirectoryName' => 'predefined-asset-metadata',
  188.             ],
  189.             [
  190.                 'storageDirectoryEnvVariableName' => 'PIMCORE_CONFIG_STORAGE_DIR_STATICROUTES',
  191.                 'defaultStorageDirectoryName' => 'staticroutes',
  192.             ],
  193.             [
  194.                 'storageDirectoryEnvVariableName' => 'PIMCORE_CONFIG_STORAGE_DIR_PERSPECTIVES',
  195.                 'defaultStorageDirectoryName' => 'perspectives',
  196.             ],
  197.             [
  198.                 'storageDirectoryEnvVariableName' => 'PIMCORE_CONFIG_STORAGE_DIR_CUSTOM_VIEWS',
  199.                 'defaultStorageDirectoryName' => 'custom-views',
  200.             ],
  201.         ];
  202.         $loader->load(function (ContainerBuilder $container) use ($loader$configArray) {
  203.             $containerConfig $container->getExtensionConfig('pimcore');
  204.             $containerConfig array_merge(...$containerConfig);
  205.             $processor = new Processor();
  206.             // @phpstan-ignore-next-line
  207.             $configuration $container->getExtension('pimcore')->getConfiguration($containerConfig$container);
  208.             $containerConfig $processor->processConfiguration($configuration, ['pimcore' => $containerConfig]);
  209.             $resolvingBag $container->getParameterBag();
  210.             $containerConfig $resolvingBag->resolveValue($containerConfig);
  211.             if (!array_key_exists(self::CONFIG_LOCATION$containerConfig)) {
  212.                 return;
  213.             }
  214.             foreach ($configArray as $config) {
  215.                 $configKey str_replace('-''_'$config['defaultStorageDirectoryName']);
  216.                 if (!isset($containerConfig[self::CONFIG_LOCATION][$configKey])) {
  217.                     continue;
  218.                 }
  219.                 $options $containerConfig[self::CONFIG_LOCATION][$configKey]['write_target']['options'];
  220.                 $configDir rtrim($options['directory'] ?? self::getStorageDirectoryFromSymfonyConfig($containerConfig$config['defaultStorageDirectoryName'], $config['storageDirectoryEnvVariableName']), '/\\');
  221.                 $configDir "$configDir/";
  222.                 if (is_dir($configDir)) {
  223.                     // @phpstan-ignore-next-line
  224.                     $loader->import($configDir);
  225.                 }
  226.             }
  227.         });
  228.     }
  229.     private static function getStorageDirectoryFromSymfonyConfig(array $configstring $configKeystring $storageDir): string
  230.     {
  231.         if (isset($_SERVER[$storageDir])) {
  232.             trigger_deprecation('pimcore/pimcore''10.6',
  233.                 sprintf('Setting storage directory (%s) in the .env file is deprecated, instead use the symfony config. It will be removed in Pimcore 11.'$storageDir));
  234.             return $_SERVER[$storageDir];
  235.         }
  236.         return $config[self::CONFIG_LOCATION][$configKey]['write_target']['options']['directory'];
  237.     }
  238.     /**
  239.      * @param ContainerBuilder $container
  240.      *
  241.      * @return void
  242.      *
  243.      * @deprecated Remove in Pimcore 11
  244.      */
  245.     private function registerExtensionConfigFileResources(ContainerBuilder $container)
  246.     {
  247.         $filenames = [
  248.             'extensions.php',
  249.             sprintf('extensions_%s.php'$this->getEnvironment()),
  250.         ];
  251.         $directories = [
  252.             PIMCORE_CUSTOM_CONFIGURATION_DIRECTORY,
  253.             PIMCORE_CONFIGURATION_DIRECTORY,
  254.         ];
  255.         // add possible extensions.php files as file existence resources (only for the current env)
  256.         foreach ($directories as $directory) {
  257.             foreach ($filenames as $filename) {
  258.                 $container->addResource(new FileExistenceResource($directory '/' $filename));
  259.             }
  260.         }
  261.         // add extensions.php as container resource
  262.         if ($this->extensionConfig->configFileExists()) {
  263.             $container->addResource(new FileResource($this->extensionConfig->locateConfigFile()));
  264.         }
  265.     }
  266.     /**
  267.      * {@inheritdoc}
  268.      */
  269.     public function boot()
  270.     {
  271.         if (true === $this->booted) {
  272.             // make sure container reset is handled properly
  273.             parent::boot();
  274.             return;
  275.         }
  276.         // handle system requirements
  277.         $this->setSystemRequirements();
  278.         // initialize extension manager config
  279.         $this->extensionConfig = new Extension\Config();
  280.         parent::boot();
  281.     }
  282.     /**
  283.      * {@inheritdoc}
  284.      */
  285.     public function shutdown()
  286.     {
  287.         if (true === $this->booted) {
  288.             // cleanup runtime cache, doctrine, monolog ... to free some memory and avoid locking issues
  289.             $this->container->get(\Pimcore\Helper\LongRunningHelper::class)->cleanUp();
  290.         }
  291.         parent::shutdown();
  292.     }
  293.     /**
  294.      * {@inheritdoc}
  295.      */
  296.     protected function initializeContainer()
  297.     {
  298.         parent::initializeContainer();
  299.         // initialize runtime cache (defined as synthetic service)
  300.         RuntimeCache::getInstance();
  301.         // set the extension config on the container
  302.         $this->getContainer()->set(Extension\Config::class, $this->extensionConfig);
  303.         \Pimcore::initLogger();
  304.         \Pimcore\Cache::init();
  305.         // on pimcore shutdown
  306.         register_shutdown_function(function () {
  307.             // check if container still exists at this point as it could already
  308.             // be cleared (e.g. when running tests which boot multiple containers)
  309.             try {
  310.                 $container $this->getContainer();
  311.             } catch (\LogicException) {
  312.                 // Container is cleared. Allow tests to finish.
  313.             }
  314.             if (isset($container) && $container instanceof ContainerInterface) {
  315.                 $container->get('event_dispatcher')->dispatch(new GenericEvent(), SystemEvents::SHUTDOWN);
  316.             }
  317.             \Pimcore::shutdown();
  318.         });
  319.     }
  320.     /**
  321.      * Returns an array of bundles to register.
  322.      *
  323.      * @return BundleInterface[] An array of bundle instances
  324.      */
  325.     public function registerBundles(): array
  326.     {
  327.         $collection $this->createBundleCollection();
  328.         if (is_file($this->getProjectDir().'/config/bundles.php')) {
  329.             $flexBundles = [];
  330.             array_push($flexBundles, ...$this->microKernelRegisterBundles());
  331.             $collection->addBundles($flexBundles);
  332.         }
  333.         // core bundles (Symfony, Pimcore)
  334.         $this->registerCoreBundlesToCollection($collection);
  335.         // custom bundles
  336.         $this->registerBundlesToCollection($collection);
  337.         // bundles registered in extensions.php
  338.         $this->registerExtensionManagerBundles($collection);
  339.         $bundles $collection->getBundles($this->getEnvironment());
  340.         $this->bundleCollection $collection;
  341.         return $bundles;
  342.     }
  343.     /**
  344.      * Creates bundle collection. Use this method to set bundles on the collection
  345.      * early.
  346.      *
  347.      * @return BundleCollection
  348.      */
  349.     protected function createBundleCollection(): BundleCollection
  350.     {
  351.         return new BundleCollection();
  352.     }
  353.     /**
  354.      * Returns the bundle collection which was used to build the set of used bundles
  355.      *
  356.      * @return BundleCollection
  357.      */
  358.     public function getBundleCollection(): BundleCollection
  359.     {
  360.         return $this->bundleCollection;
  361.     }
  362.     /**
  363.      * Registers "core" bundles
  364.      *
  365.      * @param BundleCollection $collection
  366.      */
  367.     protected function registerCoreBundlesToCollection(BundleCollection $collection)
  368.     {
  369.         $collection->addBundles([
  370.             // symfony "core"/standard
  371.             new FrameworkBundle(),
  372.             new SecurityBundle(),
  373.             new TwigBundle(),
  374.             new TwigExtraBundle(),
  375.             new MonologBundle(),
  376.             new DoctrineBundle(),
  377.             new DoctrineMigrationsBundle(),
  378.             new SensioFrameworkExtraBundle(),
  379.             new CmfRoutingBundle(),
  380.             new PrestaSitemapBundle(),
  381.             new SchebTwoFactorBundle(),
  382.             new FOSJsRoutingBundle(),
  383.             new FlysystemBundle(),
  384.         ], 100);
  385.         // pimcore bundles
  386.         $collection->addBundles([
  387.             new PimcoreCoreBundle(),
  388.             new PimcoreAdminBundle(),
  389.         ], 60);
  390.         // load development bundles only in matching environments
  391.         if (in_array($this->getEnvironment(), $this->getEnvironmentsForDevBundles(), true)) {
  392.             $collection->addBundles([
  393.                 new DebugBundle(),
  394.                 new WebProfilerBundle(),
  395.             ], 80);
  396.         }
  397.     }
  398.     protected function getEnvironmentsForDevBundles(): array
  399.     {
  400.         return ['dev''test'];
  401.     }
  402.     /**
  403.      * Registers bundles enabled via extension manager
  404.      *
  405.      * @deprecated will be removed in Pimcore 11
  406.      *
  407.      * @param BundleCollection $collection
  408.      */
  409.     protected function registerExtensionManagerBundles(BundleCollection $collection)
  410.     {
  411.         $stateConfig = new StateConfig($this->extensionConfig);
  412.         foreach ($stateConfig->getEnabledBundles() as $className => $options) {
  413.             if (!class_exists($className)) {
  414.                 continue;
  415.             }
  416.             // do not register bundles twice - skip if it was already loaded manually
  417.             if ($collection->hasItem($className)) {
  418.                 continue;
  419.             }
  420.             // use lazy loaded item to instantiate the bundle only if environment matches
  421.             $collection->add(new LazyLoadedItem(
  422.                 $className,
  423.                 $options['priority'],
  424.                 $options['environments'],
  425.                 ItemInterface::SOURCE_EXTENSION_MANAGER_CONFIG
  426.             ));
  427.         }
  428.     }
  429.     /**
  430.      * Adds bundles to register to the bundle collection. The collection is able
  431.      * to handle priorities and environment specific bundles.
  432.      *
  433.      * To be implemented in child classes
  434.      *
  435.      * @param BundleCollection $collection
  436.      */
  437.     public function registerBundlesToCollection(BundleCollection $collection)
  438.     {
  439.     }
  440.     /**
  441.      * Handle system settings and requirements
  442.      */
  443.     protected function setSystemRequirements()
  444.     {
  445.         // try to set system-internal variables
  446.         $maxExecutionTime 240;
  447.         if (php_sapi_name() === 'cli') {
  448.             $maxExecutionTime 0;
  449.         }
  450.         //@ini_set("memory_limit", "1024M");
  451.         @ini_set('max_execution_time', (string) $maxExecutionTime);
  452.         @set_time_limit($maxExecutionTime);
  453.         ini_set('default_charset''UTF-8');
  454.         // set internal character encoding to UTF-8
  455.         mb_internal_encoding('UTF-8');
  456.         // zlib.output_compression conflicts with while (@ob_end_flush()) ;
  457.         // see also: https://github.com/pimcore/pimcore/issues/291
  458.         if (ini_get('zlib.output_compression')) {
  459.             @ini_set('zlib.output_compression''Off');
  460.         }
  461.         // set dummy timezone if no tz is specified / required for example by the logger, ...
  462.         $defaultTimezone = @date_default_timezone_get();
  463.         if (!$defaultTimezone) {
  464.             date_default_timezone_set('UTC'); // UTC -> default timezone
  465.         }
  466.     }
  467.     /**
  468.      * {@inheritdoc}
  469.      */
  470.     public function locateResource(string $name)
  471.     {
  472.         // BC layer for supporting both presta/sitemap-bundle": "^2.1 || ^3.2
  473.         // @TODO to be removed in Pimcore 11
  474.         if ($name === '@PrestaSitemapBundle/Resources/config/routing.yml') {
  475.             try {
  476.                 // try the new location of v3 first, as most probably this is used
  477.                 return parent::locateResource('@PrestaSitemapBundle/config/routing.yml');
  478.             } catch (\InvalidArgumentException $e) {
  479.                 // if the file doesnt exist in the new location, try the v2 location
  480.                 return parent::locateResource($name);
  481.             }
  482.         }
  483.         return parent::locateResource($name);
  484.     }
  485. }