From 0b5f6b9c13f5516c2d16fb938e77c9168a74b76d Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 7 May 2013 22:16:02 +0200 Subject: [PATCH 01/10] Move autoloader to it's own class --- lib/autoloader.php | 65 ++++++++++++++++++++++++++++++++++++++++++++++ lib/base.php | 62 +++++-------------------------------------- 2 files changed, 71 insertions(+), 56 deletions(-) create mode 100644 lib/autoloader.php diff --git a/lib/autoloader.php b/lib/autoloader.php new file mode 100644 index 00000000000..27052e60a79 --- /dev/null +++ b/lib/autoloader.php @@ -0,0 +1,65 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC; + +class Autoloader { + public function load($class) { + $class = trim($class, '\\'); + + if (array_key_exists($class, \OC::$CLASSPATH)) { + $path = \OC::$CLASSPATH[$class]; + /** @TODO: Remove this when necessary + Remove "apps/" from inclusion path for smooth migration to mutli app dir + */ + if (strpos($path, 'apps/') === 0) { + \OC_Log::write('core', 'include path for class "' . $class . '" starts with "apps/"', \OC_Log::DEBUG); + $path = str_replace('apps/', '', $path); + } + } elseif (strpos($class, 'OC_') === 0) { + $path = strtolower(str_replace('_', '/', substr($class, 3)) . '.php'); + } elseif (strpos($class, 'OC\\') === 0) { + $path = strtolower(str_replace('\\', '/', substr($class, 3)) . '.php'); + } elseif (strpos($class, 'OCP\\') === 0) { + $path = 'public/' . strtolower(str_replace('\\', '/', substr($class, 3)) . '.php'); + } elseif (strpos($class, 'OCA\\') === 0) { + foreach (\OC::$APPSROOTS as $appDir) { + $path = strtolower(str_replace('\\', '/', substr($class, 4)) . '.php'); + $fullPath = stream_resolve_include_path($appDir['path'] . '/' . $path); + if (file_exists($fullPath)) { + require_once $fullPath; + return false; + } + // If not found in the root of the app directory, insert '/lib' after app id and try again. + $libpath = substr($path, 0, strpos($path, '/')) . '/lib' . substr($path, strpos($path, '/')); + $fullPath = stream_resolve_include_path($appDir['path'] . '/' . $libpath); + if (file_exists($fullPath)) { + require_once $fullPath; + return false; + } + } + } elseif (strpos($class, 'Sabre_') === 0) { + $path = str_replace('_', '/', $class) . '.php'; + } elseif (strpos($class, 'Symfony\\Component\\Routing\\') === 0) { + $path = 'symfony/routing/' . str_replace('\\', '/', $class) . '.php'; + } elseif (strpos($class, 'Sabre\\VObject') === 0) { + $path = str_replace('\\', '/', $class) . '.php'; + } elseif (strpos($class, 'Test_') === 0) { + $path = 'tests/lib/' . strtolower(str_replace('_', '/', substr($class, 5)) . '.php'); + } elseif (strpos($class, 'Test\\') === 0) { + $path = 'tests/lib/' . strtolower(str_replace('\\', '/', substr($class, 5)) . '.php'); + } else { + return false; + } + + if ($fullPath = stream_resolve_include_path($path)) { + require_once $fullPath; + } + return false; + } +} diff --git a/lib/base.php b/lib/base.php index 8633ae9b637..eb3bd410d3b 100644 --- a/lib/base.php +++ b/lib/base.php @@ -75,61 +75,9 @@ class OC { protected static $router = null; /** - * SPL autoload + * @var \OC\Autoloader $loader */ - public static function autoload($className) { - $className = trim($className, '\\'); - - if (array_key_exists($className, OC::$CLASSPATH)) { - $path = OC::$CLASSPATH[$className]; - /** @TODO: Remove this when necessary - Remove "apps/" from inclusion path for smooth migration to mutli app dir - */ - if (strpos($path, 'apps/') === 0) { - OC_Log::write('core', 'include path for class "' . $className . '" starts with "apps/"', OC_Log::DEBUG); - $path = str_replace('apps/', '', $path); - } - } elseif (strpos($className, 'OC_') === 0) { - $path = strtolower(str_replace('_', '/', substr($className, 3)) . '.php'); - } elseif (strpos($className, 'OC\\') === 0) { - $path = strtolower(str_replace('\\', '/', substr($className, 3)) . '.php'); - } elseif (strpos($className, 'OCP\\') === 0) { - $path = 'public/' . strtolower(str_replace('\\', '/', substr($className, 3)) . '.php'); - } elseif (strpos($className, 'OCA\\') === 0) { - foreach (self::$APPSROOTS as $appDir) { - $path = strtolower(str_replace('\\', '/', substr($className, 4)) . '.php'); - $fullPath = stream_resolve_include_path($appDir['path'] . '/' . $path); - if (file_exists($fullPath)) { - require_once $fullPath; - return false; - } - // If not found in the root of the app directory, insert '/lib' after app id and try again. - $libpath = substr($path, 0, strpos($path, '/')) . '/lib' . substr($path, strpos($path, '/')); - $fullPath = stream_resolve_include_path($appDir['path'] . '/' . $libpath); - if (file_exists($fullPath)) { - require_once $fullPath; - return false; - } - } - } elseif (strpos($className, 'Sabre_') === 0) { - $path = str_replace('_', '/', $className) . '.php'; - } elseif (strpos($className, 'Symfony\\Component\\Routing\\') === 0) { - $path = 'symfony/routing/' . str_replace('\\', '/', $className) . '.php'; - } elseif (strpos($className, 'Sabre\\VObject') === 0) { - $path = str_replace('\\', '/', $className) . '.php'; - } elseif (strpos($className, 'Test_') === 0) { - $path = 'tests/lib/' . strtolower(str_replace('_', '/', substr($className, 5)) . '.php'); - } elseif (strpos($className, 'Test\\') === 0) { - $path = 'tests/lib/' . strtolower(str_replace('\\', '/', substr($className, 5)) . '.php'); - } else { - return false; - } - - if ($fullPath = stream_resolve_include_path($path)) { - require_once $fullPath; - } - return false; - } + public static $loader = null; public static function initPaths() { // calculate the root directories @@ -396,7 +344,9 @@ class OC { public static function init() { // register autoloader - spl_autoload_register(array('OC', 'autoload')); + require_once 'autoloader.php'; + self::$loader=new \OC\Autoloader(); + spl_autoload_register(array(self::$loader, 'load')); OC_Util::issetlocaleworking(); // set some stuff @@ -643,7 +593,7 @@ class OC { // Deny the redirect if the URL contains a @ // This prevents unvalidated redirects like ?redirect_url=:user@domain.com - if (strpos($location, '@') === FALSE) { + if (strpos($location, '@') === false) { header('Location: ' . $location); return; } From 19cfe74bf5d74c6f761513baf60da9ef7945f30e Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 7 May 2013 22:19:00 +0200 Subject: [PATCH 02/10] Add per-autoloader classPath --- lib/autoloader.php | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/lib/autoloader.php b/lib/autoloader.php index 27052e60a79..091c4de9674 100644 --- a/lib/autoloader.php +++ b/lib/autoloader.php @@ -9,13 +9,34 @@ namespace OC; class Autoloader { + private $classPaths = array(); + + /** + * Add a custom classpath to the autoloader + * + * @param string $class + * @param string $path + */ + public function registerClass($class, $path) { + $this->classPaths[$class] = $path; + } + + /** + * Load the specified class + * + * @param string $class + * @return bool + */ public function load($class) { $class = trim($class, '\\'); - if (array_key_exists($class, \OC::$CLASSPATH)) { + if (array_key_exists($class, $this->classPaths)) { + $path = $this->classPaths[$class]; + } else if (array_key_exists($class, \OC::$CLASSPATH)) { $path = \OC::$CLASSPATH[$class]; - /** @TODO: Remove this when necessary - Remove "apps/" from inclusion path for smooth migration to mutli app dir + /** + * @TODO: Remove this when necessary + * Remove "apps/" from inclusion path for smooth migration to mutli app dir */ if (strpos($path, 'apps/') === 0) { \OC_Log::write('core', 'include path for class "' . $class . '" starts with "apps/"', \OC_Log::DEBUG); From d1fcb7eb5237d597a878e5f7b61693e7dee29ca8 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 7 May 2013 22:21:59 +0200 Subject: [PATCH 03/10] Allow the autoloader to try mutliple possible paths for each path --- lib/autoloader.php | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/lib/autoloader.php b/lib/autoloader.php index 091c4de9674..9547ddc7d91 100644 --- a/lib/autoloader.php +++ b/lib/autoloader.php @@ -30,10 +30,11 @@ class Autoloader { public function load($class) { $class = trim($class, '\\'); + $paths = array(); if (array_key_exists($class, $this->classPaths)) { - $path = $this->classPaths[$class]; + $paths[] = $this->classPaths[$class]; } else if (array_key_exists($class, \OC::$CLASSPATH)) { - $path = \OC::$CLASSPATH[$class]; + $paths[] = \OC::$CLASSPATH[$class]; /** * @TODO: Remove this when necessary * Remove "apps/" from inclusion path for smooth migration to mutli app dir @@ -43,43 +44,35 @@ class Autoloader { $path = str_replace('apps/', '', $path); } } elseif (strpos($class, 'OC_') === 0) { - $path = strtolower(str_replace('_', '/', substr($class, 3)) . '.php'); + $paths[] = strtolower(str_replace('_', '/', substr($class, 3)) . '.php'); } elseif (strpos($class, 'OC\\') === 0) { - $path = strtolower(str_replace('\\', '/', substr($class, 3)) . '.php'); + $paths[] = strtolower(str_replace('\\', '/', substr($class, 3)) . '.php'); } elseif (strpos($class, 'OCP\\') === 0) { - $path = 'public/' . strtolower(str_replace('\\', '/', substr($class, 3)) . '.php'); + $paths[] = 'public/' . strtolower(str_replace('\\', '/', substr($class, 3)) . '.php'); } elseif (strpos($class, 'OCA\\') === 0) { foreach (\OC::$APPSROOTS as $appDir) { - $path = strtolower(str_replace('\\', '/', substr($class, 4)) . '.php'); - $fullPath = stream_resolve_include_path($appDir['path'] . '/' . $path); - if (file_exists($fullPath)) { - require_once $fullPath; - return false; - } + $paths[] = $appDir['path'] . '/' . strtolower(str_replace('\\', '/', substr($class, 4)) . '.php'); // If not found in the root of the app directory, insert '/lib' after app id and try again. - $libpath = substr($path, 0, strpos($path, '/')) . '/lib' . substr($path, strpos($path, '/')); - $fullPath = stream_resolve_include_path($appDir['path'] . '/' . $libpath); - if (file_exists($fullPath)) { - require_once $fullPath; - return false; - } + $paths[] = $appDir['path'] . '/lib/' . strtolower(str_replace('\\', '/', substr($class, 4)) . '.php'); } } elseif (strpos($class, 'Sabre_') === 0) { - $path = str_replace('_', '/', $class) . '.php'; + $paths[] = str_replace('_', '/', $class) . '.php'; } elseif (strpos($class, 'Symfony\\Component\\Routing\\') === 0) { - $path = 'symfony/routing/' . str_replace('\\', '/', $class) . '.php'; + $paths[] = 'symfony/routing/' . str_replace('\\', '/', $class) . '.php'; } elseif (strpos($class, 'Sabre\\VObject') === 0) { - $path = str_replace('\\', '/', $class) . '.php'; + $paths[] = str_replace('\\', '/', $class) . '.php'; } elseif (strpos($class, 'Test_') === 0) { - $path = 'tests/lib/' . strtolower(str_replace('_', '/', substr($class, 5)) . '.php'); + $paths[] = 'tests/lib/' . strtolower(str_replace('_', '/', substr($class, 5)) . '.php'); } elseif (strpos($class, 'Test\\') === 0) { - $path = 'tests/lib/' . strtolower(str_replace('\\', '/', substr($class, 5)) . '.php'); + $paths[] = 'tests/lib/' . strtolower(str_replace('\\', '/', substr($class, 5)) . '.php'); } else { return false; } - if ($fullPath = stream_resolve_include_path($path)) { - require_once $fullPath; + foreach ($paths as $path) { + if ($fullPath = stream_resolve_include_path($path)) { + require_once $fullPath; + } } return false; } From cac86bb4db670e868ae61aef176d229c814452c0 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 7 May 2013 22:24:47 +0200 Subject: [PATCH 04/10] Allow disabling the global classpath in an autoloader --- lib/autoloader.php | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/autoloader.php b/lib/autoloader.php index 9547ddc7d91..94c0ac7cb5d 100644 --- a/lib/autoloader.php +++ b/lib/autoloader.php @@ -9,6 +9,8 @@ namespace OC; class Autoloader { + private $useGlobalClassPath = true; + private $classPaths = array(); /** @@ -21,6 +23,20 @@ class Autoloader { $this->classPaths[$class] = $path; } + /** + * disable the usage of the global classpath \OC::$CLASSPATH + */ + public function disableGlobalClassPath() { + $this->useGlobalClassPath = false; + } + + /** + * enable the usage of the global classpath \OC::$CLASSPATH + */ + public function enableGlobalClassPath() { + $this->useGlobalClassPath = true; + } + /** * Load the specified class * @@ -33,15 +49,15 @@ class Autoloader { $paths = array(); if (array_key_exists($class, $this->classPaths)) { $paths[] = $this->classPaths[$class]; - } else if (array_key_exists($class, \OC::$CLASSPATH)) { + } else if ($this->useGlobalClassPath and array_key_exists($class, \OC::$CLASSPATH)) { $paths[] = \OC::$CLASSPATH[$class]; /** * @TODO: Remove this when necessary * Remove "apps/" from inclusion path for smooth migration to mutli app dir */ - if (strpos($path, 'apps/') === 0) { + if (strpos(\OC::$CLASSPATH[$class], 'apps/') === 0) { \OC_Log::write('core', 'include path for class "' . $class . '" starts with "apps/"', \OC_Log::DEBUG); - $path = str_replace('apps/', '', $path); + $path = str_replace('apps/', '', \OC::$CLASSPATH[$class]); } } elseif (strpos($class, 'OC_') === 0) { $paths[] = strtolower(str_replace('_', '/', substr($class, 3)) . '.php'); From 72ed74f28acc9f7897e1591e1d7f6e4e28e8b107 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 7 May 2013 22:26:55 +0200 Subject: [PATCH 05/10] Autoloader: split getting the class paths and loading the class --- lib/autoloader.php | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/lib/autoloader.php b/lib/autoloader.php index 94c0ac7cb5d..95b73fe8903 100644 --- a/lib/autoloader.php +++ b/lib/autoloader.php @@ -38,12 +38,12 @@ class Autoloader { } /** - * Load the specified class + * get the possible paths for a class * * @param string $class - * @return bool + * @return array|bool an array of possible paths or false if the class is not part of ownCloud */ - public function load($class) { + public function findClass($class) { $class = trim($class, '\\'); $paths = array(); @@ -57,7 +57,7 @@ class Autoloader { */ if (strpos(\OC::$CLASSPATH[$class], 'apps/') === 0) { \OC_Log::write('core', 'include path for class "' . $class . '" starts with "apps/"', \OC_Log::DEBUG); - $path = str_replace('apps/', '', \OC::$CLASSPATH[$class]); + $paths[] = str_replace('apps/', '', \OC::$CLASSPATH[$class]); } } elseif (strpos($class, 'OC_') === 0) { $paths[] = strtolower(str_replace('_', '/', substr($class, 3)) . '.php'); @@ -84,10 +84,23 @@ class Autoloader { } else { return false; } + return $paths; + } + + /** + * Load the specified class + * + * @param string $class + * @return bool + */ + public function load($class) { + $paths = $this->findClass($class); - foreach ($paths as $path) { - if ($fullPath = stream_resolve_include_path($path)) { - require_once $fullPath; + if (is_array($paths)) { + foreach ($paths as $path) { + if ($fullPath = stream_resolve_include_path($path)) { + require_once $fullPath; + } } } return false; From 6d903cf7ae30ef3b9fb9faa34ee8b8347ac47e93 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 7 May 2013 22:39:35 +0200 Subject: [PATCH 06/10] Autoloader: add support for custom namespace paths --- lib/autoloader.php | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/autoloader.php b/lib/autoloader.php index 95b73fe8903..976ec6b1a87 100644 --- a/lib/autoloader.php +++ b/lib/autoloader.php @@ -11,8 +11,20 @@ namespace OC; class Autoloader { private $useGlobalClassPath = true; + private $namespacePaths = array(); + private $classPaths = array(); + /** + * Add a custom namespace to the autoloader + * + * @param string $namespace + * @param string $path + */ + public function registerNamespace($namespace, $path) { + $this->namespacePaths[$namespace] = $path; + } + /** * Add a custom classpath to the autoloader * @@ -60,6 +72,8 @@ class Autoloader { $paths[] = str_replace('apps/', '', \OC::$CLASSPATH[$class]); } } elseif (strpos($class, 'OC_') === 0) { + // first check for legacy classes if underscores are used + $paths[] = 'legacy/' . strtolower(str_replace('_', '/', substr($class, 3)) . '.php'); $paths[] = strtolower(str_replace('_', '/', substr($class, 3)) . '.php'); } elseif (strpos($class, 'OC\\') === 0) { $paths[] = strtolower(str_replace('\\', '/', substr($class, 3)) . '.php'); @@ -82,7 +96,11 @@ class Autoloader { } elseif (strpos($class, 'Test\\') === 0) { $paths[] = 'tests/lib/' . strtolower(str_replace('\\', '/', substr($class, 5)) . '.php'); } else { - return false; + foreach ($this->namespacePaths as $namespace => $dir) { + if (0 === strpos($class, $namespace)) { + $paths[] = $dir . '/' . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php'; + } + } } return $paths; } From 0d25c0001ca276c3262476ebadcaba4f33bcd54a Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 7 May 2013 22:53:07 +0200 Subject: [PATCH 07/10] check for setlocale after setting up the paths to prevent autoloader confusion --- lib/base.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/base.php b/lib/base.php index eb3bd410d3b..667202d3aef 100644 --- a/lib/base.php +++ b/lib/base.php @@ -344,10 +344,14 @@ class OC { public static function init() { // register autoloader - require_once 'autoloader.php'; + require_once __DIR__ . '/autoloader.php'; self::$loader=new \OC\Autoloader(); + self::$loader->registerPrefix('Doctrine\\Common', 'doctrine/common/lib'); + self::$loader->registerPrefix('Doctrine\\DBAL', 'doctrine/dbal/lib'); + self::$loader->registerPrefix('Symfony\\Component\\Routing', 'symfony/routing'); + self::$loader->registerPrefix('Sabre\\VObject', '3rdparty'); + self::$loader->registerPrefix('Sabre_', '3rdparty'); spl_autoload_register(array(self::$loader, 'load')); - OC_Util::issetlocaleworking(); // set some stuff //ob_start(); @@ -404,6 +408,7 @@ class OC { } self::initPaths(); + OC_Util::issetlocaleworking(); // set debug mode if an xdebug session is active if (!defined('DEBUG') || !DEBUG) { From 2a01d3994080756316017e34b8c46c773332283f Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 7 May 2013 23:07:47 +0200 Subject: [PATCH 08/10] Autoloader: load the 3rdparty libraries using prefixes --- lib/autoloader.php | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/lib/autoloader.php b/lib/autoloader.php index 976ec6b1a87..d84924d5969 100644 --- a/lib/autoloader.php +++ b/lib/autoloader.php @@ -11,18 +11,18 @@ namespace OC; class Autoloader { private $useGlobalClassPath = true; - private $namespacePaths = array(); + private $prefixPaths = array(); private $classPaths = array(); /** - * Add a custom namespace to the autoloader + * Add a custom prefix to the autoloader * - * @param string $namespace + * @param string $prefix * @param string $path */ - public function registerNamespace($namespace, $path) { - $this->namespacePaths[$namespace] = $path; + public function registerPrefix($prefix, $path) { + $this->prefixPaths[$prefix] = $path; } /** @@ -81,24 +81,23 @@ class Autoloader { $paths[] = 'public/' . strtolower(str_replace('\\', '/', substr($class, 3)) . '.php'); } elseif (strpos($class, 'OCA\\') === 0) { foreach (\OC::$APPSROOTS as $appDir) { - $paths[] = $appDir['path'] . '/' . strtolower(str_replace('\\', '/', substr($class, 4)) . '.php'); - // If not found in the root of the app directory, insert '/lib' after app id and try again. - $paths[] = $appDir['path'] . '/lib/' . strtolower(str_replace('\\', '/', substr($class, 4)) . '.php'); + list(, $app,) = explode('\\', $class); + if (stream_resolve_include_path($appDir['path'] . '/' . strtolower($app))) { + $paths[] = $appDir['path'] . '/' . strtolower(str_replace('\\', '/', substr($class, 4)) . '.php'); + // If not found in the root of the app directory, insert '/lib' after app id and try again. + $paths[] = $appDir['path'] . '/lib/' . strtolower(str_replace('\\', '/', substr($class, 4)) . '.php'); + } } - } elseif (strpos($class, 'Sabre_') === 0) { - $paths[] = str_replace('_', '/', $class) . '.php'; - } elseif (strpos($class, 'Symfony\\Component\\Routing\\') === 0) { - $paths[] = 'symfony/routing/' . str_replace('\\', '/', $class) . '.php'; - } elseif (strpos($class, 'Sabre\\VObject') === 0) { - $paths[] = str_replace('\\', '/', $class) . '.php'; } elseif (strpos($class, 'Test_') === 0) { $paths[] = 'tests/lib/' . strtolower(str_replace('_', '/', substr($class, 5)) . '.php'); } elseif (strpos($class, 'Test\\') === 0) { $paths[] = 'tests/lib/' . strtolower(str_replace('\\', '/', substr($class, 5)) . '.php'); } else { - foreach ($this->namespacePaths as $namespace => $dir) { - if (0 === strpos($class, $namespace)) { - $paths[] = $dir . '/' . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php'; + foreach ($this->prefixPaths as $prefix => $dir) { + if (0 === strpos($class, $prefix)) { + $path = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php'; + $path = str_replace('_', DIRECTORY_SEPARATOR, $path); + $paths[] = $dir . '/' . $path; } } } From e21a3a1a2324684f2e34bce024082d7d1d244b6a Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 7 May 2013 23:08:36 +0200 Subject: [PATCH 09/10] Autoloader: test cases --- tests/lib/autoloader.php | 58 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/tests/lib/autoloader.php b/tests/lib/autoloader.php index e769bf3bcf6..d9fc016adf5 100644 --- a/tests/lib/autoloader.php +++ b/tests/lib/autoloader.php @@ -6,14 +6,62 @@ * See the COPYING-README file. */ -class Test_AutoLoader extends PHPUnit_Framework_TestCase { +namespace Test; - public function testLeadingSlashOnClassName(){ - $this->assertTrue(class_exists('\OC\Files\Storage\Local')); +class AutoLoader extends \PHPUnit_Framework_TestCase { + /** + * @var \OC\Autoloader $loader + */ + private $loader; + + public function setUp() { + $this->loader = new \OC\AutoLoader(); + } + + public function testLeadingSlashOnClassName() { + $this->assertEquals(array('files/storage/local.php'), $this->loader->findClass('\OC\Files\Storage\Local')); + } + + public function testNoLeadingSlashOnClassName() { + $this->assertEquals(array('files/storage/local.php'), $this->loader->findClass('OC\Files\Storage\Local')); + } + + public function testLegacyPath() { + $this->assertEquals(array('legacy/files.php', 'files.php'), $this->loader->findClass('OC_Files')); + } + + public function testClassPath() { + $this->loader->registerClass('Foo\Bar', 'foobar.php'); + $this->assertEquals(array('foobar.php'), $this->loader->findClass('Foo\Bar')); + } + + public function testPrefixNamespace() { + $this->loader->registerPrefix('Foo', 'foo'); + $this->assertEquals(array('foo/Foo/Bar.php'), $this->loader->findClass('Foo\Bar')); + } + + public function testPrefix() { + $this->loader->registerPrefix('Foo_', 'foo'); + $this->assertEquals(array('foo/Foo/Bar.php'), $this->loader->findClass('Foo_Bar')); + } + + public function loadTestNamespace() { + $this->assertEquals(array('test/foo/bar.php'), $this->loader->findClass('Test\Foo\Bar')); } - public function testNoLeadingSlashOnClassName(){ - $this->assertTrue(class_exists('OC\Files\Storage\Local')); + public function loadTest() { + $this->assertEquals(array('test/foo/bar.php'), $this->loader->findClass('Test_Foo_Bar')); } + public function loadCoreNamespace() { + $this->assertEquals(array('lib/foo/bar.php'), $this->loader->findClass('OC\Foo\Bar')); + } + + public function loadCore() { + $this->assertEquals(array('lib/legacy/foo/bar.php', 'lib/foo/bar.php'), $this->loader->findClass('OC_Foo_Bar')); + } + + public function loadPublicNamespace() { + $this->assertEquals(array('lib/public/foo/bar.php'), $this->loader->findClass('OCP\Foo\Bar')); + } } From 71fc4a2cf4b5eaabdf44fae0fffe73690eb506dd Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 8 May 2013 00:50:33 +0200 Subject: [PATCH 10/10] Autoloader: fix loading app clases located in lib/ --- lib/autoloader.php | 11 ++++++----- tests/lib/autoloader.php | 27 +++++++++++++++++---------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/lib/autoloader.php b/lib/autoloader.php index d84924d5969..9615838a9a2 100644 --- a/lib/autoloader.php +++ b/lib/autoloader.php @@ -78,14 +78,15 @@ class Autoloader { } elseif (strpos($class, 'OC\\') === 0) { $paths[] = strtolower(str_replace('\\', '/', substr($class, 3)) . '.php'); } elseif (strpos($class, 'OCP\\') === 0) { - $paths[] = 'public/' . strtolower(str_replace('\\', '/', substr($class, 3)) . '.php'); + $paths[] = 'public/' . strtolower(str_replace('\\', '/', substr($class, 4)) . '.php'); } elseif (strpos($class, 'OCA\\') === 0) { + list(, $app, $rest) = explode('\\', $class, 3); + $app = strtolower($app); foreach (\OC::$APPSROOTS as $appDir) { - list(, $app,) = explode('\\', $class); - if (stream_resolve_include_path($appDir['path'] . '/' . strtolower($app))) { - $paths[] = $appDir['path'] . '/' . strtolower(str_replace('\\', '/', substr($class, 4)) . '.php'); + if (stream_resolve_include_path($appDir['path'] . '/' . $app)) { + $paths[] = $appDir['path'] . '/' . $app . '/' . strtolower(str_replace('\\', '/', $rest) . '.php'); // If not found in the root of the app directory, insert '/lib' after app id and try again. - $paths[] = $appDir['path'] . '/lib/' . strtolower(str_replace('\\', '/', substr($class, 4)) . '.php'); + $paths[] = $appDir['path'] . '/' . $app . '/lib/' . strtolower(str_replace('\\', '/', $rest) . '.php'); } } } elseif (strpos($class, 'Test_') === 0) { diff --git a/tests/lib/autoloader.php b/tests/lib/autoloader.php index d9fc016adf5..0e7d606ccf6 100644 --- a/tests/lib/autoloader.php +++ b/tests/lib/autoloader.php @@ -45,23 +45,30 @@ class AutoLoader extends \PHPUnit_Framework_TestCase { $this->assertEquals(array('foo/Foo/Bar.php'), $this->loader->findClass('Foo_Bar')); } - public function loadTestNamespace() { - $this->assertEquals(array('test/foo/bar.php'), $this->loader->findClass('Test\Foo\Bar')); + public function testLoadTestNamespace() { + $this->assertEquals(array('tests/lib/foo/bar.php'), $this->loader->findClass('Test\Foo\Bar')); } - public function loadTest() { - $this->assertEquals(array('test/foo/bar.php'), $this->loader->findClass('Test_Foo_Bar')); + public function testLoadTest() { + $this->assertEquals(array('tests/lib/foo/bar.php'), $this->loader->findClass('Test_Foo_Bar')); } - public function loadCoreNamespace() { - $this->assertEquals(array('lib/foo/bar.php'), $this->loader->findClass('OC\Foo\Bar')); + public function testLoadCoreNamespace() { + $this->assertEquals(array('foo/bar.php'), $this->loader->findClass('OC\Foo\Bar')); } - public function loadCore() { - $this->assertEquals(array('lib/legacy/foo/bar.php', 'lib/foo/bar.php'), $this->loader->findClass('OC_Foo_Bar')); + public function testLoadCore() { + $this->assertEquals(array('legacy/foo/bar.php', 'foo/bar.php'), $this->loader->findClass('OC_Foo_Bar')); } - public function loadPublicNamespace() { - $this->assertEquals(array('lib/public/foo/bar.php'), $this->loader->findClass('OCP\Foo\Bar')); + public function testLoadPublicNamespace() { + $this->assertEquals(array('public/foo/bar.php'), $this->loader->findClass('OCP\Foo\Bar')); + } + + public function testLoadAppNamespace() { + $result = $this->loader->findClass('OCA\Files\Foobar'); + $this->assertEquals(2, count($result)); + $this->assertStringEndsWith('apps/files/foobar.php', $result[0]); + $this->assertStringEndsWith('apps/files/lib/foobar.php', $result[1]); } }