| Current Path : /var/www/surf/TYPO3/vendor/typo3/cms-core/Classes/Core/ |
| Current File : /var/www/surf/TYPO3/vendor/typo3/cms-core/Classes/Core/BootService.php |
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Core;
use Psr\Container\ContainerInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
use TYPO3\CMS\Core\Core\Event\BootCompletedEvent;
use TYPO3\CMS\Core\DependencyInjection\ContainerBuilder;
use TYPO3\CMS\Core\Package\PackageManager;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* @internal This is NOT an API class, it is for internal use in TYPO3 core only.
*/
class BootService
{
private ContainerBuilder $containerBuilder;
private ContainerInterface $failsafeContainer;
private ?ContainerInterface $container = null;
public function __construct(ContainerBuilder $containerBuilder, ContainerInterface $failsafeContainer)
{
$this->containerBuilder = $containerBuilder;
$this->failsafeContainer = $failsafeContainer;
}
public function getContainer(bool $allowCaching = true): ContainerInterface
{
return $this->container ?? $this->prepareContainer($allowCaching);
}
private function prepareContainer(bool $allowCaching = true): ContainerInterface
{
$packageManager = $this->failsafeContainer->get(PackageManager::class);
$dependencyInjectionContainerCache = $this->failsafeContainer->get('cache.di');
$failsafe = false;
// Build a non-failsafe container which is required for loading ext_localconf
$this->container = $this->containerBuilder->createDependencyInjectionContainer($packageManager, $dependencyInjectionContainerCache, $failsafe);
$this->container->set('_early.boot-service', $this);
if ($allowCaching) {
$this->container->get('boot.state')->cacheDisabled = false;
$coreCache = Bootstrap::createCache('core');
// Core cache is initialized with a NullBackend in failsafe mode.
// Replace it with a new cache that uses the real backend.
$this->container->set('_early.cache.core', $coreCache);
$this->container->set('_early.cache.assets', Bootstrap::createCache('assets'));
if (!Environment::isComposerMode()) {
$this->container->get(PackageManager::class)->setPackageCache(Bootstrap::createPackageCache($coreCache));
}
}
return $this->container;
}
/**
* Switch global context to a new context, or revert
* to the original booting container if no container
* is specified
*/
public function makeCurrent(ContainerInterface $container = null, array $backup = []): array
{
$container = $container ?? $backup['container'] ?? $this->failsafeContainer;
$newBackup = [
'singletonInstances' => GeneralUtility::getSingletonInstances(),
'container' => GeneralUtility::getContainer(),
];
GeneralUtility::purgeInstances();
// Set global state to the non-failsafe container and it's instances
GeneralUtility::setContainer($container);
ExtensionManagementUtility::setPackageManager($container->get(PackageManager::class));
$backupSingletonInstances = $backup['singletonInstances'] ?? [];
foreach ($backupSingletonInstances as $className => $instance) {
GeneralUtility::setSingletonInstance($className, $instance);
}
return $newBackup;
}
/**
* Bootstrap a non-failsafe container and load ext_localconf
*
* Use by actions like the database analyzer and the upgrade wizards which
* need additional bootstrap actions performed.
*
* Those actions can potentially fatal if some old extension is loaded that triggers
* a fatal in ext_localconf or ext_tables code! Use only if really needed.
*
* @param bool $resetContainer
* @param bool $allowCaching
*/
public function loadExtLocalconfDatabaseAndExtTables(bool $resetContainer = false, bool $allowCaching = true): ContainerInterface
{
$container = $this->getContainer($allowCaching);
$backup = $this->makeCurrent($container);
$beUserBackup = $GLOBALS['BE_USER'] ?? null;
$container->get('boot.state')->complete = false;
$eventDispatcher = $container->get(EventDispatcherInterface::class);
ExtensionManagementUtility::setEventDispatcher($eventDispatcher);
Bootstrap::loadTypo3LoadedExtAndExtLocalconf($allowCaching, $container->get('cache.core'));
Bootstrap::unsetReservedGlobalVariables();
$GLOBALS['BE_USER'] = $beUserBackup;
Bootstrap::loadBaseTca($allowCaching, $container->get('cache.core'));
$container->get('boot.state')->complete = true;
$eventDispatcher->dispatch(new BootCompletedEvent($allowCaching));
Bootstrap::loadExtTables($allowCaching, $container->get('cache.core'));
if ($resetContainer) {
$this->makeCurrent(null, $backup);
}
return $container;
}
public function resetGlobalContainer(): void
{
$this->makeCurrent(null, []);
}
public function getFailsafeContainer(): ContainerInterface
{
return $this->failsafeContainer;
}
}