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