[BUGFIX] Cleanup and simplify class alias handling 36/27236/5
authorHelmut Hummel <helmut.hummel@typo3.org>
Sat, 1 Feb 2014 15:24:16 +0000 (16:24 +0100)
committerHelmut Hummel <helmut.hummel@typo3.org>
Sat, 1 Feb 2014 21:42:16 +0000 (22:42 +0100)
There were several issues with the implementation
of class alias handling. Most importantly the
early instance alias cache depended on TYPO3_MODE
which in turn triggered a full class cache
initialization when this cache was missing in one
context.

Additionally eval() calls needed to be used in
certain situations and the building of the cache
files introduced additional complexity.

With this change the cache for early instances
is completely removed and replaced by a simple
setAliasFoClassName() call.

Resolves: #55559
Releases: 6.2
Change-Id: I59958419f28a4ff1d6de4add94ee611b56070068
Reviewed-on: https://review.typo3.org/27236
Reviewed-by: Andreas Wolf
Tested-by: Andreas Wolf
Reviewed-by: Marcin SÄ…gol
Reviewed-by: Anja Leichsenring
Tested-by: Anja Leichsenring
Reviewed-by: Helmut Hummel
Tested-by: Helmut Hummel
typo3/sysext/core/Classes/Core/ClassAliasMap.php
typo3/sysext/core/Classes/Core/ClassLoader.php

index 05bdac1..a7ef225 100644 (file)
@@ -60,11 +60,6 @@ class ClassAliasMap implements \TYPO3\CMS\Core\SingletonInterface {
         */
        protected $classLoader;
 
-       /**
-        * @var string Cache identifier
-        */
-       protected $cacheIdentifier;
-
        /**
         * @var \TYPO3\Flow\Package\Package[]
         */
@@ -91,34 +86,6 @@ class ClassAliasMap implements \TYPO3\CMS\Core\SingletonInterface {
                $this->classLoader = $classLoader;
        }
 
-       /**
-        * @return string
-        */
-       protected function getCacheIdentifier() {
-               return $this->cacheIdentifier;
-       }
-
-       /**
-        * Set cache identifier
-        *
-        * @param string $cacheIdentifier
-        * @return ClassAliasMap
-        */
-       public function setCacheIdentifier($cacheIdentifier) {
-               $this->cacheIdentifier = $cacheIdentifier;
-               return $this;
-       }
-
-       /**
-        * Get cache identifier
-        *
-        * @return string
-        */
-       protected function getCacheEntryIdentifier() {
-               $cacheIdentifier = $this->getCacheIdentifier();
-               return $cacheIdentifier !== NULL ? 'ClassAliasMap_' . TYPO3_MODE  . '_' . $cacheIdentifier : NULL;
-       }
-
        /**
         * Set packages
         *
@@ -130,51 +97,36 @@ class ClassAliasMap implements \TYPO3\CMS\Core\SingletonInterface {
                return $this;
        }
 
-       /**
-        * Load early instance mapping
-        *
-        * @return boolean
-        */
-       public function loadEarlyInstanceMappingFromCache() {
-               $cacheEntryIdentifier = $this->getCacheEntryIdentifier();
-               if (!$cacheEntryIdentifier !== NULL && $this->coreCache->has($cacheEntryIdentifier)) {
-                       return (boolean)$this->coreCache->requireOnce($cacheEntryIdentifier);
-               }
-               return FALSE;
-       }
-
        /**
         * Build mapping for early instances
         *
         * @return array
         */
        public function buildMappingAndInitializeEarlyInstanceMapping() {
+               // Simple registry to filter class names with different cases
+               $classNameRegistry = array();
+               // Needed for early instance alias mapping
                $aliasToClassNameMapping = array();
-               foreach ($this->packages as $package) {
-                       if ($package instanceof \TYPO3\CMS\Core\Package\Package) {
-                               $aliasToClassNameMapping = array_merge($aliasToClassNameMapping, $package->getClassAliases());
-                       }
-               }
-               $lowercasedAliasToClassNameMapping = array();
-               foreach ($aliasToClassNameMapping as $aliasClassName => $className) {
-                       $lowercasedAliasToClassNameMapping[strtolower($aliasClassName)] = $className;
-               }
-               $aliasToClassNameMapping = $lowercasedAliasToClassNameMapping;
+               // Final mapping array
                $classNameToAliasMapping = array();
-               foreach (array_flip($aliasToClassNameMapping) as $className => $aliasClassName) {
-                       $lookUpClassName = strtolower($className);
-                       if (!isset($classNameToAliasMapping[$lookUpClassName])) {
-                               $classNameToAliasMapping[$lookUpClassName] = array();
+               foreach ($this->packages as $package) {
+                       if (!$package instanceof \TYPO3\CMS\Core\Package\Package) {
+                               continue;
                        }
-                       $classNameToAliasMapping[$lookUpClassName][] = $aliasClassName;
-               }
 
-               $this->buildEarlyInstanceMappingAndSaveToCache($aliasToClassNameMapping);
+                       foreach ($package->getClassAliases() as $aliasClassName => $className) {
+                               $lookUpClassName = strtolower($className);
+                               if (isset($classNameRegistry[$lookUpClassName])) {
+                                       continue;
+                               }
 
-               $classNameToAliasMapping = array();
-               foreach ($aliasToClassNameMapping as $aliasClassName => $originalClassName) {
-                       $classNameToAliasMapping[$originalClassName][$aliasClassName] = $aliasClassName;
+                               $classNameRegistry[$lookUpClassName] = TRUE;
+                               $lowercasedAliasClassName = strtolower($aliasClassName);
+                               $aliasToClassNameMapping[$lowercasedAliasClassName] = $className;
+                               $classNameToAliasMapping[$className][$lowercasedAliasClassName] = $lowercasedAliasClassName;
+                       }
                }
+               $this->initializeAndSetAliasesForEarlyInstances($aliasToClassNameMapping);
 
                return $classNameToAliasMapping;
        }
@@ -207,54 +159,15 @@ class ClassAliasMap implements \TYPO3\CMS\Core\SingletonInterface {
         * @param array $aliasToClassNameMapping
         * @return void
         */
-       protected function buildEarlyInstanceMappingAndSaveToCache(array $aliasToClassNameMapping) {
-               $classedLoadedPriorToClassLoader = array_intersect($aliasToClassNameMapping, array_merge(get_declared_classes(), get_declared_interfaces()));
-               if (!empty($classedLoadedPriorToClassLoader)) {
-                       $proxyContent = array($this->buildClassLoaderCommand());
-                       foreach ($classedLoadedPriorToClassLoader as $aliasClassName => $originalClassName) {
-                               $proxyContent[] = $this->buildAliasCommand($aliasClassName, $originalClassName);
-                       }
-                       $cacheEntryIdentifier = $this->getCacheEntryIdentifier();
-                       if ($cacheEntryIdentifier !== NULL) {
-                               $this->coreCache->set($this->getCacheEntryIdentifier(), implode(LF, $proxyContent));
-                               if ($this->coreCache->requireOnce($cacheEntryIdentifier) === NULL) {
-                                       // Just happens on TYPO3\CMS\Core\Cache\Backend\NullBackend, cause we don't get a return value.
-                                       eval(implode(PHP_EOL, $proxyContent));
-                               }
-                       } else {
-                               eval(implode(PHP_EOL, $proxyContent));
-                       }
+       protected function initializeAndSetAliasesForEarlyInstances(array $aliasToClassNameMapping) {
+               $classesLoadedPriorToClassLoader = array_intersect($aliasToClassNameMapping, array_merge(get_declared_classes(), get_declared_interfaces()));
+               if (empty($classesLoadedPriorToClassLoader)) {
+                       return;
                }
-       }
 
-       /**
-        * String command to build class loader
-        *
-        * @return string
-        */
-       protected function buildClassLoaderCommand() {
-               return '$classLoader = \\TYPO3\\CMS\\Core\\Core\\Bootstrap::getInstance()->getEarlyInstance(\'TYPO3\\CMS\\Core\\Core\\ClassLoader\');';
-       }
-
-       /**
-        * String command to build class alias
-        *
-        * @param string $aliasClassName
-        * @param string $originalClassName
-        * @return string
-        */
-       protected function buildAliasCommand($aliasClassName, $originalClassName) {
-               return sprintf('%s->setAliasForClassName(\'%s\', \'%s\');', '$classLoader', $aliasClassName, $originalClassName);
-       }
-
-       /**
-        * Creates a require_once command for the given file.
-        *
-        * @param string $requiredFile
-        * @return string
-        */
-       protected function buildRequireOnceCommand($requiredFile) {
-               return sprintf('require_once \'%s\';', $requiredFile);
+               foreach ($classesLoadedPriorToClassLoader as $aliasClassName => $originalClassName) {
+                       $this->setAliasForClassName($aliasClassName, $originalClassName);
+               }
        }
 
        /**
index 7ac6c6d..88d15f7 100644 (file)
@@ -372,7 +372,6 @@ class ClassLoader {
         */
        public function setCacheIdentifier($cacheIdentifier) {
                $this->cacheIdentifier = $cacheIdentifier;
-               $this->classAliasMap->setCacheIdentifier($cacheIdentifier);
                return $this;
        }
 
@@ -384,7 +383,7 @@ class ClassLoader {
         */
        public function setPackages(array $packages) {
                $this->packages = $packages;
-               if (!$this->loadPackageNamespacesFromCache() || !$this->classAliasMap->loadEarlyInstanceMappingFromCache()) {
+               if (!$this->loadPackageNamespacesFromCache()) {
                        $this->buildPackageNamespacesAndClassesPaths();
                } else {
                        $this->classAliasMap->setPackages($packages);