Passed
Push — master ( 970d9b...cc8532 )
by
unknown
14:07
created

Bootstrap::setDefaultTimezone()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
c 0
b 0
f 0
nc 3
nop 0
dl 0
loc 14
rs 10
1
<?php
2
3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
 * It is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License, either version 2
8
 * of the License, or any later version.
9
 *
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
 * The TYPO3 project - inspiring people to share!
14
 */
15
16
namespace TYPO3\CMS\Core\Core;
17
18
use Composer\Autoload\ClassLoader;
19
use Doctrine\Common\Annotations\AnnotationReader;
20
use Doctrine\Common\Annotations\AnnotationRegistry;
21
use Psr\Container\ContainerInterface;
22
use Psr\EventDispatcher\EventDispatcherInterface;
23
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
24
use TYPO3\CMS\Core\Cache\Backend\BackendInterface;
25
use TYPO3\CMS\Core\Cache\Backend\NullBackend;
26
use TYPO3\CMS\Core\Cache\Backend\Typo3DatabaseBackend;
27
use TYPO3\CMS\Core\Cache\CacheManager;
28
use TYPO3\CMS\Core\Cache\Exception\InvalidBackendException;
29
use TYPO3\CMS\Core\Cache\Exception\InvalidCacheException;
30
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
31
use TYPO3\CMS\Core\Cache\Frontend\PhpFrontend;
32
use TYPO3\CMS\Core\Cache\Frontend\VariableFrontend;
33
use TYPO3\CMS\Core\Configuration\ConfigurationManager;
34
use TYPO3\CMS\Core\Database\TableConfigurationPostProcessingHookInterface;
35
use TYPO3\CMS\Core\DependencyInjection\Cache\ContainerBackend;
36
use TYPO3\CMS\Core\DependencyInjection\ContainerBuilder;
37
use TYPO3\CMS\Core\Imaging\IconRegistry;
38
use TYPO3\CMS\Core\IO\PharStreamWrapperInterceptor;
39
use TYPO3\CMS\Core\Localization\LanguageService;
40
use TYPO3\CMS\Core\Log\LogManager;
41
use TYPO3\CMS\Core\Package\FailsafePackageManager;
42
use TYPO3\CMS\Core\Package\PackageManager;
43
use TYPO3\CMS\Core\Page\PageRenderer;
44
use TYPO3\CMS\Core\Service\DependencyOrderingService;
45
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
46
use TYPO3\CMS\Core\Utility\GeneralUtility;
47
use TYPO3\CMS\Core\Utility\StringUtility;
48
use TYPO3\PharStreamWrapper\Behavior;
49
use TYPO3\PharStreamWrapper\Interceptor\ConjunctionInterceptor;
50
use TYPO3\PharStreamWrapper\Interceptor\PharMetaDataInterceptor;
51
use TYPO3\PharStreamWrapper\Manager;
52
use TYPO3\PharStreamWrapper\PharStreamWrapper;
53
54
/**
55
 * This class encapsulates bootstrap related methods.
56
 * It is required directly as the very first thing in entry scripts and
57
 * used to define all base things like constants and paths and so on.
58
 *
59
 * Most methods in this class have dependencies to each other. They can
60
 * not be called in arbitrary order. The methods are ordered top down, so
61
 * a method at the beginning has lower dependencies than a method further
62
 * down. Do not fiddle with the load order in own scripts except you know
63
 * exactly what you are doing!
64
 */
65
class Bootstrap
66
{
67
    /**
68
     * Bootstrap TYPO3 and return a Container that may be used
69
     * to initialize an Application class.
70
     *
71
     * @param ClassLoader $classLoader an instance of the class loader
72
     * @param bool $failsafe true if no caching and a failsafe package manager should be used
73
     * @return ContainerInterface
74
     */
75
    public static function init(
76
        ClassLoader $classLoader,
77
        bool $failsafe = false
78
    ): ContainerInterface {
79
        $requestId = substr(md5(StringUtility::getUniqueId()), 0, 13);
80
81
        static::initializeClassLoader($classLoader);
82
        if (!Environment::isComposerMode() && ClassLoadingInformation::isClassLoadingInformationAvailable()) {
83
            ClassLoadingInformation::registerClassLoadingInformation();
84
        }
85
86
        static::startOutputBuffering();
87
88
        $configurationManager = static::createConfigurationManager();
89
        if (!static::checkIfEssentialConfigurationExists($configurationManager)) {
90
            $failsafe = true;
91
        }
92
        static::populateLocalConfiguration($configurationManager);
93
94
        $logManager = new LogManager($requestId);
95
        // LogManager is used by the core ErrorHandler (using GeneralUtility::makeInstance),
96
        // therefore we have to push the LogManager to GeneralUtility, in case there
97
        // happen errors before we call GeneralUtility::setContainer().
98
        GeneralUtility::setSingletonInstance(LogManager::class, $logManager);
99
100
        static::initializeErrorHandling();
101
        static::initializeIO();
102
103
        $disableCaching = $failsafe ? true : false;
104
        $coreCache = static::createCache('core', $disableCaching);
105
        $packageManager = static::createPackageManager(
106
            $failsafe ? FailsafePackageManager::class : PackageManager::class,
107
            $coreCache
108
        );
109
110
        static::setDefaultTimezone();
111
        static::setMemoryLimit();
112
113
        $assetsCache = static::createCache('assets', $disableCaching);
114
        $dependencyInjectionContainerCache = static::createCache('di');
115
116
        $bootState = new \stdClass();
117
        $bootState->done = false;
118
        $bootState->cacheDisabled = $disableCaching;
119
120
        $builder = new ContainerBuilder([
121
            ClassLoader::class => $classLoader,
122
            ApplicationContext::class => Environment::getContext(),
123
            ConfigurationManager::class => $configurationManager,
124
            LogManager::class => $logManager,
125
            'cache.di' => $dependencyInjectionContainerCache,
126
            'cache.core' => $coreCache,
127
            'cache.assets' => $assetsCache,
128
            PackageManager::class => $packageManager,
129
130
            // @internal
131
            'boot.state' => $bootState,
132
        ]);
133
134
        $container = $builder->createDependencyInjectionContainer($packageManager, $dependencyInjectionContainerCache, $failsafe);
135
136
        // Push the container to GeneralUtility as we want to make sure its
137
        // makeInstance() method creates classes using the container from now on.
138
        GeneralUtility::setContainer($container);
139
140
        // Reset LogManager singleton instance in order for GeneralUtility::makeInstance()
141
        // to proxy LogManager retrieval to ContainerInterface->get() from now on.
142
        GeneralUtility::removeSingletonInstance(LogManager::class, $logManager);
143
144
        // Push PackageManager instance to ExtensionManagementUtility
145
        ExtensionManagementUtility::setPackageManager($packageManager);
146
147
        if ($failsafe) {
148
            $bootState->done = true;
149
            return $container;
150
        }
151
152
        IconRegistry::setCache($assetsCache);
153
        PageRenderer::setCache($assetsCache);
154
        ExtensionManagementUtility::setEventDispatcher($container->get(EventDispatcherInterface::class));
155
        static::loadTypo3LoadedExtAndExtLocalconf(true, $coreCache);
156
        static::unsetReservedGlobalVariables();
157
        $bootState->done = true;
158
        static::loadBaseTca(true, $coreCache);
159
        static::checkEncryptionKey();
160
161
        return $container;
162
    }
163
164
    /**
165
     * Prevent any unwanted output that may corrupt AJAX/compression.
166
     * This does not interfere with "die()" or "echo"+"exit()" messages!
167
     *
168
     * @internal This is not a public API method, do not use in own extensions
169
     */
170
    public static function startOutputBuffering()
171
    {
172
        ob_start();
173
    }
174
175
    /**
176
     * Run the base setup that checks server environment, determines paths,
177
     * populates base files and sets common configuration.
178
     *
179
     * Script execution will be aborted if something fails here.
180
     *
181
     * @throws \RuntimeException when TYPO3_REQUESTTYPE was not set before, setRequestType() needs to be called before
182
     * @internal This is not a public API method, do not use in own extensions
183
     */
184
    public static function baseSetup()
185
    {
186
        if (!defined('TYPO3_REQUESTTYPE')) {
187
            throw new \RuntimeException('No Request Type was set, TYPO3 does not know in which context it is run.', 1450561838);
188
        }
189
        if (!Environment::isComposerMode() && ClassLoadingInformation::isClassLoadingInformationAvailable()) {
190
            ClassLoadingInformation::registerClassLoadingInformation();
191
        }
192
    }
193
194
    /**
195
     * Sets the class loader to the bootstrap
196
     *
197
     * @param ClassLoader $classLoader an instance of the class loader
198
     * @internal This is not a public API method, do not use in own extensions
199
     */
200
    public static function initializeClassLoader(ClassLoader $classLoader)
201
    {
202
        ClassLoadingInformation::setClassLoader($classLoader);
203
204
        /** @see initializeAnnotationRegistry */
205
        AnnotationRegistry::registerLoader([$classLoader, 'loadClass']);
206
207
        // Annotations used in unit tests
208
        AnnotationReader::addGlobalIgnoredName('test');
209
210
        // Annotations that control the extension scanner
211
        AnnotationReader::addGlobalIgnoredName('extensionScannerIgnoreFile');
212
        AnnotationReader::addGlobalIgnoredName('extensionScannerIgnoreLine');
213
    }
214
215
    /**
216
     * checks if LocalConfiguration.php or PackageStates.php is missing,
217
     * used to see if a redirect to the install tool is needed
218
     *
219
     * @param ConfigurationManager $configurationManager
220
     * @return bool TRUE when the essential configuration is available, otherwise FALSE
221
     * @internal This is not a public API method, do not use in own extensions
222
     */
223
    protected static function checkIfEssentialConfigurationExists(ConfigurationManager $configurationManager): bool
224
    {
225
        return file_exists($configurationManager->getLocalConfigurationFileLocation())
226
            && file_exists(Environment::getLegacyConfigPath() . '/PackageStates.php');
227
    }
228
229
    /**
230
     * Initializes the package system and loads the package configuration and settings
231
     * provided by the packages.
232
     *
233
     * @param string $packageManagerClassName Define an alternative package manager implementation (usually for the installer)
234
     * @param FrontendInterface $coreCache
235
     * @return PackageManager
236
     * @internal This is not a public API method, do not use in own extensions
237
     */
238
    public static function createPackageManager($packageManagerClassName, FrontendInterface $coreCache): PackageManager
239
    {
240
        $dependencyOrderingService = GeneralUtility::makeInstance(DependencyOrderingService::class);
241
        /** @var \TYPO3\CMS\Core\Package\PackageManager $packageManager */
242
        $packageManager = new $packageManagerClassName($dependencyOrderingService);
243
        $packageManager->injectCoreCache($coreCache);
244
        $packageManager->initialize();
245
246
        return $packageManager;
247
    }
248
249
    /**
250
     * Load ext_localconf of extensions
251
     *
252
     * @param bool $allowCaching
253
     * @param FrontendInterface $coreCache
254
     * @internal This is not a public API method, do not use in own extensions
255
     */
256
    public static function loadTypo3LoadedExtAndExtLocalconf($allowCaching = true, FrontendInterface $coreCache = null)
257
    {
258
        if ($allowCaching) {
259
            $coreCache = $coreCache ?? GeneralUtility::makeInstance(CacheManager::class)->getCache('core');
260
        }
261
        ExtensionManagementUtility::loadExtLocalconf($allowCaching, $coreCache);
262
    }
263
264
    /**
265
     * We need an early instance of the configuration manager.
266
     * Since makeInstance relies on the object configuration, we create it here with new instead.
267
     *
268
     * @return ConfigurationManager
269
     */
270
    public static function createConfigurationManager(): ConfigurationManager
271
    {
272
        return new ConfigurationManager();
273
    }
274
275
    /**
276
     * We need an early instance of the configuration manager.
277
     * Since makeInstance relies on the object configuration, we create it here with new instead.
278
     *
279
     * @param ConfigurationManager $configurationManager
280
     * @internal This is not a public API method, do not use in own extensions
281
     */
282
    protected static function populateLocalConfiguration(ConfigurationManager $configurationManager)
283
    {
284
        $configurationManager->exportConfiguration();
285
    }
286
287
    /**
288
     * Instantiates an early cache instance
289
     *
290
     * Creates a cache instances independently from the CacheManager.
291
     * The is used to create the core cache during early bootstrap when the CacheManager
292
     * is not yet available (i.e. configuration is not yet loaded).
293
     *
294
     * @param string $identifier
295
     * @param bool $disableCaching
296
     * @return FrontendInterface
297
     * @internal
298
     */
299
    public static function createCache(string $identifier, bool $disableCaching = false): FrontendInterface
300
    {
301
        $cacheConfigurations = $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'] ?? [];
302
        $cacheConfigurations['di']['frontend'] = PhpFrontend::class;
303
        $cacheConfigurations['di']['backend'] = ContainerBackend::class;
304
        $cacheConfigurations['di']['options'] = [];
305
        $configuration = $cacheConfigurations[$identifier] ?? [];
306
307
        $frontend = $configuration['frontend'] ?? VariableFrontend::class;
308
        $backend = $configuration['backend'] ?? Typo3DatabaseBackend::class;
309
        $options = $configuration['options'] ?? [];
310
311
        if ($disableCaching) {
312
            $backend = NullBackend::class;
313
            $options = [];
314
        }
315
316
        $backendInstance = new $backend('production', $options);
317
        if (!$backendInstance instanceof BackendInterface) {
318
            throw new InvalidBackendException('"' . $backend . '" is not a valid cache backend object.', 1545260108);
319
        }
320
        if (is_callable([$backendInstance, 'initializeObject'])) {
321
            $backendInstance->initializeObject();
0 ignored issues
show
Bug introduced by
The method initializeObject() does not exist on TYPO3\CMS\Core\Cache\Backend\BackendInterface. It seems like you code against a sub-type of TYPO3\CMS\Core\Cache\Backend\BackendInterface such as TYPO3\CMS\Core\Cache\Backend\RedisBackend or TYPO3\CMS\Core\Cache\Backend\PdoBackend or TYPO3\CMS\Core\Cache\Backend\MemcachedBackend or TYPO3\CMS\Core\Cache\Backend\MemcachedBackend or TYPO3\CMS\Core\Tests\Uni...InitializeObjectFixture or TYPO3\CMS\Core\Cache\Backend\RedisBackend or TYPO3\CMS\Core\Cache\Backend\PdoBackend or TYPO3\CMS\Core\Cache\Backend\MemcachedBackend. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

321
            $backendInstance->/** @scrutinizer ignore-call */ 
322
                              initializeObject();
Loading history...
322
        }
323
324
        $frontendInstance = new $frontend($identifier, $backendInstance);
325
        if (!$frontendInstance instanceof FrontendInterface) {
326
            throw new InvalidCacheException('"' . $frontend . '" is not a valid cache frontend object.', 1545260109);
327
        }
328
        if (is_callable([$frontendInstance, 'initializeObject'])) {
329
            $frontendInstance->initializeObject();
0 ignored issues
show
Bug introduced by
The method initializeObject() does not exist on TYPO3\CMS\Core\Cache\Frontend\FrontendInterface. It seems like you code against a sub-type of TYPO3\CMS\Core\Cache\Frontend\FrontendInterface such as TYPO3\CMS\Core\Tests\Uni...InitializeObjectFixture. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

329
            $frontendInstance->/** @scrutinizer ignore-call */ 
330
                               initializeObject();
Loading history...
330
        }
331
332
        return $frontendInstance;
333
    }
334
335
    /**
336
     * Set default timezone
337
     */
338
    protected static function setDefaultTimezone()
339
    {
340
        $timeZone = $GLOBALS['TYPO3_CONF_VARS']['SYS']['phpTimeZone'];
341
        if (empty($timeZone)) {
342
            // Time zone from the server environment (TZ env or OS query)
343
            $defaultTimeZone = @date_default_timezone_get();
344
            if ($defaultTimeZone !== '') {
345
                $timeZone = $defaultTimeZone;
346
            } else {
347
                $timeZone = 'UTC';
348
            }
349
        }
350
        // Set default to avoid E_WARNINGs with PHP > 5.3
351
        date_default_timezone_set($timeZone);
352
    }
353
354
    /**
355
     * Configure and set up exception and error handling
356
     *
357
     * @throws \RuntimeException
358
     */
359
    protected static function initializeErrorHandling()
360
    {
361
        static::initializeBasicErrorReporting();
362
        $displayErrors = 0;
363
        $exceptionHandlerClassName = null;
364
        $productionExceptionHandlerClassName = $GLOBALS['TYPO3_CONF_VARS']['SYS']['productionExceptionHandler'];
365
        $debugExceptionHandlerClassName = $GLOBALS['TYPO3_CONF_VARS']['SYS']['debugExceptionHandler'];
366
367
        $errorHandlerClassName = $GLOBALS['TYPO3_CONF_VARS']['SYS']['errorHandler'];
368
        $errorHandlerErrors = $GLOBALS['TYPO3_CONF_VARS']['SYS']['errorHandlerErrors'] | E_USER_DEPRECATED;
369
        $exceptionalErrors = $GLOBALS['TYPO3_CONF_VARS']['SYS']['exceptionalErrors'];
370
371
        $displayErrorsSetting = (int)$GLOBALS['TYPO3_CONF_VARS']['SYS']['displayErrors'];
372
        switch ($displayErrorsSetting) {
373
            case -1:
374
                $ipMatchesDevelopmentSystem = GeneralUtility::cmpIP(GeneralUtility::getIndpEnv('REMOTE_ADDR'), $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask']);
375
                $exceptionHandlerClassName = $ipMatchesDevelopmentSystem ? $debugExceptionHandlerClassName : $productionExceptionHandlerClassName;
376
                $displayErrors = $ipMatchesDevelopmentSystem ? 1 : 0;
377
                $exceptionalErrors = $ipMatchesDevelopmentSystem ? $exceptionalErrors : 0;
378
                break;
379
            case 0:
380
                $exceptionHandlerClassName = $productionExceptionHandlerClassName;
381
                $displayErrors = 0;
382
                break;
383
            case 1:
384
                $exceptionHandlerClassName = $debugExceptionHandlerClassName;
385
                $displayErrors = 1;
386
                break;
387
            default:
388
                // Throw exception if an invalid option is set. A default for displayErrors is set
389
                // in very early install tool, coming from DefaultConfiguration.php. It is safe here
390
                // to just throw if there is no value for whatever reason.
391
                throw new \RuntimeException(
392
                    'The option $TYPO3_CONF_VARS[SYS][displayErrors] is not set to "-1", "0" or "1".',
393
                    1476046290
394
                );
395
        }
396
        @ini_set('display_errors', (string)$displayErrors);
397
398
        if (!empty($errorHandlerClassName)) {
399
            // Register an error handler for the given errorHandlerError
400
            $errorHandler = GeneralUtility::makeInstance($errorHandlerClassName, $errorHandlerErrors);
401
            $errorHandler->setExceptionalErrors($exceptionalErrors);
402
            if (is_callable([$errorHandler, 'setDebugMode'])) {
403
                $errorHandler->setDebugMode($displayErrors === 1);
404
            }
405
        }
406
        if (!empty($exceptionHandlerClassName)) {
407
            // Registering the exception handler is done in the constructor
408
            GeneralUtility::makeInstance($exceptionHandlerClassName);
409
        }
410
    }
411
412
    /**
413
     * Initialize basic error reporting.
414
     *
415
     * There are a lot of extensions that have no strict / notice / deprecated free
416
     * ext_localconf or ext_tables. Since the final error reporting must be set up
417
     * after those extension files are read, a default configuration is needed to
418
     * suppress error reporting meanwhile during further bootstrap.
419
     *
420
     * Please note: if you comment out this code, TYPO3 would never set any error reporting
421
     * which would need to have TYPO3 Core and ALL used extensions to be notice free and deprecation
422
     * free. However, commenting this out and running functional and acceptance tests shows what
423
     * needs to be done to make TYPO3 Core mostly notice-free (unit tests do not execute this code here).
424
     */
425
    protected static function initializeBasicErrorReporting(): void
426
    {
427
        // Core should be notice free at least until this point ...
428
        error_reporting(E_ALL & ~(E_STRICT | E_NOTICE | E_DEPRECATED));
429
    }
430
431
    /**
432
     * Initializes IO and stream wrapper related behavior.
433
     */
434
    protected static function initializeIO()
435
    {
436
        if (in_array('phar', stream_get_wrappers())) {
437
            // destroy and re-initialize PharStreamWrapper for TYPO3 core
438
            Manager::destroy();
439
            Manager::initialize(
440
                (new Behavior())
441
                    ->withAssertion(new ConjunctionInterceptor([
442
                        new PharStreamWrapperInterceptor(),
443
                        new PharMetaDataInterceptor()
444
                    ]))
445
            );
446
447
            stream_wrapper_unregister('phar');
448
            stream_wrapper_register('phar', PharStreamWrapper::class);
449
        }
450
    }
451
452
    /**
453
     * Set PHP memory limit depending on value of
454
     * $GLOBALS['TYPO3_CONF_VARS']['SYS']['setMemoryLimit']
455
     */
456
    protected static function setMemoryLimit()
457
    {
458
        if ((int)$GLOBALS['TYPO3_CONF_VARS']['SYS']['setMemoryLimit'] > 16) {
459
            @ini_set('memory_limit', (string)((int)$GLOBALS['TYPO3_CONF_VARS']['SYS']['setMemoryLimit'] . 'm'));
460
        }
461
    }
462
463
    /**
464
     * Unsetting reserved global variables:
465
     * Those are set in "ext:core/ext_tables.php" file:
466
     *
467
     * @internal This is not a public API method, do not use in own extensions
468
     */
469
    public static function unsetReservedGlobalVariables()
470
    {
471
        unset($GLOBALS['PAGES_TYPES']);
472
        unset($GLOBALS['TCA']);
473
        unset($GLOBALS['TBE_MODULES']);
474
        unset($GLOBALS['TBE_STYLES']);
475
        unset($GLOBALS['BE_USER']);
476
        // Those set otherwise:
477
        unset($GLOBALS['TBE_MODULES_EXT']);
478
        unset($GLOBALS['TCA_DESCR']);
479
    }
480
481
    /**
482
     * Load $TCA
483
     *
484
     * This will mainly set up $TCA through extMgm API.
485
     *
486
     * @param bool $allowCaching True, if loading TCA from cache is allowed
487
     * @param FrontendInterface $coreCache
488
     * @internal This is not a public API method, do not use in own extensions
489
     */
490
    public static function loadBaseTca(bool $allowCaching = true, FrontendInterface $coreCache = null)
491
    {
492
        if ($allowCaching) {
493
            $coreCache = $coreCache ?? GeneralUtility::makeInstance(CacheManager::class)->getCache('core');
494
        }
495
        ExtensionManagementUtility::loadBaseTca($allowCaching, $coreCache);
496
    }
497
498
    /**
499
     * Check if a configuration key has been configured
500
     */
501
    protected static function checkEncryptionKey()
502
    {
503
        if (empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'])) {
504
            throw new \RuntimeException(
505
                'TYPO3 Encryption is empty. $GLOBALS[\'TYPO3_CONF_VARS\'][\'SYS\'][\'encryptionKey\'] needs to be set for TYPO3 to work securely',
506
                1502987245
507
            );
508
        }
509
    }
510
511
    /**
512
     * Load ext_tables and friends.
513
     *
514
     * This will mainly load and execute ext_tables.php files of loaded extensions
515
     * or the according cache file if exists.
516
     *
517
     * @param bool $allowCaching True, if reading compiled ext_tables file from cache is allowed
518
     * @internal This is not a public API method, do not use in own extensions
519
     */
520
    public static function loadExtTables(bool $allowCaching = true)
521
    {
522
        ExtensionManagementUtility::loadExtTables($allowCaching);
523
        static::runExtTablesPostProcessingHooks();
524
    }
525
526
    /**
527
     * Check for registered ext tables hooks and run them
528
     *
529
     * @throws \UnexpectedValueException
530
     */
531
    protected static function runExtTablesPostProcessingHooks()
532
    {
533
        foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['extTablesInclusion-PostProcessing'] ?? [] as $className) {
534
            /** @var \TYPO3\CMS\Core\Database\TableConfigurationPostProcessingHookInterface $hookObject */
535
            $hookObject = GeneralUtility::makeInstance($className);
536
            if (!$hookObject instanceof TableConfigurationPostProcessingHookInterface) {
537
                throw new \UnexpectedValueException(
538
                    '$hookObject "' . $className . '" must implement interface TYPO3\\CMS\\Core\\Database\\TableConfigurationPostProcessingHookInterface',
539
                    1320585902
540
                );
541
            }
542
            $hookObject->processData();
543
        }
544
    }
545
546
    /**
547
     * Initialize the Routing for the TYPO3 Backend
548
     * Loads all routes registered inside all packages and stores them inside the Router
549
     *
550
     * @internal This is not a public API method, do not use in own extensions
551
     * @deprecated this does not do anything anymore, as TYPO3's dependency injection already loads the routes on demand.
552
     */
553
    public static function initializeBackendRouter()
554
    {
555
        // TODO: Once typo3/testing-framework is adapted, this code can be dropped / deprecated. As DI is already
556
        // loading all routes on demand, this method is not needed anymore.
557
    }
558
559
    /**
560
     * Initialize backend user object in globals
561
     *
562
     * @param string $className usually \TYPO3\CMS\Core\Authentication\BackendUserAuthentication::class but can be used for CLI
563
     * @internal This is not a public API method, do not use in own extensions
564
     */
565
    public static function initializeBackendUser($className = BackendUserAuthentication::class)
566
    {
567
        /** @var \TYPO3\CMS\Core\Authentication\BackendUserAuthentication $backendUser */
568
        $backendUser = GeneralUtility::makeInstance($className);
569
        // The global must be available very early, because methods below
570
        // might trigger code which relies on it. See: #45625
571
        $GLOBALS['BE_USER'] = $backendUser;
572
        $backendUser->start();
573
    }
574
575
    /**
576
     * Initializes and ensures authenticated access
577
     *
578
     * @internal This is not a public API method, do not use in own extensions
579
     * @param bool $proceedIfNoUserIsLoggedIn if set to TRUE, no forced redirect to the login page will be done
580
     */
581
    public static function initializeBackendAuthentication($proceedIfNoUserIsLoggedIn = false)
582
    {
583
        $GLOBALS['BE_USER']->backendCheckLogin($proceedIfNoUserIsLoggedIn);
584
    }
585
586
    /**
587
     * Initialize language object
588
     *
589
     * @internal This is not a public API method, do not use in own extensions
590
     */
591
    public static function initializeLanguageObject()
592
    {
593
        /** @var \TYPO3\CMS\Core\Localization\LanguageService $GLOBALS['LANG'] */
594
        $GLOBALS['LANG'] = LanguageService::createFromUserPreferences($GLOBALS['BE_USER']);
595
    }
596
}
597