[!!!][FEATURE] Discard TYPO3 class loader
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Core / ClassLoadingInformation.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 Composer\Autoload\ClassLoader as ComposerClassLoader;
18 use TYPO3\CMS\Core\Package\PackageInterface;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20
21 /**
22 * Get and manipulate class loading information, only necessary/in use
23 * when TYPO3 is not purely set up by composer but when e.g. extensions are installed via the extension manager
24 * by utilizing the composer class loader and adding more information built by the ClassLoadingInformationGenerator
25 * class.
26 *
27 * @internal
28 */
29 class ClassLoadingInformation {
30
31 /**
32 * Base directory storing all autoload information
33 */
34 const AUTOLOAD_INFO_DIR = 'typo3temp/autoload/';
35
36 /**
37 * Name of file that contains all classes-filename mappings
38 */
39 const AUTOLOAD_CLASSMAP_FILENAME = 'autoload_classmap.php';
40
41 /**
42 * Name of file that contains all PSR4 mappings, fetched from the composer.json files of extensions
43 */
44 const AUTOLOAD_PSR4_FILENAME = 'autoload_psr4.php';
45
46 /**
47 * Name of file that contains all class alias mappings
48 */
49 const AUTOLOAD_CLASSALIASMAP_FILENAME = 'autoload_classaliasmap.php';
50
51 /**
52 * Checks if the autoload_classmap.php exists. Used to see if the ClassLoadingInformationGenerator
53 * should be called.
54 *
55 * @return bool
56 */
57 static public function classLoadingInformationExists() {
58 return file_exists(PATH_site . self::AUTOLOAD_INFO_DIR . self::AUTOLOAD_CLASSMAP_FILENAME);
59 }
60
61 /**
62 * Puts all information compiled by the ClassLoadingInformationGenerator to files
63 */
64 static public function writeClassLoadingInformation() {
65 self::ensureAutoloadInfoDirExists();
66 $classInfoFiles = ClassLoadingInformationGenerator::buildAutoloadInformationFiles();
67 GeneralUtility::writeFile(PATH_site . self::AUTOLOAD_INFO_DIR . self::AUTOLOAD_CLASSMAP_FILENAME, $classInfoFiles['classMapFile']);
68 GeneralUtility::writeFile(PATH_site . self::AUTOLOAD_INFO_DIR . self::AUTOLOAD_PSR4_FILENAME, $classInfoFiles['psr-4File']);
69
70 $classAliasMapFile = ClassLoadingInformationGenerator::buildClassAliasMapFile();
71 GeneralUtility::writeFile(PATH_site . self::AUTOLOAD_INFO_DIR . self::AUTOLOAD_CLASSALIASMAP_FILENAME, $classAliasMapFile);
72 }
73
74 /**
75 * Registers the class aliases, the class maps and the PSR4 prefixes previously identified by
76 * the ClassLoadingInformationGenerator during runtime.
77 */
78 static public function registerClassLoadingInformation() {
79 $composerClassLoader = static::getClassLoader();
80
81 $dynamicClassAliasMapFile = PATH_site . self::AUTOLOAD_INFO_DIR . self::AUTOLOAD_CLASSALIASMAP_FILENAME;
82 if (file_exists($dynamicClassAliasMapFile)) {
83 $classAliasMap = require $dynamicClassAliasMapFile;
84 if (is_array($classAliasMap) && !empty($classAliasMap['aliasToClassNameMapping']) && !empty($classAliasMap['classNameToAliasMapping'])) {
85 $composerClassLoader->addAliasMap($classAliasMap);
86 }
87 }
88
89 $dynamicClassMapFile = PATH_site . self::AUTOLOAD_INFO_DIR . self::AUTOLOAD_CLASSMAP_FILENAME;
90 if (file_exists($dynamicClassMapFile)) {
91 $classMap = require $dynamicClassMapFile;
92 if (is_array($classMap)) {
93 $composerClassLoader->addClassMap($classMap);
94 }
95 }
96
97 $dynamicPsr4File = PATH_site . self::AUTOLOAD_INFO_DIR . self::AUTOLOAD_PSR4_FILENAME;
98 if (file_exists($dynamicPsr4File)) {
99 $psr4 = require $dynamicPsr4File;
100 if (is_array($psr4)) {
101 foreach ($psr4 as $prefix => $paths) {
102 $composerClassLoader->setPsr4($prefix, $paths);
103 }
104 }
105 }
106 }
107
108 /**
109 * Sets class loading information for a package for the current web request
110 *
111 * @param PackageInterface $package
112 * @throws \TYPO3\CMS\Core\Error\Exception
113 */
114 static public function registerTransientClassLoadingInformationForPackage(PackageInterface $package) {
115 $composerClassLoader = static::getClassLoader();
116 $classInformation = ClassLoadingInformationGenerator::buildClassLoadingInformationForPackage($package);
117 $composerClassLoader->addClassMap($classInformation['classMap']);
118 foreach ($classInformation['psr-4'] as $prefix => $paths) {
119 $composerClassLoader->setPsr4($prefix, $paths);
120 }
121 if (is_callable(array($composerClassLoader, 'addAliasMap'))) {
122 $aliasMap = ClassLoadingInformationGenerator::buildClassAliasMapForPackage($package);
123 $composerClassLoader->addAliasMap($aliasMap);
124 }
125 }
126
127 /**
128 * Get class name for alias
129 *
130 * @param string $alias
131 * @return mixed
132 */
133 static public function getClassNameForAlias($alias) {
134 $composerClassLoader = static::getClassLoader();
135 if (!is_callable(array($composerClassLoader, 'getClassNameForAlias'))) {
136 return $alias;
137 }
138 return $composerClassLoader->getClassNameForAlias($alias);
139 }
140
141 /**
142 * Ensures the defined path for class information files exists
143 */
144 static protected function ensureAutoloadInfoDirExists() {
145 $autoloadInfoDir = PATH_site . self::AUTOLOAD_INFO_DIR;
146 if (!file_exists($autoloadInfoDir)) {
147 GeneralUtility::mkdir_deep($autoloadInfoDir);
148 }
149 }
150
151 /**
152 * Internal method calling the bootstrap to fetch the composer class loader
153 *
154 * @return ComposerClassLoader
155 * @throws \TYPO3\CMS\Core\Exception
156 */
157 static protected function getClassLoader() {
158 return Bootstrap::getInstance()->getEarlyInstance(ComposerClassLoader::class);
159 }
160
161 }