[BUGFIX] Correct path for redirect to Installer
[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 TYPO3\CMS\Core\Utility;
18
19 /**
20 * This class encapsulates bootstrap related methods.
21 * It is required directly as the very first thing in entry scripts and
22 * used to define all base things like constants and pathes and so on.
23 *
24 * Most methods in this class have dependencies to each other. They can
25 * not be called in arbitrary order. The methods are ordered top down, so
26 * a method at the beginning has lower dependencies than a method further
27 * down. Do not fiddle with the load order in own scripts except you know
28 * exactly what you are doing!
29 *
30 * @author Christian Kuhn <lolli@schwarzbu.ch>
31 */
32 class Bootstrap {
33
34 /**
35 * @var \TYPO3\CMS\Core\Core\Bootstrap
36 */
37 static protected $instance = NULL;
38
39 /**
40 * Unique Request ID
41 *
42 * @var string
43 */
44 protected $requestId;
45
46 /**
47 * The application context
48 *
49 * @var \TYPO3\CMS\Core\Core\ApplicationContext
50 */
51 protected $applicationContext;
52
53 /**
54 * @var array List of early instances
55 */
56 protected $earlyInstances = array();
57
58 /**
59 * @var string Path to install tool
60 */
61 protected $installToolPath;
62
63 /**
64 * @var string The currently active exception handling class. It is set after LocalConfiguration is included and might be changed after ex_localconf.php are loaded.
65 */
66 protected $activeExceptionHandlerClassName;
67
68 /**
69 * @var string The currently active error handling class. It is set after LocalConfiguration is included and might be changed after ex_localconf.php are loaded.
70 */
71 protected $activeErrorHandlerClassName;
72
73 /**
74 * registered request handlers
75 * @var RequestHandlerInterface[]
76 */
77 protected $availableRequestHandlers = array();
78
79 /**
80 * @var bool
81 */
82 static protected $usesComposerClassLoading = FALSE;
83
84 /**
85 * Disable direct creation of this object.
86 * Set unique requestId and the application context
87 *
88 * @var string Application context
89 */
90 protected function __construct($applicationContext) {
91 $this->requestId = substr(md5(uniqid('', TRUE)), 0, 13);
92 $this->applicationContext = new ApplicationContext($applicationContext);
93 }
94
95 /**
96 * @return bool
97 */
98 static public function usesComposerClassLoading() {
99 return self::$usesComposerClassLoading;
100 }
101
102 /**
103 * Disable direct cloning of this object.
104 */
105 protected function __clone() {
106
107 }
108
109 /**
110 * Return 'this' as singleton
111 *
112 * @return Bootstrap
113 * @internal This is not a public API method, do not use in own extensions
114 */
115 static public function getInstance() {
116 if (is_null(static::$instance)) {
117 $composerClassLoader = self::initializeComposerClassLoader();
118 $applicationContext = getenv('TYPO3_CONTEXT') ?: (getenv('REDIRECT_TYPO3_CONTEXT') ?: 'Production');
119 self::$instance = new static($applicationContext);
120 // Establish an alias for Flow/Package interoperability
121 class_alias(get_class(static::$instance), \TYPO3\Flow\Core\Bootstrap::class);
122 self::$instance->setEarlyInstance(\Composer\Autoload\ClassLoader::class, $composerClassLoader);
123 }
124 return static::$instance;
125 }
126
127 /**
128 * Gets the request's unique ID
129 *
130 * @return string Unique request ID
131 * @internal This is not a public API method, do not use in own extensions
132 */
133 public function getRequestId() {
134 return $this->requestId;
135 }
136
137 /**
138 * Returns the application context this bootstrap was started in.
139 *
140 * @return \TYPO3\CMS\Core\Core\ApplicationContext The application context encapsulated in an object
141 * @internal This is not a public API method, do not use in own extensions.
142 * Use \TYPO3\CMS\Core\Utility\GeneralUtility::getApplicationContext() instead
143 */
144 public function getApplicationContext() {
145 return $this->applicationContext;
146 }
147
148 /**
149 * Prevent any unwanted output that may corrupt AJAX/compression.
150 * This does not interfere with "die()" or "echo"+"exit()" messages!
151 *
152 * @return Bootstrap
153 * @internal This is not a public API method, do not use in own extensions
154 */
155 public function startOutputBuffering() {
156 ob_start();
157 return $this;
158 }
159
160 /**
161 * Main entry point called at every request usually from Global scope. Checks if everthing is correct,
162 * and sets up the base request information for a regular request, then
163 * resolves the RequestHandler which handles the request.
164 *
165 * @param string $relativePathPart Relative path of entry script back to document root
166 * @return Bootstrap
167 */
168 public function run($relativePathPart = '') {
169 $this->baseSetup($relativePathPart);
170
171 // Failsafe minimal setup mode for the install tool
172 if (defined('TYPO3_enterInstallScript')) {
173 $this->startOutputBuffering()
174 ->loadConfigurationAndInitialize(FALSE, \TYPO3\CMS\Core\Package\FailsafePackageManager::class);
175 } elseif (!$this->checkIfEssentialConfigurationExists() && !defined('TYPO3_cliMode')) {
176 // Redirect to install tool if base configuration is not found
177 $backPathToSiteRoot = str_repeat('../', count(explode('/', $relativePathPart)) - 1);
178 $this->redirectToInstallTool($backPathToSiteRoot);
179 } else {
180 // Regular request (Frontend, AJAX, Backend, CLI)
181 $this->startOutputBuffering()
182 ->loadConfigurationAndInitialize()
183 ->loadTypo3LoadedExtAndExtLocalconf(TRUE)
184 ->applyAdditionalConfigurationSettings()
185 ->initializeTypo3DbGlobal();
186 }
187
188 // Resolve request handler that were registered based on TYPO3_MODE
189 $this->registerRequestHandlers();
190 $requestHandler = $this->resolveRequestHandler();
191 $requestHandler->handleRequest();
192 return $this;
193 }
194
195 /**
196 * Run the base setup that checks server environment, determines pathes,
197 * populates base files and sets common configuration.
198 *
199 * Script execution will be aborted if something fails here.
200 *
201 * @param string $relativePathPart Relative path of entry script back to document root
202 * @return Bootstrap
203 * @internal This is not a public API method, do not use in own extensions
204 */
205 public function baseSetup($relativePathPart = '') {
206 SystemEnvironmentBuilder::run($relativePathPart);
207 $this->addDynamicClassAliasMapsToComposerClassLoader();
208 Utility\GeneralUtility::presetApplicationContext($this->applicationContext);
209 return $this;
210 }
211
212 /**
213 * @return \Composer\Autoload\ClassLoader|\Helhum\ClassAliasLoader\Composer\ClassAliasLoader
214 */
215 static protected function initializeComposerClassLoader() {
216 $possiblePaths = array(
217 'distribution' => __DIR__ . '/../../../../../../Packages/Libraries/autoload.php',
218 'fallback' => __DIR__ . '/../../../../contrib/vendor/autoload.php',
219 );
220 foreach ($possiblePaths as $autoLoadType => $possiblePath) {
221 if (file_exists($possiblePath)) {
222 if ($autoLoadType === 'distribution') {
223 self::$usesComposerClassLoading = TRUE;
224 }
225 return include $possiblePath;
226 }
227 }
228
229 throw new \LogicException('No class loading information found for TYPO3 CMS. Please make sure you installed TYPO3 with composer or the typo3/contrib/vendor folder is present.', 1425153762);
230 }
231
232 /**
233 * Includes an alias mapping file if present.
234 * The file is generated during extension install.
235 *
236 * @throws \TYPO3\CMS\Core\Exception
237 */
238 protected function addDynamicClassAliasMapsToComposerClassLoader() {
239 if (self::$usesComposerClassLoading) {
240 return;
241 }
242 $dynamicClassAliasMapFile = PATH_site . 'typo3conf/autoload_classaliasmap.php';
243 if (file_exists($dynamicClassAliasMapFile)) {
244 $composerClassLoader = $this->getEarlyInstance(\Composer\Autoload\ClassLoader::class);
245 $classAliasMap = require $dynamicClassAliasMapFile;
246 if (is_array($classAliasMap) && !empty($classAliasMap['aliasToClassNameMapping']) && !empty($classAliasMap['classNameToAliasMapping'])) {
247 $composerClassLoader->addAliasMap($classAliasMap);
248 }
249 }
250 }
251
252 /**
253 * checks if LocalConfiguration.php or PackageStates.php is missing,
254 * used to see if a redirect to the install tool is needed
255 *
256 * @return bool TRUE when the essential configuration is available, otherwise FALSE
257 */
258 protected function checkIfEssentialConfigurationExists() {
259 $configurationManager = new \TYPO3\CMS\Core\Configuration\ConfigurationManager;
260 $this->setEarlyInstance(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, $configurationManager);
261 return (!file_exists($configurationManager->getLocalConfigurationFileLocation()) || !file_exists(PATH_typo3conf . 'PackageStates.php')) ? FALSE : TRUE;
262 }
263
264 /**
265 * Redirect to install tool if LocalConfiguration.php is missing.
266 *
267 * @param string $pathUpToDocumentRoot Can contain '../' if called from a sub directory
268 * @internal This is not a public API method, do not use in own extensions
269 */
270 public function redirectToInstallTool($pathUpToDocumentRoot = '') {
271 define('TYPO3_enterInstallScript', '1');
272 $this->defineTypo3RequestTypes();
273 Utility\HttpUtility::redirect($pathUpToDocumentRoot . 'typo3/sysext/install/Start/Install.php');
274 }
275
276 /**
277 * Adds available request handlers, which currently hard-coded here based on the TYPO3_MODE. The extensability
278 * of adding own request handlers would be too complex for now, but can be added later.
279 *
280 * @return Bootstrap
281 * @internal This is not a public API method, do not use in own extensions
282 */
283 protected function registerRequestHandlers() {
284 // Use the install tool handler if in install tool mode
285 if (!$this->checkIfEssentialConfigurationExists() || (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_INSTALL)) {
286 $this->availableRequestHandlers = array(
287 \TYPO3\CMS\Install\RequestHandler::class
288 );
289 } elseif (TYPO3_MODE == 'BE') {
290 $this->availableRequestHandlers = array(
291 \TYPO3\CMS\Backend\RequestHandler::class,
292 \TYPO3\CMS\Backend\BackendModuleRequestHandler::class,
293 \TYPO3\CMS\Backend\AjaxRequestHandler::class,
294 \TYPO3\CMS\Backend\CliRequestHandler::class
295 );
296 } elseif (TYPO3_MODE == 'FE') {
297 $this->availableRequestHandlers = array(
298 \TYPO3\CMS\Frontend\RequestHandler::class,
299 \TYPO3\CMS\Frontend\EidRequestHandler::class
300 );
301 }
302 return $this;
303 }
304
305 /**
306 * Fetches the request handler that suits the best based on the priority and the interface
307 * Be sure to always have the constants that are defined in $this->defineTypo3RequestTypes() are set,
308 * so most RequestHandlers can check if they can handle the request.
309 *
310 * @return RequestHandlerInterface
311 * @throws \TYPO3\CMS\Core\Exception
312 * @internal This is not a public API method, do not use in own extensions
313 */
314 public function resolveRequestHandler() {
315 $suitableRequestHandlers = array();
316 foreach ($this->availableRequestHandlers as $requestHandlerClassName) {
317 $requestHandler = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($requestHandlerClassName, $this);
318 if ($requestHandler->canHandleRequest()) {
319 $priority = $requestHandler->getPriority();
320 if (isset($suitableRequestHandlers[$priority])) {
321 throw new \TYPO3\CMS\Core\Exception('More than one request handler with the same priority can handle the request, but only one handler may be active at a time!', 1176471352);
322 }
323 $suitableRequestHandlers[$priority] = $requestHandler;
324 }
325 }
326 if (count($suitableRequestHandlers) === 0) {
327 throw new \TYPO3\CMS\Core\Exception('No suitable request handler found.', 1225418233);
328 }
329 ksort($suitableRequestHandlers);
330 return array_pop($suitableRequestHandlers);
331 }
332
333 /**
334 * Registers the instance of the specified object for an early boot stage.
335 * On finalizing the Object Manager initialization, all those instances will
336 * be transferred to the Object Manager's registry.
337 *
338 * @param string $objectName Object name, as later used by the Object Manager
339 * @param object $instance The instance to register
340 * @return void
341 */
342 public function setEarlyInstance($objectName, $instance) {
343 $this->earlyInstances[$objectName] = $instance;
344 }
345
346 /**
347 * Returns an instance which was registered earlier through setEarlyInstance()
348 *
349 * @param string $objectName Object name of the registered instance
350 * @return object
351 * @throws \TYPO3\CMS\Core\Exception
352 */
353 public function getEarlyInstance($objectName) {
354 if (!isset($this->earlyInstances[$objectName])) {
355 throw new \TYPO3\CMS\Core\Exception('Unknown early instance "' . $objectName . '"', 1365167380);
356 }
357 return $this->earlyInstances[$objectName];
358 }
359
360 /**
361 * Returns all registered early instances indexed by object name
362 *
363 * @return array
364 */
365 public function getEarlyInstances() {
366 return $this->earlyInstances;
367 }
368
369 /**
370 * Includes LocalConfiguration.php and sets several
371 * global settings depending on configuration.
372 *
373 * @param bool $allowCaching Whether to allow caching - affects cache_core (autoloader)
374 * @param string $packageManagerClassName Define an alternative package manager implementation (usually for the installer)
375 * @return Bootstrap
376 * @internal This is not a public API method, do not use in own extensions
377 */
378 public function loadConfigurationAndInitialize($allowCaching = TRUE, $packageManagerClassName = \TYPO3\CMS\Core\Package\PackageManager::class) {
379 $this->initializeClassLoader()
380 ->populateLocalConfiguration();
381 if (!$allowCaching) {
382 $this->disableCoreAndClassesCache();
383 }
384 $this->initializeCachingFramework()
385 ->initializeClassLoaderCaches()
386 ->initializePackageManagement($packageManagerClassName)
387 ->initializeRuntimeActivatedPackagesFromConfiguration();
388
389 $this->defineDatabaseConstants()
390 ->defineUserAgentConstant()
391 ->registerExtDirectComponents()
392 ->transferDeprecatedCurlSettings()
393 ->setCacheHashOptions()
394 ->setDefaultTimezone()
395 ->initializeL10nLocales()
396 ->convertPageNotFoundHandlingToBoolean()
397 ->registerGlobalDebugFunctions()
398 ->configureExceptionHandling()
399 ->initializeExceptionHandling()
400 ->setMemoryLimit()
401 ->defineTypo3RequestTypes();
402 return $this;
403 }
404
405 /**
406 * Initializes the Class Loader
407 *
408 * @return Bootstrap
409 * @internal This is not a public API method, do not use in own extensions
410 */
411 public function initializeClassLoader() {
412 $classLoader = new ClassLoader($this->applicationContext);
413 $this->setEarlyInstance(\TYPO3\CMS\Core\Core\ClassLoader::class, $classLoader);
414 $classAliasMap = new ClassAliasMap();
415 $classAliasMap->injectClassLoader($classLoader);
416 $classAliasMap->injectComposerClassLoader($this->getEarlyInstance(\Composer\Autoload\ClassLoader::class));
417 $this->setEarlyInstance(\TYPO3\CMS\Core\Core\ClassAliasMap::class, $classAliasMap);
418 $classLoader->injectClassAliasMap($classAliasMap);
419 spl_autoload_register(array($classLoader, 'loadClass'), TRUE, FALSE);
420 return $this;
421 }
422
423 /**
424 * Unregister class loader
425 *
426 * @return Bootstrap
427 * @internal This is not a public API method, do not use in own extensions
428 */
429 public function unregisterClassLoader() {
430 $currentClassLoader = $this->getEarlyInstance(\TYPO3\CMS\Core\Core\ClassLoader::class);
431 spl_autoload_unregister(array($currentClassLoader, 'loadClass'));
432 return $this;
433 }
434
435 /**
436 * Initialize class loader cache.
437 *
438 * @return Bootstrap
439 * @internal This is not a public API method, do not use in own extensions
440 */
441 public function initializeClassLoaderCaches() {
442 /** @var $classLoader ClassLoader */
443 $classLoader = $this->getEarlyInstance(\TYPO3\CMS\Core\Core\ClassLoader::class);
444 $classLoader->injectCoreCache($this->getEarlyInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('cache_core'));
445 $classLoader->injectClassesCache($this->getEarlyInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('cache_classes'));
446 return $this;
447 }
448
449 /**
450 * Initializes the package system and loads the package configuration and settings
451 * provided by the packages.
452 *
453 * @param string $packageManagerClassName Define an alternative package manager implementation (usually for the installer)
454 * @return Bootstrap
455 * @internal This is not a public API method, do not use in own extensions
456 */
457 public function initializePackageManagement($packageManagerClassName) {
458 /** @var \TYPO3\CMS\Core\Package\PackageManager $packageManager */
459 $packageManager = new $packageManagerClassName();
460 $this->setEarlyInstance(\TYPO3\Flow\Package\PackageManager::class, $packageManager);
461 Utility\ExtensionManagementUtility::setPackageManager($packageManager);
462 $packageManager->injectClassLoader($this->getEarlyInstance(\TYPO3\CMS\Core\Core\ClassLoader::class));
463 $packageManager->injectCoreCache($this->getEarlyInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('cache_core'));
464 $packageManager->injectDependencyResolver(Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Package\DependencyResolver::class));
465 $packageManager->initialize($this);
466 Utility\GeneralUtility::setSingletonInstance(\TYPO3\CMS\Core\Package\PackageManager::class, $packageManager);
467 return $this;
468 }
469
470 /**
471 * Activates a package during runtime. This is used in AdditionalConfiguration.php
472 * to enable extensions under conditions.
473 *
474 * @return Bootstrap
475 */
476 protected function initializeRuntimeActivatedPackagesFromConfiguration() {
477 if (isset($GLOBALS['TYPO3_CONF_VARS']['EXT']['runtimeActivatedPackages']) && is_array($GLOBALS['TYPO3_CONF_VARS']['EXT']['runtimeActivatedPackages'])) {
478 /** @var \TYPO3\CMS\Core\Package\PackageManager $packageManager */
479 $packageManager = $this->getEarlyInstance(\TYPO3\Flow\Package\PackageManager::class);
480 foreach ($GLOBALS['TYPO3_CONF_VARS']['EXT']['runtimeActivatedPackages'] as $runtimeAddedPackageKey) {
481 $packageManager->activatePackageDuringRuntime($runtimeAddedPackageKey);
482 }
483 }
484 return $this;
485 }
486
487 /**
488 * Load ext_localconf of extensions
489 *
490 * @param bool $allowCaching
491 * @return Bootstrap
492 * @internal This is not a public API method, do not use in own extensions
493 */
494 public function loadTypo3LoadedExtAndExtLocalconf($allowCaching = TRUE) {
495 Utility\ExtensionManagementUtility::loadExtLocalconf($allowCaching);
496 return $this;
497 }
498
499 /**
500 * Sets up additional configuration applied in all scopes
501 *
502 * @return Bootstrap
503 * @internal This is not a public API method, do not use in own extensions
504 */
505 public function applyAdditionalConfigurationSettings() {
506 $this->initializeExceptionHandling()
507 ->setFinalCachingFrameworkCacheConfiguration()
508 ->defineLoggingAndExceptionConstants()
509 ->unsetReservedGlobalVariables();
510 return $this;
511 }
512
513 /**
514 * Throws an exception if no browser could be identified
515 *
516 * @return Bootstrap
517 * @throws \RuntimeException
518 * @internal This is not a public API method, do not use in own extensions
519 */
520 public function checkValidBrowserOrDie() {
521 // Checks for proper browser
522 if (empty($GLOBALS['CLIENT']['BROWSER'])) {
523 throw new \RuntimeException('Browser Error: Your browser version looks incompatible with this TYPO3 version!', 1294587023);
524 }
525 return $this;
526 }
527
528 /**
529 * We need an early instance of the configuration manager.
530 * Since makeInstance relies on the object configuration, we create it here with new instead.
531 *
532 * @return Bootstrap
533 */
534 public function populateLocalConfiguration() {
535 try {
536 $configurationManager = $this->getEarlyInstance(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class);
537 } catch(\TYPO3\CMS\Core\Exception $exception) {
538 $configurationManager = new \TYPO3\CMS\Core\Configuration\ConfigurationManager();
539 $this->setEarlyInstance(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, $configurationManager);
540 }
541 $configurationManager->exportConfiguration();
542 return $this;
543 }
544
545 /**
546 * Set cache_core to null backend, effectively disabling eg. the autoloader cache
547 *
548 * @return \TYPO3\CMS\Core\Core\Bootstrap
549 * @internal This is not a public API method, do not use in own extensions
550 */
551 public function disableCoreAndClassesCache() {
552 $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_core']['backend']
553 = \TYPO3\CMS\Core\Cache\Backend\NullBackend::class;
554 unset($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_core']['options']);
555 $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_classes']['backend']
556 = \TYPO3\CMS\Core\Cache\Backend\TransientMemoryBackend::class;
557 unset($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_classes']['options']);
558 return $this;
559 }
560
561 /**
562 * Define database constants
563 *
564 * @return \TYPO3\CMS\Core\Core\Bootstrap
565 */
566 protected function defineDatabaseConstants() {
567 define('TYPO3_db', $GLOBALS['TYPO3_CONF_VARS']['DB']['database']);
568 define('TYPO3_db_username', $GLOBALS['TYPO3_CONF_VARS']['DB']['username']);
569 define('TYPO3_db_password', $GLOBALS['TYPO3_CONF_VARS']['DB']['password']);
570 define('TYPO3_db_host', $GLOBALS['TYPO3_CONF_VARS']['DB']['host']);
571 define('TYPO3_extTableDef_script',
572 isset($GLOBALS['TYPO3_CONF_VARS']['DB']['extTablesDefinitionScript'])
573 ? $GLOBALS['TYPO3_CONF_VARS']['DB']['extTablesDefinitionScript']
574 : 'extTables.php');
575 return $this;
576 }
577
578 /**
579 * Define user agent constant
580 *
581 * @return \TYPO3\CMS\Core\Core\Bootstrap
582 */
583 protected function defineUserAgentConstant() {
584 define('TYPO3_user_agent', 'User-Agent: ' . $GLOBALS['TYPO3_CONF_VARS']['HTTP']['userAgent']);
585 return $this;
586 }
587
588 /**
589 * Register default ExtDirect components
590 *
591 * @return Bootstrap
592 */
593 protected function registerExtDirectComponents() {
594 if (TYPO3_MODE === 'BE') {
595 Utility\ExtensionManagementUtility::registerExtDirectComponent('TYPO3.Components.PageTree.DataProvider', \TYPO3\CMS\Backend\Tree\Pagetree\ExtdirectTreeDataProvider::class);
596 Utility\ExtensionManagementUtility::registerExtDirectComponent('TYPO3.Components.PageTree.Commands', \TYPO3\CMS\Backend\Tree\Pagetree\ExtdirectTreeCommands::class);
597 Utility\ExtensionManagementUtility::registerExtDirectComponent('TYPO3.Components.PageTree.ContextMenuDataProvider', \TYPO3\CMS\Backend\ContextMenu\Pagetree\Extdirect\ContextMenuConfiguration::class);
598 Utility\ExtensionManagementUtility::registerExtDirectComponent('TYPO3.LiveSearchActions.ExtDirect', \TYPO3\CMS\Backend\Search\LiveSearch\ExtDirect\LiveSearchDataProvider::class, 'web_list', 'user,group');
599 Utility\ExtensionManagementUtility::registerExtDirectComponent('TYPO3.BackendUserSettings.ExtDirect', \TYPO3\CMS\Backend\User\ExtDirect\BackendUserSettingsDataProvider::class);
600 if (Utility\ExtensionManagementUtility::isLoaded('context_help')) {
601 Utility\ExtensionManagementUtility::registerExtDirectComponent('TYPO3.CSH.ExtDirect', \TYPO3\CMS\ContextHelp\ExtDirect\ContextHelpDataProvider::class);
602 }
603 Utility\ExtensionManagementUtility::registerExtDirectComponent('TYPO3.ExtDirectStateProvider.ExtDirect', \TYPO3\CMS\Backend\InterfaceState\ExtDirect\DataProvider::class);
604 Utility\ExtensionManagementUtility::registerExtDirectComponent(
605 'TYPO3.Components.DragAndDrop.CommandController',
606 Utility\ExtensionManagementUtility::extPath('backend') . 'Classes/View/PageLayout/Extdirect/ExtdirectPageCommands.php:' . \TYPO3\CMS\Backend\View\PageLayout\ExtDirect\ExtdirectPageCommands::class
607 );
608 }
609 return $this;
610 }
611
612 /**
613 * Initialize caching framework
614 *
615 * @return Bootstrap
616 * @internal This is not a public API method, do not use in own extensions
617 */
618 public function initializeCachingFramework() {
619 $this->setEarlyInstance(\TYPO3\CMS\Core\Cache\CacheManager::class, \TYPO3\CMS\Core\Cache\Cache::initializeCachingFramework());
620 return $this;
621 }
622
623 /**
624 * Parse old curl options and set new http ones instead
625 *
626 * @TODO: Move this functionality to the silent updater in the Install Tool
627 * @return Bootstrap
628 */
629 protected function transferDeprecatedCurlSettings() {
630 if (!empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['curlProxyServer']) && empty($GLOBALS['TYPO3_CONF_VARS']['HTTP']['proxy_host'])) {
631 $curlProxy = rtrim(preg_replace('#^https?://#', '', $GLOBALS['TYPO3_CONF_VARS']['SYS']['curlProxyServer']), '/');
632 $proxyParts = Utility\GeneralUtility::revExplode(':', $curlProxy, 2);
633 $GLOBALS['TYPO3_CONF_VARS']['HTTP']['proxy_host'] = $proxyParts[0];
634 $GLOBALS['TYPO3_CONF_VARS']['HTTP']['proxy_port'] = $proxyParts[1];
635 }
636 if (!empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['curlProxyUserPass']) && empty($GLOBALS['TYPO3_CONF_VARS']['HTTP']['proxy_user'])) {
637 $userPassParts = explode(':', $GLOBALS['TYPO3_CONF_VARS']['SYS']['curlProxyUserPass'], 2);
638 $GLOBALS['TYPO3_CONF_VARS']['HTTP']['proxy_user'] = $userPassParts[0];
639 $GLOBALS['TYPO3_CONF_VARS']['HTTP']['proxy_password'] = $userPassParts[1];
640 }
641 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['curlUse']) {
642 $GLOBALS['TYPO3_CONF_VARS']['HTTP']['adapter'] = 'curl';
643 }
644 return $this;
645 }
646
647 /**
648 * Set cacheHash options
649 *
650 * @return Bootstrap
651 */
652 protected function setCacheHashOptions() {
653 $GLOBALS['TYPO3_CONF_VARS']['FE']['cacheHash'] = array(
654 'cachedParametersWhiteList' => Utility\GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['FE']['cHashOnlyForParameters'], TRUE),
655 'excludedParameters' => Utility\GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['FE']['cHashExcludedParameters'], TRUE),
656 'requireCacheHashPresenceParameters' => Utility\GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['FE']['cHashRequiredParameters'], TRUE)
657 );
658 if (trim($GLOBALS['TYPO3_CONF_VARS']['FE']['cHashExcludedParametersIfEmpty']) === '*') {
659 $GLOBALS['TYPO3_CONF_VARS']['FE']['cacheHash']['excludeAllEmptyParameters'] = TRUE;
660 } else {
661 $GLOBALS['TYPO3_CONF_VARS']['FE']['cacheHash']['excludedParametersIfEmpty'] = Utility\GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['FE']['cHashExcludedParametersIfEmpty'], TRUE);
662 }
663 return $this;
664 }
665
666 /**
667 * Set default timezone
668 *
669 * @return Bootstrap
670 */
671 protected function setDefaultTimezone() {
672 $timeZone = $GLOBALS['TYPO3_CONF_VARS']['SYS']['phpTimeZone'];
673 if (empty($timeZone)) {
674 // Time zone from the server environment (TZ env or OS query)
675 $defaultTimeZone = @date_default_timezone_get();
676 if ($defaultTimeZone !== '') {
677 $timeZone = $defaultTimeZone;
678 } else {
679 $timeZone = 'UTC';
680 }
681 }
682 // Set default to avoid E_WARNINGs with PHP > 5.3
683 date_default_timezone_set($timeZone);
684 return $this;
685 }
686
687 /**
688 * Initialize the locales handled by TYPO3
689 *
690 * @return Bootstrap
691 */
692 protected function initializeL10nLocales() {
693 \TYPO3\CMS\Core\Localization\Locales::initialize();
694 return $this;
695 }
696
697 /**
698 * Convert type of "pageNotFound_handling" setting in case it was written as a
699 * string (e.g. if edited in Install Tool)
700 *
701 * @TODO : Remove, if the Install Tool handles such data types correctly
702 * @return Bootstrap
703 */
704 protected function convertPageNotFoundHandlingToBoolean() {
705 if (!strcasecmp($GLOBALS['TYPO3_CONF_VARS']['FE']['pageNotFound_handling'], 'TRUE')) {
706 $GLOBALS['TYPO3_CONF_VARS']['FE']['pageNotFound_handling'] = TRUE;
707 }
708 return $this;
709 }
710
711 /**
712 * Register xdebug(), debug(), debugBegin() and debugEnd() as global functions
713 *
714 * Note: Yes, this is possible in php! xdebug() is then a global function, even
715 * if registerGlobalDebugFunctions() is encapsulated in class scope.
716 *
717 * @return Bootstrap
718 */
719 protected function registerGlobalDebugFunctions() {
720 require_once('GlobalDebugFunctions.php');
721 return $this;
722 }
723
724 /**
725 * Configure and set up exception and error handling
726 *
727 * @return Bootstrap
728 */
729 protected function configureExceptionHandling() {
730 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['errors']['exceptionHandler'] = $GLOBALS['TYPO3_CONF_VARS']['SYS']['productionExceptionHandler'];
731 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['errors']['exceptionalErrors'] = $GLOBALS['TYPO3_CONF_VARS']['SYS']['exceptionalErrors'];
732 $doesIpMatch = Utility\GeneralUtility::cmpIP(Utility\GeneralUtility::getIndpEnv('REMOTE_ADDR'), $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask']);
733 $displayErrors = (int)$GLOBALS['TYPO3_CONF_VARS']['SYS']['displayErrors'];
734 // Turn error logging on/off.
735 if ($displayErrors !== -1) {
736 // Special value "2" enables this feature only if $GLOBALS['TYPO3_CONF_VARS'][SYS][devIPmask] matches
737 if ($displayErrors === 2) {
738 $displayErrors = (int)$doesIpMatch;
739 }
740 if ($displayErrors === 0) {
741 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['errors']['exceptionalErrors'] = 0;
742 }
743 if ($displayErrors === 1) {
744 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['errors']['exceptionHandler'] = $GLOBALS['TYPO3_CONF_VARS']['SYS']['debugExceptionHandler'];
745 define('TYPO3_ERRORHANDLER_MODE', 'debug');
746 }
747 @ini_set('display_errors', $displayErrors);
748 } elseif ($doesIpMatch) {
749 // With displayErrors = -1 (default), turn on debugging if devIPmask matches:
750 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['errors']['exceptionHandler'] = $GLOBALS['TYPO3_CONF_VARS']['SYS']['debugExceptionHandler'];
751 }
752 return $this;
753 }
754
755 /**
756 * Set PHP memory limit depending on value of
757 * $GLOBALS['TYPO3_CONF_VARS']['SYS']['setMemoryLimit']
758 *
759 * @return Bootstrap
760 */
761 protected function setMemoryLimit() {
762 if ((int)$GLOBALS['TYPO3_CONF_VARS']['SYS']['setMemoryLimit'] > 16) {
763 @ini_set('memory_limit', ((int)$GLOBALS['TYPO3_CONF_VARS']['SYS']['setMemoryLimit'] . 'm'));
764 }
765 return $this;
766 }
767
768 /**
769 * Define TYPO3_REQUESTTYPE* constants
770 * so devs exactly know what type of request it is
771 *
772 * @return Bootstrap
773 */
774 protected function defineTypo3RequestTypes() {
775 define('TYPO3_REQUESTTYPE_FE', 1);
776 define('TYPO3_REQUESTTYPE_BE', 2);
777 define('TYPO3_REQUESTTYPE_CLI', 4);
778 define('TYPO3_REQUESTTYPE_AJAX', 8);
779 define('TYPO3_REQUESTTYPE_INSTALL', 16);
780 define('TYPO3_REQUESTTYPE', (TYPO3_MODE == 'FE' ? TYPO3_REQUESTTYPE_FE : 0) | (TYPO3_MODE == 'BE' ? TYPO3_REQUESTTYPE_BE : 0) | (defined('TYPO3_cliMode') && TYPO3_cliMode ? TYPO3_REQUESTTYPE_CLI : 0) | (defined('TYPO3_enterInstallScript') && TYPO3_enterInstallScript ? TYPO3_REQUESTTYPE_INSTALL : 0) | ($GLOBALS['TYPO3_AJAX'] ? TYPO3_REQUESTTYPE_AJAX : 0));
781 return $this;
782 }
783
784 /**
785 * Initialize exception handling
786 * This method is called twice. First when LocalConfiguration has been loaded
787 * and a second time after extension ext_loclconf.php have been included to allow extensions
788 * to change the exception and error handler configuration.
789 *
790 * @return Bootstrap
791 */
792 protected function initializeExceptionHandling() {
793 if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['errors']['exceptionHandler'])) {
794 if (!empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['errorHandler'])) {
795 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['errorHandler'] !== $this->activeErrorHandlerClassName) {
796 $this->activeErrorHandlerClassName = $GLOBALS['TYPO3_CONF_VARS']['SYS']['errorHandler'];
797 // Register an error handler for the given errorHandlerErrors
798 $errorHandler = Utility\GeneralUtility::makeInstance($this->activeErrorHandlerClassName, $GLOBALS['TYPO3_CONF_VARS']['SYS']['errorHandlerErrors']);
799 // Set errors which will be converted in an exception
800 $errorHandler->setExceptionalErrors($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['errors']['exceptionalErrors']);
801 }
802 } elseif (!empty($this->activeErrorHandlerClassName)) {
803 // Restore error handler in case extensions have unset the configuration in ext_localconf.php
804 restore_error_handler();
805 }
806 if ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['errors']['exceptionHandler'] !== $this->activeExceptionHandlerClassName) {
807 $this->activeExceptionHandlerClassName = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['errors']['exceptionHandler'];
808 // Registering the exception handler is done in the constructor
809 Utility\GeneralUtility::makeInstance($this->activeExceptionHandlerClassName);
810 }
811 } elseif (!empty($this->activeExceptionHandlerClassName)) {
812 // Restore exception handler in case extensions have unset the configuration in ext_localconf.php
813 restore_exception_handler();
814 }
815 return $this;
816 }
817
818 /**
819 * Extensions may register new caches, so we set the
820 * global cache array to the manager again at this point
821 *
822 * @return Bootstrap
823 */
824 protected function setFinalCachingFrameworkCacheConfiguration() {
825 $this->getEarlyInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->setCacheConfigurations($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']);
826 return $this;
827 }
828
829 /**
830 * Define logging and exception constants
831 *
832 * @return Bootstrap
833 */
834 protected function defineLoggingAndExceptionConstants() {
835 define('TYPO3_DLOG', $GLOBALS['TYPO3_CONF_VARS']['SYS']['enable_DLOG']);
836 define('TYPO3_ERROR_DLOG', $GLOBALS['TYPO3_CONF_VARS']['SYS']['enable_errorDLOG']);
837 define('TYPO3_EXCEPTION_DLOG', $GLOBALS['TYPO3_CONF_VARS']['SYS']['enable_exceptionDLOG']);
838 return $this;
839 }
840
841 /**
842 * Unsetting reserved global variables:
843 * Those are set in "ext:core/ext_tables.php" file:
844 *
845 * @return Bootstrap
846 */
847 protected function unsetReservedGlobalVariables() {
848 unset($GLOBALS['PAGES_TYPES']);
849 unset($GLOBALS['TCA']);
850 unset($GLOBALS['TBE_MODULES']);
851 unset($GLOBALS['TBE_STYLES']);
852 unset($GLOBALS['FILEICONS']);
853 // Those set in init.php:
854 unset($GLOBALS['BE_USER']);
855 // Those set otherwise:
856 unset($GLOBALS['TBE_MODULES_EXT']);
857 unset($GLOBALS['TCA_DESCR']);
858 unset($GLOBALS['LOCAL_LANG']);
859 unset($GLOBALS['TYPO3_AJAX']);
860 return $this;
861 }
862
863 /**
864 * Initialize database connection in $GLOBALS and connect if requested
865 *
866 * @return \TYPO3\CMS\Core\Core\Bootstrap
867 * @internal This is not a public API method, do not use in own extensions
868 */
869 public function initializeTypo3DbGlobal() {
870 /** @var $databaseConnection \TYPO3\CMS\Core\Database\DatabaseConnection */
871 $databaseConnection = Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\DatabaseConnection::class);
872 $databaseConnection->setDatabaseName(TYPO3_db);
873 $databaseConnection->setDatabaseUsername(TYPO3_db_username);
874 $databaseConnection->setDatabasePassword(TYPO3_db_password);
875
876 $databaseHost = TYPO3_db_host;
877 if (isset($GLOBALS['TYPO3_CONF_VARS']['DB']['port'])) {
878 $databaseConnection->setDatabasePort($GLOBALS['TYPO3_CONF_VARS']['DB']['port']);
879 } elseif (strpos($databaseHost, ':') > 0) {
880 // @TODO: Find a way to handle this case in the install tool and drop this
881 list($databaseHost, $databasePort) = explode(':', $databaseHost);
882 $databaseConnection->setDatabasePort($databasePort);
883 }
884 if (isset($GLOBALS['TYPO3_CONF_VARS']['DB']['socket'])) {
885 $databaseConnection->setDatabaseSocket($GLOBALS['TYPO3_CONF_VARS']['DB']['socket']);
886 }
887 $databaseConnection->setDatabaseHost($databaseHost);
888
889 $databaseConnection->debugOutput = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sqlDebug'];
890
891 if (
892 isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['no_pconnect'])
893 && !$GLOBALS['TYPO3_CONF_VARS']['SYS']['no_pconnect']
894 ) {
895 $databaseConnection->setPersistentDatabaseConnection(TRUE);
896 }
897
898 $isDatabaseHostLocalHost = $databaseHost === 'localhost' || $databaseHost === '127.0.0.1' || $databaseHost === '::1';
899 if (
900 isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['dbClientCompress'])
901 && $GLOBALS['TYPO3_CONF_VARS']['SYS']['dbClientCompress']
902 && !$isDatabaseHostLocalHost
903 ) {
904 $databaseConnection->setConnectionCompression(TRUE);
905 }
906
907 if (!empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['setDBinit'])) {
908 $commandsAfterConnect = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(
909 LF,
910 str_replace('\' . LF . \'', LF, $GLOBALS['TYPO3_CONF_VARS']['SYS']['setDBinit']),
911 TRUE
912 );
913 $databaseConnection->setInitializeCommandsAfterConnect($commandsAfterConnect);
914 }
915
916 $GLOBALS['TYPO3_DB'] = $databaseConnection;
917 // $GLOBALS['TYPO3_DB'] needs to be defined first in order to work for DBAL
918 $GLOBALS['TYPO3_DB']->initialize();
919
920 return $this;
921 }
922
923 /**
924 * Check adminOnly configuration variable and redirects
925 * to an URL in file typo3conf/LOCK_BACKEND or exit the script
926 *
927 * @throws \RuntimeException
928 * @return Bootstrap
929 * @internal This is not a public API method, do not use in own extensions
930 */
931 public function checkLockedBackendAndRedirectOrDie() {
932 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['adminOnly'] < 0) {
933 throw new \RuntimeException('TYPO3 Backend locked: Backend and Install Tool are locked for maintenance. [BE][adminOnly] is set to "' . (int)$GLOBALS['TYPO3_CONF_VARS']['BE']['adminOnly'] . '".', 1294586847);
934 }
935 if (@is_file((PATH_typo3conf . 'LOCK_BACKEND'))) {
936 if (TYPO3_PROCEED_IF_NO_USER === 2) {
937
938 } else {
939 $fileContent = Utility\GeneralUtility::getUrl(PATH_typo3conf . 'LOCK_BACKEND');
940 if ($fileContent) {
941 header('Location: ' . $fileContent);
942 } else {
943 throw new \RuntimeException('TYPO3 Backend locked: Browser backend is locked for maintenance. Remove lock by removing the file "typo3conf/LOCK_BACKEND" or use CLI-scripts.', 1294586848);
944 }
945 die;
946 }
947 }
948 return $this;
949 }
950
951 /**
952 * Compare client IP with IPmaskList and exit the script run
953 * if the client is not allowed to access the backend
954 *
955 * @return Bootstrap
956 * @internal This is not a public API method, do not use in own extensions
957 * @throws \RuntimeException
958 */
959 public function checkBackendIpOrDie() {
960 if (trim($GLOBALS['TYPO3_CONF_VARS']['BE']['IPmaskList'])) {
961 if (!Utility\GeneralUtility::cmpIP(Utility\GeneralUtility::getIndpEnv('REMOTE_ADDR'), $GLOBALS['TYPO3_CONF_VARS']['BE']['IPmaskList'])) {
962 throw new \RuntimeException('TYPO3 Backend access denied: The IP address of your client does not match the list of allowed IP addresses.', 1389265900);
963 }
964 }
965 return $this;
966 }
967
968 /**
969 * Check lockSSL configuration variable and redirect
970 * to https version of the backend if needed
971 *
972 * @return Bootstrap
973 * @internal This is not a public API method, do not use in own extensions
974 * @throws \RuntimeException
975 */
976 public function checkSslBackendAndRedirectIfNeeded() {
977 if ((int)$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSL']) {
978 if ((int)$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSLPort']) {
979 $sslPortSuffix = ':' . (int)$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSLPort'];
980 } else {
981 $sslPortSuffix = '';
982 }
983 if ((int)$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSL'] === 3) {
984 $requestStr = substr(Utility\GeneralUtility::getIndpEnv('TYPO3_REQUEST_SCRIPT'), strlen(Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . TYPO3_mainDir));
985 if ($requestStr === 'index.php' && !Utility\GeneralUtility::getIndpEnv('TYPO3_SSL')) {
986 list(, $url) = explode('://', Utility\GeneralUtility::getIndpEnv('TYPO3_REQUEST_URL'), 2);
987 list($server, $address) = explode('/', $url, 2);
988 header('Location: https://' . $server . $sslPortSuffix . '/' . $address);
989 die;
990 }
991 } elseif (!Utility\GeneralUtility::getIndpEnv('TYPO3_SSL')) {
992 if ((int)$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSL'] === 2) {
993 list(, $url) = explode('://', Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . TYPO3_mainDir, 2);
994 list($server, $address) = explode('/', $url, 2);
995 header('Location: https://' . $server . $sslPortSuffix . '/' . $address);
996 die;
997 } else {
998 throw new \RuntimeException('TYPO3 Backend not accessed via SSL: TYPO3 Backend is configured to only be accessible through SSL. Change the URL in your browser and try again.', 1389265726);
999 }
1000 }
1001 }
1002 return $this;
1003 }
1004
1005 /**
1006 * Load TCA for frontend
1007 *
1008 * This method is *only* executed in frontend scope. The idea is to execute the
1009 * whole TCA and ext_tables (which manipulate TCA) on first frontend access,
1010 * and then cache the full TCA on disk to be used for the next run again.
1011 *
1012 * This way, ext_tables.php ist not executed every time, but $GLOBALS['TCA']
1013 * is still always there.
1014 *
1015 * @return Bootstrap
1016 * @internal This is not a public API method, do not use in own extensions
1017 */
1018 public function loadCachedTca() {
1019 $cacheIdentifier = 'tca_fe_' . sha1((TYPO3_version . PATH_site . 'tca_fe'));
1020 /** @var $codeCache \TYPO3\CMS\Core\Cache\Frontend\PhpFrontend */
1021 $codeCache = $this->getEarlyInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('cache_core');
1022 if ($codeCache->has($cacheIdentifier)) {
1023 // substr is necessary, because the php frontend wraps php code around the cache value
1024 $GLOBALS['TCA'] = unserialize(substr($codeCache->get($cacheIdentifier), 6, -2));
1025 } else {
1026 $this->loadExtensionTables(TRUE);
1027 $codeCache->set($cacheIdentifier, serialize($GLOBALS['TCA']));
1028 }
1029 return $this;
1030 }
1031
1032 /**
1033 * Load ext_tables and friends.
1034 *
1035 * This will mainly set up $TCA and several other global arrays
1036 * through API's like extMgm.
1037 * Executes ext_tables.php files of loaded extensions or the
1038 * according cache file if exists.
1039 *
1040 * @param bool $allowCaching True, if reading compiled ext_tables file from cache is allowed
1041 * @return Bootstrap
1042 * @internal This is not a public API method, do not use in own extensions
1043 */
1044 public function loadExtensionTables($allowCaching = TRUE) {
1045 Utility\ExtensionManagementUtility::loadBaseTca($allowCaching);
1046 Utility\ExtensionManagementUtility::loadExtTables($allowCaching);
1047 $this->executeExtTablesAdditionalFile();
1048 $this->runExtTablesPostProcessingHooks();
1049 return $this;
1050 }
1051
1052 /**
1053 * Execute TYPO3_extTableDef_script if defined and exists
1054 *
1055 * Note: For backwards compatibility some global variables are
1056 * explicitly set as global to be used without $GLOBALS[] in
1057 * the extension table script. It is discouraged to access variables like
1058 * $TBE_MODULES directly, but we can not prohibit
1059 * this without heavily breaking backwards compatibility.
1060 *
1061 * @TODO : We could write a scheduler / reports module or an update checker
1062 * @TODO : It should be defined, which global arrays are ok to be manipulated
1063 *
1064 * @return void
1065 */
1066 protected function executeExtTablesAdditionalFile() {
1067 // It is discouraged to use those global variables directly, but we
1068 // can not prohibit this without breaking backwards compatibility
1069 global $T3_SERVICES, $T3_VAR, $TYPO3_CONF_VARS;
1070 global $TBE_MODULES, $TBE_MODULES_EXT, $TCA;
1071 global $PAGES_TYPES, $TBE_STYLES, $FILEICONS;
1072 global $_EXTKEY;
1073 // Load additional ext tables script if the file exists
1074 $extTablesFile = PATH_typo3conf . TYPO3_extTableDef_script;
1075 if (file_exists($extTablesFile) && is_file($extTablesFile)) {
1076 include $extTablesFile;
1077 }
1078 }
1079
1080 /**
1081 * Check for registered ext tables hooks and run them
1082 *
1083 * @throws \UnexpectedValueException
1084 * @return void
1085 */
1086 protected function runExtTablesPostProcessingHooks() {
1087 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['extTablesInclusion-PostProcessing'])) {
1088 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['extTablesInclusion-PostProcessing'] as $classReference) {
1089 /** @var $hookObject \TYPO3\CMS\Core\Database\TableConfigurationPostProcessingHookInterface */
1090 $hookObject = Utility\GeneralUtility::getUserObj($classReference);
1091 if (!$hookObject instanceof \TYPO3\CMS\Core\Database\TableConfigurationPostProcessingHookInterface) {
1092 throw new \UnexpectedValueException('$hookObject must implement interface TYPO3\\CMS\\Core\\Database\\TableConfigurationPostProcessingHookInterface', 1320585902);
1093 }
1094 $hookObject->processData();
1095 }
1096 }
1097 }
1098
1099 /**
1100 * Initialize sprite manager
1101 *
1102 * @return Bootstrap
1103 * @internal This is not a public API method, do not use in own extensions
1104 */
1105 public function initializeSpriteManager() {
1106 \TYPO3\CMS\Backend\Sprite\SpriteManager::initialize();
1107 return $this;
1108 }
1109
1110 /**
1111 * Initialize backend user object in globals
1112 *
1113 * @return Bootstrap
1114 * @internal This is not a public API method, do not use in own extensions
1115 */
1116 public function initializeBackendUser() {
1117 /** @var $backendUser \TYPO3\CMS\Core\Authentication\BackendUserAuthentication */
1118 $backendUser = Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Authentication\BackendUserAuthentication::class);
1119 $backendUser->warningEmail = $GLOBALS['TYPO3_CONF_VARS']['BE']['warning_email_addr'];
1120 $backendUser->lockIP = $GLOBALS['TYPO3_CONF_VARS']['BE']['lockIP'];
1121 $backendUser->auth_timeout_field = (int)$GLOBALS['TYPO3_CONF_VARS']['BE']['sessionTimeout'];
1122 if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI) {
1123 $backendUser->dontSetCookie = TRUE;
1124 }
1125 // The global must be available very early, because methods below
1126 // might trigger code which relies on it. See: #45625
1127 $GLOBALS['BE_USER'] = $backendUser;
1128 $backendUser->start();
1129 return $this;
1130 }
1131
1132 /**
1133 * Initializes and ensures authenticated access
1134 *
1135 * @internal This is not a public API method, do not use in own extensions
1136 * @return \TYPO3\CMS\Core\Core\Bootstrap
1137 */
1138 public function initializeBackendAuthentication() {
1139 $GLOBALS['BE_USER']->checkCLIuser();
1140 $GLOBALS['BE_USER']->backendCheckLogin();
1141 return $this;
1142 }
1143
1144 /**
1145 * Initialize language object
1146 *
1147 * @return Bootstrap
1148 * @internal This is not a public API method, do not use in own extensions
1149 */
1150 public function initializeLanguageObject() {
1151 /** @var $GLOBALS['LANG'] \TYPO3\CMS\Lang\LanguageService */
1152 $GLOBALS['LANG'] = Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Lang\LanguageService::class);
1153 $GLOBALS['LANG']->init($GLOBALS['BE_USER']->uc['lang']);
1154 return $this;
1155 }
1156
1157 /**
1158 * Throw away all output that may have happened during bootstrapping by weird extensions
1159 *
1160 * @return Bootstrap
1161 * @internal This is not a public API method, do not use in own extensions
1162 */
1163 public function endOutputBufferingAndCleanPreviousOutput() {
1164 ob_clean();
1165 return $this;
1166 }
1167
1168 /**
1169 * Initialize output compression if configured
1170 *
1171 * @return Bootstrap
1172 * @internal This is not a public API method, do not use in own extensions
1173 */
1174 public function initializeOutputCompression() {
1175 if (extension_loaded('zlib') && $GLOBALS['TYPO3_CONF_VARS']['BE']['compressionLevel']) {
1176 if (Utility\MathUtility::canBeInterpretedAsInteger($GLOBALS['TYPO3_CONF_VARS']['BE']['compressionLevel'])) {
1177 @ini_set('zlib.output_compression_level', $GLOBALS['TYPO3_CONF_VARS']['BE']['compressionLevel']);
1178 }
1179 ob_start('ob_gzhandler');
1180 }
1181 return $this;
1182 }
1183
1184 /**
1185 * Send HTTP headers if configured
1186 *
1187 * @return Bootstrap
1188 * @internal This is not a public API method, do not use in own extensions
1189 */
1190 public function sendHttpHeaders() {
1191 if (!empty($GLOBALS['TYPO3_CONF_VARS']['BE']['HTTP']['Response']['Headers']) && is_array($GLOBALS['TYPO3_CONF_VARS']['BE']['HTTP']['Response']['Headers'])) {
1192 foreach ($GLOBALS['TYPO3_CONF_VARS']['BE']['HTTP']['Response']['Headers'] as $header) {
1193 header($header);
1194 }
1195 }
1196 return $this;
1197 }
1198
1199 /**
1200 * Things that should be performed to shut down the framework.
1201 * This method is called in all important scripts for a clean
1202 * shut down of the system.
1203 *
1204 * @return Bootstrap
1205 * @internal This is not a public API method, do not use in own extensions
1206 */
1207 public function shutdown() {
1208 return $this;
1209 }
1210
1211 /**
1212 * Provides an instance of "template" for backend-modules to
1213 * work with.
1214 *
1215 * @return Bootstrap
1216 * @internal This is not a public API method, do not use in own extensions
1217 */
1218 public function initializeBackendTemplate() {
1219 $GLOBALS['TBE_TEMPLATE'] = Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Template\DocumentTemplate::class);
1220 return $this;
1221 }
1222
1223 }