Completed
Push — master ( 0f9475...4a0502 )
by
unknown
14:19
created

Bootstrap::createCache()   B

Complexity

Conditions 6
Paths 14

Size

Total Lines 34
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 22
nc 14
nop 2
dl 0
loc 34
rs 8.9457
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\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\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(uniqid('', true)), 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
        // Push PackageManager instance to ExtensionManagementUtility
110
        // Should be fetched through the container (later) but currently a PackageManager
111
        // singleton instance is required by PackageManager->activePackageDuringRuntime
112
        GeneralUtility::setSingletonInstance(PackageManager::class, $packageManager);
113
        ExtensionManagementUtility::setPackageManager($packageManager);
114
115
        static::setDefaultTimezone();
116
        static::setMemoryLimit();
117
118
        $assetsCache = static::createCache('assets', $disableCaching);
119
        $dependencyInjectionContainerCache = static::createCache('di');
120
121
        $bootState = new \stdClass();
122
        $bootState->done = false;
123
        $bootState->cacheDisabled = $disableCaching;
124
125
        $builder = new ContainerBuilder([
126
            ClassLoader::class => $classLoader,
127
            ApplicationContext::class => Environment::getContext(),
128
            ConfigurationManager::class => $configurationManager,
129
            LogManager::class => $logManager,
130
            'cache.di' => $dependencyInjectionContainerCache,
131
            'cache.core' => $coreCache,
132
            'cache.assets' => $assetsCache,
133
            PackageManager::class => $packageManager,
134
135
            // @internal
136
            'boot.state' => $bootState,
137
        ]);
138
139
        $container = $builder->createDependencyInjectionContainer($packageManager, $dependencyInjectionContainerCache, $failsafe);
140
141
        // Push the container to GeneralUtility as we want to make sure its
142
        // makeInstance() method creates classes using the container from now on.
143
        GeneralUtility::setContainer($container);
144
145
        // Reset singleton instances in order for GeneralUtility::makeInstance() to use
146
        // ContainerInterface->get() for early services from now on.
147
        GeneralUtility::removeSingletonInstance(LogManager::class, $logManager);
148
        GeneralUtility::removeSingletonInstance(PackageManager::class, $packageManager);
149
150
        if ($failsafe) {
151
            $bootState->done = true;
152
            return $container;
153
        }
154
155
        IconRegistry::setCache($assetsCache);
156
        PageRenderer::setCache($assetsCache);
157
        ExtensionManagementUtility::setEventDispatcher($container->get(EventDispatcherInterface::class));
158
        static::loadTypo3LoadedExtAndExtLocalconf(true, $coreCache);
159
        static::unsetReservedGlobalVariables();
160
        $bootState->done = true;
161
        static::loadBaseTca(true, $coreCache);
162
        static::checkEncryptionKey();
163
164
        return $container;
165
    }
166
167
    /**
168
     * Prevent any unwanted output that may corrupt AJAX/compression.
169
     * This does not interfere with "die()" or "echo"+"exit()" messages!
170
     *
171
     * @internal This is not a public API method, do not use in own extensions
172
     */
173
    public static function startOutputBuffering()
174
    {
175
        ob_start();
176
    }
177
178
    /**
179
     * Run the base setup that checks server environment, determines paths,
180
     * populates base files and sets common configuration.
181
     *
182
     * Script execution will be aborted if something fails here.
183
     *
184
     * @throws \RuntimeException when TYPO3_REQUESTTYPE was not set before, setRequestType() needs to be called before
185
     * @internal This is not a public API method, do not use in own extensions
186
     */
187
    public static function baseSetup()
188
    {
189
        if (!defined('TYPO3_REQUESTTYPE')) {
190
            throw new \RuntimeException('No Request Type was set, TYPO3 does not know in which context it is run.', 1450561838);
191
        }
192
        if (!Environment::isComposerMode() && ClassLoadingInformation::isClassLoadingInformationAvailable()) {
193
            ClassLoadingInformation::registerClassLoadingInformation();
194
        }
195
    }
196
197
    /**
198
     * Sets the class loader to the bootstrap
199
     *
200
     * @param ClassLoader $classLoader an instance of the class loader
201
     * @internal This is not a public API method, do not use in own extensions
202
     */
203
    public static function initializeClassLoader(ClassLoader $classLoader)
204
    {
205
        ClassLoadingInformation::setClassLoader($classLoader);
206
207
        /** @see initializeAnnotationRegistry */
208
        AnnotationRegistry::registerLoader([$classLoader, 'loadClass']);
209
210
        // Annotations used in unit tests
211
        AnnotationReader::addGlobalIgnoredName('test');
212
213
        // Annotations that control the extension scanner
214
        AnnotationReader::addGlobalIgnoredName('extensionScannerIgnoreFile');
215
        AnnotationReader::addGlobalIgnoredName('extensionScannerIgnoreLine');
216
    }
217
218
    /**
219
     * checks if LocalConfiguration.php or PackageStates.php is missing,
220
     * used to see if a redirect to the install tool is needed
221
     *
222
     * @param ConfigurationManager $configurationManager
223
     * @return bool TRUE when the essential configuration is available, otherwise FALSE
224
     * @internal This is not a public API method, do not use in own extensions
225
     */
226
    protected static function checkIfEssentialConfigurationExists(ConfigurationManager $configurationManager): bool
227
    {
228
        return file_exists($configurationManager->getLocalConfigurationFileLocation())
229
            && file_exists(Environment::getLegacyConfigPath() . '/PackageStates.php');
230
    }
231
232
    /**
233
     * Initializes the package system and loads the package configuration and settings
234
     * provided by the packages.
235
     *
236
     * @param string $packageManagerClassName Define an alternative package manager implementation (usually for the installer)
237
     * @param FrontendInterface $coreCache
238
     * @return PackageManager
239
     * @internal This is not a public API method, do not use in own extensions
240
     */
241
    public static function createPackageManager($packageManagerClassName, FrontendInterface $coreCache): PackageManager
242
    {
243
        $dependencyOrderingService = GeneralUtility::makeInstance(DependencyOrderingService::class);
244
        /** @var \TYPO3\CMS\Core\Package\PackageManager $packageManager */
245
        $packageManager = new $packageManagerClassName($dependencyOrderingService);
246
        $packageManager->injectCoreCache($coreCache);
247
        $packageManager->initialize();
248
249
        return $packageManager;
250
    }
251
252
    /**
253
     * Load ext_localconf of extensions
254
     *
255
     * @param bool $allowCaching
256
     * @param FrontendInterface $coreCache
257
     * @internal This is not a public API method, do not use in own extensions
258
     */
259
    public static function loadTypo3LoadedExtAndExtLocalconf($allowCaching = true, FrontendInterface $coreCache = null)
260
    {
261
        if ($allowCaching) {
262
            $coreCache = $coreCache ?? GeneralUtility::makeInstance(CacheManager::class)->getCache('core');
263
        }
264
        ExtensionManagementUtility::loadExtLocalconf($allowCaching, $coreCache);
265
    }
266
267
    /**
268
     * We need an early instance of the configuration manager.
269
     * Since makeInstance relies on the object configuration, we create it here with new instead.
270
     *
271
     * @return ConfigurationManager
272
     */
273
    public static function createConfigurationManager(): ConfigurationManager
274
    {
275
        return new ConfigurationManager();
276
    }
277
278
    /**
279
     * We need an early instance of the configuration manager.
280
     * Since makeInstance relies on the object configuration, we create it here with new instead.
281
     *
282
     * @param ConfigurationManager $configurationManager
283
     * @internal This is not a public API method, do not use in own extensions
284
     */
285
    protected static function populateLocalConfiguration(ConfigurationManager $configurationManager)
286
    {
287
        $configurationManager->exportConfiguration();
288
    }
289
290
    /**
291
     * Instantiates an early cache instance
292
     *
293
     * Creates a cache instances independently from the CacheManager.
294
     * The is used to create the core cache during early bootstrap when the CacheManager
295
     * is not yet available (i.e. configuration is not yet loaded).
296
     *
297
     * @param string $identifier
298
     * @param bool $disableCaching
299
     * @return FrontendInterface
300
     * @internal
301
     */
302
    public static function createCache(string $identifier, bool $disableCaching = false): FrontendInterface
303
    {
304
        $cacheConfigurations = $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'] ?? [];
305
        $cacheConfigurations['di']['frontend'] = PhpFrontend::class;
306
        $cacheConfigurations['di']['backend'] = ContainerBackend::class;
307
        $cacheConfigurations['di']['options'] = [];
308
        $configuration = $cacheConfigurations[$identifier] ?? [];
309
310
        $frontend = $configuration['frontend'] ?? VariableFrontend::class;
311
        $backend = $configuration['backend'] ?? Typo3DatabaseBackend::class;
312
        $options = $configuration['options'] ?? [];
313
314
        if ($disableCaching) {
315
            $backend = NullBackend::class;
316
            $options = [];
317
        }
318
319
        $backendInstance = new $backend('production', $options);
320
        if (!$backendInstance instanceof BackendInterface) {
321
            throw new InvalidBackendException('"' . $backend . '" is not a valid cache backend object.', 1545260108);
322
        }
323
        if (is_callable([$backendInstance, 'initializeObject'])) {
324
            $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

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

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