17 use Composer\Autoload\ClassLoader;
18 use Composer\Autoload\ClassMapGenerator;
27 class ClassLoadingInformationGenerator
32 protected $activeExtensionPackages;
37 protected $classLoader;
42 protected $installationRoot;
55 public function __construct(ClassLoader $classLoader, array $activeExtensionPackages, $installationRoot, $isDevMode =
false)
57 $this->classLoader = $classLoader;
58 $this->activeExtensionPackages = $activeExtensionPackages;
59 $this->installationRoot = $installationRoot;
60 $this->isDevMode = $isDevMode;
70 public function buildClassLoadingInformationForPackage(PackageInterface $package, $useRelativePaths =
false)
74 $packagePath = $package->getPackagePath();
75 $manifest = $package->getValueFromComposerManifest();
77 if (empty($manifest->autoload)) {
79 $classMap = $this->createClassMap($packagePath, $useRelativePaths, !$this->isDevMode);
81 $autoloadPsr4 = $this->getAutoloadSectionFromManifest($manifest,
'psr-4');
82 if (!empty($autoloadPsr4)) {
83 foreach ($autoloadPsr4 as $namespacePrefix => $paths) {
84 foreach ((array)$paths as $path) {
85 $namespacePath = $packagePath . $path;
86 $namespaceRealPath = realpath($namespacePath);
87 if ($useRelativePaths) {
88 $psr4[$namespacePrefix][] = $this->makePathRelative($namespacePath, $namespaceRealPath);
90 $psr4[$namespacePrefix][] = $namespacePath;
92 if (!empty($namespaceRealPath) && is_dir($namespaceRealPath)) {
94 $classMap = array_merge($classMap, $this->createClassMap($namespacePath, $useRelativePaths,
false, $namespacePrefix));
99 $autoloadClassmap = $this->getAutoloadSectionFromManifest($manifest,
'classmap');
100 if (!empty($autoloadClassmap)) {
101 foreach ($autoloadClassmap as $path) {
102 $classMap = array_merge($classMap, $this->createClassMap($packagePath . $path, $useRelativePaths));
107 return [
'classMap' => $classMap,
'psr-4' => $psr4];
118 protected function getAutoloadSectionFromManifest($manifest, $section)
120 $finalAutoloadSection = [];
121 $autoloadDefinition = json_decode(json_encode($manifest->autoload),
true);
122 if (!empty($autoloadDefinition[$section]) && is_array($autoloadDefinition[$section])) {
123 $finalAutoloadSection = $autoloadDefinition[$section];
125 if ($this->isDevMode) {
126 if (isset($manifest->{
'autoload-dev'})) {
127 $autoloadDefinitionDev = json_decode(json_encode($manifest->{
'autoload-dev'}),
true);
128 if (!empty($autoloadDefinitionDev[$section]) && is_array($autoloadDefinitionDev[$section])) {
129 $finalAutoloadSection = array_merge($finalAutoloadSection, $autoloadDefinitionDev[$section]);
134 return $finalAutoloadSection;
146 protected function createClassMap($classesPath, $useRelativePaths =
false, $ignorePotentialTestClasses =
false, $namespace =
null)
149 $blacklistExpression =
null;
150 if ($ignorePotentialTestClasses) {
151 $blacklistPathPrefix = realpath($classesPath);
152 $blacklistPathPrefix = str_replace(
'\\',
'/', $blacklistPathPrefix);
153 $blacklistExpression =
"{($blacklistPathPrefix/tests/|$blacklistPathPrefix/Tests/|$blacklistPathPrefix/Resources/|$blacklistPathPrefix/res/|$blacklistPathPrefix/class.ext_update.php)}";
155 foreach (ClassMapGenerator::createMap($classesPath, $blacklistExpression,
null, $namespace) as $class => $path) {
156 if ($useRelativePaths) {
157 $classMap[$class] = $this->makePathRelative($classesPath, $path);
159 $classMap[$class] = $path;
172 public function buildClassAliasMapForPackage(PackageInterface $package)
174 $aliasToClassNameMapping = [];
175 $classNameToAliasMapping = [];
176 $possibleClassAliasFiles = [];
177 $manifest = $package->getValueFromComposerManifest();
178 if (!empty($manifest->extra->{
'typo3/class-alias-loader'}->{
'class-alias-maps'})) {
179 $possibleClassAliasFiles = $manifest->extra->{
'typo3/class-alias-loader'}->{
'class-alias-maps'};
180 if (!is_array($possibleClassAliasFiles)) {
181 throw new \TYPO3\CMS\Core\Error\Exception(
'"typo3/class-alias-loader"/"class-alias-maps" must return an array!', 1444142481);
184 $possibleClassAliasFiles[] =
'Migrations/Code/ClassAliasMap.php';
186 $packagePath = $package->getPackagePath();
187 foreach ($possibleClassAliasFiles as $possibleClassAliasFile) {
188 $possiblePathToClassAliasFile = $packagePath . $possibleClassAliasFile;
189 if (file_exists($possiblePathToClassAliasFile)) {
190 $packageAliasMap = require $possiblePathToClassAliasFile;
191 if (!is_array($packageAliasMap)) {
192 throw new \TYPO3\CMS\Core\Error\Exception(
'"class alias maps" must return an array', 1422625075);
194 foreach ($packageAliasMap as $aliasClassName => $className) {
195 $lowerCasedAliasClassName = strtolower($aliasClassName);
196 $aliasToClassNameMapping[$lowerCasedAliasClassName] = $className;
197 $classNameToAliasMapping[$className][$lowerCasedAliasClassName] = $lowerCasedAliasClassName;
202 return [
'aliasToClassNameMapping' => $aliasToClassNameMapping,
'classNameToAliasMapping' => $classNameToAliasMapping];
210 public function buildAutoloadInformationFiles()
212 $psr4File = $classMapFile = <<<EOF
224 foreach ($this->activeExtensionPackages as $package) {
225 $classLoadingInformation = $this->buildClassLoadingInformationForPackage($package,
true);
226 $classMap = array_merge($classMap, $classLoadingInformation[
'classMap']);
227 $psr4 = array_merge($psr4, $classLoadingInformation[
'psr-4']);
232 foreach ($classMap as $class => $relativePath) {
233 $classMapFile .= sprintf(
' %s => %s,', var_export($class,
true), $this->getPathCode($relativePath)) .
"\n";
235 $classMapFile .=
");\n";
237 foreach ($psr4 as $prefix => $relativePaths) {
238 $psr4File .= sprintf(
' %s => array(%s),', var_export($prefix,
true), implode(
',', array_map([$this,
'getPathCode'], $relativePaths))) .
"\n";
242 return [
'classMapFile' => $classMapFile,
'psr-4File' => $psr4File];
253 protected function makePathRelative($packagePath, $realPathOfClassFile, $relativeToRoot =
true)
255 $realPathOfClassFile = GeneralUtility::fixWindowsFilePath($realPathOfClassFile);
256 $packageRealPath = GeneralUtility::fixWindowsFilePath(realpath($packagePath));
257 $relativePackagePath = rtrim(substr($packagePath, strlen($this->installationRoot)),
'/');
258 if ($relativeToRoot) {
259 if ($realPathOfClassFile === $packageRealPath) {
260 $relativePathToClassFile = $relativePackagePath;
262 $relativePathToClassFile = $relativePackagePath .
'/' . ltrim(substr($realPathOfClassFile, strlen($packageRealPath)),
'/');
265 $relativePathToClassFile = ltrim(substr($realPathOfClassFile, strlen($packageRealPath)),
'/');
268 return $relativePathToClassFile;
277 protected function getPathCode($relativePathToClassFile)
279 return '$typo3InstallDir . ' . var_export($relativePathToClassFile,
true);
289 public function buildClassAliasMapFile()
291 $aliasToClassNameMapping = [];
292 $classNameToAliasMapping = [];
293 foreach ($this->activeExtensionPackages as $package) {
294 $aliasMappingForPackage = $this->buildClassAliasMapForPackage($package);
295 $aliasToClassNameMapping = array_merge($aliasToClassNameMapping, $aliasMappingForPackage[
'aliasToClassNameMapping']);
296 $classNameToAliasMapping = array_merge($classNameToAliasMapping, $aliasMappingForPackage[
'classNameToAliasMapping']);
299 'aliasToClassNameMapping' => $aliasToClassNameMapping,
300 'classNameToAliasMapping' => $classNameToAliasMapping
302 $fileContent =
"<?php\nreturn ";
303 $fileContent .= var_export($exportArray,
true);
304 $fileContent .=
";\n";