[!!!][FEATURE] Discard TYPO3 class loader 27/39827/21
authorHelmut Hummel <helmut.hummel@typo3.org>
Sat, 30 May 2015 11:34:18 +0000 (13:34 +0200)
committerBenjamin Mack <benni@typo3.org>
Wed, 10 Jun 2015 17:41:34 +0000 (19:41 +0200)
Use composer class loader instead of the TYPO3 class loader
when TYPO3 is not installed via composer, thus building the same
class information logic during runtime (and caching it away) as
composer does with its "dump-autoload" command.

Releases: master
Resolves: #67212
Change-Id: Id032411a690d67ca690a724748c3c796d2bb5f6e
Reviewed-on: http://review.typo3.org/39827
Reviewed-by: Thomas Maroschik <tmaroschik@dfau.de>
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
Reviewed-by: Benjamin Mack <benni@typo3.org>
Tested-by: Benjamin Mack <benni@typo3.org>
34 files changed:
composer.json
typo3/sysext/backend/Tests/Unit/BackendModuleRequestHandlerTest.php
typo3/sysext/compatibility6/Migrations/Code/ClassAliasMap.php
typo3/sysext/compatibility6/Migrations/Code/LegacyClassesForIde.php
typo3/sysext/core/Build/UnitTestsBootstrap.php
typo3/sysext/core/Classes/Cache/Backend/ClassLoaderBackend.php [deleted file]
typo3/sysext/core/Classes/Cache/Backend/EarlyClassLoaderBackend.php [deleted file]
typo3/sysext/core/Classes/Core/Bootstrap.php
typo3/sysext/core/Classes/Core/ClassAliasMap.php [deleted file]
typo3/sysext/core/Classes/Core/ClassLoader.php [deleted file]
typo3/sysext/core/Classes/Core/ClassLoadingInformation.php [new file with mode: 0644]
typo3/sysext/core/Classes/Core/ClassLoadingInformationGenerator.php [new file with mode: 0644]
typo3/sysext/core/Classes/Package/PackageManager.php
typo3/sysext/core/Classes/Package/UnitTestPackageManager.php
typo3/sysext/core/Classes/Utility/GeneralUtility.php
typo3/sysext/core/Configuration/DefaultConfiguration.php
typo3/sysext/core/Documentation/Changelog/master/Breaking-67212-DiscardLegacyClassLoader.rst [new file with mode: 0644]
typo3/sysext/core/Resources/PHP/ClassMapGenerator.php [new file with mode: 0644]
typo3/sysext/core/Tests/Unit/Core/ClassLoaderTest.php [deleted file]
typo3/sysext/core/Tests/Unit/Package/PackageManagerTest.php
typo3/sysext/core/composer.json
typo3/sysext/core/ext_localconf.php
typo3/sysext/extbase/Classes/Object/Container/Container.php
typo3/sysext/extbase/Classes/Property/PropertyMapper.php
typo3/sysext/extbase/Classes/Property/PropertyMappingConfiguration.php
typo3/sysext/extensionmanager/Classes/Utility/InstallUtility.php
typo3/sysext/fluid/Classes/Core/Parser/TemplateParser.php
typo3/sysext/form/Migrations/Code/ClassAliasMap.php [new file with mode: 0644]
typo3/sysext/form/ext_autoload.php [deleted file]
typo3/sysext/install/Classes/Controller/AbstractController.php
typo3/sysext/install/Classes/Controller/Action/AbstractAction.php
typo3/sysext/install/Classes/Controller/Action/Step/DatabaseConnect.php
typo3/sysext/install/Classes/Service/ClearCacheService.php
typo3/sysext/rtehtmlarea/ext_autoload.php [deleted file]

index 7fdda25..892f30a 100644 (file)
                "phpwhois/idna-convert": "0.8.2",
                "swiftmailer/swiftmailer": "5.4.1",
                "symfony/console": "2.5.11",
                "phpwhois/idna-convert": "0.8.2",
                "swiftmailer/swiftmailer": "5.4.1",
                "symfony/console": "2.5.11",
+               "symfony/finder": "2.6.9",
+               "doctrine/instantiator": "1.0.4",
                "helhum/class-alias-loader": "1.1.4",
                "helhum/class-alias-loader": "1.1.4",
-               "typo3/cms-composer-installers": "1.1.2",
-               "doctrine/instantiator": "1.0.4"
+               "typo3/cms-composer-installers": "1.1.2"
        },
        "require-dev": {
                "mikey179/vfsStream": "1.4.*@dev",
        },
        "require-dev": {
                "mikey179/vfsStream": "1.4.*@dev",
                        "TYPO3\\CMS\\Sv\\": "typo3/sysext/sv/Classes/",
                        "TYPO3\\CMS\\T3skin\\": "typo3/sysext/t3skin/Classes/"
                },
                        "TYPO3\\CMS\\Sv\\": "typo3/sysext/sv/Classes/",
                        "TYPO3\\CMS\\T3skin\\": "typo3/sysext/t3skin/Classes/"
                },
-               "classmap": ["typo3/sysext/core/Resources/PHP/RemoveXSS.php"]
+               "classmap": [
+                       "typo3/sysext/core/Resources/PHP/"
+               ]
        },
        "autoload-dev": {
                "psr-4": {
        },
        "autoload-dev": {
                "psr-4": {
index 6bb5d0f..9ef4de9 100644 (file)
@@ -18,6 +18,7 @@ use PHPUnit_Framework_MockObject_MockObject;
 use TYPO3\CMS\Backend\BackendModuleRequestHandler;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Core\Bootstrap;
 use TYPO3\CMS\Backend\BackendModuleRequestHandler;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\FormProtection\AbstractFormProtection;
 use TYPO3\CMS\Core\Tests\AccessibleObjectInterface;
 use TYPO3\CMS\Core\Tests\UnitTestCase;
 
 use TYPO3\CMS\Core\Tests\AccessibleObjectInterface;
 use TYPO3\CMS\Core\Tests\UnitTestCase;
 
@@ -37,7 +38,7 @@ class BackendModuleRequestHandlerTest extends UnitTestCase {
        protected $formProtectionMock;
 
        public function setUp() {
        protected $formProtectionMock;
 
        public function setUp() {
-               $this->formProtectionMock = $this->getMock('AbstractFormProtection', array('validateToken'));
+               $this->formProtectionMock = $this->getMockForAbstractClass(AbstractFormProtection::class, array(), '', TRUE, TRUE, TRUE, array('validateToken'));
                $this->subject = $this->getAccessibleMock(BackendModuleRequestHandler::class, array('boot', 'getFormProtection'), array(), '', FALSE);
        }
 
                $this->subject = $this->getAccessibleMock(BackendModuleRequestHandler::class, array('boot', 'getFormProtection'), array(), '', FALSE);
        }
 
index 859601d..043dd0e 100644 (file)
@@ -128,7 +128,6 @@ return array(
        't3lib_extjs_ExtDirectDebug' => \TYPO3\CMS\Core\ExtDirect\ExtDirectDebug::class,
        't3lib_userAuth' => \TYPO3\CMS\Core\Authentication\AbstractUserAuthentication::class,
        't3lib_beUserAuth' => \TYPO3\CMS\Core\Authentication\BackendUserAuthentication::class,
        't3lib_extjs_ExtDirectDebug' => \TYPO3\CMS\Core\ExtDirect\ExtDirectDebug::class,
        't3lib_userAuth' => \TYPO3\CMS\Core\Authentication\AbstractUserAuthentication::class,
        't3lib_beUserAuth' => \TYPO3\CMS\Core\Authentication\BackendUserAuthentication::class,
-       't3lib_autoloader' => \TYPO3\CMS\Core\Core\ClassLoader::class,
        't3lib_cache_backend_AbstractBackend' => \TYPO3\CMS\Core\Cache\Backend\AbstractBackend::class,
        't3lib_cache_backend_ApcBackend' => \TYPO3\CMS\Core\Cache\Backend\ApcBackend::class,
        't3lib_cache_backend_Backend' => \TYPO3\CMS\Core\Cache\Backend\BackendInterface::class,
        't3lib_cache_backend_AbstractBackend' => \TYPO3\CMS\Core\Cache\Backend\AbstractBackend::class,
        't3lib_cache_backend_ApcBackend' => \TYPO3\CMS\Core\Cache\Backend\ApcBackend::class,
        't3lib_cache_backend_Backend' => \TYPO3\CMS\Core\Cache\Backend\BackendInterface::class,
index 8f13ece..bc0b605 100644 (file)
@@ -654,11 +654,6 @@ class t3lib_beUserAuth extends \TYPO3\CMS\Core\Authentication\BackendUserAuthent
 /**
  * @deprecated since 6.0, removed since 7.0
  */
 /**
  * @deprecated since 6.0, removed since 7.0
  */
-class t3lib_autoloader extends \TYPO3\CMS\Core\Core\ClassLoader {}
-
-/**
- * @deprecated since 6.0, removed since 7.0
- */
 abstract class t3lib_cache_backend_AbstractBackend extends \TYPO3\CMS\Core\Cache\Backend\AbstractBackend {}
 
 /**
 abstract class t3lib_cache_backend_AbstractBackend extends \TYPO3\CMS\Core\Cache\Backend\AbstractBackend {}
 
 /**
index 7517732..3a9d427 100644 (file)
@@ -173,9 +173,7 @@ class UnitTestsBootstrap {
        protected function includeAndStartCoreBootstrap() {
                require_once PATH_site . '/typo3/sysext/core/Classes/Core/Bootstrap.php';
 
        protected function includeAndStartCoreBootstrap() {
                require_once PATH_site . '/typo3/sysext/core/Classes/Core/Bootstrap.php';
 
-               Bootstrap::getInstance()
-                       ->baseSetup()
-                       ->initializeClassLoader();
+               Bootstrap::getInstance()->baseSetup();
 
                return $this;
        }
 
                return $this;
        }
@@ -202,10 +200,10 @@ class UnitTestsBootstrap {
         */
        protected function finishCoreBootstrap() {
                Bootstrap::getInstance()
         */
        protected function finishCoreBootstrap() {
                Bootstrap::getInstance()
-                       ->disableCoreAndClassesCache()
+                       ->disableCoreCache()
                        ->initializeCachingFramework()
                        ->initializeCachingFramework()
-                       ->initializeClassLoaderCaches()
-                       ->initializePackageManagement(\TYPO3\CMS\Core\Package\UnitTestPackageManager::class);
+                       ->initializePackageManagement(\TYPO3\CMS\Core\Package\UnitTestPackageManager::class)
+                       ->ensureClassLoadingInformationExists();
 
                return $this;
        }
 
                return $this;
        }
diff --git a/typo3/sysext/core/Classes/Cache/Backend/ClassLoaderBackend.php b/typo3/sysext/core/Classes/Cache/Backend/ClassLoaderBackend.php
deleted file mode 100644 (file)
index cc42d9a..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-<?php
-namespace TYPO3\CMS\Core\Cache\Backend;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Core\Utility\PathUtility;
-
-/**
- * A caching backend customized explicitly for the class loader.
- * This backend is NOT public API!
- *
- * @internal
- */
-class ClassLoaderBackend extends SimpleFileBackend {
-
-       /**
-        * This string will be used for writing the require statement in the
-        * cache file and for getting the required path via regex.
-        *
-        * @var string
-        */
-       protected $requireFileTemplate = '<?php require \'%s\';';
-
-       /**
-        * Set a class loader cache content
-        *
-        * @TODO: Rename method
-        * @param string $entryIdentifier
-        * @param string $filePath
-        * @throws \InvalidArgumentException
-        * @internal This is not an API method
-        */
-       public function setLinkToPhpFile($entryIdentifier, $filePath) {
-               if ($entryIdentifier === '') {
-                       throw new \InvalidArgumentException('The specified entry identifier must not be empty.', 1364205170);
-               }
-               if (!PathUtility::isAbsolutePath($filePath)) {
-                       throw new \InvalidArgumentException('Only absolute paths are allowed for the class loader, given path was: ' . $filePath, 1381923089);
-               }
-               if (!@file_exists($filePath)) {
-                       throw new \InvalidArgumentException('The specified file path (' . $filePath . ') must exist.', 1364205235);
-               }
-               if (strtolower(substr($filePath, -4)) !== '.php') {
-                       throw new \InvalidArgumentException('The specified file (' . $filePath . ') must be a php file.', 1364205377);
-               }
-               if ($entryIdentifier !== basename($entryIdentifier)) {
-                       throw new \InvalidArgumentException('The specified entry identifier (' . $entryIdentifier . ') must not contain a path segment.', 1364205166);
-               }
-
-               $this->set($entryIdentifier, sprintf($this->requireFileTemplate, $filePath));
-       }
-
-       /**
-        * Used to set alias for class
-        *
-        * @TODO: Rename method
-        * @param string $entryIdentifier
-        * @param string $otherEntryIdentifier
-        * @internal
-        */
-       public function setLinkToOtherCacheEntry($entryIdentifier, $otherEntryIdentifier) {
-               $otherCacheEntryPathAndFilename = $this->cacheDirectory . $otherEntryIdentifier . $this->cacheEntryFileExtension;
-               $this->setLinkToPhpFile($entryIdentifier, $otherCacheEntryPathAndFilename);
-       }
-
-       /**
-        * Loads data from a cache file.
-        *
-        * @param string $entryIdentifier An identifier which describes the cache entry to load
-        * @return mixed The cache entry's content as a string or FALSE if the cache entry could not be loaded
-        * @throws \InvalidArgumentException If identifier is invalid
-        * @internal
-        */
-       public function get($entryIdentifier) {
-               if ($entryIdentifier !== basename($entryIdentifier)) {
-                       throw new \InvalidArgumentException('The specified entry identifier must not contain a path segment.', 1334756880);
-               }
-               $pathAndFilename = $this->cacheDirectory . $entryIdentifier . $this->cacheEntryFileExtension;
-               if (!@file_exists($pathAndFilename)) {
-                       return FALSE;
-               }
-               return file_get_contents($pathAndFilename);
-       }
-
-       /**
-        * Retrieves the path and filename that is passed to the require
-        * command in the cache entry with the given identifier.
-        *
-        * @param string $entryIdentifier
-        * @return bool|string FALSE if required path can not be retrieved or the required file path on success
-        * @internal
-        */
-       public function getPathOfRequiredFileInCacheEntry($entryIdentifier) {
-               $result = FALSE;
-
-               $fileContent = $this->get($entryIdentifier);
-               if ($fileContent !== FALSE) {
-                       $pattern = '!^' . sprintf(preg_quote($this->requireFileTemplate), '(.+)') . '!i';
-                       $matches = array();
-                       if (preg_match($pattern, $fileContent, $matches) === 1) {
-                               $requireString = $matches[1];
-                               $result = $requireString;
-                       }
-               }
-               return $result;
-       }
-
-       /**
-        * Checks if a cache entry with the specified identifier exists.
-        *
-        * @param string $entryIdentifier
-        * @return bool TRUE if such an entry exists, FALSE if not
-        * @throws \InvalidArgumentException
-        * @internal
-        */
-       public function has($entryIdentifier) {
-               if ($entryIdentifier !== basename($entryIdentifier)) {
-                       throw new \InvalidArgumentException('The specified entry identifier must not contain a path segment.', 1334756879);
-               }
-               $pathAndFilename = $this->cacheDirectory . $entryIdentifier . $this->cacheEntryFileExtension;
-               return @file_exists($pathAndFilename);
-       }
-
-       /**
-        * Checks if the given cache entry files are still valid or if their
-        * lifetime has exceeded.
-        *
-        * @param string $cacheEntryPathAndFilename
-        * @return bool
-        * @internal
-        */
-       protected function isCacheFileExpired($cacheEntryPathAndFilename) {
-               return @file_exists($cacheEntryPathAndFilename) === FALSE;
-       }
-
-       /**
-        * Tries to find the cache entry for the specified identifier.
-        *
-        * @TODO: This methods is implemented in simple, file and this backend, but never called?
-        * @param string $entryIdentifier The cache entry identifier
-        * @return mixed The file names (including path) as an array if one or more entries could be found, otherwise FALSE
-        */
-       protected function findCacheFilesByIdentifier($entryIdentifier) {
-               $pathAndFilename = $this->cacheDirectory . $entryIdentifier . $this->cacheEntryFileExtension;
-               return @file_exists($pathAndFilename) ? array($pathAndFilename) : FALSE;
-       }
-
-       /**
-        * Loads PHP code from the cache and require_onces it right away.
-        *
-        * @param string $entryIdentifier An identifier which describes the cache entry to load
-        * @return mixed Potential return value from the include operation
-        * @throws \InvalidArgumentException
-        * @internal
-        */
-       public function requireOnce($entryIdentifier) {
-               $pathAndFilename = $this->cacheDirectory . $entryIdentifier . $this->cacheEntryFileExtension;
-               return @file_exists($pathAndFilename) ? require_once $pathAndFilename : FALSE;
-       }
-
-}
diff --git a/typo3/sysext/core/Classes/Cache/Backend/EarlyClassLoaderBackend.php b/typo3/sysext/core/Classes/Cache/Backend/EarlyClassLoaderBackend.php
deleted file mode 100644 (file)
index 003921c..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-<?php
-namespace TYPO3\CMS\Core\Cache\Backend;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * A caching backend customized explicitly for the class loader.
- * This backend is NOT public API
- *
- * @internal
- */
-class EarlyClassLoaderBackend extends \TYPO3\CMS\Core\Cache\Backend\AbstractBackend implements \TYPO3\CMS\Core\Cache\Backend\PhpCapableBackendInterface {
-
-       /**
-        * @var array Holds cache entries
-        */
-       protected $memoryBackend = array();
-
-       /**
-        * Construct this backend
-        */
-       public function __construct() {
-               parent::__construct('production', array());
-       }
-
-       /**
-        * Saves data in the cache.
-        *
-        * @param string $entryIdentifier An identifier for this specific cache entry
-        * @param string $data The data to be stored
-        * @param array $tags Tags to associate with this cache entry. If the backend does not support tags, this option can be ignored.
-        * @param int $lifetime Lifetime of this cache entry in seconds. If NULL is specified, the default lifetime is used. "0" means unlimited lifetime.
-        * @return void
-        * @throws \TYPO3\CMS\Core\Cache\Exception if no cache frontend has been set.
-        * @throws \TYPO3\CMS\Core\Cache\Exception\InvalidDataException if the data is not a string
-        * @api
-        */
-       public function set($entryIdentifier, $data, array $tags = array(), $lifetime = NULL) {
-               $this->memoryBackend[$entryIdentifier] = $data;
-       }
-
-       /**
-        * Loads data from the cache.
-        *
-        * @param string $entryIdentifier An identifier which describes the cache entry to load
-        * @return mixed The cache entry's content as a string or FALSE if the cache entry could not be loaded
-        * @api
-        */
-       public function get($entryIdentifier) {
-               return isset($this->memoryBackend[$entryIdentifier]) ? $this->memoryBackend[$entryIdentifier] : FALSE;
-       }
-
-       /**
-        * A method that returns all records
-        *
-        * @return array
-        */
-       public function getAll() {
-               return $this->memoryBackend;
-       }
-
-       /**
-        * Checks if a cache entry with the specified identifier exists.
-        *
-        * @param string $entryIdentifier An identifier specifying the cache entry
-        * @return bool TRUE if such an entry exists, FALSE if not
-        * @api
-        */
-       public function has($entryIdentifier) {
-               return isset($this->memoryBackend[$entryIdentifier]);
-       }
-
-       /**
-        * Removes all cache entries matching the specified identifier.
-        * Usually this only affects one entry but if - for what reason ever -
-        * old entries for the identifier still exist, they are removed as well.
-        *
-        * @param string $entryIdentifier Specifies the cache entry to remove
-        * @return bool TRUE if (at least) an entry could be removed or FALSE if no entry was found
-        * @api
-        */
-       public function remove($entryIdentifier) {
-               if (isset($this->memoryBackend[$entryIdentifier])) {
-                       unset($this->memoryBackend[$entryIdentifier]);
-                       return TRUE;
-               }
-               return FALSE;
-       }
-
-       /**
-        * Removes all cache entries of this cache.
-        *
-        * @return void
-        * @api
-        */
-       public function flush() {
-               $this->memoryBackend = array();
-       }
-
-       /**
-        * Does garbage collection
-        *
-        * @return void
-        * @api
-        */
-       public function collectGarbage() {
-       }
-
-       /**
-        * Loads PHP code from the cache and require_onces it right away.
-        *
-        * @param string $entryIdentifier An identifier which describes the cache entry to load
-        * @return mixed Potential return value from the include operation
-        * @api
-        */
-       public function requireOnce($entryIdentifier) {
-               return isset($this->memoryBackend[$entryIdentifier]) ? require_once ($this->memoryBackend[$entryIdentifier]) : FALSE;
-       }
-
-       /**
-        * Used to set alias for class
-        *
-        * @TODO: Rename method
-        * @param string $entryIdentifier
-        * @param string $filePath
-        * @internal This is not an API method
-        */
-       public function setLinkToPhpFile($entryIdentifier, $filePath) {
-               $this->memoryBackend[$entryIdentifier] = $filePath;
-       }
-
-}
index c2829cb..ac1b762 100644 (file)
@@ -205,7 +205,9 @@ class Bootstrap {
         */
        public function baseSetup($relativePathPart = '') {
                SystemEnvironmentBuilder::run($relativePathPart);
         */
        public function baseSetup($relativePathPart = '') {
                SystemEnvironmentBuilder::run($relativePathPart);
-               $this->addDynamicClassAliasMapsToComposerClassLoader();
+               if (!self::$usesComposerClassLoading) {
+                       ClassLoadingInformation::registerClassLoadingInformation();
+               }
                Utility\GeneralUtility::presetApplicationContext($this->applicationContext);
                return $this;
        }
                Utility\GeneralUtility::presetApplicationContext($this->applicationContext);
                return $this;
        }
@@ -231,26 +233,6 @@ class Bootstrap {
        }
 
        /**
        }
 
        /**
-        * Includes an alias mapping file if present.
-        * The file is generated during extension install.
-        *
-        * @throws \TYPO3\CMS\Core\Exception
-        */
-       protected function addDynamicClassAliasMapsToComposerClassLoader() {
-               if (self::$usesComposerClassLoading) {
-                       return;
-               }
-               $dynamicClassAliasMapFile = PATH_site . 'typo3conf/autoload_classaliasmap.php';
-               if (file_exists($dynamicClassAliasMapFile)) {
-                       $composerClassLoader = $this->getEarlyInstance(\Composer\Autoload\ClassLoader::class);
-                       $classAliasMap = require $dynamicClassAliasMapFile;
-                       if (is_array($classAliasMap) && !empty($classAliasMap['aliasToClassNameMapping']) && !empty($classAliasMap['classNameToAliasMapping'])) {
-                               $composerClassLoader->addAliasMap($classAliasMap);
-                       }
-               }
-       }
-
-       /**
         * checks if LocalConfiguration.php or PackageStates.php is missing,
         * used to see if a redirect to the install tool is needed
         *
         * checks if LocalConfiguration.php or PackageStates.php is missing,
         * used to see if a redirect to the install tool is needed
         *
@@ -377,13 +359,11 @@ class Bootstrap {
         * @internal This is not a public API method, do not use in own extensions
         */
        public function loadConfigurationAndInitialize($allowCaching = TRUE, $packageManagerClassName = \TYPO3\CMS\Core\Package\PackageManager::class) {
         * @internal This is not a public API method, do not use in own extensions
         */
        public function loadConfigurationAndInitialize($allowCaching = TRUE, $packageManagerClassName = \TYPO3\CMS\Core\Package\PackageManager::class) {
-               $this->initializeClassLoader()
-                       ->populateLocalConfiguration();
+               $this->populateLocalConfiguration();
                if (!$allowCaching) {
                if (!$allowCaching) {
-                       $this->disableCoreAndClassesCache();
+                       $this->disableCoreCache();
                }
                $this->initializeCachingFramework()
                }
                $this->initializeCachingFramework()
-                       ->initializeClassLoaderCaches()
                        ->initializePackageManagement($packageManagerClassName)
                        ->initializeRuntimeActivatedPackagesFromConfiguration();
 
                        ->initializePackageManagement($packageManagerClassName)
                        ->initializeRuntimeActivatedPackagesFromConfiguration();
 
@@ -400,50 +380,9 @@ class Bootstrap {
                        ->initializeExceptionHandling()
                        ->setMemoryLimit()
                        ->defineTypo3RequestTypes();
                        ->initializeExceptionHandling()
                        ->setMemoryLimit()
                        ->defineTypo3RequestTypes();
-               return $this;
-       }
-
-       /**
-        * Initializes the Class Loader
-        *
-        * @return Bootstrap
-        * @internal This is not a public API method, do not use in own extensions
-        */
-       public function initializeClassLoader() {
-               $classLoader = new ClassLoader($this->applicationContext);
-               $this->setEarlyInstance(\TYPO3\CMS\Core\Core\ClassLoader::class, $classLoader);
-               $classAliasMap = new ClassAliasMap();
-               $classAliasMap->injectClassLoader($classLoader);
-               $classAliasMap->injectComposerClassLoader($this->getEarlyInstance(\Composer\Autoload\ClassLoader::class));
-               $this->setEarlyInstance(\TYPO3\CMS\Core\Core\ClassAliasMap::class, $classAliasMap);
-               $classLoader->injectClassAliasMap($classAliasMap);
-               spl_autoload_register(array($classLoader, 'loadClass'), TRUE, FALSE);
-               return $this;
-       }
-
-       /**
-        * Unregister class loader
-        *
-        * @return Bootstrap
-        * @internal This is not a public API method, do not use in own extensions
-        */
-       public function unregisterClassLoader() {
-               $currentClassLoader = $this->getEarlyInstance(\TYPO3\CMS\Core\Core\ClassLoader::class);
-               spl_autoload_unregister(array($currentClassLoader, 'loadClass'));
-               return $this;
-       }
-
-       /**
-        * Initialize class loader cache.
-        *
-        * @return Bootstrap
-        * @internal This is not a public API method, do not use in own extensions
-        */
-       public function initializeClassLoaderCaches() {
-               /** @var $classLoader ClassLoader */
-               $classLoader = $this->getEarlyInstance(\TYPO3\CMS\Core\Core\ClassLoader::class);
-               $classLoader->injectCoreCache($this->getEarlyInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('cache_core'));
-               $classLoader->injectClassesCache($this->getEarlyInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('cache_classes'));
+               if ($allowCaching) {
+                       $this->ensureClassLoadingInformationExists();
+               }
                return $this;
        }
 
                return $this;
        }
 
@@ -460,7 +399,6 @@ class Bootstrap {
                $packageManager = new $packageManagerClassName();
                $this->setEarlyInstance(\TYPO3\CMS\Core\Package\PackageManager::class, $packageManager);
                Utility\ExtensionManagementUtility::setPackageManager($packageManager);
                $packageManager = new $packageManagerClassName();
                $this->setEarlyInstance(\TYPO3\CMS\Core\Package\PackageManager::class, $packageManager);
                Utility\ExtensionManagementUtility::setPackageManager($packageManager);
-               $packageManager->injectClassLoader($this->getEarlyInstance(\TYPO3\CMS\Core\Core\ClassLoader::class));
                $packageManager->injectCoreCache($this->getEarlyInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('cache_core'));
                $packageManager->injectDependencyResolver(Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Package\DependencyResolver::class));
                $packageManager->initialize($this);
                $packageManager->injectCoreCache($this->getEarlyInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('cache_core'));
                $packageManager->injectDependencyResolver(Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Package\DependencyResolver::class));
                $packageManager->initialize($this);
@@ -469,6 +407,20 @@ class Bootstrap {
        }
 
        /**
        }
 
        /**
+        * Writes class loading information if not yet present
+        *
+        * @return Bootstrap
+        * @internal This is not a public API method, do not use in own extensions
+        */
+       public function ensureClassLoadingInformationExists() {
+               if (!self::$usesComposerClassLoading && !ClassLoadingInformation::classLoadingInformationExists()) {
+                       ClassLoadingInformation::writeClassLoadingInformation();
+                       ClassLoadingInformation::registerClassLoadingInformation();
+               }
+               return $this;
+       }
+
+       /**
         * Activates a package during runtime. This is used in AdditionalConfiguration.php
         * to enable extensions under conditions.
         *
         * Activates a package during runtime. This is used in AdditionalConfiguration.php
         * to enable extensions under conditions.
         *
@@ -530,18 +482,15 @@ class Bootstrap {
        }
 
        /**
        }
 
        /**
-        * Set cache_core to null backend, effectively disabling eg. the autoloader cache
+        * Set cache_core to null backend, effectively disabling eg. the cache for ext_localconf and PackageManager etc.
         *
         * @return \TYPO3\CMS\Core\Core\Bootstrap
         * @internal This is not a public API method, do not use in own extensions
         */
         *
         * @return \TYPO3\CMS\Core\Core\Bootstrap
         * @internal This is not a public API method, do not use in own extensions
         */
-       public function disableCoreAndClassesCache() {
+       public function disableCoreCache() {
                $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_core']['backend']
                        = \TYPO3\CMS\Core\Cache\Backend\NullBackend::class;
                unset($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_core']['options']);
                $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_core']['backend']
                        = \TYPO3\CMS\Core\Cache\Backend\NullBackend::class;
                unset($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_core']['options']);
-               $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_classes']['backend']
-                       = \TYPO3\CMS\Core\Cache\Backend\TransientMemoryBackend::class;
-               unset($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_classes']['options']);
                return $this;
        }
 
                return $this;
        }
 
diff --git a/typo3/sysext/core/Classes/Core/ClassAliasMap.php b/typo3/sysext/core/Classes/Core/ClassAliasMap.php
deleted file mode 100644 (file)
index 9490d03..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-<?php
-namespace TYPO3\CMS\Core\Core;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use Helhum\ClassAliasLoader\Composer\ClassAliasLoader;
-
-/**
- * This class is responsible for setting and containing class aliases
- */
-class ClassAliasMap implements \TYPO3\CMS\Core\SingletonInterface {
-
-       /**
-        * Old class name to new class name mapping
-        *
-        * @var array
-        */
-       protected $aliasToClassNameMapping = array();
-
-       /**
-        * New class name to old class name mapping
-        *
-        * @var array
-        */
-       protected $classNameToAliasMapping = array();
-
-       /**
-        * @var \TYPO3\CMS\Core\Cache\Frontend\StringFrontend
-        */
-       protected $classesCache;
-
-       /**
-        * @var \TYPO3\CMS\Core\Cache\Frontend\PhpFrontend
-        */
-       protected $coreCache;
-
-       /**
-        * @var ClassLoader
-        */
-       protected $classLoader;
-
-       /**
-        * @var ClassAliasLoader
-        */
-       protected $composerClassLoader;
-
-       /**
-        * @var \TYPO3\CMS\Core\Package\Package[]
-        */
-       protected $packages = array();
-
-       /**
-        * @param \TYPO3\CMS\Core\Cache\Frontend\StringFrontend $classesCache
-        */
-       public function injectClassesCache(\TYPO3\CMS\Core\Cache\Frontend\StringFrontend $classesCache) {
-               $this->classesCache = $classesCache;
-       }
-
-       /**
-        * @param \TYPO3\CMS\Core\Cache\Frontend\PhpFrontend $coreCache
-        */
-       public function injectCoreCache(\TYPO3\CMS\Core\Cache\Frontend\PhpFrontend $coreCache) {
-               $this->coreCache = $coreCache;
-       }
-
-       /**
-        * @param ClassLoader
-        */
-       public function injectClassLoader(ClassLoader $classLoader) {
-               $this->classLoader = $classLoader;
-       }
-
-       /**
-        * @param ClassAliasLoader $composerClassLoader
-        */
-       public function injectComposerClassLoader(ClassAliasLoader $composerClassLoader) {
-               $this->composerClassLoader = $composerClassLoader;
-       }
-
-       /**
-        * Set packages
-        *
-        * @param array $packages
-        * @return ClassAliasMap
-        */
-       public function setPackages(array $packages) {
-               $this->packages = $packages;
-               return $this;
-       }
-
-       /**
-        * Build mapping for early instances
-        *
-        * @return array
-        */
-       public function buildMappingAndInitializeEarlyInstanceMapping() {
-               // Needed for early instance alias mapping
-               $aliasToClassNameMapping = array();
-               // Final mapping array
-               $classNameToAliasMapping = array();
-               foreach ($this->packages as $package) {
-                       if (!$package instanceof \TYPO3\CMS\Core\Package\Package || $package->isProtected()) {
-                               // Skip non core packages and all protected packages.
-                               // The latter will be covered by composer class loader.
-                               continue;
-                       }
-                       foreach ($package->getClassAliases() as $aliasClassName => $className) {
-                               $lowercasedAliasClassName = strtolower($aliasClassName);
-                               $aliasToClassNameMapping[$lowercasedAliasClassName] = $className;
-                               $classNameToAliasMapping[$className][$lowercasedAliasClassName] = $lowercasedAliasClassName;
-                       }
-               }
-               $this->initializeAndSetAliasesForEarlyInstances($aliasToClassNameMapping);
-
-               return $classNameToAliasMapping;
-       }
-
-       /**
-        * Build mapping files
-        *
-        * @param array $classNameToAliasMapping
-        * @return void
-        */
-       public function buildMappingFiles(array $classNameToAliasMapping) {
-               foreach ($classNameToAliasMapping as $originalClassName => $aliasClassNames) {
-                       $originalClassNameCacheEntryIdentifier = str_replace('\\', '_', strtolower($originalClassName));
-                       // Trigger autoloading for all aliased class names, so a cache entry is created
-                       $classLoadingInformation = $this->classLoader->buildClassLoadingInformation($originalClassName);
-                       if (FALSE !== $classLoadingInformation) {
-                               $classLoadingInformation = implode("\xff", array_merge($classLoadingInformation, $aliasClassNames));
-                               $this->classesCache->set($originalClassNameCacheEntryIdentifier, $classLoadingInformation);
-                               foreach ($aliasClassNames as $aliasClassName) {
-                                       $aliasClassNameCacheEntryIdentifier = str_replace('\\', '_', strtolower($aliasClassName));
-                                       $this->classesCache->set($aliasClassNameCacheEntryIdentifier, $classLoadingInformation);
-                               }
-                       }
-               }
-       }
-
-       /**
-        * Build static mapping file
-        *
-        * This is needed as long as we don't have full composer support to generate a map
-        * which is later bound to composer class loading
-        *
-        * @return void
-        * @throws \Exception
-        * @internal
-        */
-       public function buildStaticMappingFile() {
-               $aliasToClassNameMapping = array();
-               $classNameToAliasMapping = array();
-               foreach ($this->packages as $package) {
-                       if (!$package instanceof \TYPO3\CMS\Core\Package\Package || $package->isProtected()) {
-                               // Skip non core packages and all protected packages.
-                               // The latter will be covered by composer class loader.
-                               continue;
-                       }
-                       $possibleClassAliasFile = $package->getPackagePath() . 'Migrations/Code/ClassAliasMap.php';
-                       if (file_exists($possibleClassAliasFile)) {
-                               $packageAliasMap = require $possibleClassAliasFile;
-                               if (!is_array($packageAliasMap)) {
-                                       throw new \Exception('"class alias maps" must return an array', 1422625075);
-                               }
-                               foreach ($packageAliasMap as $aliasClassName => $className) {
-                                       $lowerCasedAliasClassName = strtolower($aliasClassName);
-                                       $aliasToClassNameMapping[$lowerCasedAliasClassName] = $className;
-                                       $classNameToAliasMapping[$className][$lowerCasedAliasClassName] = $lowerCasedAliasClassName;
-                               }
-                       }
-               }
-               $exportArray = array(
-                       'aliasToClassNameMapping' => $aliasToClassNameMapping,
-                       'classNameToAliasMapping' => $classNameToAliasMapping
-               );
-               $fileContent = '<?php' . chr(10) . 'return ';
-               $fileContent .= var_export($exportArray, TRUE);
-               $fileContent .= ';';
-
-               file_put_contents(PATH_site . 'typo3conf/autoload_classaliasmap.php', $fileContent);
-       }
-
-       /**
-        * Build and save mapping files to cache
-        *
-        * @param array $aliasToClassNameMapping
-        * @return void
-        */
-       protected function initializeAndSetAliasesForEarlyInstances(array $aliasToClassNameMapping) {
-               $classesLoadedPriorToClassLoader = array_intersect($aliasToClassNameMapping, array_merge(get_declared_classes(), get_declared_interfaces()));
-               if (empty($classesLoadedPriorToClassLoader)) {
-                       return;
-               }
-
-               foreach ($classesLoadedPriorToClassLoader as $aliasClassName => $originalClassName) {
-                       $this->setAliasForClassName($aliasClassName, $originalClassName);
-               }
-       }
-
-       /**
-        * Set an alias for a class name
-        *
-        * @param string $aliasClassName
-        * @param string $originalClassName
-        * @return bool true on success or false on failure
-        */
-       public function setAliasForClassName($aliasClassName, $originalClassName) {
-               if (isset($this->aliasToClassNameMapping[$lowercasedAliasClassName = strtolower($aliasClassName)])) {
-                       return TRUE;
-               }
-               $this->aliasToClassNameMapping[$lowercasedAliasClassName] = $originalClassName;
-               $this->classNameToAliasMapping[strtolower($originalClassName)][$lowercasedAliasClassName] = $aliasClassName;
-               return (class_exists($aliasClassName, FALSE) || interface_exists($aliasClassName, FALSE)) ? TRUE : class_alias($originalClassName, $aliasClassName);
-       }
-
-       /**
-        * Get final class name of alias
-        *
-        * @param string $alias
-        * @return string
-        */
-       public function getClassNameForAlias($alias) {
-               $lookUpClassName = strtolower($alias);
-               $className = $this->composerClassLoader->getClassNameForAlias($alias);
-               return isset($this->aliasToClassNameMapping[$lookUpClassName]) ? $this->aliasToClassNameMapping[$lookUpClassName] : $className;
-       }
-
-
-       /**
-        * Get list of aliases for class name
-        *
-        * @param string $className
-        * @return mixed
-        */
-       public function getAliasesForClassName($className) {
-               $lookUpClassName = strtolower($className);
-               return isset($this->classNameToAliasMapping[$lookUpClassName]) ? $this->classNameToAliasMapping[$lookUpClassName] : array($className);
-       }
-
-}
\ No newline at end of file
diff --git a/typo3/sysext/core/Classes/Core/ClassLoader.php b/typo3/sysext/core/Classes/Core/ClassLoader.php
deleted file mode 100644 (file)
index 6b39821..0000000
+++ /dev/null
@@ -1,814 +0,0 @@
-<?php
-namespace TYPO3\CMS\Core\Core;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Core\Cache;
-use TYPO3\CMS\Core\Locking\Exception\LockCreateException;
-use TYPO3\CMS\Core\Locking\LockFactory;
-use TYPO3\CMS\Core\Locking\LockingStrategyInterface;
-use TYPO3\CMS\Core\Package\PackageInterface;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-
-/**
- * Class Loader implementation which loads .php files found in the classes
- * directory of an object.
- */
-class ClassLoader {
-
-       const VALID_CLASSNAME_PATTERN = '/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9\\\\_\x7f-\xff]*$/';
-
-       /**
-        * @var ApplicationContext
-        */
-       protected $context;
-
-       /**
-        * @var ClassAliasMap
-        */
-       protected $classAliasMap;
-
-       /**
-        * @var ClassAliasMap
-        */
-       static protected $staticAliasMap;
-
-       /**
-        * @var \TYPO3\CMS\Core\Cache\Frontend\StringFrontend
-        */
-       protected $classesCache;
-
-       /**
-        * @var \TYPO3\CMS\Core\Cache\Frontend\PhpFrontend
-        */
-       protected $coreCache;
-
-       /**
-        * @var string
-        */
-       protected $cacheIdentifier;
-
-       /**
-        * @var \TYPO3\CMS\Core\Package\Package[]
-        */
-       protected $packages = array();
-
-       /**
-        * @var bool
-        */
-       protected $isEarlyCache = TRUE;
-
-       /**
-        * @var array
-        */
-       protected $runtimeClassLoadingInformationCache = array();
-
-       /**
-        * A list of namespaces this class loader is definitely responsible for
-        *
-        * @var array
-        */
-       protected $packageNamespaces = array();
-
-       /**
-        * A list of packages and their replaces pointing to class paths
-        *
-        * @var array
-        */
-       protected $packageClassesPaths = array();
-
-       /**
-        * Is TRUE while loading the Locker class to prevent a deadlock in the implicit call to loadClass
-        *
-        * @var bool
-        */
-       protected $isLoadingLocker = FALSE;
-
-       /**
-        * @var LockingStrategyInterface
-        */
-       protected $lockObject = NULL;
-
-       /**
-        * Is set to TRUE if the shutdown function for die in lock is registered, so it won't be registered twice.
-        *
-        * @var bool
-        */
-       protected $shutdownRegistered = FALSE;
-
-       /**
-        * Constructor
-        *
-        * @param ApplicationContext $context
-        */
-       public function __construct(ApplicationContext $context) {
-               $this->context = $context;
-               $this->classesCache = new Cache\Frontend\StringFrontend('cache_classes', new Cache\Backend\TransientMemoryBackend($context));
-       }
-
-       /**
-        * Get class alias map list injected
-        *
-        * @param ClassAliasMap
-        * @return void
-        */
-       public function injectClassAliasMap(ClassAliasMap $classAliasMap) {
-               $this->classAliasMap = $classAliasMap;
-               static::$staticAliasMap = $classAliasMap;
-       }
-
-       /**
-        * Get core cache injected
-        *
-        * @param \TYPO3\CMS\Core\Cache\Frontend\PhpFrontend $coreCache
-        * @return void
-        */
-       public function injectCoreCache(Cache\Frontend\PhpFrontend $coreCache) {
-               $this->coreCache = $coreCache;
-               $this->classAliasMap->injectCoreCache($coreCache);
-       }
-
-       /**
-        * Get classes cache injected
-        *
-        * @param \TYPO3\CMS\Core\Cache\Frontend\StringFrontend $classesCache
-        * @return void
-        */
-       public function injectClassesCache(Cache\Frontend\StringFrontend $classesCache) {
-               $earlyClassesCache = $this->classesCache;
-               $this->classesCache = $classesCache;
-               $this->isEarlyCache = FALSE;
-               $this->classAliasMap->injectClassesCache($classesCache);
-               foreach ($earlyClassesCache->getByTag('early') as $originalClassLoadingInformation) {
-                       $classLoadingInformation = explode("\xff", $originalClassLoadingInformation);
-                       $cacheEntryIdentifier = strtolower(str_replace('\\', '_', $classLoadingInformation[1]));
-                       if (!$this->classesCache->has($cacheEntryIdentifier)) {
-                               $this->classesCache->set($cacheEntryIdentifier, $originalClassLoadingInformation);
-                       }
-               }
-       }
-
-       /**
-        * Loads php files containing classes or interfaces found in the classes directory of
-        * a package and specifically registered classes.
-        *
-        * Caution: This function may be called "recursively" by the spl_autoloader if a class depends on another classes.
-        *
-        * @param string $className Name of the class/interface to load
-        * @return bool
-        */
-       public function loadClass($className) {
-               if ($className[0] === '\\') {
-                       $className = substr($className, 1);
-               }
-
-               if (!$this->isValidClassName($className)) {
-                       return FALSE;
-               }
-
-               $cacheEntryIdentifier = strtolower(str_replace('\\', '_', $className));
-               $classLoadingInformation = $this->getClassLoadingInformationFromCache($cacheEntryIdentifier);
-               // Handle a cache miss
-               if ($classLoadingInformation === FALSE) {
-                       $classLoadingInformation = $this->buildCachedClassLoadingInformation($cacheEntryIdentifier, $className);
-               }
-
-               // Class loading information structure
-               // array(
-               //   0 => class file path
-               //   1 => original class name
-               //   2 and following => alias class names
-               // )
-               $loadingSuccessful = FALSE;
-               if (!empty($classLoadingInformation)) {
-                       // The call to class_exists/interface_exists fixes a rare case when early instances need to be aliased
-                       // but PHP fails to recognize the real path of the class. See #55904
-                       $loadingSuccessful = class_exists($classLoadingInformation[1], FALSE)
-                               || interface_exists($classLoadingInformation[1], FALSE)
-                               || (bool)require_once $classLoadingInformation[0];
-               }
-               if ($loadingSuccessful && count($classLoadingInformation) > 2) {
-                       $originalClassName = $classLoadingInformation[1];
-                       foreach (array_slice($classLoadingInformation, 2) as $aliasClassName) {
-                               $this->setAliasForClassName($aliasClassName, $originalClassName);
-                       }
-               }
-
-               return $loadingSuccessful;
-       }
-
-       /**
-        * Get class loading information for the given identifier for cache
-        * Return values:
-        *  - array with class information (empty if the class is invalid)
-        *  - FALSE if no class information is found in cache (cache miss)
-        *  - NULL if the cache identifier is invalid (cache failure)
-        *
-        * @param string $cacheEntryIdentifier The identifier to fetch entry from cache
-        * @return array|FALSE The class information, empty array if class is unknown or FALSE if class information was not found in cache.
-        */
-       public function getClassLoadingInformationFromCache($cacheEntryIdentifier) {
-               $rawClassLoadingInformation = $this->classesCache->get($cacheEntryIdentifier);
-
-               if ($rawClassLoadingInformation === '') {
-                       return array();
-               }
-
-               if ($rawClassLoadingInformation) {
-                       return explode("\xff", $rawClassLoadingInformation);
-               }
-               return FALSE;
-       }
-
-       /**
-        * Builds the class loading information and writes it to the cache. It handles Locking for this cache.
-        *
-        * Caution: The function loadClass can be called "recursively" by spl_autoloader. This needs to be observed when
-        * locking for cache access. Only the first call to loadClass may acquire and release the lock!
-        *
-        * @param string $cacheEntryIdentifier Cache identifier for this class
-        * @param string $className Name of class this information is for
-        *
-        * @return array|FALSE The class information, empty array if class is unknown or FALSE if class information was not found in cache.
-        */
-       protected function buildCachedClassLoadingInformation($cacheEntryIdentifier, $className) {
-               // We do not need locking if we are in earlyCache mode
-               $didLock = FALSE;
-               if (!$this->isEarlyCache) {
-                       $didLock = $this->acquireLock();
-               }
-
-               // Look again into the cache after we got the lock, data might have been generated meanwhile
-               $classLoadingInformation = $this->getClassLoadingInformationFromCache($cacheEntryIdentifier);
-               // Handle repeated cache miss
-               if ($classLoadingInformation === FALSE) {
-                       // Generate class information
-                       $classLoadingInformation = $this->buildClassLoadingInformation($className);
-
-                       if ($classLoadingInformation !== FALSE) {
-                               // If we found class information, cache it
-                               $this->classesCache->set(
-                                       $cacheEntryIdentifier,
-                                       implode("\xff", $classLoadingInformation),
-                                       $this->isEarlyCache ? array('early') : array()
-                               );
-                       } elseif (!$this->isEarlyCache) {
-                               if ($this->context->isProduction()) {
-                                       // Cache that the class is unknown
-                                       $this->classesCache->set($cacheEntryIdentifier, '');
-                               }
-                       }
-               }
-
-               $this->releaseLock($didLock);
-
-               return $classLoadingInformation;
-       }
-
-       /**
-        * Builds the class loading information
-        *
-        * @param string $className Name of class this information is for
-        *
-        * @return array|FALSE The class information or FALSE if class was not found
-        */
-       public function buildClassLoadingInformation($className) {
-               $classLoadingInformation = $this->buildClassLoadingInformationForClassFromCorePackage($className);
-
-               if ($classLoadingInformation === FALSE) {
-                       $classLoadingInformation = $this->fetchClassLoadingInformationFromRuntimeCache($className);
-               }
-
-               if ($classLoadingInformation === FALSE) {
-                       $classLoadingInformation = $this->buildClassLoadingInformationForClassFromRegisteredPackages($className);
-               }
-
-               if ($classLoadingInformation === FALSE) {
-                       $classLoadingInformation = $this->buildClassLoadingInformationForClassByNamingConvention($className);
-               }
-
-               return $classLoadingInformation;
-       }
-
-       /**
-        * Find out if a class name is valid
-        *
-        * @param string $className
-        * @return bool
-        */
-       protected function isValidClassName($className) {
-               return (bool)preg_match(self::VALID_CLASSNAME_PATTERN, $className);
-       }
-
-       /**
-        * Retrieve class loading information for class from core package
-        *
-        * @param string $className
-        * @return array|FALSE
-        */
-       protected function buildClassLoadingInformationForClassFromCorePackage($className) {
-               if (substr($className, 0, 14) === 'TYPO3\\CMS\\Core') {
-                       $classesFolder = substr($className, 15, 5) === 'Tests' ? '' : 'Classes/';
-                       $classFilePath = PATH_typo3 . 'sysext/core/' . $classesFolder . str_replace('\\', '/', substr($className, 15)) . '.php';
-                       if (@file_exists($classFilePath)) {
-                               return array($classFilePath, $className);
-                       }
-               }
-               return FALSE;
-       }
-
-       /**
-        * Retrieve class loading information from early class name autoload registry cache
-        *
-        * @param string $className
-        * @return array|FALSE
-        */
-       protected function fetchClassLoadingInformationFromRuntimeCache($className) {
-               $lowercasedClassName = strtolower($className);
-               if (!isset($this->runtimeClassLoadingInformationCache[$lowercasedClassName])) {
-                       return FALSE;
-               }
-               $classInformation = $this->runtimeClassLoadingInformationCache[$lowercasedClassName];
-               return @file_exists($classInformation[0]) ? $classInformation : FALSE;
-       }
-
-       /**
-        * Retrieve class loading information from registered packages
-        *
-        * @param string $className
-        * @return array|FALSE
-        */
-       protected function buildClassLoadingInformationForClassFromRegisteredPackages($className) {;
-               foreach ($this->packageNamespaces as $packageNamespace => $packageData) {
-                       if (substr(str_replace('_', '\\', $className), 0, $packageData['namespaceLength']) === $packageNamespace) {
-                               // If it's a TYPO3 package, classes don't comply to PSR-0.
-                               // The namespace part is substituted.
-                               $classPathAndFilename = '/' . str_replace('\\', '/', ltrim(substr($className, $packageData['namespaceLength']), '\\')) . '.php';
-                               if (strtolower(substr($className, $packageData['namespaceLength'], 5)) === 'tests') {
-                                       $classPathAndFilename = $packageData['packagePath'] . $classPathAndFilename;
-                               } else {
-                                       $classPathAndFilename = $packageData['classesPath'] . $classPathAndFilename;
-                               }
-                               if (@file_exists($classPathAndFilename)) {
-                                       return array($classPathAndFilename, $className);
-                               }
-                       }
-               }
-               return FALSE;
-       }
-
-       /**
-        * Retrieve class loading information based on 'extbase' naming convention into the registry.
-        *
-        * @param string $className Class name to find source file of
-        * @return array|FALSE
-        */
-       protected function buildClassLoadingInformationForClassByNamingConvention($className) {
-               $delimiter = '_';
-               // To handle namespaced class names, split the class name at the
-               // namespace delimiters.
-               if (strpos($className, '\\') !== FALSE) {
-                       $delimiter = '\\';
-               }
-
-               $classNameParts = explode($delimiter, $className, 4);
-
-               // We only handle classes that follow the convention Vendor\Product\Classname or is longer
-               // so we won't deal with class names that only have one or two parts
-               if (count($classNameParts) <= 2) {
-                       return FALSE;
-               }
-
-               if (
-                               isset($classNameParts[0])
-                               && isset($classNameParts[1])
-                               && $classNameParts[0] === 'TYPO3'
-                               && $classNameParts[1] === 'CMS'
-               ) {
-                       $extensionKey = GeneralUtility::camelCaseToLowerCaseUnderscored($classNameParts[2]);
-                       $classNameWithoutVendorAndProduct = $classNameParts[3];
-               } else {
-                       $extensionKey = GeneralUtility::camelCaseToLowerCaseUnderscored($classNameParts[1]);
-                       $classNameWithoutVendorAndProduct = $classNameParts[2];
-
-                       if (isset($classNameParts[3])) {
-                               $classNameWithoutVendorAndProduct .= $delimiter . $classNameParts[3];
-                       }
-               }
-
-               if ($extensionKey && isset($this->packageClassesPaths[$extensionKey])) {
-                       if (substr(strtolower($classNameWithoutVendorAndProduct), 0, 5) === 'tests') {
-                               $classesPath = $this->packages[$extensionKey]->getPackagePath();
-                       } else {
-                               $classesPath = $this->packageClassesPaths[$extensionKey];
-                       }
-                       $classFilePath = $classesPath . strtr($classNameWithoutVendorAndProduct, $delimiter, '/') . '.php';
-                       if (@file_exists($classFilePath)) {
-                               return array($classFilePath, $className);
-                       }
-               }
-
-               return FALSE;
-       }
-
-       /**
-        * Get cache entry identifier for the package namespaces cache
-        *
-        * @return string|NULL identifier
-        */
-       protected function getCacheEntryIdentifier() {
-               return $this->cacheIdentifier !== NULL
-                       ? 'ClassLoader_' . $this->cacheIdentifier
-                       : NULL;
-       }
-
-       /**
-        * Set cache identifier
-        *
-        * @param string $cacheIdentifier Cache identifier for package namespaces cache
-        * @return ClassLoader
-        */
-       public function setCacheIdentifier($cacheIdentifier) {
-               $this->cacheIdentifier = $cacheIdentifier;
-               return $this;
-       }
-
-       /**
-        * Sets the available packages
-        *
-        * @param array $packages An array of \TYPO3\CMS\Core\Package\Package objects
-        * @return ClassLoader
-        */
-       public function setPackages(array $packages) {
-               $this->packages = $packages;
-
-               if (!$this->loadPackageNamespacesFromCache()) {
-                       $this->buildPackageNamespacesAndClassesPaths();
-               } else {
-                       $this->classAliasMap->setPackages($packages);
-               }
-               // Clear the runtime cache for runtime activated packages
-               $this->runtimeClassLoadingInformationCache = array();
-               return $this;
-       }
-
-       /**
-        * Add a package to class loader just during runtime, so classes can be loaded without the need for a new request
-        *
-        * @param PackageInterface $package
-        * @return ClassLoader
-        */
-       public function addActivePackage(PackageInterface $package) {
-               $packageKey = $package->getPackageKey();
-               if (!isset($this->packages[$packageKey])) {
-                       $this->packages[$packageKey] = $package;
-                       $this->buildPackageNamespaceAndClassesPath($package);
-                       $this->sortPackageNamespaces();
-                       $this->loadClassFilesFromAutoloadRegistryIntoRuntimeClassInformationCache(array($package));
-               }
-               return $this;
-       }
-
-       /**
-        * Builds the package namespaces and classes paths for the given packages
-        *
-        * @throws \Exception
-        * @return void
-        */
-       protected function buildPackageNamespacesAndClassesPaths() {
-               $didLock = $this->acquireLock();
-
-               // Take a look again, after lock is acquired
-               if (!$this->loadPackageNamespacesFromCache()) {
-                       try {
-                               foreach ($this->packages as $package) {
-                                       $this->buildPackageNamespaceAndClassesPath($package);
-                               }
-                               $this->sortPackageNamespaces();
-                               $this->savePackageNamespacesAndClassesPathsToCache();
-                               // The class alias map has to be rebuilt first, because ext_autoload files can contain
-                               // old class names that need established class aliases.
-                               $classNameToAliasMapping = $this->classAliasMap->setPackages($this->packages)->buildMappingAndInitializeEarlyInstanceMapping();
-                               $this->loadClassFilesFromAutoloadRegistryIntoRuntimeClassInformationCache($this->packages);
-                               $this->classAliasMap->buildMappingFiles($classNameToAliasMapping);
-                               $this->transferRuntimeClassInformationCacheEntriesToClassesCache();
-                       } catch (\Exception $e) {
-                               // Catching all Exceptions, as we don't know where in the process the class cache building breaks we
-                               // need to clear our cache and also release our lock before we throw the Exception again to the user.
-                               $this->clearClassesCache();
-                               $this->releaseLock($didLock);
-                               throw $e;
-                       }
-               }
-
-               $this->releaseLock($didLock);
-       }
-
-       /**
-        * Builds the namespace and class paths for a single package
-        *
-        * @param PackageInterface $package
-        * @return void
-        */
-       protected function buildPackageNamespaceAndClassesPath(PackageInterface $package) {
-               if ($package instanceof PackageInterface) {
-                       $this->buildPackageNamespace($package);
-                       $this->buildPackageClassPathsForLegacyExtension($package);
-               }
-       }
-
-       /**
-        * Load package namespaces from cache
-        *
-        * @return bool TRUE if package namespaces were loaded
-        */
-       protected function loadPackageNamespacesFromCache() {
-               $cacheEntryIdentifier = $this->getCacheEntryIdentifier();
-               if ($cacheEntryIdentifier === NULL) {
-                       return FALSE;
-               }
-               $packageData = $this->coreCache->requireOnce($cacheEntryIdentifier);
-               if ($packageData !== FALSE) {
-                       list($packageNamespaces, $packageClassesPaths) = $packageData;
-                       if (is_array($packageNamespaces) && is_array($packageClassesPaths)) {
-                               $this->packageNamespaces = $packageNamespaces;
-                               $this->packageClassesPaths = $packageClassesPaths;
-                               return TRUE;
-                       }
-               }
-               return FALSE;
-       }
-
-       /**
-        * Extracts the namespace from a package
-        *
-        * @param PackageInterface $package
-        * @return void
-        */
-       protected function buildPackageNamespace(PackageInterface $package) {
-               $packageNamespace = $package->getNamespace();
-               // Ignore legacy extensions with unknown vendor name
-               if ($packageNamespace[0] !== '*') {
-                       $this->packageNamespaces[$packageNamespace] = array(
-                               'namespaceLength' => strlen($packageNamespace),
-                               'classesPath' => $package->getClassesPath(),
-                               'packagePath' => $package->getPackagePath(),
-                       );
-               }
-       }
-
-       /**
-        * Save autoload registry to cache
-        *
-        * @param array $packages
-        * @return void
-        */
-       protected function loadClassFilesFromAutoloadRegistryIntoRuntimeClassInformationCache(array $packages) {
-               $classFileAutoloadRegistry = array();
-               foreach ($packages as $package) {
-                       if ($package instanceof PackageInterface) {
-                               $classFilesFromAutoloadRegistry = $package->getClassFilesFromAutoloadRegistry();
-                               if (is_array($classFilesFromAutoloadRegistry)) {
-                                       $classFileAutoloadRegistry = array_merge($classFileAutoloadRegistry, $classFilesFromAutoloadRegistry);
-                               }
-                       }
-               }
-               foreach ($classFileAutoloadRegistry as $className => $classFilePath) {
-                       $lowercasedClassName = strtolower($className);
-                       if (!isset($this->runtimeClassLoadingInformationCache[$lowercasedClassName]) && @file_exists($classFilePath)) {
-                               $this->runtimeClassLoadingInformationCache[$lowercasedClassName] = array($classFilePath, $className);
-                       }
-               }
-       }
-
-       /**
-        * Transfers all entries from the early class information cache to
-        * the classes cache in order to make them persistent
-        *
-        * @return void
-        */
-       protected function transferRuntimeClassInformationCacheEntriesToClassesCache() {
-               foreach ($this->runtimeClassLoadingInformationCache as $classLoadingInformation) {
-                       $cacheEntryIdentifier = strtolower(str_replace('\\', '_', $classLoadingInformation[1]));
-                       if (!$this->classesCache->has($cacheEntryIdentifier)) {
-                               $this->classesCache->set($cacheEntryIdentifier, implode("\xff", $classLoadingInformation));
-                       }
-               }
-       }
-
-       /**
-        * @param PackageInterface $package
-        * @return void
-        */
-       protected function buildPackageClassPathsForLegacyExtension(PackageInterface $package) {
-               $this->packageClassesPaths[$package->getPackageKey()] = $package->getClassesPath();
-               foreach ($package->getPackageReplacementKeys() as $packageToReplace => $_) {
-                       $this->packageClassesPaths[$packageToReplace] = $package->getClassesPath();
-               }
-       }
-
-       /**
-        * Save package namespaces and classes paths to cache
-        *
-        * @return void
-        */
-       protected function savePackageNamespacesAndClassesPathsToCache() {
-               $cacheEntryIdentifier = $this->getCacheEntryIdentifier();
-               if ($cacheEntryIdentifier !== NULL) {
-                       $this->coreCache->set(
-                               $this->getCacheEntryIdentifier(),
-                               'return ' . var_export(array($this->packageNamespaces, $this->packageClassesPaths), TRUE) . ';'
-                       );
-               }
-       }
-
-       /**
-        * Sorts longer package namespaces first, to find specific matches before generic ones
-        *
-        * @return void
-        */
-       protected function sortPackageNamespaces() {
-               $sortPackages = function ($a, $b) {
-                       if (($lenA = strlen($a)) === ($lenB = strlen($b))) {
-                               return strcmp($a, $b);
-                       }
-                       return $lenA > $lenB ? -1 : 1;
-               };
-               uksort($this->packageNamespaces, $sortPackages);
-       }
-
-       /**
-        * This method is necessary for the early loading of the cores autoload registry
-        *
-        * @param array $classFileAutoloadRegistry
-        * @return void
-        */
-       public function setRuntimeClassLoadingInformationFromAutoloadRegistry(array $classFileAutoloadRegistry) {
-               foreach ($classFileAutoloadRegistry as $className => $classFilePath) {
-                       $lowercasedClassName = strtolower($className);
-                       if (!isset($this->runtimeClassLoadingInformationCache[$lowercasedClassName])) {
-                               $this->runtimeClassLoadingInformationCache[$lowercasedClassName] = array($classFilePath, $className);
-                       }
-               }
-       }
-
-       /**
-        * Set alias for class name
-        *
-        * @param string $aliasClassName
-        * @param string $originalClassName
-        * @return bool
-        */
-       public function setAliasForClassName($aliasClassName, $originalClassName) {
-               return $this->classAliasMap->setAliasForClassName($aliasClassName, $originalClassName);
-       }
-
-       /**
-        * Get class name for alias
-        *
-        * @param string $alias
-        * @return mixed
-        */
-       static public function getClassNameForAlias($alias) {
-               return static::$staticAliasMap->getClassNameForAlias($alias);
-       }
-
-       /**
-        * Get an aliases for a class name
-        *
-        * @param string $className
-        * @return mixed
-        */
-       static public function getAliasesForClassName($className) {
-               return static::$staticAliasMap->getAliasesForClassName($className);
-       }
-
-       /**
-        * Acquires a lock for the cache if we didn't already lock before.
-        *
-        * @return bool TRUE if the cache was acquired by this call and needs to be released
-        * @throws \RuntimeException
-        */
-       protected function acquireLock() {
-               if (!$this->isLoadingLocker) {
-                       $lockObject = $this->getLocker();
-
-                       if ($lockObject === NULL) {
-                               // During installation typo3temp does not yet exist, so the locker can not
-                               // do its job. In this case it does not need to be released again.
-                               return FALSE;
-                       }
-
-                       // We didn't lock yet so do it
-                       if (!$lockObject->isAcquired()) {
-                               if (!$lockObject->acquire()) {
-                                       throw new \RuntimeException('Could not acquire lock for ClassLoader cache creation.', 1394480725);
-                               }
-
-                               if (!$this->shutdownRegistered) {
-                                       $this->shutdownRegistered = TRUE;
-                                       register_shutdown_function(array($this, 'checkForCrashAndCleanup'));
-                               }
-
-                               return TRUE;
-                       }
-               }
-               return FALSE;
-       }
-
-       /**
-        * Clean the cache and release lock
-        *
-        * If building the cache for classes failed, we don't know in which state we are. So we need to clear the cache
-        * completely and remove the lock which should exist.
-        * If the PHP process receives either the SIGTERM or SIGKILL signal, this function will NOT be called.
-        * It might still be called on a SIGSEGV signal though, but we can't trust the members of this class then,
-        * hence, the contents of $this->* might be nonsense and its usage might lead to undesired behavior.
-        *
-        * This function needs to be public, so it can be called as shutdown-function, but this function may be changed,
-        * renamed or deleted without deprecation, also in bugfix-releases.
-        *
-        * @return void
-        * @internal
-        */
-       public function checkForCrashAndCleanup() {
-               // As we are used as shutdownFunction we need to test if we get called while the lock is set.
-               // If this is the case, the cache creation has crashed.
-               $error = error_get_last();
-
-               // $this->lockObject can be null in installer context without typo3temp, but then this method shouldn't
-               // be registered as shutdown-function due to caching being disabled in this case.
-               // See @getLocker for more information.
-               if ($error !== NULL && $this->lockObject !== NULL && $this->lockObject->isAcquired()) {
-                       $this->clearClassesCache();
-                       $this->releaseLock(TRUE);
-               }
-       }
-
-       /**
-        * Releases a lock
-        *
-        * @param bool $needRelease The result of the call to acquireLock()
-        * @return void
-        */
-       protected function releaseLock($needRelease) {
-               if ($needRelease) {
-                       $lockObject = $this->getLocker();
-                       $lockObject->release();
-               }
-       }
-
-       /**
-        * Cleares the complete cache for class loader.
-        *
-        * @return void
-        */
-       protected function clearClassesCache() {
-               $this->coreCache->flush();
-               $this->classesCache->flush();
-       }
-
-       /**
-        * Gets the TYPO3 Locker object or creates an instance of it.
-        *
-        * @throws \RuntimeException
-        * @return LockingStrategyInterface|NULL Only NULL if we are in installer and typo3temp does not exist yet
-        */
-       protected function getLocker() {
-               if (NULL === $this->lockObject) {
-                       $this->isLoadingLocker = TRUE;
-
-                       try {
-                               $this->lockObject = (new LockFactory())->createLocker('ClassLoader-cache-classes');
-                       } catch (LockCreateException $e) {
-                               // The LockCreateException in constructor happens if directory typo3temp/locks could not be created.
-                               // This usually happens during installation step 1 where typo3temp itself does not exist yet. In
-                               // this case we proceed without locking, otherwise a missing typo3temp directory indicates a
-                               // hard problem of the instance and we throw up.
-                               // @TODO: This solution currently conflicts with separation of concerns since the class loader
-                               // handles installation specific stuff. Find a better way to do this.
-                               if (defined('TYPO3_enterInstallScript') && TYPO3_enterInstallScript) {
-                                       // Installer is running => So work without Locking.
-                                       return NULL;
-                               } else {
-                                       throw $e;
-                               }
-                       }
-                       $this->isLoadingLocker = FALSE;
-               }
-
-               return $this->lockObject;
-       }
-
-}
diff --git a/typo3/sysext/core/Classes/Core/ClassLoadingInformation.php b/typo3/sysext/core/Classes/Core/ClassLoadingInformation.php
new file mode 100644 (file)
index 0000000..f5604c9
--- /dev/null
@@ -0,0 +1,161 @@
+<?php
+namespace TYPO3\CMS\Core\Core;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use Composer\Autoload\ClassLoader as ComposerClassLoader;
+use TYPO3\CMS\Core\Package\PackageInterface;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Get and manipulate class loading information, only necessary/in use
+ * when TYPO3 is not purely set up by composer but when e.g. extensions are installed via the extension manager
+ * by utilizing the composer class loader and adding more information built by the ClassLoadingInformationGenerator
+ * class.
+ *
+ * @internal
+ */
+class ClassLoadingInformation {
+
+       /**
+        * Base directory storing all autoload information
+        */
+       const AUTOLOAD_INFO_DIR = 'typo3temp/autoload/';
+
+       /**
+        * Name of file that contains all classes-filename mappings
+        */
+       const AUTOLOAD_CLASSMAP_FILENAME = 'autoload_classmap.php';
+
+       /**
+        * Name of file that contains all PSR4 mappings, fetched from the composer.json files of extensions
+        */
+       const AUTOLOAD_PSR4_FILENAME = 'autoload_psr4.php';
+
+       /**
+        * Name of file that contains all class alias mappings
+        */
+       const AUTOLOAD_CLASSALIASMAP_FILENAME = 'autoload_classaliasmap.php';
+
+       /**
+        * Checks if the autoload_classmap.php exists. Used to see if the ClassLoadingInformationGenerator
+        * should be called.
+        *
+        * @return bool
+        */
+       static public function classLoadingInformationExists() {
+               return file_exists(PATH_site . self::AUTOLOAD_INFO_DIR . self::AUTOLOAD_CLASSMAP_FILENAME);
+       }
+
+       /**
+        * Puts all information compiled by the ClassLoadingInformationGenerator to files
+        */
+       static public function writeClassLoadingInformation() {
+               self::ensureAutoloadInfoDirExists();
+               $classInfoFiles = ClassLoadingInformationGenerator::buildAutoloadInformationFiles();
+               GeneralUtility::writeFile(PATH_site . self::AUTOLOAD_INFO_DIR . self::AUTOLOAD_CLASSMAP_FILENAME, $classInfoFiles['classMapFile']);
+               GeneralUtility::writeFile(PATH_site . self::AUTOLOAD_INFO_DIR . self::AUTOLOAD_PSR4_FILENAME, $classInfoFiles['psr-4File']);
+
+               $classAliasMapFile = ClassLoadingInformationGenerator::buildClassAliasMapFile();
+               GeneralUtility::writeFile(PATH_site . self::AUTOLOAD_INFO_DIR . self::AUTOLOAD_CLASSALIASMAP_FILENAME, $classAliasMapFile);
+       }
+
+       /**
+        * Registers the class aliases, the class maps and the PSR4 prefixes previously identified by
+        * the ClassLoadingInformationGenerator during runtime.
+        */
+       static public function registerClassLoadingInformation() {
+               $composerClassLoader = static::getClassLoader();
+
+               $dynamicClassAliasMapFile = PATH_site . self::AUTOLOAD_INFO_DIR . self::AUTOLOAD_CLASSALIASMAP_FILENAME;
+               if (file_exists($dynamicClassAliasMapFile)) {
+                       $classAliasMap = require $dynamicClassAliasMapFile;
+                       if (is_array($classAliasMap) && !empty($classAliasMap['aliasToClassNameMapping']) && !empty($classAliasMap['classNameToAliasMapping'])) {
+                               $composerClassLoader->addAliasMap($classAliasMap);
+                       }
+               }
+
+               $dynamicClassMapFile = PATH_site . self::AUTOLOAD_INFO_DIR . self::AUTOLOAD_CLASSMAP_FILENAME;
+               if (file_exists($dynamicClassMapFile)) {
+                       $classMap = require $dynamicClassMapFile;
+                       if (is_array($classMap)) {
+                               $composerClassLoader->addClassMap($classMap);
+                       }
+               }
+
+               $dynamicPsr4File = PATH_site . self::AUTOLOAD_INFO_DIR . self::AUTOLOAD_PSR4_FILENAME;
+               if (file_exists($dynamicPsr4File)) {
+                       $psr4 = require $dynamicPsr4File;
+                       if (is_array($psr4)) {
+                               foreach ($psr4 as $prefix => $paths) {
+                                       $composerClassLoader->setPsr4($prefix, $paths);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Sets class loading information for a package for the current web request
+        *
+        * @param PackageInterface $package
+        * @throws \TYPO3\CMS\Core\Error\Exception
+        */
+       static public function registerTransientClassLoadingInformationForPackage(PackageInterface $package) {
+               $composerClassLoader = static::getClassLoader();
+               $classInformation = ClassLoadingInformationGenerator::buildClassLoadingInformationForPackage($package);
+               $composerClassLoader->addClassMap($classInformation['classMap']);
+               foreach ($classInformation['psr-4'] as $prefix => $paths) {
+                       $composerClassLoader->setPsr4($prefix, $paths);
+               }
+               if (is_callable(array($composerClassLoader, 'addAliasMap'))) {
+                       $aliasMap = ClassLoadingInformationGenerator::buildClassAliasMapForPackage($package);
+                       $composerClassLoader->addAliasMap($aliasMap);
+               }
+       }
+
+       /**
+        * Get class name for alias
+        *
+        * @param string $alias
+        * @return mixed
+        */
+       static public function getClassNameForAlias($alias) {
+               $composerClassLoader = static::getClassLoader();
+               if (!is_callable(array($composerClassLoader, 'getClassNameForAlias'))) {
+                       return $alias;
+               }
+               return $composerClassLoader->getClassNameForAlias($alias);
+       }
+
+       /**
+        * Ensures the defined path for class information files exists
+        */
+       static protected function ensureAutoloadInfoDirExists() {
+               $autoloadInfoDir = PATH_site . self::AUTOLOAD_INFO_DIR;
+               if (!file_exists($autoloadInfoDir)) {
+                       GeneralUtility::mkdir_deep($autoloadInfoDir);
+               }
+       }
+
+       /**
+        * Internal method calling the bootstrap to fetch the composer class loader
+        *
+        * @return ComposerClassLoader
+        * @throws \TYPO3\CMS\Core\Exception
+        */
+       static protected function getClassLoader() {
+               return Bootstrap::getInstance()->getEarlyInstance(ComposerClassLoader::class);
+       }
+
+}
diff --git a/typo3/sysext/core/Classes/Core/ClassLoadingInformationGenerator.php b/typo3/sysext/core/Classes/Core/ClassLoadingInformationGenerator.php
new file mode 100644 (file)
index 0000000..9b95988
--- /dev/null
@@ -0,0 +1,222 @@
+<?php
+namespace TYPO3\CMS\Core\Core;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use Composer\Autoload\ClassMapGenerator;
+use TYPO3\CMS\Core\Package\Exception\MissingPackageManifestException;
+use TYPO3\CMS\Core\Package\PackageInterface;
+use TYPO3\CMS\Core\Package\PackageManager;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\PathUtility;
+
+/**
+ * Generates class loading information (class maps, class aliases etc.) and writes it to files
+ * for further inclusion in the bootstrap
+ */
+class ClassLoadingInformationGenerator {
+
+       /**
+        * @var PackageInterface[]
+        */
+       static protected $activePackages;
+
+       /**
+        * Returns class loading information for a single package
+        *
+        * @param PackageInterface $package The package to generate the class loading info for
+        * @param bool $useRelativePaths If set to TRUE, make the path relative to the current TYPO3 instance (PATH_site)
+        * @return array
+        */
+       static public function buildClassLoadingInformationForPackage(PackageInterface $package, $useRelativePaths = FALSE) {
+               $classMap = array();
+               $psr4 = array();
+               $packagePath = $package->getPackagePath();
+
+               try {
+                       $manifest = self::getPackageManager()->getComposerManifest($package->getPackagePath());
+                       if (!empty($manifest->autoload->{'psr-4'})) {
+                               $psr4manifest = json_decode(json_encode($manifest->autoload->{'psr-4'}), TRUE);
+                               if (is_array($psr4manifest)) {
+                                       foreach ($psr4manifest as $namespacePrefix => $path) {
+                                               $namespacePath = $packagePath . $path;
+                                               if ($useRelativePaths) {
+                                                       $psr4[$namespacePrefix] = self::makePathRelative($namespacePath, realpath($namespacePath));
+                                               } else {
+                                                       $psr4[$namespacePrefix] = $namespacePath;
+                                               }
+                                       }
+                               }
+                       }
+               } catch (MissingPackageManifestException $e) {
+                       // Ignore missing composer manifest
+               }
+
+               foreach (ClassMapGenerator::createMap($packagePath) as $class => $path) {
+                       if ($useRelativePaths) {
+                               $classMap[$class] = self::makePathRelative($packagePath, $path);
+                       } else {
+                               $classMap[$class] = $path;
+                       }
+               }
+
+               return array('classMap' => $classMap, 'psr-4' => $psr4);
+       }
+
+       /**
+        * Returns class alias map for given package
+        *
+        * @param PackageInterface $package The package to generate the class alias info for
+        * @throws \TYPO3\CMS\Core\Error\Exception
+        * @return array
+        */
+       static public function buildClassAliasMapForPackage(PackageInterface $package) {
+               $aliasToClassNameMapping = array();
+               $classNameToAliasMapping = array();
+               $possibleClassAliasFile = $package->getPackagePath() . 'Migrations/Code/ClassAliasMap.php';
+               if (file_exists($possibleClassAliasFile)) {
+                       $packageAliasMap = require $possibleClassAliasFile;
+                       if (!is_array($packageAliasMap)) {
+                               throw new \TYPO3\CMS\Core\Error\Exception('"class alias maps" must return an array', 1422625075);
+                       }
+                       foreach ($packageAliasMap as $aliasClassName => $className) {
+                               $lowerCasedAliasClassName = strtolower($aliasClassName);
+                               $aliasToClassNameMapping[$lowerCasedAliasClassName] = $className;
+                               $classNameToAliasMapping[$className][$lowerCasedAliasClassName] = $lowerCasedAliasClassName;
+                       }
+               }
+
+               return array('aliasToClassNameMapping' => $aliasToClassNameMapping, 'classNameToAliasMapping' => $classNameToAliasMapping);
+       }
+
+       /**
+        * Generate the class map file
+        * @return string[]
+        * @internal
+        */
+       static public function buildAutoloadInformationFiles() {
+               $psr4File = $classMapFile = <<<EOF
+<?php
+
+// autoload_classmap.php @generated by TYPO3
+
+\$typo3InstallDir = PATH_site;
+
+return array(
+
+EOF;
+               $classMap = array();
+               $psr4 = array();
+               foreach (self::getActivePackages() as $package) {
+                       $classLoadingInformation = self::buildClassLoadingInformationForPackage($package, TRUE);
+                       $classMap = array_merge($classMap, $classLoadingInformation['classMap']);
+                       $psr4 = array_merge($psr4, $classLoadingInformation['psr-4']);
+               }
+
+               ksort($classMap);
+               ksort($psr4);
+               foreach ($classMap as $class => $relativePath) {
+                       $classMapFile .= sprintf('    %s => %s,', var_export($class, TRUE), self::getPathCode($relativePath)) . LF;
+               }
+               $classMapFile .= ");\n";
+
+               foreach ($psr4 as $prefix => $relativePath) {
+                       $psr4File .= sprintf('    %s => array(%s),', var_export($prefix, TRUE), self::getPathCode($relativePath)) . LF;
+               }
+               $psr4File .= ");\n";
+
+               return array('classMapFile' => $classMapFile, 'psr-4File' => $psr4File);
+       }
+
+       /**
+        * Generate a relative path string from an absolute path within a give package path
+        *
+        * @param string $packagePath
+        * @param string $realPathOfClassFile
+        * @return string
+        */
+       static protected function makePathRelative($packagePath, $realPathOfClassFile) {
+               $realPathOfClassFile = GeneralUtility::fixWindowsFilePath($realPathOfClassFile);
+               $classesRealPath = GeneralUtility::fixWindowsFilePath(realpath($packagePath));
+               $relativeClassesPath = rtrim(PathUtility::stripPathSitePrefix($packagePath), '/');
+               $relativePathToClassFile = $relativeClassesPath . '/' . ltrim(substr($realPathOfClassFile, strlen($classesRealPath)), '/');
+
+               return $relativePathToClassFile;
+       }
+
+       /**
+        * Generate a relative path string from a relative path
+        *
+        * @param string $relativePathToClassFile
+        * @return string
+        */
+       static protected function getPathCode($relativePathToClassFile) {
+               return '$typo3InstallDir . ' . var_export($relativePathToClassFile, TRUE);
+       }
+
+       /**
+        * Build class alias mapping file
+        *
+        * @return string
+        * @throws \Exception
+        * @internal
+        */
+       static public function buildClassAliasMapFile() {
+               $aliasToClassNameMapping = array();
+               $classNameToAliasMapping = array();
+               foreach (self::getActivePackages() as $package) {
+                       $aliasMappingForPackage = self::buildClassAliasMapForPackage($package);
+                       $aliasToClassNameMapping = array_merge($aliasToClassNameMapping, $aliasMappingForPackage['aliasToClassNameMapping']);
+                       $classNameToAliasMapping = array_merge($classNameToAliasMapping, $aliasMappingForPackage['classNameToAliasMapping']);
+               }
+               $exportArray = array(
+                       'aliasToClassNameMapping' => $aliasToClassNameMapping,
+                       'classNameToAliasMapping' => $classNameToAliasMapping
+               );
+               $fileContent = '<?php' . chr(10) . 'return ';
+               $fileContent .= var_export($exportArray, TRUE);
+               $fileContent .= ";\n";
+               return $fileContent;
+       }
+
+       /**
+        * Get all packages except the protected ones, as they are covered already
+        *
+        * @return \TYPO3\CMS\Core\Package\PackageInterface[]
+        */
+       static protected function getActivePackages() {
+               if (self::$activePackages === NULL) {
+                       self::$activePackages = array();
+                       foreach (self::getPackageManager()->getActivePackages() as $package) {
+                               if (!$package instanceof \TYPO3\CMS\Core\Package\Package || $package->isProtected()) {
+                                       // Skip non core packages and all protected packages.
+                                       // The latter will be covered by composer class loader.
+                                       continue;
+                               }
+                               self::$activePackages[] = $package;
+                       }
+               }
+
+               return self::$activePackages;
+       }
+
+       /**
+        * @return PackageManager
+        * @throws \TYPO3\CMS\Core\Exception
+        */
+       static protected function getPackageManager() {
+               return Bootstrap::getInstance()->getEarlyInstance(PackageManager::class);
+       }
+
+}
index 693befe..c69924a 100644 (file)
@@ -15,6 +15,7 @@ namespace TYPO3\CMS\Core\Package;
  */
 
 use TYPO3\CMS\Core\Compatibility\LoadedExtensionArrayElement;
  */
 
 use TYPO3\CMS\Core\Compatibility\LoadedExtensionArrayElement;
+use TYPO3\CMS\Core\Core\ClassLoadingInformation;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\PathUtility;
 
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\PathUtility;
 
@@ -25,11 +26,6 @@ use TYPO3\CMS\Core\Utility\PathUtility;
 class PackageManager implements \TYPO3\CMS\Core\SingletonInterface {
 
        /**
 class PackageManager implements \TYPO3\CMS\Core\SingletonInterface {
 
        /**
-        * @var \TYPO3\CMS\Core\Core\ClassLoader
-        */
-       protected $classLoader;
-
-       /**
         * @var \TYPO3\CMS\Core\Package\DependencyResolver
         */
        protected $dependencyResolver;
         * @var \TYPO3\CMS\Core\Package\DependencyResolver
         */
        protected $dependencyResolver;
@@ -131,13 +127,6 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface {
        }
 
        /**
        }
 
        /**
-        * @param \TYPO3\CMS\Core\Core\ClassLoader $classLoader
-        */
-       public function injectClassLoader(\TYPO3\CMS\Core\Core\ClassLoader $classLoader) {
-               $this->classLoader = $classLoader;
-       }
-
-       /**
         * @param \TYPO3\CMS\Core\Cache\Frontend\PhpFrontend $coreCache
         */
        public function injectCoreCache(\TYPO3\CMS\Core\Cache\Frontend\PhpFrontend $coreCache) {
         * @param \TYPO3\CMS\Core\Cache\Frontend\PhpFrontend $coreCache
         */
        public function injectCoreCache(\TYPO3\CMS\Core\Cache\Frontend\PhpFrontend $coreCache) {
@@ -170,14 +159,6 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface {
                        $this->initializeCompatibilityLoadedExtArray();
                }
 
                        $this->initializeCompatibilityLoadedExtArray();
                }
 
-               $cacheIdentifier = $this->getCacheIdentifier();
-               if ($cacheIdentifier === NULL) {
-                       // Create an artificial cache identifier if the package states file is not available yet
-                       // in order that the class loader and class alias map can cache anyways.
-                       $cacheIdentifier = md5(implode('###', array_keys($this->activePackages)));
-               }
-               $this->classLoader->setCacheIdentifier($cacheIdentifier)->setPackages($this->activePackages);
-
                foreach ($this->activePackages as $package) {
                        /** @var $package Package */
                        $package->boot($bootstrap);
                foreach ($this->activePackages as $package) {
                        /** @var $package Package */
                        $package->boot($bootstrap);
@@ -572,26 +553,6 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface {
        }
 
        /**
        }
 
        /**
-        * @return array
-        */
-       public function getExtAutoloadRegistry() {
-               if (!isset($this->extAutoloadClassFiles)) {
-                       $classRegistry = array();
-                       foreach ($this->activePackages as $packageKey => $packageData) {
-                               try {
-                                       $extensionAutoloadFile = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($packageKey, 'ext_autoload.php');
-                                       if (@file_exists($extensionAutoloadFile)) {
-                                               $classRegistry = array_merge($classRegistry, require $extensionAutoloadFile);
-                                       }
-                               } catch (\BadFunctionCallException $e) {
-                               }
-                       }
-                       $this->extAutoloadClassFiles = $classRegistry;
-               }
-               return $this->extAutoloadClassFiles;
-       }
-
-       /**
         * Returns a PackageInterface object for the specified package.
         * A package is available, if the package directory contains valid MetaData information.
         *
         * Returns a PackageInterface object for the specified package.
         * A package is available, if the package directory contains valid MetaData information.
         *
@@ -668,7 +629,6 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface {
                unset($this->activePackages[$packageKey]);
                $this->packageStatesConfiguration['packages'][$packageKey]['state'] = 'inactive';
                $this->sortAndSavePackageStates();
                unset($this->activePackages[$packageKey]);
                $this->packageStatesConfiguration['packages'][$packageKey]['state'] = 'inactive';
                $this->sortAndSavePackageStates();
-               $this->classLoader->setPackages($this->activePackages);
        }
 
        /**
        }
 
        /**
@@ -686,7 +646,7 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface {
                        $this->packageStatesConfiguration['packages'][$packageKey]['packagePath'] = str_replace($this->packagesBasePath, '', $package->getPackagePath());
                }
                $this->sortAndSavePackageStates();
                        $this->packageStatesConfiguration['packages'][$packageKey]['packagePath'] = str_replace($this->packagesBasePath, '', $package->getPackagePath());
                }
                $this->sortAndSavePackageStates();
-               $this->classLoader->addActivePackage($package);
+               $this->registerTransientClassLoadingInformationForPackage($package);
        }
 
        /**
        }
 
        /**
@@ -698,11 +658,19 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface {
        public function activatePackageDuringRuntime($packageKey) {
                $package = $this->getPackage($packageKey);
                $this->runtimeActivatedPackages[$package->getPackageKey()] = $package;
        public function activatePackageDuringRuntime($packageKey) {
                $package = $this->getPackage($packageKey);
                $this->runtimeActivatedPackages[$package->getPackageKey()] = $package;
-               $this->classLoader->addActivePackage($package);
                if (!isset($GLOBALS['TYPO3_LOADED_EXT'][$package->getPackageKey()])) {
                        $loadedExtArrayElement = new LoadedExtensionArrayElement($package);
                        $GLOBALS['TYPO3_LOADED_EXT'][$package->getPackageKey()] = $loadedExtArrayElement->toArray();
                }
                if (!isset($GLOBALS['TYPO3_LOADED_EXT'][$package->getPackageKey()])) {
                        $loadedExtArrayElement = new LoadedExtensionArrayElement($package);
                        $GLOBALS['TYPO3_LOADED_EXT'][$package->getPackageKey()] = $loadedExtArrayElement->toArray();
                }
+               $this->registerTransientClassLoadingInformationForPackage($package);
+       }
+
+       /**
+        * @param PackageInterface $package
+        * @throws \TYPO3\CMS\Core\Exception
+        */
+       protected function registerTransientClassLoadingInformationForPackage(PackageInterface $package) {
+               ClassLoadingInformation::registerTransientClassLoadingInformationForPackage($package);
        }
 
        /**
        }
 
        /**
index 86cec72..3abe0ce 100644 (file)
@@ -33,9 +33,6 @@ class UnitTestPackageManager extends PackageManager {
 
                $this->scanAvailablePackages();
                $this->activePackages = $this->packages;
 
                $this->scanAvailablePackages();
                $this->activePackages = $this->packages;
-
-               $cacheIdentifier = str_replace('.', '', uniqid('', TRUE));
-               $this->classLoader->setCacheIdentifier($cacheIdentifier)->setPackages($this->activePackages);
        }
 
        /**
        }
 
        /**
index 4c52e35..22b2fe9 100755 (executable)
@@ -15,7 +15,7 @@ namespace TYPO3\CMS\Core\Utility;
  */
 
 use TYPO3\CMS\Core\Core\ApplicationContext;
  */
 
 use TYPO3\CMS\Core\Core\ApplicationContext;
-use TYPO3\CMS\Core\Core\ClassLoader;
+use TYPO3\CMS\Core\Core\ClassLoadingInformation;
 use TYPO3\CMS\Core\Imaging\GraphicalFunctions;
 use TYPO3\CMS\Core\SingletonInterface;
 use TYPO3\CMS\Frontend\Page\PageRepository;
 use TYPO3\CMS\Core\Imaging\GraphicalFunctions;
 use TYPO3\CMS\Core\SingletonInterface;
 use TYPO3\CMS\Frontend\Page\PageRepository;
@@ -4351,7 +4351,7 @@ Connection: close
                                $className = static::getImplementationForClass($className);
                        }
                }
                                $className = static::getImplementationForClass($className);
                        }
                }
-               return ClassLoader::getClassNameForAlias($className);
+               return ClassLoadingInformation::getClassNameForAlias($className);
        }
 
        /**
        }
 
        /**
index 61992b6..9b136b5 100644 (file)
@@ -123,14 +123,6 @@ return array(
                                        ),
                                        'groups' => array('system')
                                ),
                                        ),
                                        'groups' => array('system')
                                ),
-                               'cache_classes' => array(
-                                       'frontend' => \TYPO3\CMS\Core\Cache\Frontend\StringFrontend::class,
-                                       'backend' => \TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend::class,
-                                       'options' => array(
-                                               'defaultLifetime' => 0,
-                                       ),
-                                       'groups' => array('system')
-                               ),
                                'cache_hash' => array(
                                        'frontend' => \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class,
                                        'backend' => \TYPO3\CMS\Core\Cache\Backend\Typo3DatabaseBackend::class,
                                'cache_hash' => array(
                                        'frontend' => \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class,
                                        'backend' => \TYPO3\CMS\Core\Cache\Backend\Typo3DatabaseBackend::class,
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-67212-DiscardLegacyClassLoader.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-67212-DiscardLegacyClassLoader.rst
new file mode 100644 (file)
index 0000000..7d55477
--- /dev/null
@@ -0,0 +1,40 @@
+=============================================
+Breaking: #67212 - Discard TYPO3 class loader
+=============================================
+
+Description
+===========
+
+The former TYPO3 class loader has been removed in favor of the composer class loader.
+
+
+Impact
+======
+
+ext_autoload.php files are **not** evaluated any more. Instead all class files are registered
+automatically during extension installation and written into a class map file. This class map file is
+not changed during regular requests, but only if the extension list changes (by using the Extension Manager).
+
+These class information files are located in the typo3temp/autoload/ directory and will also be automatically created
+if they do not exist.
+
+Non-namespaced classes with Tx\_ naming convention like Tx_Extension_ClassName are only resolved through
+the aforementioned class map, but not dynamically. This means that extension authors need to re-generate the class map files
+when introducing new classes. Thus it is highly recommended to use a Classes folder with PSR-4 standard class files in there.
+
+When installing TYPO3 with composer, it also means that all extensions need to bring their own composer.json file with class loading information,
+or the class loading information of all extensions need to be specified in the root composer.json for class loading to work properly.
+
+
+Affected Installations
+======================
+
+All installations are affected.
+
+
+Migration
+=========
+
+No migration is needed during upgrade if TYPO3 is installed in the classic way.
+If TYPO3 is installed in a distribution via composer, missing class loading information need to be provided in root composer.json
+for all extensions which do not bring their own composer.json manifest.
diff --git a/typo3/sysext/core/Resources/PHP/ClassMapGenerator.php b/typo3/sysext/core/Resources/PHP/ClassMapGenerator.php
new file mode 100644 (file)
index 0000000..0f05f45
--- /dev/null
@@ -0,0 +1,189 @@
+<?php
+
+/*
+ * This file is copied from the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @license MIT
+ */
+
+namespace Composer\Autoload;
+
+use Symfony\Component\Finder\Finder;
+use Composer\IO\IOInterface;
+
+/**
+ * ClassMapGenerator
+ *
+ * @author Gyula Sallai <salla016@gmail.com>
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+class ClassMapGenerator
+{
+    /**
+     * Generate a class map file
+     *
+     * @param \Traversable $dirs Directories or a single path to search in
+     * @param string       $file The name of the class map file
+     */
+    public static function dump($dirs, $file)
+    {
+        $maps = array();
+
+        foreach ($dirs as $dir) {
+            $maps = array_merge($maps, static::createMap($dir));
+        }
+
+        file_put_contents($file, sprintf('<?php return %s;', var_export($maps, true)));
+    }
+
+    /**
+     * Iterate over all files in the given directory searching for classes
+     *
+     * @param \Iterator|string $path      The path to search in or an iterator
+     * @param string           $whitelist Regex that matches against the file path
+     * @param IOInterface      $io        IO object
+     * @param string           $namespace Optional namespace prefix to filter by
+     *
+     * @return array A class map array
+     *
+     * @throws \RuntimeException When the path is neither an existing file nor directory
+     */
+    public static function createMap($path, $whitelist = null, IOInterface $io = null, $namespace = null)
+    {
+        if (is_string($path)) {
+            if (is_file($path)) {
+                $path = array(new \SplFileInfo($path));
+            } elseif (is_dir($path)) {
+                $path = Finder::create()->files()->followLinks()->name('/\.(php|inc|hh)$/')->in($path);
+            } else {
+                throw new \RuntimeException(
+                    'Could not scan for classes inside "'.$path.
+                    '" which does not appear to be a file nor a folder'
+                );
+            }
+        }
+
+        $map = array();
+
+        foreach ($path as $file) {
+            $filePath = $file->getRealPath();
+
+            if (!in_array(pathinfo($filePath, PATHINFO_EXTENSION), array('php', 'inc', 'hh'))) {
+                continue;
+            }
+
+            if ($whitelist && !preg_match($whitelist, strtr($filePath, '\\', '/'))) {
+                continue;
+            }
+
+            $classes = self::findClasses($filePath);
+
+            foreach ($classes as $class) {
+                // skip classes not within the given namespace prefix
+                if (null !== $namespace && 0 !== strpos($class, $namespace)) {
+                    continue;
+                }
+
+                if (!isset($map[$class])) {
+                    $map[$class] = $filePath;
+                } elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) {
+                    $io->writeError(
+                        '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
+                        ' was found in both "'.$map[$class].'" and "'.$filePath.'", the first will be used.</warning>'
+                    );
+                }
+            }
+        }
+
+        return $map;
+    }
+
+    /**
+     * Extract the classes in the given file
+     *
+     * @param  string            $path The file to check
+     * @throws \RuntimeException
+     * @return array             The found classes
+     */
+    private static function findClasses($path)
+    {
+        $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
+        if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
+            $extraTypes .= '|enum';
+        }
+
+        try {
+            $contents = @php_strip_whitespace($path);
+            if (!$contents) {
+                if (!file_exists($path)) {
+                    throw new \Exception('File does not exist');
+                }
+                if (!is_readable($path)) {
+                    throw new \Exception('File is not readable');
+                }
+            }
+        } catch (\Exception $e) {
+            throw new \RuntimeException('Could not scan for classes inside '.$path.": \n".$e->getMessage(), 0, $e);
+        }
+
+        // return early if there is no chance of matching anything in this file
+        if (!preg_match('{\b(?:class|interface'.$extraTypes.')\s}i', $contents)) {
+            return array();
+        }
+
+        // strip heredocs/nowdocs
+        $contents = preg_replace('{<<<\s*(\'?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\2(?=\r\n|\n|\r|;)}s', 'null', $contents);
+        // strip strings
+        $contents = preg_replace('{"[^"\\\\]*(\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(\\\\.[^\'\\\\]*)*\'}s', 'null', $contents);
+        // strip leading non-php code if needed
+        if (substr($contents, 0, 2) !== '<?') {
+            $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
+            if ($replacements === 0) {
+                return array();
+            }
+        }
+        // strip non-php blocks in the file
+        $contents = preg_replace('{\?>.+<\?}s', '?><?', $contents);
+        // strip trailing non-php code if needed
+        $pos = strrpos($contents, '?>');
+        if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
+            $contents = substr($contents, 0, $pos);
+        }
+
+        preg_match_all('{
+            (?:
+                 \b(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s+ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*)
+               | \b(?<![\$:>])(?P<ns>namespace) (?P<nsname>\s+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\s*\\\\\s*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*)? \s*[\{;]
+            )
+        }ix', $contents, $matches);
+
+        $classes = array();
+        $namespace = '';
+
+        for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
+            if (!empty($matches['ns'][$i])) {
+                $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
+            } else {
+                $name = $matches['name'][$i];
+                if ($name[0] === ':') {
+                    // This is an XHP class, https://github.com/facebook/xhp
+                    $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
+                } elseif ($matches['type'][$i] === 'enum') {
+                    // In Hack, something like:
+                    //   enum Foo: int { HERP = '123'; }
+                    // The regex above captures the colon, which isn't part of
+                    // the class name.
+                    $name = rtrim($name, ':');
+                }
+                $classes[] = ltrim($namespace . $name, '\\');
+            }
+        }
+
+        return $classes;
+    }
+}
diff --git a/typo3/sysext/core/Tests/Unit/Core/ClassLoaderTest.php b/typo3/sysext/core/Tests/Unit/Core/ClassLoaderTest.php
deleted file mode 100644 (file)
index 2b81457..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-<?php
-namespace TYPO3\CMS\Core\Tests\Unit\Core;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use org\bovigo\vfs\vfsStream;
-
-/**
- * Testcase for TYPO3\CMS\Core\Core\ClassLoader
- *
- * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
- */
-class ClassLoaderTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
-
-       /**
-        * @var array Backup of typo3CacheManager
-        */
-       protected $typo3CacheManager = NULL;
-
-       /**
-        * @var array Register of temporary extensions in typo3temp
-        */
-       protected $fakedExtensions = array();
-
-       /**
-        * @var \TYPO3\CMS\Core\Core\ClassLoader
-        */
-       protected $classLoader;
-
-       /**
-        * @var \TYPO3\CMS\Core\Core\ClassAliasMap
-        */
-       protected $orinalClassAliasMap;
-
-       /**
-        * Test flag used in in this test case
-        *
-        * @var bool
-        */
-       public static $testClassWasLoaded = FALSE;
-
-       /**
-        * Fix a race condition that GeneralUtility is not available
-        * during tearDown if fiddling with the autoloader where
-        * backupGlobals is not set up again yet
-        */
-       protected function setUp() {
-               vfsStream::setup('Test');
-
-               mkdir('vfs://Test/Packages/Application/Acme.MyApp/Classes/', 0770, TRUE);
-               file_put_contents('vfs://Test/Packages/Application/Acme.MyApp/composer.json', '{"name": "acme/myapp", "type": "flow-test"}');
-               file_put_contents('vfs://Test/Packages/Application/Acme.MyApp/ext_emconf.php', '');
-               $packageManager = $this->getMock(\TYPO3\CMS\Core\Package\PackageManager::class, array('isPackageKeyValid'));
-               $packageManager->expects($this->any())->method('isPackageKeyValid')->willReturn(TRUE);
-               $package1 = new \TYPO3\CMS\Core\Package\Package($packageManager, 'Acme.MyApp', 'vfs://Test/Packages/Application/Acme.MyApp/', 'Classes');
-
-               mkdir('vfs://Test/Packages/Application/Acme.MyAppAddon/Classes/', 0770, TRUE);
-               file_put_contents('vfs://Test/Packages/Application/Acme.MyAppAddon/composer.json', '{"name": "acme/myappaddon", "type": "flow-test"}');
-               file_put_contents('vfs://Test/Packages/Application/Acme.MyAppAddon/ext_emconf.php', '');
-               $package2 = new \TYPO3\CMS\Core\Package\Package($packageManager, 'Acme.MyAppAddon', 'vfs://Test/Packages/Application/Acme.MyAppAddon/', 'Classes');
-
-               $mockClassAliasMap = $this->getMock(\TYPO3\CMS\Core\Core\ClassAliasMap::class, array('setPackagesButDontBuildMappingFilesReturnClassNameToAliasMappingInstead', 'buildMappingFiles'), array(), '', FALSE);
-               $mockClassAliasMap->expects($this->any())->method('setPackagesButDontBuildMappingFilesReturnClassNameToAliasMappingInstead')->will($this->returnValue(array()));
-
-               $this->orinalClassAliasMap = \TYPO3\CMS\Core\Core\Bootstrap::getInstance()->getEarlyInstance(\TYPO3\CMS\Core\Core\ClassAliasMap::class);
-               $this->classLoader = new \TYPO3\CMS\Core\Core\ClassLoader(\TYPO3\CMS\Core\Core\Bootstrap::getInstance()->getApplicationContext());
-               $this->classLoader->injectClassAliasMap($mockClassAliasMap);
-               $this->classLoader->setPackages(array('Acme.MyApp' => $package1, 'Acme.MyAppAddon' => $package2));
-       }
-
-       /**
-        * The class alias map is kept static in the class loader for legacy reasons
-        * and has to be reset after mocking.
-        */
-       protected function tearDown() {
-               $this->classLoader->injectClassAliasMap($this->orinalClassAliasMap);
-               parent::tearDown();
-       }
-
-       /**
-        * Creates a fake extension inside typo3temp/. No configuration is created,
-        * just the folder, plus the extension is registered in $TYPO3_LOADED_EXT
-        *
-        * @return string The extension key
-        */
-       protected function createFakeExtension() {
-               $extKey = strtolower($this->getUniqueId('testing'));
-               $absExtPath = PATH_site . 'typo3temp/' . $extKey . '/';
-               $relPath = 'typo3temp/' . $extKey . '/';
-               \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir($absExtPath);
-               $GLOBALS['TYPO3_LOADED_EXT'][$extKey] = array(
-                       'siteRelPath' => $relPath
-               );
-               $this->fakedExtensions[] = $extKey;
-               \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::clearExtensionKeyMap();
-               return $extKey;
-       }
-
-       /**
-        * Checks if the package autoloader loads classes from subdirectories.
-        *
-        * @test
-        */
-       public function classesFromSubDirectoriesAreLoaded() {
-               mkdir('vfs://Test/Packages/Application/Acme.MyApp/Classes/SubDirectory', 0770, TRUE);
-               file_put_contents('vfs://Test/Packages/Application/Acme.MyApp/Classes/SubDirectory/ClassInSubDirectory.php', '<?php ' . __CLASS__ . '::$testClassWasLoaded = TRUE; ?>');
-
-               self::$testClassWasLoaded = FALSE;
-               $this->classLoader->loadClass('Acme\MyApp\SubDirectory\ClassInSubDirectory');
-               $this->assertTrue(self::$testClassWasLoaded);
-       }
-
-       /**
-        * @test
-        */
-       public function classesFromDeeplyNestedSubDirectoriesAreLoaded() {
-               mkdir('vfs://Test/Packages/Application/Acme.MyApp/Classes/SubDirectory/A/B/C/D', 0770, TRUE);
-               file_put_contents('vfs://Test/Packages/Application/Acme.MyApp/Classes/SubDirectory/A/B/C/D/E.php', '<?php ' . __CLASS__ . '::$testClassWasLoaded = TRUE; ?>');
-
-               self::$testClassWasLoaded = FALSE;
-               $this->classLoader->loadClass('Acme\MyApp\SubDirectory\A\B\C\D\E');
-               $this->assertTrue(self::$testClassWasLoaded);
-       }
-
-       /**
-        * Checks if the package autoloader loads classes from packages that match a
-        * substring of another package (e.g. TYPO3CR vs TYPO3).
-        *
-        * @test
-        */
-       public function classesFromSubMatchingPackagesAreLoaded() {
-               file_put_contents('vfs://Test/Packages/Application/Acme.MyAppAddon/Classes/Class.php', '<?php ' . __CLASS__ . '::$testClassWasLoaded = TRUE; ?>');
-
-               self::$testClassWasLoaded = FALSE;
-               $this->classLoader->loadClass('Acme\MyAppAddon\Class');
-               $this->assertTrue(self::$testClassWasLoaded);
-       }
-
-       /**
-        * Checks if the package autoloader loads classes from subdirectories with underscores.
-        *
-        * @test
-        */
-       public function namespaceWithUnderscoresAreLoaded() {
-               mkdir('vfs://Test/Packages/Application/Acme.MyApp/Classes/My_Underscore', 0770, TRUE);
-               file_put_contents('vfs://Test/Packages/Application/Acme.MyApp/Classes/My_Underscore/Foo.php', '<?php ' . __CLASS__ . '::$testClassWasLoaded = TRUE; ?>');
-
-               self::$testClassWasLoaded = FALSE;
-               $this->classLoader->loadClass('Acme\MyApp\My_Underscore\Foo');
-               $this->assertTrue(self::$testClassWasLoaded);
-       }
-
-       /**
-        * @test
-        */
-       public function classesWithLeadingBackslashAreLoaded() {
-               file_put_contents('vfs://Test/Packages/Application/Acme.MyApp/Classes/WithLeadingBackslash.php', '<?php ' . __CLASS__ . '::$testClassWasLoaded = TRUE; ?>');
-
-               self::$testClassWasLoaded = FALSE;
-               $this->classLoader->loadClass('\Acme\MyApp\WithLeadingBackslash');
-               $this->assertTrue(self::$testClassWasLoaded);
-       }
-
-}
index ca62f34..7d5fac2 100644 (file)
@@ -38,20 +38,16 @@ class PackageManagerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                $mockCache->expects($this->any())->method('set')->will($this->returnValue(TRUE));
                $mockCache->expects($this->any())->method('getBackend')->will($this->returnValue($mockCacheBackend));
                $mockCacheBackend->expects($this->any())->method('getCacheDirectory')->will($this->returnValue('vfs://Test/Cache'));
                $mockCache->expects($this->any())->method('set')->will($this->returnValue(TRUE));
                $mockCache->expects($this->any())->method('getBackend')->will($this->returnValue($mockCacheBackend));
                $mockCacheBackend->expects($this->any())->method('getCacheDirectory')->will($this->returnValue('vfs://Test/Cache'));
-               $this->packageManager = $this->getAccessibleMock(\TYPO3\CMS\Core\Package\PackageManager::class, array('sortAndSavePackageStates', 'sortAvailablePackagesByDependencies'));
+               $this->packageManager = $this->getAccessibleMock(\TYPO3\CMS\Core\Package\PackageManager::class, array('sortAndSavePackageStates', 'sortAvailablePackagesByDependencies', 'registerAutoloadInformationInClassLoader'));
 
                mkdir('vfs://Test/Packages/Application', 0700, TRUE);
                mkdir('vfs://Test/Configuration');
                file_put_contents('vfs://Test/Configuration/PackageStates.php', "<?php return array ('packages' => array(), 'version' => 4); ");
 
 
                mkdir('vfs://Test/Packages/Application', 0700, TRUE);
                mkdir('vfs://Test/Configuration');
                file_put_contents('vfs://Test/Configuration/PackageStates.php', "<?php return array ('packages' => array(), 'version' => 4); ");
 
-               $mockClassLoader = $this->getMock(\TYPO3\CMS\Core\Core\ClassLoader::class, array(), array(\TYPO3\CMS\Core\Core\Bootstrap::getInstance()->getApplicationContext()));
-               $mockClassLoader->expects($this->any())->method('setCacheIdentifier')->will($this->returnSelf());
-
                $composerNameToPackageKeyMap = array(
                        'typo3/flow' => 'TYPO3.Flow'
                );
 
                $composerNameToPackageKeyMap = array(
                        'typo3/flow' => 'TYPO3.Flow'
                );
 
-               $this->packageManager->injectClassLoader($mockClassLoader);
                $this->packageManager->injectCoreCache($mockCache);
                $this->inject($this->packageManager, 'composerNameToPackageKeyMap', $composerNameToPackageKeyMap);
                $this->packageManager->_set('packagesBasePath', 'vfs://Test/Packages/');
                $this->packageManager->injectCoreCache($mockCache);
                $this->inject($this->packageManager, 'composerNameToPackageKeyMap', $composerNameToPackageKeyMap);
                $this->packageManager->_set('packagesBasePath', 'vfs://Test/Packages/');
index 372938d..920f13c 100644 (file)
@@ -25,7 +25,7 @@
                "psr-4": {
                        "TYPO3\\CMS\\Core\\": "Classes/"
                },
                "psr-4": {
                        "TYPO3\\CMS\\Core\\": "Classes/"
                },
-               "classmap": ["Resources/PHP/RemoveXSS.php"]
+               "classmap": ["Resources/PHP/"]
        },
        "autoload-dev": {
                "psr-4": {
        },
        "autoload-dev": {
                "psr-4": {
index 87eb9ae..46641ed 100644 (file)
@@ -41,22 +41,18 @@ $signalSlotDispatcher->connect(
 );
 
 if (!\TYPO3\CMS\Core\Core\Bootstrap::usesComposerClassLoading()) {
 );
 
 if (!\TYPO3\CMS\Core\Core\Bootstrap::usesComposerClassLoading()) {
-       $bootstrap = \TYPO3\CMS\Core\Core\Bootstrap::getInstance();
-       $classAliasMap = $bootstrap->getEarlyInstance(\TYPO3\CMS\Core\Core\ClassAliasMap::class);
        $signalSlotDispatcher->connect(
                \TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService::class,
                'hasInstalledExtensions',
        $signalSlotDispatcher->connect(
                \TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService::class,
                'hasInstalledExtensions',
-               $classAliasMap,
-               'buildStaticMappingFile'
+               \TYPO3\CMS\Core\Core\ClassLoadingInformation::class,
+               'writeClassLoadingInformation'
        );
        );
-
        $signalSlotDispatcher->connect(
                \TYPO3\CMS\Extensionmanager\Utility\InstallUtility::class,
                'afterExtensionUninstall',
        $signalSlotDispatcher->connect(
                \TYPO3\CMS\Extensionmanager\Utility\InstallUtility::class,
                'afterExtensionUninstall',
-               $classAliasMap,
-               'buildStaticMappingFile'
+               \TYPO3\CMS\Core\Core\ClassLoadingInformation::class,
+               'writeClassLoadingInformation'
        );
        );
-       unset($bootstrap, $classAliasMap);
 }
 
 unset($signalSlotDispatcher);
 }
 
 unset($signalSlotDispatcher);
index 2e6d6f9..6d6441c 100644 (file)
@@ -160,7 +160,7 @@ class Container implements \TYPO3\CMS\Core\SingletonInterface {
                if ($className === \TYPO3\CMS\Core\Package\PackageManager::class) {
                        return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Package\PackageManager::class);
                }
                if ($className === \TYPO3\CMS\Core\Package\PackageManager::class) {
                        return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Package\PackageManager::class);
                }
-               $className = \TYPO3\CMS\Core\Core\ClassLoader::getClassNameForAlias($className);
+               $className = \TYPO3\CMS\Core\Core\ClassLoadingInformation::getClassNameForAlias($className);
                if (isset($this->singletonInstances[$className])) {
                        if (count($givenConstructorArguments) > 0) {
                                throw new \TYPO3\CMS\Extbase\Object\Exception('Object "' . $className . '" fetched from singleton cache, thus, explicit constructor arguments are not allowed.', 1292857934);
                if (isset($this->singletonInstances[$className])) {
                        if (count($givenConstructorArguments) > 0) {
                                throw new \TYPO3\CMS\Extbase\Object\Exception('Object "' . $className . '" fetched from singleton cache, thus, explicit constructor arguments are not allowed.', 1292857934);
index c28bcd7..289c964 100644 (file)
@@ -208,7 +208,7 @@ class PropertyMapper implements \TYPO3\CMS\Core\SingletonInterface {
                $targetType = $this->parseCompositeType($targetType);
                // This is needed to correctly convert old class names to new ones
                // This compatibility layer will be removed with 7.0
                $targetType = $this->parseCompositeType($targetType);
                // This is needed to correctly convert old class names to new ones
                // This compatibility layer will be removed with 7.0
-               $targetType = \TYPO3\CMS\Core\Core\ClassLoader::getClassNameForAlias($targetType);
+               $targetType = \TYPO3\CMS\Core\Core\ClassLoadingInformation::getClassNameForAlias($targetType);
 
                $targetType = TypeHandlingUtility::normalizeType($targetType);
 
 
                $targetType = TypeHandlingUtility::normalizeType($targetType);
 
index 61fa4e2..9733888 100644 (file)
@@ -21,7 +21,7 @@ namespace TYPO3\CMS\Extbase\Property;
  * The TYPO3 project - inspiring people to share!                         *
  *                                                                        */
 
  * The TYPO3 project - inspiring people to share!                         *
  *                                                                        */
 
-use TYPO3\CMS\Core\Core\ClassLoader;
+use TYPO3\CMS\Core\Core\ClassLoadingInformation;
 
 /**
  * Concrete configuration object for the PropertyMapper.
 
 /**
  * Concrete configuration object for the PropertyMapper.
@@ -290,7 +290,7 @@ class PropertyMappingConfiguration implements PropertyMappingConfigurationInterf
         */
        public function setTypeConverterOptions($typeConverter, array $options) {
                if (strpos($typeConverter, '_') !== FALSE) {
         */
        public function setTypeConverterOptions($typeConverter, array $options) {
                if (strpos($typeConverter, '_') !== FALSE) {
-                       $typeConverter = ClassLoader::getClassNameForAlias($typeConverter);
+                       $typeConverter = ClassLoadingInformation::getClassNameForAlias($typeConverter);
                }
                foreach ($this->getTypeConvertersWithParentClasses($typeConverter) as $typeConverter) {
                        $this->configuration[$typeConverter] = $options;
                }
                foreach ($this->getTypeConvertersWithParentClasses($typeConverter) as $typeConverter) {
                        $this->configuration[$typeConverter] = $options;
@@ -309,7 +309,7 @@ class PropertyMappingConfiguration implements PropertyMappingConfigurationInterf
         */
        public function setTypeConverterOption($typeConverter, $optionKey, $optionValue) {
                if (strpos($typeConverter, '_') !== FALSE) {
         */
        public function setTypeConverterOption($typeConverter, $optionKey, $optionValue) {
                if (strpos($typeConverter, '_') !== FALSE) {
-                       $typeConverter = ClassLoader::getClassNameForAlias($typeConverter);
+                       $typeConverter = ClassLoadingInformation::getClassNameForAlias($typeConverter);
                }
                foreach ($this->getTypeConvertersWithParentClasses($typeConverter) as $typeConverter) {
                        $this->configuration[$typeConverter][$optionKey] = $optionValue;
                }
                foreach ($this->getTypeConvertersWithParentClasses($typeConverter) as $typeConverter) {
                        $this->configuration[$typeConverter][$optionKey] = $optionValue;
index c42c408..156bf10 100644 (file)
@@ -302,9 +302,6 @@ class InstallUtility implements \TYPO3\CMS\Core\SingletonInterface {
         * @return void
         */
        public function reloadCaches() {
         * @return void
         */
        public function reloadCaches() {
-               // Reload class aliases defined in Migrations/Code/ClassAliasMap.php
-               \TYPO3\CMS\Core\Core\Bootstrap::getInstance()->getEarlyInstance(\TYPO3\CMS\Core\Core\ClassLoader::class)
-                       ->setPackages($this->packageManager->getActivePackages());
                \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::loadExtLocalconf(FALSE);
                \TYPO3\CMS\Core\Core\Bootstrap::getInstance()->loadExtensionTables(FALSE);
        }
                \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::loadExtLocalconf(FALSE);
                \TYPO3\CMS\Core\Core\Bootstrap::getInstance()->loadExtensionTables(FALSE);
        }
index 658a3c1..b649ab6 100644 (file)
@@ -644,7 +644,7 @@ class TemplateParser {
                        }
                        $className .= 'ViewHelper';
                        $name = $this->namespaces[$namespaceIdentifier] . $namespaceSeparator . $className;
                        }
                        $className .= 'ViewHelper';
                        $name = $this->namespaces[$namespaceIdentifier] . $namespaceSeparator . $className;
-                       $name = \TYPO3\CMS\Core\Core\ClassLoader::getClassNameForAlias($name);
+                       $name = \TYPO3\CMS\Core\Core\ClassLoadingInformation::getClassNameForAlias($name);
                        // The name isn't cached in viewHelperNameToImplementationClassNameRuntimeCache here because the
                        // class could be overloaded by extbase object manager. Thus the cache is filled in
                        // initializeViewHelperAndAddItToStack after getting the real object from the object manager.
                        // The name isn't cached in viewHelperNameToImplementationClassNameRuntimeCache here because the
                        // class could be overloaded by extbase object manager. Thus the cache is filled in
                        // initializeViewHelperAndAddItToStack after getting the real object from the object manager.
diff --git a/typo3/sysext/form/Migrations/Code/ClassAliasMap.php b/typo3/sysext/form/Migrations/Code/ClassAliasMap.php
new file mode 100644 (file)
index 0000000..488bdc3
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+return array(
+       'TYPO3\\CMS\\Form\\Domain\\Model\\Attribute\\AcceptcharsetAttribute' => \TYPO3\CMS\Form\Domain\Model\Attribute\AcceptCharsetAttribute::class,
+       'TYPO3\\CMS\\Form\\Domain\\Model\\Element\\CheckboxgroupElement' => \TYPO3\CMS\Form\Domain\Model\Element\CheckboxGroupElement::class,
+       'TYPO3\\CMS\\Form\\Domain\\Model\\Element\\RadiogroupElement' => \TYPO3\CMS\Form\Domain\Model\Element\RadioGroupElement::class,
+       'TYPO3\\CMS\\Form\\Domain\\Model\\Json\\CheckboxgroupJsonElement' => \TYPO3\CMS\Form\Domain\Model\Json\CheckboxGroupJsonElement::class,
+       'TYPO3\\CMS\\Form\\Domain\\Model\\Json\\RadiogroupJsonElement' => \TYPO3\CMS\Form\Domain\Model\Json\RadioGroupJsonElement::class,
+       'TYPO3\\CMS\\Form\\Filter\\RegexpFilter' => \TYPO3\CMS\Form\Filter\RegExpFilter::class,
+       'TYPO3\\CMS\\Form\\Filter\\StripnewlinesFilter' => \TYPO3\CMS\Form\Filter\StripNewLinesFilter::class,
+       'TYPO3\\CMS\\Form\\Filter\\TitlecaseFilter' => \TYPO3\CMS\Form\Filter\TitleCaseFilter::class,
+       'TYPO3\\CMS\\Form\\Filter\\UppercaseFilter' => \TYPO3\CMS\Form\Filter\UpperCaseFilter::class,
+       'TYPO3\\CMS\\Form\\Validation\\FileallowedtypesValidator' => \TYPO3\CMS\Form\Validation\FileAllowedTypesValidator::class,
+       'TYPO3\\CMS\\Form\\Validation\\FilemaximumsizeValidator' => \TYPO3\CMS\Form\Validation\FileMaximumSizeValidator::class,
+       'TYPO3\\CMS\\Form\\Validation\\FileminimumsizeValidator' => \TYPO3\CMS\Form\Validation\FileMinimumSizeValidator::class,
+       'TYPO3\\CMS\\Form\\Validation\\GreaterthanValidator' => \TYPO3\CMS\Form\Validation\GreaterThanValidator::class,
+       'TYPO3\\CMS\\Form\\Validation\\InarrayValidator' => \TYPO3\CMS\Form\Validation\InArrayValidator::class,
+       'TYPO3\\CMS\\Form\\Validation\\RegexpValidator' => \TYPO3\CMS\Form\Validation\RegExpValidator::class,
+       'TYPO3\\CMS\\Form\\View\\Confirmation\\Element\\CheckboxgroupElementView' => \TYPO3\CMS\Form\View\Confirmation\Element\CheckboxGroupElementView::class,
+       'TYPO3\\CMS\\Form\\View\\Confirmation\\Element\\RadiogroupElementView' => \TYPO3\CMS\Form\View\Confirmation\Element\RadioGroupElementView::class,
+       'TYPO3\\CMS\\Form\\View\\Form\\Element\\CheckboxgroupElementView' => \TYPO3\CMS\Form\View\Form\Element\CheckboxGroupElementView::class,
+       'TYPO3\\CMS\\Form\\View\\Form\\Element\\RadiogroupElementView' => \TYPO3\CMS\Form\View\Form\Element\RadioGroupElementView::class,
+       'TYPO3\\CMS\\Form\\View\\Mail\\Html\\Element\\CheckboxgroupElementView' => \TYPO3\CMS\Form\View\Mail\Html\Element\CheckboxGroupElementView::class,
+       'TYPO3\\CMS\\Form\\View\\Mail\\Html\\Element\\RadiogroupElementView' => \TYPO3\CMS\Form\View\Mail\Html\Element\RadioGroupElementView::class,
+       'TYPO3\\CMS\\Form\\View\\Mail\\Plain\\Element\\CheckboxgroupElementView' => \TYPO3\CMS\Form\View\Mail\Plain\Element\CheckboxGroupElementView::class,
+       'TYPO3\\CMS\\Form\\View\\Mail\\Plain\\Element\\RadiogroupElementView' => \TYPO3\CMS\Form\View\Mail\Plain\Element\RadioGroupElementView::class,
+       'TYPO3\\CMS\\Form\\Filter\\RemovexssFilter' => \TYPO3\CMS\Form\Filter\RemoveXssFilter::class,
+);
\ No newline at end of file
diff --git a/typo3/sysext/form/ext_autoload.php b/typo3/sysext/form/ext_autoload.php
deleted file mode 100644 (file)
index 9981d8f..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-$extPath = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('form');
-/*
- * These are classes which may be looked up with different casing than the original class
- * which is no issue with PHP as class names are case insensitive, but is an issue with our class loader
- * as it makes assumptions on the file location from the looked up class name, which fails on case sensitive file systems.
- * This file must stay as long as our class loader has to look up class files during runtime.
- */
-return array(
-       'typo3\\cms\\form\\domain\\model\\attribute\\acceptcharsetattribute' => $extPath . 'Classes/Domain/Model/Attribute/AcceptCharsetAttribute.php',
-       'typo3\\cms\\form\\domain\\model\\element\\checkboxgroupelement' => $extPath . 'Classes/Domain/Model/Element/CheckboxGroupElement.php',
-       'typo3\\cms\\form\\domain\\model\\element\\radiogroupelement' => $extPath . 'Classes/Domain/Model/Element/RadioGroupElement.php',
-       'typo3\\cms\\form\\domain\\model\\json\\checkboxgroupjsonelement' => $extPath . 'Classes/Domain/Model/Json/CheckboxGroupJsonElement.php',
-       'typo3\\cms\\form\\domain\\model\\json\\radiogroupjsonelement' => $extPath . 'Classes/Domain/Model/Json/RadioGroupJsonElement.php',
-       'typo3\\cms\\form\\filter\\regexpfilter' => $extPath . 'Classes/Filter/RegExpFilter.php',
-       'typo3\\cms\\form\\filter\\stripnewlinesfilter' => $extPath . 'Classes/Filter/StripNewLinesFilter.php',
-       'typo3\\cms\\form\\filter\\titlecasefilter' => $extPath . 'Classes/Filter/TitleCaseFilter.php',
-       'typo3\\cms\\form\\filter\\uppercasefilter' => $extPath . 'Classes/Filter/UpperCaseFilter.php',
-       'typo3\\cms\\form\\filter\\removexssfilter' => $extPath . 'Classes/Filter/RemoveXssFilter.php',
-       'typo3\\cms\\form\\validation\\fileallowedtypesvalidator' => $extPath . 'Classes/Validation/FileAllowedTypesValidator.php',
-       'typo3\\cms\\form\\validation\\filemaximumsizevalidator' => $extPath . 'Classes/Validation/FileMaximumSizeValidator.php',
-       'typo3\\cms\\form\\validation\\fileminimumsizevalidator' => $extPath . 'Classes/Validation/FileMinimumSizeValidator.php',
-       'typo3\\cms\\form\\validation\\greaterthanvalidator' => $extPath . 'Classes/Validation/GreaterThanValidator.php',
-       'typo3\\cms\\form\\validation\\inarrayvalidator' => $extPath . 'Classes/Validation/InArrayValidator.php',
-       'typo3\\cms\\form\\validation\\regexpvalidator' => $extPath . 'Classes/Validation/RegExpValidator.php',
-       'typo3\\cms\\form\\view\\confirmation\\element\\checkboxgroupelementview' => $extPath . 'Classes/View/Confirmation/Element/CheckboxGroupElementView.php',
-       'typo3\\cms\\form\\view\\confirmation\\element\\radiogroupelementview' => $extPath . 'Classes/View/Confirmation/Element/RadioGroupElementView.php',
-       'typo3\\cms\\form\\view\\form\\element\\checkboxgroupelementview' => $extPath . 'Classes/View/Form/Element/CheckboxGroupElementView.php',
-       'typo3\\cms\\form\\view\\form\\element\\radiogroupelementview' => $extPath . 'Classes/View/Form/Element/RadioGroupElementView.php',
-       'typo3\\cms\\form\\view\\mail\\html\\element\\checkboxgroupelementview' => $extPath . 'Classes/View/Mail/Html/Element/CheckboxGroupElementView.php',
-       'typo3\\cms\\form\\view\\mail\\html\\element\\radiogroupelementview' => $extPath . 'Classes/View/Mail/Html/Element/RadioGroupElementView.php',
-       'typo3\\cms\\form\\view\\mail\\plain\\element\\checkboxgroupelementview' => $extPath . 'Classes/View/Mail/Plain/Element/CheckboxGroupElementView.php',
-       'typo3\\cms\\form\\view\\mail\\plain\\element\\radiogroupelementview' => $extPath . 'Classes/View/Mail/Plain/Element/RadioGroupElementView.php',
-);
index fe63b07..ce963de 100644 (file)
@@ -419,8 +419,8 @@ class AbstractController {
 
                $cacheConfigurationsWithCachesSetToNullBackend = array();
                foreach ($cacheConfigurations as $cacheName => $cacheConfiguration) {
 
                $cacheConfigurationsWithCachesSetToNullBackend = array();
                foreach ($cacheConfigurations as $cacheName => $cacheConfiguration) {
-                       // cache_core and cache_classes are handled in bootstrap already
-                       if (is_array($cacheConfiguration) && $cacheName !== 'cache_core' && $cacheName !== 'cache_classes') {
+                       // cache_core is handled in bootstrap already
+                       if (is_array($cacheConfiguration) && $cacheName !== 'cache_core') {
                                $cacheConfiguration['backend'] = NullBackend::class;
                                $cacheConfiguration['options'] = array();
                        }
                                $cacheConfiguration['backend'] = NullBackend::class;
                                $cacheConfiguration['options'] = array();
                        }
index 6169668..b39378e 100644 (file)
@@ -246,6 +246,7 @@ abstract class AbstractAction implements ActionInterface {
         */
        protected function loadExtLocalconfDatabaseAndExtTables() {
                \TYPO3\CMS\Core\Core\Bootstrap::getInstance()
         */
        protected function loadExtLocalconfDatabaseAndExtTables() {
                \TYPO3\CMS\Core\Core\Bootstrap::getInstance()
+                       ->ensureClassLoadingInformationExists()
                        ->loadTypo3LoadedExtAndExtLocalconf(FALSE)
                        ->initializeExceptionHandling()
                        ->defineLoggingAndExceptionConstants()
                        ->loadTypo3LoadedExtAndExtLocalconf(FALSE)
                        ->initializeExceptionHandling()
                        ->defineLoggingAndExceptionConstants()
index 4c120bc..517c794 100644 (file)
@@ -170,7 +170,7 @@ class DatabaseConnect extends AbstractStepAction {
                                // and fed with connect values directly in order to obsolete the bootstrap reload.
                                \TYPO3\CMS\Core\Core\Bootstrap::getInstance()
                                        ->populateLocalConfiguration()
                                // and fed with connect values directly in order to obsolete the bootstrap reload.
                                \TYPO3\CMS\Core\Core\Bootstrap::getInstance()
                                        ->populateLocalConfiguration()
-                                       ->disableCoreAndClassesCache();
+                                       ->disableCoreCache();
                                if ($this->isDbalEnabled()) {
                                        require(ExtensionManagementUtility::extPath('dbal') . 'ext_localconf.php');
                                        \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->setCacheConfigurations($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']);
                                if ($this->isDbalEnabled()) {
                                        require(ExtensionManagementUtility::extPath('dbal') . 'ext_localconf.php');
                                        \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->setCacheConfigurations($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']);
index 73a97aa..7297b5e 100644 (file)
@@ -48,14 +48,11 @@ class ClearCacheService {
                GeneralUtility::rmdir(PATH_site . 'typo3temp/Cache', TRUE);
 
                $bootstrap = \TYPO3\CMS\Core\Core\Bootstrap::getInstance();
                GeneralUtility::rmdir(PATH_site . 'typo3temp/Cache', TRUE);
 
                $bootstrap = \TYPO3\CMS\Core\Core\Bootstrap::getInstance();
-               $bootstrap->unregisterClassLoader();
 
                \TYPO3\CMS\Core\Cache\Cache::flagCachingFrameworkForReinitialization();
 
                $bootstrap
 
                \TYPO3\CMS\Core\Cache\Cache::flagCachingFrameworkForReinitialization();
 
                $bootstrap
-                       ->initializeClassLoader()
                        ->initializeCachingFramework()
                        ->initializeCachingFramework()
-                       ->initializeClassLoaderCaches()
                        ->initializePackageManagement(\TYPO3\CMS\Core\Package\PackageManager::class);
 
                // Get all table names starting with 'cf_' and truncate them
                        ->initializePackageManagement(\TYPO3\CMS\Core\Package\PackageManager::class);
 
                // Get all table names starting with 'cf_' and truncate them
diff --git a/typo3/sysext/rtehtmlarea/ext_autoload.php b/typo3/sysext/rtehtmlarea/ext_autoload.php
deleted file mode 100644 (file)
index 291192e..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-/*
- * Register necessary class names with autoloader
- */
-$rtehtmlareaExtensionPath = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('rtehtmlarea');
-return array(
-       'AccessibilityLinkController' => $rtehtmlareaExtensionPath . 'Classes/Controller/AccessibilityLinkController.php',
-);