d0d6509374350d3394cea9c22e061d9d1ab4e780
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Core / Bootstrap.php
1 <?php
2 namespace TYPO3\CMS\Core\Core;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use Doctrine\Common\Annotations\AnnotationReader;
18 use Doctrine\Common\Annotations\AnnotationRegistry;
19 use TYPO3\CMS\Core\Log\LogManager;
20 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
21 use TYPO3\CMS\Core\Utility\GeneralUtility;
22
23 /**
24 * This class encapsulates bootstrap related methods.
25 * It is required directly as the very first thing in entry scripts and
26 * used to define all base things like constants and paths and so on.
27 *
28 * Most methods in this class have dependencies to each other. They can
29 * not be called in arbitrary order. The methods are ordered top down, so
30 * a method at the beginning has lower dependencies than a method further
31 * down. Do not fiddle with the load order in own scripts except you know
32 * exactly what you are doing!
33 */
34 class Bootstrap
35 {
36 /**
37 * @var \TYPO3\CMS\Core\Core\Bootstrap
38 */
39 protected static $instance = null;
40
41 /**
42 * Unique Request ID
43 *
44 * @var string
45 */
46 protected $requestId;
47
48 /**
49 * The application context
50 *
51 * @var \TYPO3\CMS\Core\Core\ApplicationContext
52 */
53 protected $applicationContext;
54
55 /**
56 * @var array List of early instances
57 */
58 protected $earlyInstances = [];
59
60 /**
61 * @var bool
62 */
63 protected static $usesComposerClassLoading = false;
64
65 /**
66 * Disable direct creation of this object.
67 * Set unique requestId and the application context
68 *
69 * @var string Application context
70 */
71 protected function __construct($applicationContext)
72 {
73 $this->requestId = substr(md5(uniqid('', true)), 0, 13);
74 $this->applicationContext = new ApplicationContext($applicationContext);
75 }
76
77 /**
78 * @return bool
79 */
80 public static function usesComposerClassLoading()
81 {
82 return self::$usesComposerClassLoading;
83 }
84
85 /**
86 * Disable direct cloning of this object.
87 */
88 protected function __clone()
89 {
90 }
91
92 /**
93 * Return 'this' as singleton
94 *
95 * @return Bootstrap
96 * @internal This is not a public API method, do not use in own extensions
97 */
98 public static function getInstance()
99 {
100 if (static::$instance === null) {
101 $applicationContext = getenv('TYPO3_CONTEXT') ?: (getenv('REDIRECT_TYPO3_CONTEXT') ?: 'Production');
102 self::$instance = new static($applicationContext);
103 self::$instance->defineTypo3RequestTypes();
104 GeneralUtility::setSingletonInstance(LogManager::class, new LogManager(self::$instance->requestId));
105 }
106 return static::$instance;
107 }
108
109 /**
110 * Prevent any unwanted output that may corrupt AJAX/compression.
111 * This does not interfere with "die()" or "echo"+"exit()" messages!
112 *
113 * @return Bootstrap
114 * @internal This is not a public API method, do not use in own extensions
115 */
116 public function startOutputBuffering()
117 {
118 ob_start();
119 return $this;
120 }
121
122 /**
123 * Main entry point called at every request usually from Global scope. Checks if everything is correct,
124 * and loads the Configuration.
125 *
126 * Make sure that the baseSetup() is called before and the class loader is present
127 *
128 * @return Bootstrap
129 */
130 public function configure()
131 {
132 $this->startOutputBuffering()
133 ->loadConfigurationAndInitialize()
134 ->loadTypo3LoadedExtAndExtLocalconf(true)
135 ->setFinalCachingFrameworkCacheConfiguration()
136 ->unsetReservedGlobalVariables()
137 ->loadBaseTca();
138 if (empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'])) {
139 throw new \RuntimeException(
140 'TYPO3 Encryption is empty. $GLOBALS[\'TYPO3_CONF_VARS\'][\'SYS\'][\'encryptionKey\'] needs to be set for TYPO3 to work securely',
141 1502987245
142 );
143 }
144 return $this;
145 }
146
147 /**
148 * Run the base setup that checks server environment, determines paths,
149 * populates base files and sets common configuration.
150 *
151 * Script execution will be aborted if something fails here.
152 *
153 * @param int $entryPointLevel Number of subdirectories where the entry script is located under the document root
154 * @return Bootstrap
155 * @throws \RuntimeException when TYPO3_REQUESTTYPE was not set before, setRequestType() needs to be called before
156 * @internal This is not a public API method, do not use in own extensions
157 */
158 public function baseSetup($entryPointLevel = 0)
159 {
160 if (!defined('TYPO3_REQUESTTYPE')) {
161 throw new \RuntimeException('No Request Type was set, TYPO3 does not know in which context it is run.', 1450561838);
162 }
163 GeneralUtility::presetApplicationContext($this->applicationContext);
164 SystemEnvironmentBuilder::run($entryPointLevel);
165 if (!self::$usesComposerClassLoading && ClassLoadingInformation::isClassLoadingInformationAvailable()) {
166 ClassLoadingInformation::registerClassLoadingInformation();
167 }
168 return $this;
169 }
170
171 /**
172 * Sets the class loader to the bootstrap
173 *
174 * @param \Composer\Autoload\ClassLoader $classLoader an instance of the class loader
175 * @return Bootstrap
176 * @internal This is not a public API method, do not use in own extensions
177 */
178 public function initializeClassLoader($classLoader)
179 {
180 $this->setEarlyInstance(\Composer\Autoload\ClassLoader::class, $classLoader);
181 ClassLoadingInformation::setClassLoader($classLoader);
182 if (defined('TYPO3_COMPOSER_MODE') && TYPO3_COMPOSER_MODE) {
183 self::$usesComposerClassLoading = true;
184 }
185
186 /** @see initializeAnnotationRegistry */
187 AnnotationRegistry::registerLoader([$classLoader, 'loadClass']);
188
189 /*
190 * All annotations defined by and for Extbase need to be
191 * ignored during their deprecation. Later, their usage may and
192 * should throw an Exception
193 */
194 AnnotationReader::addGlobalIgnoredName('inject');
195 AnnotationReader::addGlobalIgnoredName('transient');
196 AnnotationReader::addGlobalIgnoredName('lazy');
197 AnnotationReader::addGlobalIgnoredName('validate');
198 AnnotationReader::addGlobalIgnoredName('cascade');
199 AnnotationReader::addGlobalIgnoredName('ignorevalidation');
200 AnnotationReader::addGlobalIgnoredName('cli');
201 AnnotationReader::addGlobalIgnoredName('flushesCaches');
202 AnnotationReader::addGlobalIgnoredName('uuid');
203 AnnotationReader::addGlobalIgnoredName('identity');
204
205 // Annotations used in unit tests
206 AnnotationReader::addGlobalIgnoredName('test');
207
208 // Annotations that control the extension scanner
209 AnnotationReader::addGlobalIgnoredName('extensionScannerIgnoreFile');
210 AnnotationReader::addGlobalIgnoredName('extensionScannerIgnoreLine');
211
212 return $this;
213 }
214
215 /**
216 * checks if LocalConfiguration.php or PackageStates.php is missing,
217 * used to see if a redirect to the install tool is needed
218 *
219 * @return bool TRUE when the essential configuration is available, otherwise FALSE
220 * @internal This is not a public API method, do not use in own extensions
221 */
222 public function checkIfEssentialConfigurationExists()
223 {
224 $configurationManager = new \TYPO3\CMS\Core\Configuration\ConfigurationManager;
225 $this->setEarlyInstance(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, $configurationManager);
226 return file_exists($configurationManager->getLocalConfigurationFileLocation()) && file_exists(PATH_typo3conf . 'PackageStates.php');
227 }
228
229 /**
230 * Registers the instance of the specified object for an early boot stage.
231 * On finalizing the Object Manager initialization, all those instances will
232 * be transferred to the Object Manager's registry.
233 *
234 * @param string $objectName Object name, as later used by the Object Manager
235 * @param object $instance The instance to register
236 * @internal This is not a public API method, do not use in own extensions
237 */
238 public function setEarlyInstance($objectName, $instance)
239 {
240 $this->earlyInstances[$objectName] = $instance;
241 }
242
243 /**
244 * Returns an instance which was registered earlier through setEarlyInstance()
245 *
246 * @param string $objectName Object name of the registered instance
247 * @return object
248 * @throws \TYPO3\CMS\Core\Exception
249 * @internal This is not a public API method, do not use in own extensions
250 */
251 public function getEarlyInstance($objectName)
252 {
253 if (!isset($this->earlyInstances[$objectName])) {
254 throw new \TYPO3\CMS\Core\Exception('Unknown early instance "' . $objectName . '"', 1365167380);
255 }
256 return $this->earlyInstances[$objectName];
257 }
258
259 /**
260 * Returns all registered early instances indexed by object name
261 *
262 * @return array
263 * @internal This is not a public API method, do not use in own extensions
264 */
265 public function getEarlyInstances()
266 {
267 return $this->earlyInstances;
268 }
269
270 /**
271 * Includes LocalConfiguration.php and sets several
272 * global settings depending on configuration.
273 *
274 * @param bool $allowCaching Whether to allow caching - affects cache_core (autoloader)
275 * @param string $packageManagerClassName Define an alternative package manager implementation (usually for the installer)
276 * @return Bootstrap
277 * @internal This is not a public API method, do not use in own extensions
278 */
279 public function loadConfigurationAndInitialize($allowCaching = true, $packageManagerClassName = \TYPO3\CMS\Core\Package\PackageManager::class)
280 {
281 $this->populateLocalConfiguration()
282 ->initializeErrorHandling();
283 if (!$allowCaching) {
284 $this->disableCoreCache();
285 }
286 $this->initializeCachingFramework()
287 ->initializePackageManagement($packageManagerClassName)
288 ->initializeRuntimeActivatedPackagesFromConfiguration()
289 ->setDefaultTimezone()
290 ->initializeL10nLocales()
291 ->setMemoryLimit();
292 return $this;
293 }
294
295 /**
296 * Initializes the package system and loads the package configuration and settings
297 * provided by the packages.
298 *
299 * @param string $packageManagerClassName Define an alternative package manager implementation (usually for the installer)
300 * @return Bootstrap
301 * @internal This is not a public API method, do not use in own extensions
302 */
303 public function initializePackageManagement($packageManagerClassName)
304 {
305 /** @var \TYPO3\CMS\Core\Package\PackageManager $packageManager */
306 $packageManager = new $packageManagerClassName();
307 GeneralUtility::setSingletonInstance(\TYPO3\CMS\Core\Package\PackageManager::class, $packageManager);
308 $this->setEarlyInstance(\TYPO3\CMS\Core\Package\PackageManager::class, $packageManager);
309 ExtensionManagementUtility::setPackageManager($packageManager);
310 $packageManager->injectCoreCache(GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('cache_core'));
311 $dependencyResolver = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Package\DependencyResolver::class);
312 $dependencyResolver->injectDependencyOrderingService(GeneralUtility::makeInstance(\TYPO3\CMS\Core\Service\DependencyOrderingService::class));
313 $packageManager->injectDependencyResolver($dependencyResolver);
314 $packageManager->initialize();
315 return $this;
316 }
317
318 /**
319 * Activates a package during runtime. This is used in AdditionalConfiguration.php
320 * to enable extensions under conditions.
321 *
322 * @return Bootstrap
323 */
324 protected function initializeRuntimeActivatedPackagesFromConfiguration()
325 {
326 $packages = $GLOBALS['TYPO3_CONF_VARS']['EXT']['runtimeActivatedPackages'] ?? [];
327 if (!empty($packages)) {
328 $packageManager = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Package\PackageManager::class);
329 foreach ($packages as $runtimeAddedPackageKey) {
330 $packageManager->activatePackageDuringRuntime($runtimeAddedPackageKey);
331 }
332 }
333 return $this;
334 }
335
336 /**
337 * Load ext_localconf of extensions
338 *
339 * @param bool $allowCaching
340 * @return Bootstrap
341 * @internal This is not a public API method, do not use in own extensions
342 */
343 public function loadTypo3LoadedExtAndExtLocalconf($allowCaching = true)
344 {
345 ExtensionManagementUtility::loadExtLocalconf($allowCaching);
346 return $this;
347 }
348
349 /**
350 * We need an early instance of the configuration manager.
351 * Since makeInstance relies on the object configuration, we create it here with new instead.
352 *
353 * @return Bootstrap
354 * @internal This is not a public API method, do not use in own extensions
355 */
356 public function populateLocalConfiguration()
357 {
358 try {
359 $configurationManager = $this->getEarlyInstance(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class);
360 } catch (\TYPO3\CMS\Core\Exception $exception) {
361 $configurationManager = new \TYPO3\CMS\Core\Configuration\ConfigurationManager();
362 $this->setEarlyInstance(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, $configurationManager);
363 }
364 $configurationManager->exportConfiguration();
365 return $this;
366 }
367
368 /**
369 * Set cache_core to null backend, effectively disabling eg. the cache for ext_localconf and PackageManager etc.
370 *
371 * @return \TYPO3\CMS\Core\Core\Bootstrap
372 * @internal This is not a public API method, do not use in own extensions
373 */
374 public function disableCoreCache()
375 {
376 $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_core']['backend']
377 = \TYPO3\CMS\Core\Cache\Backend\NullBackend::class;
378 unset($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_core']['options']);
379 return $this;
380 }
381
382 /**
383 * Initialize caching framework, and re-initializes it (e.g. in the install tool) by recreating the instances
384 * again despite the Singleton instance
385 *
386 * @return Bootstrap
387 * @internal This is not a public API method, do not use in own extensions
388 */
389 public function initializeCachingFramework()
390 {
391 $cacheManager = new \TYPO3\CMS\Core\Cache\CacheManager();
392 $cacheManager->setCacheConfigurations($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']);
393 GeneralUtility::setSingletonInstance(\TYPO3\CMS\Core\Cache\CacheManager::class, $cacheManager);
394 $this->setEarlyInstance(\TYPO3\CMS\Core\Cache\CacheManager::class, $cacheManager);
395 return $this;
396 }
397
398 /**
399 * Set default timezone
400 *
401 * @return Bootstrap
402 */
403 protected function setDefaultTimezone()
404 {
405 $timeZone = $GLOBALS['TYPO3_CONF_VARS']['SYS']['phpTimeZone'];
406 if (empty($timeZone)) {
407 // Time zone from the server environment (TZ env or OS query)
408 $defaultTimeZone = @date_default_timezone_get();
409 if ($defaultTimeZone !== '') {
410 $timeZone = $defaultTimeZone;
411 } else {
412 $timeZone = 'UTC';
413 }
414 }
415 // Set default to avoid E_WARNINGs with PHP > 5.3
416 date_default_timezone_set($timeZone);
417 return $this;
418 }
419
420 /**
421 * Initialize the locales handled by TYPO3
422 *
423 * @return Bootstrap
424 */
425 protected function initializeL10nLocales()
426 {
427 \TYPO3\CMS\Core\Localization\Locales::initialize();
428 return $this;
429 }
430
431 /**
432 * Configure and set up exception and error handling
433 *
434 * @return Bootstrap
435 * @throws \RuntimeException
436 */
437 protected function initializeErrorHandling()
438 {
439 $productionExceptionHandlerClassName = $GLOBALS['TYPO3_CONF_VARS']['SYS']['productionExceptionHandler'];
440 $debugExceptionHandlerClassName = $GLOBALS['TYPO3_CONF_VARS']['SYS']['debugExceptionHandler'];
441
442 $errorHandlerClassName = $GLOBALS['TYPO3_CONF_VARS']['SYS']['errorHandler'];
443 $errorHandlerErrors = $GLOBALS['TYPO3_CONF_VARS']['SYS']['errorHandlerErrors'];
444 $exceptionalErrors = $GLOBALS['TYPO3_CONF_VARS']['SYS']['exceptionalErrors'];
445
446 $displayErrorsSetting = (int)$GLOBALS['TYPO3_CONF_VARS']['SYS']['displayErrors'];
447 switch ($displayErrorsSetting) {
448 case -1:
449 $ipMatchesDevelopmentSystem = GeneralUtility::cmpIP(GeneralUtility::getIndpEnv('REMOTE_ADDR'), $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask']);
450 $exceptionHandlerClassName = $ipMatchesDevelopmentSystem ? $debugExceptionHandlerClassName : $productionExceptionHandlerClassName;
451 $displayErrors = $ipMatchesDevelopmentSystem ? 1 : 0;
452 $exceptionalErrors = $ipMatchesDevelopmentSystem ? $exceptionalErrors : 0;
453 break;
454 case 0:
455 $exceptionHandlerClassName = $productionExceptionHandlerClassName;
456 $displayErrors = 0;
457 break;
458 case 1:
459 $exceptionHandlerClassName = $debugExceptionHandlerClassName;
460 $displayErrors = 1;
461 break;
462 default:
463 if (!(TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_INSTALL)) {
464 // Throw exception if an invalid option is set.
465 throw new \RuntimeException(
466 'The option $TYPO3_CONF_VARS[SYS][displayErrors] is not set to "-1", "0" or "1".',
467 1476046290
468 );
469 }
470 }
471 @ini_set('display_errors', (string)$displayErrors);
472
473 if (!empty($errorHandlerClassName)) {
474 // Register an error handler for the given errorHandlerError
475 $errorHandler = GeneralUtility::makeInstance($errorHandlerClassName, $errorHandlerErrors);
476 $errorHandler->setExceptionalErrors($exceptionalErrors);
477 if (is_callable([$errorHandler, 'setDebugMode'])) {
478 $errorHandler->setDebugMode($displayErrors === 1);
479 }
480 }
481 if (!empty($exceptionHandlerClassName)) {
482 // Registering the exception handler is done in the constructor
483 GeneralUtility::makeInstance($exceptionHandlerClassName);
484 }
485 return $this;
486 }
487
488 /**
489 * Set PHP memory limit depending on value of
490 * $GLOBALS['TYPO3_CONF_VARS']['SYS']['setMemoryLimit']
491 *
492 * @return Bootstrap
493 */
494 protected function setMemoryLimit()
495 {
496 if ((int)$GLOBALS['TYPO3_CONF_VARS']['SYS']['setMemoryLimit'] > 16) {
497 @ini_set('memory_limit', (string)((int)$GLOBALS['TYPO3_CONF_VARS']['SYS']['setMemoryLimit'] . 'm'));
498 }
499 return $this;
500 }
501
502 /**
503 * Define TYPO3_REQUESTTYPE* constants that can be used for developers to see if any context has been hit
504 * also see setRequestType(). Is done at the very beginning so these parameters are always available.
505 */
506 protected function defineTypo3RequestTypes()
507 {
508 define('TYPO3_REQUESTTYPE_FE', 1);
509 define('TYPO3_REQUESTTYPE_BE', 2);
510 define('TYPO3_REQUESTTYPE_CLI', 4);
511 define('TYPO3_REQUESTTYPE_AJAX', 8);
512 define('TYPO3_REQUESTTYPE_INSTALL', 16);
513 }
514
515 /**
516 * Defines the TYPO3_REQUESTTYPE constant so the environment knows which context the request is running.
517 *
518 * @param int $requestType
519 * @throws \RuntimeException if the method was already called during a request
520 * @return Bootstrap
521 */
522 public function setRequestType($requestType)
523 {
524 if (defined('TYPO3_REQUESTTYPE')) {
525 throw new \RuntimeException('TYPO3_REQUESTTYPE has already been set, cannot be called multiple times', 1450561878);
526 }
527 define('TYPO3_REQUESTTYPE', $requestType);
528 return $this;
529 }
530
531 /**
532 * Extensions may register new caches, so we set the
533 * global cache array to the manager again at this point
534 *
535 * @return Bootstrap
536 * @internal This is not a public API method, do not use in own extensions
537 */
538 public function setFinalCachingFrameworkCacheConfiguration()
539 {
540 GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->setCacheConfigurations($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']);
541 return $this;
542 }
543
544 /**
545 * Unsetting reserved global variables:
546 * Those are set in "ext:core/ext_tables.php" file:
547 *
548 * @return Bootstrap
549 * @internal This is not a public API method, do not use in own extensions
550 */
551 public function unsetReservedGlobalVariables()
552 {
553 unset($GLOBALS['PAGES_TYPES']);
554 unset($GLOBALS['TCA']);
555 unset($GLOBALS['TBE_MODULES']);
556 unset($GLOBALS['TBE_STYLES']);
557 unset($GLOBALS['BE_USER']);
558 // Those set otherwise:
559 unset($GLOBALS['TBE_MODULES_EXT']);
560 unset($GLOBALS['TCA_DESCR']);
561 unset($GLOBALS['LOCAL_LANG']);
562 return $this;
563 }
564
565 /**
566 * Load $TCA
567 *
568 * This will mainly set up $TCA through extMgm API.
569 *
570 * @param bool $allowCaching True, if loading TCA from cache is allowed
571 * @return Bootstrap
572 * @internal This is not a public API method, do not use in own extensions
573 */
574 public function loadBaseTca(bool $allowCaching = true): Bootstrap
575 {
576 ExtensionManagementUtility::loadBaseTca($allowCaching);
577 return $this;
578 }
579
580 /**
581 * Load ext_tables and friends.
582 *
583 * This will mainly load and execute ext_tables.php files of loaded extensions
584 * or the according cache file if exists.
585 *
586 * @param bool $allowCaching True, if reading compiled ext_tables file from cache is allowed
587 * @return Bootstrap
588 * @internal This is not a public API method, do not use in own extensions
589 */
590 public function loadExtTables(bool $allowCaching = true): Bootstrap
591 {
592 ExtensionManagementUtility::loadExtTables($allowCaching);
593 $this->runExtTablesPostProcessingHooks();
594 return $this;
595 }
596
597 /**
598 * Check for registered ext tables hooks and run them
599 *
600 * @throws \UnexpectedValueException
601 */
602 protected function runExtTablesPostProcessingHooks()
603 {
604 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['extTablesInclusion-PostProcessing'] ?? [] as $className) {
605 /** @var $hookObject \TYPO3\CMS\Core\Database\TableConfigurationPostProcessingHookInterface */
606 $hookObject = GeneralUtility::makeInstance($className);
607 if (!$hookObject instanceof \TYPO3\CMS\Core\Database\TableConfigurationPostProcessingHookInterface) {
608 throw new \UnexpectedValueException(
609 '$hookObject "' . $className . '" must implement interface TYPO3\\CMS\\Core\\Database\\TableConfigurationPostProcessingHookInterface',
610 1320585902
611 );
612 }
613 $hookObject->processData();
614 }
615 }
616
617 /**
618 * Initialize the Routing for the TYPO3 Backend
619 * Loads all routes registered inside all packages and stores them inside the Router
620 *
621 * @return Bootstrap
622 * @internal This is not a public API method, do not use in own extensions
623 */
624 public function initializeBackendRouter()
625 {
626 // See if the Routes.php from all active packages have been built together already
627 $cacheIdentifier = 'BackendRoutesFromPackages_' . sha1((TYPO3_version . PATH_site . 'BackendRoutesFromPackages'));
628
629 /** @var $codeCache \TYPO3\CMS\Core\Cache\Frontend\FrontendInterface */
630 $codeCache = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('cache_core');
631 $routesFromPackages = [];
632 if ($codeCache->has($cacheIdentifier)) {
633 // substr is necessary, because the php frontend wraps php code around the cache value
634 $routesFromPackages = unserialize(substr($codeCache->get($cacheIdentifier), 6, -2));
635 } else {
636 // Loop over all packages and check for a Configuration/Backend/Routes.php file
637 $packageManager = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Package\PackageManager::class);
638 $packages = $packageManager->getActivePackages();
639 foreach ($packages as $package) {
640 $routesFileNameForPackage = $package->getPackagePath() . 'Configuration/Backend/Routes.php';
641 if (file_exists($routesFileNameForPackage)) {
642 $definedRoutesInPackage = require $routesFileNameForPackage;
643 if (is_array($definedRoutesInPackage)) {
644 $routesFromPackages = array_merge($routesFromPackages, $definedRoutesInPackage);
645 }
646 }
647 $routesFileNameForPackage = $package->getPackagePath() . 'Configuration/Backend/AjaxRoutes.php';
648 if (file_exists($routesFileNameForPackage)) {
649 $definedRoutesInPackage = require $routesFileNameForPackage;
650 if (is_array($definedRoutesInPackage)) {
651 foreach ($definedRoutesInPackage as $routeIdentifier => $routeOptions) {
652 // prefix the route with "ajax_" as "namespace"
653 $routeOptions['path'] = '/ajax' . $routeOptions['path'];
654 $routesFromPackages['ajax_' . $routeIdentifier] = $routeOptions;
655 $routesFromPackages['ajax_' . $routeIdentifier]['ajax'] = true;
656 }
657 }
658 }
659 }
660 // Store the data from all packages in the cache
661 $codeCache->set($cacheIdentifier, serialize($routesFromPackages));
662 }
663
664 // Build Route objects from the data
665 $router = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\Router::class);
666 foreach ($routesFromPackages as $name => $options) {
667 $path = $options['path'];
668 unset($options['path']);
669 $route = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\Route::class, $path, $options);
670 $router->addRoute($name, $route);
671 }
672 return $this;
673 }
674
675 /**
676 * Initialize backend user object in globals
677 *
678 * @param string $className usually \TYPO3\CMS\Core\Authentication\BackendUserAuthentication::class but can be used for CLI
679 * @return Bootstrap
680 * @internal This is not a public API method, do not use in own extensions
681 */
682 public function initializeBackendUser($className = \TYPO3\CMS\Core\Authentication\BackendUserAuthentication::class)
683 {
684 /** @var $backendUser \TYPO3\CMS\Core\Authentication\BackendUserAuthentication */
685 $backendUser = GeneralUtility::makeInstance($className);
686 // The global must be available very early, because methods below
687 // might trigger code which relies on it. See: #45625
688 $GLOBALS['BE_USER'] = $backendUser;
689 $backendUser->start();
690 return $this;
691 }
692
693 /**
694 * Initializes and ensures authenticated access
695 *
696 * @internal This is not a public API method, do not use in own extensions
697 * @param bool $proceedIfNoUserIsLoggedIn if set to TRUE, no forced redirect to the login page will be done
698 * @return \TYPO3\CMS\Core\Core\Bootstrap
699 */
700 public function initializeBackendAuthentication($proceedIfNoUserIsLoggedIn = false)
701 {
702 $GLOBALS['BE_USER']->backendCheckLogin($proceedIfNoUserIsLoggedIn);
703 return $this;
704 }
705
706 /**
707 * Initialize language object
708 *
709 * @return Bootstrap
710 * @internal This is not a public API method, do not use in own extensions
711 */
712 public function initializeLanguageObject()
713 {
714 /** @var $GLOBALS['LANG'] \TYPO3\CMS\Core\Localization\LanguageService */
715 $GLOBALS['LANG'] = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Localization\LanguageService::class);
716 $GLOBALS['LANG']->init($GLOBALS['BE_USER']->uc['lang']);
717 return $this;
718 }
719 }