[FEATURE] Make autoloader namespace aware
authorAnja Leichsenring <aleichsenring@ab-softlab.de>
Fri, 20 Jul 2012 14:55:02 +0000 (16:55 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Sat, 21 Jul 2012 07:59:13 +0000 (09:59 +0200)
The autoloader will now recognize classnames with fully
qualified namespaces names. So, it is now possible to
autoload a class called '\Tx\ExtensionName\Foo\Bar' that is
located in 'extPath'/Classes/Foo/Bar.php.

Change-Id: I9b3f130ca201eee94b595c2eee6f64e1c9a63e93
Resolves: #39147
Releases: 6.0
Reviewed-on: http://review.typo3.org/12944
Reviewed-by: Helmut Hummel
Tested-by: Helmut Hummel
Reviewed-by: Daniel Lorenz
Tested-by: Daniel Lorenz
Reviewed-by: Christian Kuhn
Tested-by: Christian Kuhn
t3lib/class.t3lib_autoloader.php
tests/Unit/t3lib/class.t3lib_autoloaderTest.php

index e79e66b..f723789 100644 (file)
@@ -173,6 +173,14 @@ class t3lib_autoloader {
         */
        public static function getClassPathByRegistryLookup($className) {
                $classPath = NULL;
+
+                       // To handle namespaced class names, get rid of the first backslash
+                       // and replace the remaining ones with underscore. This will simulate
+                       // a 'usual' "extbase" structure like 'Tx_ExtensionName_Foo_bar'
+               if (strpos($className, '\\') === 0 ) {
+                       $className = str_replace('\\', '_', ltrim($className, '\\'));
+               }
+
                $classNameLower = t3lib_div::strtolower($className);
 
                        // Try to resolve extbase naming scheme if class is not already in cache file
index aeec1bb..8a84b36 100644 (file)
@@ -413,5 +413,63 @@ class t3lib_autoloaderTest extends Tx_Phpunit_TestCase {
                t3lib_autoloader::getClassPathByRegistryLookup('ux_' . $class);
                t3lib_autoloader::unregisterAutoloader();
        }
+
+       /**
+        * @test
+        */
+       public function autoloadFindsClassFileThatRespectsExtbaseNamingSchemeWithNamespace() {
+               $extKey = $this->createFakeExtension();
+               $extPath = PATH_site . 'typo3temp/' . $extKey . '/';
+
+                       // Create a class named \Tx\Extension\Foo123\Bar456
+                       // to find file extension/Classes/Foo123/Bar456.php
+               $pathSegment = 'Foo' . uniqid();
+               $fileName = 'Bar' . uniqid();
+               $namespacedClass = '\Tx\\' . $extKey . '\\' . $pathSegment . '\\' . $fileName;
+
+               $file = $extPath . 'Classes/' . $pathSegment . '/' . $fileName . '.php';
+
+               t3lib_div::mkdir_deep($extPath . 'Classes/' . $pathSegment);
+               file_put_contents(
+                       $file,
+                       '<?php' . LF .
+                               'throw new RuntimeException(\'\', 1342800577);' . LF .
+                       '?>'
+               );
+
+                       // Re-initialize autoloader registry to force it to recognize the new extension
+               t3lib_autoloader::unregisterAutoloader();
+               t3lib_autoloader::registerAutoloader();
+
+                       // Expect the exception of the file to be thrown
+               $this->setExpectedException('RuntimeException', '', 1342800577);
+               t3lib_autoloader::autoload($namespacedClass);
+       }
+
+       /**
+        * @test
+        */
+       public function unregisterAutoloaderWritesClassFileLocationOfClassRespectingExtbaseNamingSchemeWithNamespaceToCacheFile() {
+               $extKey = $this->createFakeExtension();
+               $extPath = PATH_site . 'typo3temp/' . $extKey . '/';
+
+               $pathSegment = 'Foo' . uniqid();
+               $fileName = 'Bar' . uniqid();
+               $namespacedClass = '\Tx\\' . $extKey . '\\' . $pathSegment . '\\' . $fileName;
+               $file = $extPath . 'Classes/' . $pathSegment . '/' . $fileName . '.php';
+
+               t3lib_div::mkdir_deep($extPath . 'Classes/' . $pathSegment);
+               file_put_contents($file, '<?php'.LF . $foo = 'bar;'.LF.'?>');
+
+               $mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove', 'flush', 'flushByTag', 'requireOnce'), array(), '', FALSE);
+               $GLOBALS['typo3CacheManager'] = $this->getMock('t3lib_cache_Manager', array('getCache'));
+               $GLOBALS['typo3CacheManager']->expects($this->any())->method('getCache')->will($this->returnValue($mockCache));
+
+                       // Expect that an entry to the cache is written containing the newly found class
+               $mockCache->expects($this->once())->method('set')->with($this->anything(), $this->stringContains(strtolower($file), $this->anything()));
+
+               t3lib_autoloader::autoload($namespacedClass);
+               t3lib_autoloader::unregisterAutoloader();
+       }
 }
 ?>
\ No newline at end of file