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