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