‪TYPO3CMS  ‪main
Bootstrap.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
16 namespace ‪TYPO3\CMS\Core\Core;
17 
18 use Composer\Autoload\ClassLoader;
19 use Composer\InstalledVersions;
20 use Doctrine\Common\Annotations\AnnotationReader;
21 use Psr\Container\ContainerInterface;
22 use Psr\EventDispatcher\EventDispatcherInterface;
23 use Psr\Http\Message\ServerRequestInterface;
33 use TYPO3\CMS\Core\Configuration\ConfigurationManager;
39 use TYPO3\CMS\Core\DependencyInjection\ContainerBuilder;
41 use TYPO3\CMS\Core\Package\Cache\ComposerPackageArtifact;
45 use TYPO3\CMS\Core\Package\PackageManager;
49 
62 {
70  public static function ‪init(
71  ClassLoader $classLoader,
72  bool $failsafe = false
73  ): ContainerInterface {
74  $requestId = new ‪RequestId();
75 
76  static::initializeClassLoader($classLoader);
79  }
80 
81  static::startOutputBuffering();
82 
83  $configurationManager = static::createConfigurationManager();
84  if (!static::checkIfEssentialConfigurationExists($configurationManager)) {
85  $failsafe = true;
86  }
87  static::populateLocalConfiguration($configurationManager);
88 
89  $logManager = new ‪LogManager((string)$requestId);
90  // LogManager is used by the core ErrorHandler (using GeneralUtility::makeInstance),
91  // therefore we have to push the LogManager to GeneralUtility, in case there
92  // happen errors before we call GeneralUtility::setContainer().
93  GeneralUtility::setSingletonInstance(LogManager::class, $logManager);
94 
95  static::initializeErrorHandling();
96 
97  $disableCaching = $failsafe ? true : false;
99  $coreCache = static::createCache('core', $disableCaching);
100  $packageCache = static::createPackageCache($coreCache);
101  $packageManager = static::createPackageManager(
102  $failsafe ? FailsafePackageManager::class : PackageManager::class,
103  $packageCache
104  );
105 
106  static::setDefaultTimezone();
107  static::setMemoryLimit();
108 
109  $assetsCache = static::createCache('assets', $disableCaching);
110  $dependencyInjectionContainerCache = static::createCache('di');
111 
112  $bootState = new \stdClass();
113  $bootState->complete = false;
114  $bootState->cacheDisabled = $disableCaching;
115 
116  $builder = new ContainerBuilder([
117  ClassLoader::class => $classLoader,
118  ApplicationContext::class => ‪Environment::getContext(),
119  ConfigurationManager::class => $configurationManager,
120  LogManager::class => $logManager,
121  RequestId::class => $requestId,
122  'cache.di' => $dependencyInjectionContainerCache,
123  'cache.core' => $coreCache,
124  'cache.assets' => $assetsCache,
125  PackageManager::class => $packageManager,
126 
127  // @internal
128  'boot.state' => $bootState,
129  ]);
130 
131  $container = $builder->createDependencyInjectionContainer($packageManager, $dependencyInjectionContainerCache, $failsafe);
132 
133  // Push the container to GeneralUtility as we want to make sure its
134  // makeInstance() method creates classes using the container from now on.
135  GeneralUtility::setContainer($container);
136 
137  // Reset LogManager singleton instance in order for GeneralUtility::makeInstance()
138  // to proxy LogManager retrieval to ContainerInterface->get() from now on.
139  GeneralUtility::removeSingletonInstance(LogManager::class, $logManager);
140 
141  // Push PackageManager instance to ExtensionManagementUtility
143 
144  if ($failsafe) {
145  $bootState->complete = true;
146  return $container;
147  }
148 
149  $eventDispatcher = $container->get(EventDispatcherInterface::class);
150  $tcaFactory = $container->get(TcaFactory::class);
151  $container->get(ExtLocalconfFactory::class)->load();
152  static::unsetReservedGlobalVariables();
153  ‪$GLOBALS['TCA'] = $tcaFactory->get();
154  static::checkEncryptionKey();
155  $bootState->complete = true;
156  $eventDispatcher->dispatch(new ‪BootCompletedEvent(true));
157 
158  return $container;
159  }
160 
167  public static function ‪startOutputBuffering()
168  {
169  ob_start();
170  }
171 
180  public static function ‪baseSetup()
181  {
184  }
185  }
186 
193  public static function ‪initializeClassLoader(ClassLoader $classLoader)
194  {
196 
197  // Annotations used in unit tests
198  AnnotationReader::addGlobalIgnoredName('test');
199 
200  // Annotations that control the extension scanner
201  AnnotationReader::addGlobalIgnoredName('extensionScannerIgnoreFile');
202  AnnotationReader::addGlobalIgnoredName('extensionScannerIgnoreLine');
203  }
204 
214  public static function ‪checkIfEssentialConfigurationExists(ConfigurationManager $configurationManager): bool
215  {
217  && !file_exists(‪Environment::getLegacyConfigPath() . '/PackageStates.php')
218  ) {
219  // Early return in case system is not properly set up
220  return false;
221  }
222 
223  $systemConfigurationPath = $configurationManager->getSystemConfigurationFileLocation();
224  $additionalConfigurationPath = $configurationManager->getAdditionalConfigurationFileLocation();
225 
226  $systemConfigurationFileExists = file_exists($systemConfigurationPath);
227  $additionalConfigurationFileExists = file_exists($additionalConfigurationPath);
228  if ($systemConfigurationFileExists && $additionalConfigurationFileExists) {
229  // We have a complete configuration, off we go
230  return true;
231  }
232 
233  // If system configuration file exists and no legacy additional configuration is present, we are good
234  $legacyAdditionConfigurationPath = ‪Environment::getLegacyConfigPath() . '/AdditionalConfiguration.php';
235  $legacyAdditionalConfigurationFileExists = file_exists($legacyAdditionConfigurationPath);
236  if ($systemConfigurationFileExists && !$legacyAdditionalConfigurationFileExists) {
237  return true;
238  }
239 
240  // @deprecated All code below is deprecated and can be removed with TYPO3 v14.0 and replaced with `return false;`
241 
242  // All other cases will probably need some migration work
243  $migrated = false;
244 
245  // In case no system configuration file exists at this point, check for the legacy "LocalConfiguration"
246  // file. If it exists, move it to the new location. Otherwise, the system is not complete.
247  if (!$systemConfigurationFileExists) {
248  $legacyLocalConfigurationPath = $configurationManager->getLocalConfigurationFileLocation();
249  $legacySystemConfigurationFileExists = file_exists($legacyLocalConfigurationPath);
250  if ($legacySystemConfigurationFileExists) {
251  mkdir(dirname($systemConfigurationPath), 02775, true);
252  rename($legacyLocalConfigurationPath, $systemConfigurationPath);
253  $migrated = true;
254  } else {
255  // Directly return as essential system configuration does not exist
256  return false;
257  }
258  }
259  // In case no additional configuration file exists at this point, check for the legacy
260  // "AdditionalConfiguration" file. If it exists, move it to the new location as well.
261  if (!$additionalConfigurationFileExists && $legacyAdditionalConfigurationFileExists) {
262  rename($legacyAdditionConfigurationPath, $additionalConfigurationPath);
263  $migrated = true;
264  }
265 
266  return $migrated;
267  }
268 
276  public static function ‪createPackageManager($packageManagerClassName, ‪PackageCacheInterface $packageCache): PackageManager
277  {
278  $dependencyOrderingService = GeneralUtility::makeInstance(DependencyOrderingService::class);
280  $packageManager = new $packageManagerClassName($dependencyOrderingService);
281  $packageManager->setPackageCache($packageCache);
282  $packageManager->initialize();
283 
284  return $packageManager;
285  }
286 
291  {
293  return new ‪PackageStatesPackageCache(‪Environment::getLegacyConfigPath() . '/PackageStates.php', $coreCache);
294  }
295 
296  $composerInstallersPath = InstalledVersions::getInstallPath('typo3/cms-composer-installers');
297  if ($composerInstallersPath === null) {
298  throw new \RuntimeException('Package "typo3/cms-composer-installers" not found. Replacing the package is not allowed. Fork the package instead and pull in the fork with the same name.', 1636145677);
299  }
300 
301  return new ComposerPackageArtifact(dirname($composerInstallersPath));
302  }
303 
308  public static function ‪createConfigurationManager(): ConfigurationManager
309  {
310  return new ConfigurationManager();
311  }
312 
319  protected static function ‪populateLocalConfiguration(ConfigurationManager $configurationManager)
320  {
321  $configurationManager->exportConfiguration();
322  }
323 
335  public static function ‪createCache(string ‪$identifier, bool $disableCaching = false): ‪FrontendInterface
336  {
337  $cacheConfigurations = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'] ?? [];
338  $cacheConfigurations['di']['frontend'] = PhpFrontend::class;
339  $cacheConfigurations['di']['backend'] = ContainerBackend::class;
340  $cacheConfigurations['di']['options'] = [];
341  $configuration = $cacheConfigurations[‪$identifier] ?? [];
342 
343  $frontend = $configuration['frontend'] ?? VariableFrontend::class;
344  $backend = $configuration['backend'] ?? Typo3DatabaseBackend::class;
345  $options = $configuration['options'] ?? [];
346 
347  if ($disableCaching) {
348  $backend = NullBackend::class;
349  $options = [];
350  }
351 
352  $backendInstance = new $backend('production', $options);
353  if (!$backendInstance instanceof ‪BackendInterface) {
354  throw new ‪InvalidBackendException('"' . $backend . '" is not a valid cache backend object.', 1545260108);
355  }
356  if (is_callable([$backendInstance, 'initializeObject'])) {
357  $backendInstance->initializeObject();
358  }
359 
360  $frontendInstance = new $frontend(‪$identifier, $backendInstance);
361  if (!$frontendInstance instanceof ‪FrontendInterface) {
362  throw new ‪InvalidCacheException('"' . $frontend . '" is not a valid cache frontend object.', 1545260109);
363  }
364  if (is_callable([$frontendInstance, 'initializeObject'])) {
365  $frontendInstance->initializeObject();
366  }
367 
368  return $frontendInstance;
369  }
370 
374  protected static function ‪setDefaultTimezone()
375  {
376  $timeZone = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['phpTimeZone'];
377  if (empty($timeZone)) {
378  // Time zone from the server environment (TZ env or OS query)
379  $defaultTimeZone = @date_default_timezone_get();
380  if ($defaultTimeZone !== '') {
381  $timeZone = $defaultTimeZone;
382  } else {
383  $timeZone = 'UTC';
384  }
385  }
386  // Set default to avoid E_WARNINGs with PHP > 5.3
387  date_default_timezone_set($timeZone);
388  }
389 
395  protected static function ‪initializeErrorHandling()
396  {
397  $productionExceptionHandlerClassName = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['productionExceptionHandler'];
398  $debugExceptionHandlerClassName = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['debugExceptionHandler'];
399 
400  $errorHandlerClassName = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['errorHandler'];
401  $errorHandlerErrors = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['errorHandlerErrors'] | E_USER_DEPRECATED;
402  $exceptionalErrors = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['exceptionalErrors'];
403 
404  $displayErrorsSetting = (int)‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['displayErrors'];
405  switch ($displayErrorsSetting) {
406  case -1:
407  $ipMatchesDevelopmentSystem = ‪GeneralUtility::cmpIP(GeneralUtility::getIndpEnv('REMOTE_ADDR'), ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask']);
408  $exceptionHandlerClassName = $ipMatchesDevelopmentSystem ? $debugExceptionHandlerClassName : $productionExceptionHandlerClassName;
409  $displayErrors = $ipMatchesDevelopmentSystem ? 1 : 0;
410  $exceptionalErrors = $ipMatchesDevelopmentSystem ? $exceptionalErrors : 0;
411  break;
412  case 0:
413  $exceptionHandlerClassName = $productionExceptionHandlerClassName;
414  $displayErrors = 0;
415  break;
416  case 1:
417  $exceptionHandlerClassName = $debugExceptionHandlerClassName;
418  $displayErrors = 1;
419  break;
420  default:
421  // Throw exception if an invalid option is set. A default for displayErrors is set
422  // in very early install tool, coming from DefaultConfiguration.php. It is safe here
423  // to just throw if there is no value for whatever reason.
424  throw new \RuntimeException(
425  'The option $TYPO3_CONF_VARS[SYS][displayErrors] is not set to "-1", "0" or "1".',
426  1476046290
427  );
428  }
429  @ini_set('display_errors', (string)$displayErrors);
430 
431  if (!empty($errorHandlerClassName)) {
432  // Register an error handler for the given errorHandlerError
433  $errorHandler = GeneralUtility::makeInstance($errorHandlerClassName, $errorHandlerErrors);
434  $errorHandler->setExceptionalErrors($exceptionalErrors);
435  if (is_callable([$errorHandler, 'setDebugMode'])) {
436  $errorHandler->setDebugMode($displayErrors === 1);
437  }
438  if (is_callable([$errorHandler, 'registerErrorHandler'])) {
439  $errorHandler->registerErrorHandler();
440  }
441  }
442  if (!empty($exceptionHandlerClassName)) {
443  // Registering the exception handler is done in the constructor
444  GeneralUtility::makeInstance($exceptionHandlerClassName);
445  }
446  }
447 
452  protected static function ‪setMemoryLimit()
453  {
454  if ((int)‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['setMemoryLimit'] > 16) {
455  @ini_set('memory_limit', (string)((int)‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['setMemoryLimit'] . 'm'));
456  }
457  }
458 
465  public static function ‪unsetReservedGlobalVariables()
466  {
467  unset(‪$GLOBALS['TCA']);
468  unset(‪$GLOBALS['BE_USER']);
469  }
470 
474  protected static function ‪checkEncryptionKey()
475  {
476  if (empty(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'])) {
477  throw new \RuntimeException(
478  'TYPO3 Encryption is empty. $GLOBALS[\'TYPO3_CONF_VARS\'][\'SYS\'][\'encryptionKey\'] needs to be set for TYPO3 to work securely',
479  1502987245
480  );
481  }
482  }
483 
495  public static function ‪loadExtTables(bool $allowCaching = true, ‪FrontendInterface $coreCache = null)
496  {
497  $container = GeneralUtility::getContainer();
498  if ($allowCaching) {
499  $container->get(ExtTablesFactory::class)->load();
500  } else {
501  $container->get(ExtTablesFactory::class)->loadUncached();
502  }
503  }
504 
512  public static function ‪initializeBackendUser($className = BackendUserAuthentication::class, ServerRequestInterface $request = null)
513  {
515  $backendUser = GeneralUtility::makeInstance($className);
516  // The global must be available very early, because methods below
517  // might trigger code which relies on it. See: #45625
518  ‪$GLOBALS['BE_USER'] = $backendUser;
519  $backendUser->start($request);
520  }
521 
527  public static function ‪initializeBackendAuthentication()
528  {
529  ‪$GLOBALS['BE_USER']->backendCheckLogin();
530  }
531 }
‪TYPO3\CMS\Core\Configuration\Tca\TcaFactory
Definition: TcaFactory.php:34
‪TYPO3\CMS\Core\DependencyInjection\Cache\ContainerBackend
Definition: ContainerBackend.php:26
‪TYPO3\CMS\Core\Core\Bootstrap\baseSetup
‪static baseSetup()
Definition: Bootstrap.php:180
‪TYPO3\CMS\Core\Package\FailsafePackageManager
Definition: FailsafePackageManager.php:27
‪TYPO3\CMS\Core\Core\Bootstrap\unsetReservedGlobalVariables
‪static unsetReservedGlobalVariables()
Definition: Bootstrap.php:465
‪TYPO3\CMS\Core\Package\Cache\PackageStatesPackageCache
Definition: PackageStatesPackageCache.php:32
‪TYPO3\CMS\Core\Core\Environment\isComposerMode
‪static isComposerMode()
Definition: Environment.php:137
‪TYPO3\CMS\Core\Cache\Frontend\PhpFrontend
Definition: PhpFrontend.php:25
‪TYPO3\CMS\Core\Core\Bootstrap\createPackageCache
‪static createPackageCache(FrontendInterface $coreCache)
Definition: Bootstrap.php:290
‪TYPO3\CMS\Core\Cache\Exception\InvalidBackendException
Definition: InvalidBackendException.php:23
‪TYPO3\CMS\Core\Core\ClassLoadingInformation\isClassLoadingInformationAvailable
‪static bool isClassLoadingInformationAvailable()
Definition: ClassLoadingInformation.php:81
‪TYPO3\CMS\Core\Cache\Backend\Typo3DatabaseBackend
Definition: Typo3DatabaseBackend.php:30
‪TYPO3\CMS\Core\Utility\GeneralUtility\cmpIP
‪static bool cmpIP(string $baseIP, string $list)
Definition: GeneralUtility.php:113
‪TYPO3\CMS\Core\Core\Bootstrap\checkEncryptionKey
‪static checkEncryptionKey()
Definition: Bootstrap.php:474
‪TYPO3\CMS\Core\Core\Bootstrap\setMemoryLimit
‪static setMemoryLimit()
Definition: Bootstrap.php:452
‪TYPO3\CMS\Core\Core\Environment\getLegacyConfigPath
‪static getLegacyConfigPath()
Definition: Environment.php:268
‪TYPO3\CMS\Core\Core\Bootstrap\initializeClassLoader
‪static initializeClassLoader(ClassLoader $classLoader)
Definition: Bootstrap.php:193
‪TYPO3\CMS\Core\Core\Bootstrap\createConfigurationManager
‪static createConfigurationManager()
Definition: Bootstrap.php:308
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:32
‪TYPO3\CMS\Core\Cache\Backend\BackendInterface
Definition: BackendInterface.php:25
‪TYPO3\CMS\Core\Core\Bootstrap\setDefaultTimezone
‪static setDefaultTimezone()
Definition: Bootstrap.php:374
‪TYPO3\CMS\Core\Core\Bootstrap\initializeBackendUser
‪static initializeBackendUser($className=BackendUserAuthentication::class, ServerRequestInterface $request=null)
Definition: Bootstrap.php:512
‪TYPO3\CMS\Core\Package\Cache\PackageCacheInterface
Definition: PackageCacheInterface.php:33
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\setPackageManager
‪static setPackageManager(PackageManager $packageManager)
Definition: ExtensionManagementUtility.php:41
‪TYPO3\CMS\Core\Core\Bootstrap\initializeErrorHandling
‪static initializeErrorHandling()
Definition: Bootstrap.php:395
‪TYPO3\CMS\Core\Core\Bootstrap\init
‪static init(ClassLoader $classLoader, bool $failsafe=false)
Definition: Bootstrap.php:70
‪TYPO3\CMS\Core\Cache\Frontend\VariableFrontend
Definition: VariableFrontend.php:25
‪TYPO3\CMS\Core\Core\RequestId
Definition: RequestId.php:26
‪TYPO3\CMS\Core\Cache\Backend\NullBackend
Definition: NullBackend.php:22
‪TYPO3\CMS\Core\Core\Bootstrap\createPackageManager
‪static createPackageManager($packageManagerClassName, PackageCacheInterface $packageCache)
Definition: Bootstrap.php:276
‪TYPO3\CMS\Core\Service\DependencyOrderingService
Definition: DependencyOrderingService.php:32
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Core\Configuration\Extension\ExtLocalconfFactory
Definition: ExtLocalconfFactory.php:28
‪TYPO3\CMS\Core\Cache\Exception\InvalidCacheException
Definition: InvalidCacheException.php:23
‪TYPO3\CMS\Core\Core\Event\BootCompletedEvent
Definition: BootCompletedEvent.php:24
‪TYPO3\CMS\Core\Configuration\Extension\ExtTablesFactory
Definition: ExtTablesFactory.php:28
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:22
‪TYPO3\CMS\Core\Core\Bootstrap\createCache
‪static createCache(string $identifier, bool $disableCaching=false)
Definition: Bootstrap.php:335
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Log\LogManager
Definition: LogManager.php:33
‪TYPO3\CMS\Core\Core
Definition: ApplicationContext.php:16
‪TYPO3\CMS\Core\Core\Bootstrap
Definition: Bootstrap.php:62
‪TYPO3\CMS\Core\Core\Bootstrap\checkIfEssentialConfigurationExists
‪static bool checkIfEssentialConfigurationExists(ConfigurationManager $configurationManager)
Definition: Bootstrap.php:214
‪TYPO3\CMS\Core\Core\Bootstrap\populateLocalConfiguration
‪static populateLocalConfiguration(ConfigurationManager $configurationManager)
Definition: Bootstrap.php:319
‪TYPO3\CMS\Core\Core\ClassLoadingInformation\registerClassLoadingInformation
‪static registerClassLoadingInformation()
Definition: ClassLoadingInformation.php:108
‪TYPO3\CMS\Core\Core\Bootstrap\loadExtTables
‪static loadExtTables(bool $allowCaching=true, FrontendInterface $coreCache=null)
Definition: Bootstrap.php:495
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Core\Bootstrap\startOutputBuffering
‪static startOutputBuffering()
Definition: Bootstrap.php:167
‪TYPO3\CMS\Core\Core\Environment\getContext
‪static getContext()
Definition: Environment.php:128
‪TYPO3\CMS\Core\Core\ClassLoadingInformation\setClassLoader
‪static setClassLoader(ClassLoader $classLoader)
Definition: ClassLoadingInformation.php:70
‪TYPO3\CMS\Core\Core\Bootstrap\initializeBackendAuthentication
‪static initializeBackendAuthentication()
Definition: Bootstrap.php:527
‪TYPO3\CMS\Webhooks\Message\$identifier
‪identifier readonly string $identifier
Definition: FileAddedMessage.php:37