Passed
Push — master ( ba4afd...fb25eb )
by
unknown
26:33 queued 08:07
created

Bootstrap::initializeLanguageObject()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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

319
            $backendInstance->/** @scrutinizer ignore-call */ 
320
                              initializeObject();
Loading history...
320
        }
321
322
        $frontendInstance = new $frontend($identifier, $backendInstance);
323
        if (!$frontendInstance instanceof FrontendInterface) {
324
            throw new InvalidCacheException('"' . $frontend . '" is not a valid cache frontend object.', 1545260109);
325
        }
326
        if (is_callable([$frontendInstance, 'initializeObject'])) {
327
            $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

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