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