diff --git a/core/Form/Primitives/PrimitiveClass.class.php b/core/Form/Primitives/PrimitiveClass.class.php index 021e9cf588..409c1ffbbd 100644 --- a/core/Form/Primitives/PrimitiveClass.class.php +++ b/core/Form/Primitives/PrimitiveClass.class.php @@ -51,7 +51,7 @@ public function of($class) Assert::isTrue( class_exists($className, true) || interface_exists($className, true), - "knows nothing about '{$className}' class" + "knows nothing about '{$className}' class/interface" ); $this->ofClassName = $className; diff --git a/doc/ChangeLog b/doc/ChangeLog index c27ed570ad..374360d6b9 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,25 @@ +2012-24-10 Alexey S. Denisov + * global.inc.php.tpl + main/Autoloader/Autoloader.class.php + main/Autoloader/AutoloaderClassNotFound.class.php + main/Autoloader/AutoloaderClassPathCache.class.php + main/Autoloader/AutoloaderNoCache.class.php + main/Autoloader/AutoloaderPool.class.php + main/Autoloader/AutoloaderRecachable.class.php + main/Autoloader/AutoloaderWithNamespace.class.php + main/Autoloader/NamespaceDirScaner.class.php + main/Autoloader/NamespaceDirScanerOnPHP.class.php + main/Autoloader/NamespaceDirScanerPSR0.class.php + main/Autoloader/NamespaceResolver.class.php + main/Autoloader/NamespaceResolverOnPHP.class.php + main/Autoloader/NamespaceResolverPSR0.class.php + main/Autoloader/require.inc.php + meta/bin/build.php + meta/classes/MetaConfiguration.class.php + misc/Autoloader.inc.php + misc/BaseException.inc.php: + New Autoloader which work without include_paths and use optional namespaces + 2012-09-29 Alexey S. Denisov * core/DB/DB.class.php diff --git a/global.inc.php.tpl b/global.inc.php.tpl index 56e75d04d0..6b41db5178 100644 --- a/global.inc.php.tpl +++ b/global.inc.php.tpl @@ -16,15 +16,6 @@ throw new BaseException($string, $code); } - /* void */ function __autoload_failed($classname, $message) - { - eval( - 'if (!class_exists("ClassNotFoundException", false)) { ' - .'final class ClassNotFoundException extends BaseException {/*_*/} }' - .'throw new ClassNotFoundException("'.$classname.': '.$message.'");' - ); - } - // file extensions define('EXT_CLASS', '.class.php'); define('EXT_TPL', '.tpl.html'); @@ -40,20 +31,6 @@ sys_get_temp_dir().DIRECTORY_SEPARATOR.'onPHP'.DIRECTORY_SEPARATOR ); - if (!defined('ONPHP_CLASS_CACHE')) - define('ONPHP_CLASS_CACHE', ONPHP_TEMP_PATH); - - // classes autoload magic - if (!defined('ONPHP_CLASS_CACHE_TYPE')) - define('ONPHP_CLASS_CACHE_TYPE', 'classPathCache'); - - require - dirname(__FILE__).DIRECTORY_SEPARATOR - .'misc'.DIRECTORY_SEPARATOR - .'Autoloader'.EXT_MOD; - - spl_autoload_register(array('Autoloader', ONPHP_CLASS_CACHE_TYPE), false); - // system settings error_reporting(E_ALL | E_STRICT); set_error_handler('error2Exception', E_ALL | E_STRICT); @@ -89,114 +66,125 @@ ONPHP_ROOT_PATH.'incubator'.DIRECTORY_SEPARATOR ); - set_include_path( - // current path - get_include_path().PATH_SEPARATOR - + if (!defined('ONPHP_CLASS_CACHE')) + define('ONPHP_CLASS_CACHE', ONPHP_TEMP_PATH); + + // classes autoload magic + if (!defined('ONPHP_CLASS_CACHE_TYPE')) + define('ONPHP_CLASS_CACHE_TYPE', 'AutoloaderClassPathCache'); + + require ONPHP_MAIN_PATH.'Autoloader'.DIRECTORY_SEPARATOR.'require'.EXT_MOD; + + $autoloader = ONPHP_CLASS_CACHE_TYPE; + AutoloaderPool::set('onPHP', $autoloader = new $autoloader()); + /* @var $autoloader AutoloaderClassPathCache */ + $autoloader->setNamespaceResolver(NamespaceResolverOnPHP::create())->register(); + + $autoloader->addPaths(array( // core classes - .ONPHP_CORE_PATH.'Base' .PATH_SEPARATOR - .ONPHP_CORE_PATH.'Cache' .PATH_SEPARATOR + ONPHP_CORE_PATH.'Base' , + ONPHP_CORE_PATH.'Cache' , - .ONPHP_CORE_PATH.'DB' .PATH_SEPARATOR - .ONPHP_CORE_PATH.'DB'.DIRECTORY_SEPARATOR.'Transaction'.PATH_SEPARATOR - .ONPHP_CORE_PATH.'DB'.DIRECTORY_SEPARATOR.'NoSQL'.PATH_SEPARATOR + ONPHP_CORE_PATH.'DB' , + ONPHP_CORE_PATH.'DB'.DIRECTORY_SEPARATOR.'Transaction', + ONPHP_CORE_PATH.'DB'.DIRECTORY_SEPARATOR.'NoSQL', - .ONPHP_CORE_PATH.'Exceptions' .PATH_SEPARATOR + ONPHP_CORE_PATH.'Exceptions' , - .ONPHP_CORE_PATH.'Form' .PATH_SEPARATOR - .ONPHP_CORE_PATH.'Form'.DIRECTORY_SEPARATOR.'Filters'.PATH_SEPARATOR - .ONPHP_CORE_PATH.'Form'.DIRECTORY_SEPARATOR.'Primitives'.PATH_SEPARATOR + ONPHP_CORE_PATH.'Form' , + ONPHP_CORE_PATH.'Form'.DIRECTORY_SEPARATOR.'Filters', + ONPHP_CORE_PATH.'Form'.DIRECTORY_SEPARATOR.'Primitives', - .ONPHP_CORE_PATH.'Logic' .PATH_SEPARATOR - .ONPHP_CORE_PATH.'OSQL' .PATH_SEPARATOR + ONPHP_CORE_PATH.'Logic' , + ONPHP_CORE_PATH.'OSQL' , // main framework - .ONPHP_MAIN_PATH.'Base' .PATH_SEPARATOR + ONPHP_MAIN_PATH.'Base' , - .ONPHP_MAIN_PATH.'Criteria' .PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Criteria'.DIRECTORY_SEPARATOR.'Projections'.PATH_SEPARATOR + ONPHP_MAIN_PATH.'Criteria' , + ONPHP_MAIN_PATH.'Criteria'.DIRECTORY_SEPARATOR.'Projections', - .ONPHP_MAIN_PATH.'Crypto' .PATH_SEPARATOR + ONPHP_MAIN_PATH.'Crypto' , - .ONPHP_MAIN_PATH.'DAOs' .PATH_SEPARATOR - .ONPHP_MAIN_PATH.'DAOs'.DIRECTORY_SEPARATOR.'Handlers'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'DAOs'.DIRECTORY_SEPARATOR.'Workers'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'DAOs'.DIRECTORY_SEPARATOR.'Uncachers'.PATH_SEPARATOR + ONPHP_MAIN_PATH.'DAOs' , + ONPHP_MAIN_PATH.'DAOs'.DIRECTORY_SEPARATOR.'Handlers', + ONPHP_MAIN_PATH.'DAOs'.DIRECTORY_SEPARATOR.'Workers', + ONPHP_MAIN_PATH.'DAOs'.DIRECTORY_SEPARATOR.'Uncachers', - .ONPHP_MAIN_PATH.'Flow' .PATH_SEPARATOR - .ONPHP_MAIN_PATH.'SPL' .PATH_SEPARATOR + ONPHP_MAIN_PATH.'Flow' , + ONPHP_MAIN_PATH.'SPL' , - .ONPHP_MAIN_PATH.'Net' .PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Http'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Mail'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Ip'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Soap'.PATH_SEPARATOR + ONPHP_MAIN_PATH.'Net' , + ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Http', + ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Mail', + ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Ip', + ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Soap', - .ONPHP_MAIN_PATH.'Math' .PATH_SEPARATOR + ONPHP_MAIN_PATH.'Math' , - .ONPHP_MAIN_PATH.'Markup' .PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Markup'.DIRECTORY_SEPARATOR.'Feed'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Markup'.DIRECTORY_SEPARATOR.'Html'.PATH_SEPARATOR + ONPHP_MAIN_PATH.'Markup' , + ONPHP_MAIN_PATH.'Markup'.DIRECTORY_SEPARATOR.'Feed', + ONPHP_MAIN_PATH.'Markup'.DIRECTORY_SEPARATOR.'Html', - .ONPHP_MAIN_PATH.'OQL' .PATH_SEPARATOR - .ONPHP_MAIN_PATH.'OQL'.DIRECTORY_SEPARATOR.'Expressions'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'OQL'.DIRECTORY_SEPARATOR.'Parsers'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'OQL'.DIRECTORY_SEPARATOR.'Statements'.PATH_SEPARATOR + ONPHP_MAIN_PATH.'OQL' , + ONPHP_MAIN_PATH.'OQL'.DIRECTORY_SEPARATOR.'Expressions', + ONPHP_MAIN_PATH.'OQL'.DIRECTORY_SEPARATOR.'Parsers', + ONPHP_MAIN_PATH.'OQL'.DIRECTORY_SEPARATOR.'Statements', - .ONPHP_MAIN_PATH.'OpenId' .PATH_SEPARATOR + ONPHP_MAIN_PATH.'OpenId' , - .ONPHP_MAIN_PATH.'EntityProto'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'EntityProto'.DIRECTORY_SEPARATOR.'Builders'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'EntityProto'.DIRECTORY_SEPARATOR.'Accessors'.PATH_SEPARATOR + ONPHP_MAIN_PATH.'EntityProto', + ONPHP_MAIN_PATH.'EntityProto'.DIRECTORY_SEPARATOR.'Builders', + ONPHP_MAIN_PATH.'EntityProto'.DIRECTORY_SEPARATOR.'Accessors', - .ONPHP_MAIN_PATH.'UnifiedContainer'.PATH_SEPARATOR + ONPHP_MAIN_PATH.'UnifiedContainer', - .ONPHP_MAIN_PATH.'UI'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'UI'.DIRECTORY_SEPARATOR.'View'.PATH_SEPARATOR - - .ONPHP_MAIN_PATH.'Utils' .PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'TuringTest'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'Archivers'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'IO'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'Logging'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'Mobile'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'CommandLine'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'Routers'.PATH_SEPARATOR + ONPHP_MAIN_PATH.'UI', + ONPHP_MAIN_PATH.'UI'.DIRECTORY_SEPARATOR.'View', + + ONPHP_MAIN_PATH.'Utils' , + ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'TuringTest', + ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'Archivers', + ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'IO', + ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'Logging', + ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'Mobile', + ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'CommandLine', + ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'Routers', - .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'AMQP'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'AMQP' - .DIRECTORY_SEPARATOR.'Pecl'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'AMQP' - .DIRECTORY_SEPARATOR.'Exceptions'.PATH_SEPARATOR + ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'AMQP', + ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'AMQP' + .DIRECTORY_SEPARATOR.'Pecl', + ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'AMQP' + .DIRECTORY_SEPARATOR.'Exceptions', - .ONPHP_MAIN_PATH.'Messages' .PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Messages'.DIRECTORY_SEPARATOR.'Interface'.PATH_SEPARATOR + ONPHP_MAIN_PATH.'Messages' , + ONPHP_MAIN_PATH.'Messages'.DIRECTORY_SEPARATOR.'Interface', - .ONPHP_MAIN_PATH.'Application' .PATH_SEPARATOR + ONPHP_MAIN_PATH.'Application' , - .ONPHP_MAIN_PATH.'Charts'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Charts'.DIRECTORY_SEPARATOR.'Google'.PATH_SEPARATOR - .ONPHP_MAIN_PATH.'Monitoring'.PATH_SEPARATOR + ONPHP_MAIN_PATH.'Charts', + ONPHP_MAIN_PATH.'Charts'.DIRECTORY_SEPARATOR.'Google', + ONPHP_MAIN_PATH.'Monitoring', - .ONPHP_META_CLASSES.PATH_SEPARATOR + ONPHP_META_CLASSES, /* - .ONPHP_INCUBATOR_PATH - .'classes'.DIRECTORY_SEPARATOR - .'Application'.DIRECTORY_SEPARATOR.PATH_SEPARATOR + ONPHP_INCUBATOR_PATH + .'classes'.DIRECTORY_SEPARATOR + .'Application'.DIRECTORY_SEPARATOR, - .ONPHP_INCUBATOR_PATH - .'classes'.DIRECTORY_SEPARATOR - .'Application'.DIRECTORY_SEPARATOR - .'Markups'.DIRECTORY_SEPARATOR.PATH_SEPARATOR - - .ONPHP_INCUBATOR_PATH - .'classes'.DIRECTORY_SEPARATOR - .'Application'.DIRECTORY_SEPARATOR - .'Markups'.DIRECTORY_SEPARATOR - .'Documents'.DIRECTORY_SEPARATOR.PATH_SEPARATOR + ONPHP_INCUBATOR_PATH + .'classes'.DIRECTORY_SEPARATOR + .'Application'.DIRECTORY_SEPARATOR + .'Markups'.DIRECTORY_SEPARATOR, + + ONPHP_INCUBATOR_PATH + .'classes'.DIRECTORY_SEPARATOR + .'Application'.DIRECTORY_SEPARATOR + .'Markups'.DIRECTORY_SEPARATOR + .'Documents'.DIRECTORY_SEPARATOR, */ - ); + )); //NOTE: disable by default //see http://pgfoundry.org/docman/view.php/1000079/117/README.txt diff --git a/misc/BaseException.inc.php b/main/Autoloader/Autoloader.class.php similarity index 74% rename from misc/BaseException.inc.php rename to main/Autoloader/Autoloader.class.php index 4eb069f973..9bd7dec976 100644 --- a/misc/BaseException.inc.php +++ b/main/Autoloader/Autoloader.class.php @@ -1,6 +1,6 @@ message] in: \n". - $this->getTraceAsString(); - } + public function autoload($className); + + public function register(); + + public function unregister(); } ?> \ No newline at end of file diff --git a/main/Autoloader/AutoloaderClassNotFound.class.php b/main/Autoloader/AutoloaderClassNotFound.class.php new file mode 100644 index 0000000000..997ad2c6e2 --- /dev/null +++ b/main/Autoloader/AutoloaderClassNotFound.class.php @@ -0,0 +1,64 @@ +unregister(); + spl_autoload_register(array($this, 'autoload')); + } + + public function unregister() + { + spl_autoload_unregister(array($this, 'autoload')); + } + } +?> \ No newline at end of file diff --git a/main/Autoloader/AutoloaderClassPathCache.class.php b/main/Autoloader/AutoloaderClassPathCache.class.php new file mode 100644 index 0000000000..aa497ca484 --- /dev/null +++ b/main/Autoloader/AutoloaderClassPathCache.class.php @@ -0,0 +1,197 @@ +namespaceResolver = $namespaceResolver; + return $this; + } + + /** + * @return NamespaceResolver + */ + public function getNamespaceResolver() + { + return $this->namespaceResolver; + } + + /** + * @param string $path + * @return AutoloaderClassPathCache + */ + public function addPath($path, $namespace = null) + { + $this->namespaceResolver->addPath($path, $namespace); + + return $this; + } + + /** + * @param array $paths + * @return AutoloaderClassPathCache + */ + public function addPaths(array $paths, $namespace = null) + { + $this->namespaceResolver->addPaths($paths, $namespace); + + return $this; + } + + /** + * @param string $path + * @return AutoloaderClassPathCache + */ + public function setClassCachePath($path) + { + $this->classCachePath = rtrim($path, DIRECTORY_SEPARATOR) + .DIRECTORY_SEPARATOR; + return $this; + } + + public function autoloadWithRecache($className) { + return $this->autoload($className, true); + } + + public function autoload($className, $recache = false) + { + if (strpos($className, "\0") !== false) { + // we can not avoid fatal error in this case + return /* void */; + } + + $currentPath = serialize($this->namespaceResolver->getPaths()); + + if ($currentPath != $this->pathHash) { + $this->checksum = crc32($currentPath.ONPHP_VERSION); + $this->pathHash = $currentPath; + } + + $cacheFile = $this->classCachePath.$this->checksum.'.occ'; + + if (!$recache && $this->cache && ($this->cache[self::ONPHP_CLASS_CACHE_CHECKSUM] <> $this->checksum)) + $this->cache = null; + + if (!$recache && !$this->cache) { + try { + $this->cache = unserialize(@file_get_contents($cacheFile, false)); + } catch (BaseException $e) { + /* ignore */ + } + + if ($fileName = $this->getFileName($className)) { + try { + return $this->includeFile($fileName); + } catch (ClassNotFoundException $e) { + throw $e; + } catch (BaseException $e) { + $this->cache = null; + } + } + } + + if ($recache || !$this->cache) { + $this->cache = $this->namespaceResolver->getClassPathList(); + $this->cache[self::ONPHP_CLASS_CACHE_CHECKSUM] = $this->checksum; + + if ( + is_writable(dirname($cacheFile)) + && ( + !file_exists($cacheFile) + || is_writable($cacheFile) + ) + ) + file_put_contents($cacheFile, serialize($this->cache)); + } + + if ($fileName = $this->getFileName($className)) { + try { + return $this->includeFile($fileName); + } catch (BaseException $e) { + if (is_readable($fileName) || $recache) + // class compiling failed + throw $e; + else { + // cache is not actual + $this->cache[self::ONPHP_CLASS_CACHE_CHECKSUM] = null; + $this->autoload($className, true); + } + } + } else { + /* try another auto loader */ + } + } + + public function register() + { + $this->unregister(); + spl_autoload_register(array($this, 'autoload')); + AutoloaderPool::registerRecache($this); + AutoloaderClassNotFound::me()->register(); + } + + public function unregister() + { + AutoloaderPool::unregisterRecache($this); + spl_autoload_unregister(array($this, 'autoload')); + } + + /** + * moved to separate method to allow mock it for tests + * @param string $fileName + */ + protected function includeFile($fileName) + { + include $fileName; + } + + private function getFileName($className) + { + $className = '\\'.ltrim($className, '\\'); + + if (!isset($this->cache[$className])) + return; + + $classParts = explode('\\', $className); + $onlyClassName = $classParts[count($classParts) - 1]; + + return $this->cache[$this->cache[$className]].$onlyClassName + .$this->namespaceResolver->getClassExtension(); + } + } +?> \ No newline at end of file diff --git a/main/Autoloader/AutoloaderNoCache.class.php b/main/Autoloader/AutoloaderNoCache.class.php new file mode 100644 index 0000000000..25ff4c1f8e --- /dev/null +++ b/main/Autoloader/AutoloaderNoCache.class.php @@ -0,0 +1,90 @@ +namespaceResolver = $namespaceResolver; + return $this; + } + + /** + * @return NamespaceResolver + */ + public function getNamespaceResolver() + { + return $this->namespaceResolver; + } + + /** + * @param string $path + * @return AutoloaderNoCache + */ + public function addPath($path, $namespace = null) + { + $this->namespaceResolver->addPath($path, $namespace); + + return $this; + } + + /** + * @param array $pathes + * @return AutoloaderWholeClassCache + */ + public function addPaths(array $paths, $namespace = null) + { + $this->namespaceResolver->addPaths($paths, $namespace); + + return $this; + } + + public function autoload($className) + { + if (strpos($className, "\0") !== false) { + /* are you sane? */ + return; + } + + if ($path = $this->namespaceResolver->getClassPath($className)) { + try { + include $path; + } catch (ClassNotFoundException $e) { + throw $e; + } catch (BaseException $e) { + /* try another auto loader */ + } + } + } + + public function register() + { + $this->unregister(); + spl_autoload_register(array($this, 'autoload')); + AutoloaderClassNotFound::me()->register(); + } + + public function unregister() + { + spl_autoload_unregister(array($this, 'autoload')); + } + } +?> \ No newline at end of file diff --git a/main/Autoloader/AutoloaderPool.class.php b/main/Autoloader/AutoloaderPool.class.php new file mode 100644 index 0000000000..2fc3398499 --- /dev/null +++ b/main/Autoloader/AutoloaderPool.class.php @@ -0,0 +1,60 @@ + $registeredAutoloader) { + if ($registeredAutoloader == $autoloader) + unset(self::$recacheMap[$key]); + } + } + + public static function autoloadWithRecache($className) + { + foreach (self::$recacheMap as $autoloader) { + /* @var $autoloader AutoloaderRecachable */ + $autoloader->autoloadWithRecache($className); + + if (class_exists($className, false)) + return; + } + } + } +?> \ No newline at end of file diff --git a/main/Autoloader/AutoloaderRecachable.class.php b/main/Autoloader/AutoloaderRecachable.class.php new file mode 100644 index 0000000000..8a4447c375 --- /dev/null +++ b/main/Autoloader/AutoloaderRecachable.class.php @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/main/Autoloader/AutoloaderWithNamespace.class.php b/main/Autoloader/AutoloaderWithNamespace.class.php new file mode 100644 index 0000000000..2163f3e762 --- /dev/null +++ b/main/Autoloader/AutoloaderWithNamespace.class.php @@ -0,0 +1,37 @@ + \ No newline at end of file diff --git a/main/Autoloader/NamespaceDirScaner.class.php b/main/Autoloader/NamespaceDirScaner.class.php new file mode 100644 index 0000000000..9b314f4780 --- /dev/null +++ b/main/Autoloader/NamespaceDirScaner.class.php @@ -0,0 +1,47 @@ +classExtension = $classExtension; + return $this; + } + + public function clear() { + $this->list = array(); + $this->dirCount = 0; + } + + public function getList() { + return $this->list; + } + } +?> \ No newline at end of file diff --git a/main/Autoloader/NamespaceDirScanerOnPHP.class.php b/main/Autoloader/NamespaceDirScanerOnPHP.class.php new file mode 100644 index 0000000000..08a86e3045 --- /dev/null +++ b/main/Autoloader/NamespaceDirScanerOnPHP.class.php @@ -0,0 +1,33 @@ +list[$this->dirCount] = $directory; + + if ($paths = glob($directory.'*'.$this->classExtension, GLOB_NOSORT)) { + foreach ($paths as $path) { + $fullClassName = ($namespace ? ('\\' . $namespace) : '') . '\\' + .basename($path, $this->classExtension); + if (!isset($this->list[$fullClassName])) + $this->list[$fullClassName] = $this->dirCount; + } + } + + ++$this->dirCount; + } + } +?> \ No newline at end of file diff --git a/main/Autoloader/NamespaceDirScanerPSR0.class.php b/main/Autoloader/NamespaceDirScanerPSR0.class.php new file mode 100644 index 0000000000..295e5eb691 --- /dev/null +++ b/main/Autoloader/NamespaceDirScanerPSR0.class.php @@ -0,0 +1,88 @@ +allowedUnderline = ($allowedUnderline === true); + return $this; + } + + public function scan($directory, $namespace = '') + { + $this->subScanDir($namespace, array(), $directory); + } + + private function subScanDir($baseNs, array $nsList, $dir) + { + $this->scanCurrentDir($baseNs, $nsList, $dir); + + if ($paths = glob($dir.'*', GLOB_ONLYDIR)) { + foreach ($paths as $subDir) { + $subNs = basename($subDir); + if ( + (mb_strpos($subNs, '.') !== false) + || (mb_strpos($subNs, '_') !== false) + ) { + continue; + } + + $this->subScanDir( + $baseNs, + array_merge($nsList, array($subNs)), + $subDir.DIRECTORY_SEPARATOR + ); + } + } + } + + private function scanCurrentDir($baseNs, array $nsList, $dir) + { + $this->list[$this->dirCount] = $dir; + + if ($paths = glob($dir.'*'.$this->classExtension)) { + foreach ($paths as $path) { + $classNsList = array_merge( + $nsList, + array(basename($path, $this->classExtension)) + ); + + $classNs = implode('\\', $classNsList); + $fullClassName = ($baseNs ? ('\\' . $baseNs) : ''); + $fullClassName .= ($classNs ? ('\\' . $classNs) : ''); + if (!isset($this->list[$fullClassName])) { + $this->list[$fullClassName] = $this->dirCount; + } + + if ($this->allowedUnderline) { + $classNs = implode('_', $classNsList); + $fullClassName = ($baseNs ? ('\\' . $baseNs) : ''); + $fullClassName .= ($classNs ? ('\\' . $classNs) : ''); + if (!isset($this->list[$fullClassName])) { + $this->list[$fullClassName] = $this->dirCount; + } + } + } + } + + ++$this->dirCount; + } + } +?> \ No newline at end of file diff --git a/main/Autoloader/NamespaceResolver.class.php b/main/Autoloader/NamespaceResolver.class.php new file mode 100644 index 0000000000..046b4447d9 --- /dev/null +++ b/main/Autoloader/NamespaceResolver.class.php @@ -0,0 +1,59 @@ + \ No newline at end of file diff --git a/main/Autoloader/NamespaceResolverOnPHP.class.php b/main/Autoloader/NamespaceResolverOnPHP.class.php new file mode 100644 index 0000000000..bf5bb0da2b --- /dev/null +++ b/main/Autoloader/NamespaceResolverOnPHP.class.php @@ -0,0 +1,134 @@ +paths[$namespace])) { + $this->paths[$namespace] = array(); + } + + $this->paths[$namespace][] = rtrim($path, self::DS).self::DS; + + return $this; + } + + /** + * @param string $path + * @return NamespaceResolverOnPHP + */ + public function addPaths(array $pathList, $namespace = null) + { + foreach ($pathList as $path) + $this->addPath($path, $namespace); + + return $this; + } + + public function getPaths() + { + return $this->paths; + } + + /** + * @param string $classExtension + * @return NamespaceResolverOnPHP + */ + public function setClassExtension($classExtension) + { + $this->classExtension = $classExtension; + return $this; + } + + /** + * @return string + */ + public function getClassExtension() + { + return $this->classExtension; + } + + /** + * Return path to className or null if path not found + * + * @param string $className + * @return string + */ + public function getClassPath($className) + { + $className = ltrim($className, '\\'); + + foreach ($this->paths as $namespace => $namespacePaths) { + if ($path = $this->searchClass($className, $namespace, $namespacePaths)) + return $path; + } + } + + /** + * Return special array numeric keys contains directories paths + * and other keys (className keys) contains keys of directories + * + * @return array + */ + public function getClassPathList() + { + $dirScaner = $this->getDirScaner() + ->setClassExtension($this->getClassExtension()); + + foreach ($this->paths as $namespace => $namespacePaths) { + foreach ($namespacePaths as $directory) { + $dirScaner->scan($directory, $namespace); + } + } + return $dirScaner->getList(); + } + + protected function searchClass($className, $namespace, $paths) + { + $classParts = explode('\\', $className); + $onlyClassName = array_pop($classParts); + + $requiredNamespace = implode('\\', $classParts); + if ($requiredNamespace == $namespace) { + foreach ($paths as $directory) { + if ($paths = glob($directory.$onlyClassName.$this->classExtension, GLOB_NOSORT)) { + return $paths[0]; + } + } + } + } + + /** + * @return NamespaceDirScaner + */ + protected function getDirScaner() { + return new NamespaceDirScanerOnPHP(); + } + } +?> \ No newline at end of file diff --git a/main/Autoloader/NamespaceResolverPSR0.class.php b/main/Autoloader/NamespaceResolverPSR0.class.php new file mode 100644 index 0000000000..13b14cb823 --- /dev/null +++ b/main/Autoloader/NamespaceResolverPSR0.class.php @@ -0,0 +1,72 @@ +allowedUnderline = ($allowedUnderline === true); + return $this; + } + + protected function searchClass($className, $namespace, $paths) + { + $splitPattern = $this->allowedUnderline ? '~(\\\\+|_+)~' : '~(\\\\+)~'; + $classParts = preg_split($splitPattern, $className); + $onlyClassName = array_pop($classParts); + + $requiredNamespace = implode('\\', $classParts); + if ( + empty($namespace) + || $requiredNamespace == $namespace + || mb_strpos($requiredNamespace, $namespace) == 0 + ) { + $subPath = preg_replace('~\\\\~', self::DS, trim( + mb_substr($requiredNamespace, mb_strlen($namespace)), + '\\' + )); + + $checkPath = ($subPath ? ($subPath . self::DS) : '').$onlyClassName + .$this->getClassExtension(); + + foreach ($paths as $directory) { + if ($paths = glob($directory.$checkPath)) { + return $paths[0]; + } + } + } + } + + /** + * @return NamespaceDirScaner + */ + protected function getDirScaner() { + $dirScaner = new NamespaceDirScanerPSR0(); + return $dirScaner->setAllowedUnderline($this->allowedUnderline); + } + } +?> \ No newline at end of file diff --git a/main/Autoloader/require.inc.php b/main/Autoloader/require.inc.php new file mode 100644 index 0000000000..9cd472e77a --- /dev/null +++ b/main/Autoloader/require.inc.php @@ -0,0 +1,30 @@ + \ No newline at end of file diff --git a/meta/bin/build.php b/meta/bin/build.php index f6d5490010..81eb0b70e8 100755 --- a/meta/bin/build.php +++ b/meta/bin/build.php @@ -45,12 +45,12 @@ function init() define('ONPHP_META_PATTERNS', ONPHP_META_PATH.'patterns'.DIRECTORY_SEPARATOR); define('ONPHP_META_TYPES', ONPHP_META_PATH.'types'.DIRECTORY_SEPARATOR); - set_include_path( - get_include_path().PATH_SEPARATOR - .ONPHP_META_BUILDERS.PATH_SEPARATOR - .ONPHP_META_PATTERNS.PATH_SEPARATOR - .ONPHP_META_TYPES.PATH_SEPARATOR - ); + AutoloaderPool::get('onPHP')-> + addPaths(array( + ONPHP_META_BUILDERS, + ONPHP_META_PATTERNS, + ONPHP_META_TYPES, + )); if (!defined('ONPHP_META_DAO_DIR')) define( diff --git a/meta/classes/MetaConfiguration.class.php b/meta/classes/MetaConfiguration.class.php index 0da7c4c786..ce5f7fe414 100644 --- a/meta/classes/MetaConfiguration.class.php +++ b/meta/classes/MetaConfiguration.class.php @@ -438,15 +438,15 @@ public function checkIntegrity() infoLine('Checking sanity of generated files: ')-> newLine(); - set_include_path( - get_include_path().PATH_SEPARATOR - .ONPHP_META_BUSINESS_DIR.PATH_SEPARATOR - .ONPHP_META_DAO_DIR.PATH_SEPARATOR - .ONPHP_META_PROTO_DIR.PATH_SEPARATOR - .ONPHP_META_AUTO_BUSINESS_DIR.PATH_SEPARATOR - .ONPHP_META_AUTO_DAO_DIR.PATH_SEPARATOR - .ONPHP_META_AUTO_PROTO_DIR.PATH_SEPARATOR - ); + AutoloaderPool::get('onPHP')-> + addPaths(array( + ONPHP_META_BUSINESS_DIR, + ONPHP_META_DAO_DIR, + ONPHP_META_PROTO_DIR, + ONPHP_META_AUTO_BUSINESS_DIR, + ONPHP_META_AUTO_DAO_DIR, + ONPHP_META_AUTO_PROTO_DIR, + )); $out->info("\t"); diff --git a/misc/Autoloader.inc.php b/misc/Autoloader.inc.php deleted file mode 100644 index f74a3db544..0000000000 --- a/misc/Autoloader.inc.php +++ /dev/null @@ -1,218 +0,0 @@ - $checksum)) - $cache = null; - - if (!$cache) { - try { - $cache = unserialize(@file_get_contents($cacheFile, false)); - } catch (BaseException $e) { - /* ignore */ - } - - if (isset($cache[$classname])) { - try { - include $cache[$cache[$classname]].$classname.EXT_CLASS; - return /* void */; - } catch (ClassNotFoundException $e) { - throw $e; - } catch (BaseException $e) { - $cache = null; - } - } - } - - if (!$cache) { - $cache = array(); - $dirCount = 0; - - foreach (explode(PATH_SEPARATOR, get_include_path()) as $directory) { - $cache[$dirCount] = realpath($directory).DIRECTORY_SEPARATOR; - - if ($paths = glob($cache[$dirCount].'*'.EXT_CLASS, GLOB_NOSORT)) { - foreach ($paths as $class) { - $class = basename($class, EXT_CLASS); - - // emulating include_path searching behaviour - if (!isset($cache[$class])) - $cache[$class] = $dirCount; - } - } - - ++$dirCount; - } - - $cache[ONPHP_CLASS_CACHE_CHECKSUM] = $checksum; - - if ( - is_writable(dirname($cacheFile)) - && ( - !file_exists($cacheFile) - || is_writable($cacheFile) - ) - ) - file_put_contents($cacheFile, serialize($cache)); - } - - if (isset($cache[$classname])) { - $fileName = $cache[$cache[$classname]].$classname.EXT_CLASS; - - try { - include $fileName; - } catch (BaseException $e) { - if (is_readable($fileName)) - // class compiling failed - throw $e; - else { - // cache is not actual - $cache[ONPHP_CLASS_CACHE_CHECKSUM] = null; - self::classPathCache($classname); - } - } - } else { - // ok, last chance to find class in non-cached include_path - try { - include $classname.EXT_CLASS; - $cache[ONPHP_CLASS_CACHE_CHECKSUM] = null; - return /* void */; - } catch (BaseException $e) { - __autoload_failed($classname, $e->getMessage()); - } - } - } - - public static function noCache($classname) - { - if (strpos($classname, "\0") !== false) { - /* are you sane? */ - return; - } - - try { - include $classname.EXT_CLASS; - return /* void */; - } catch (BaseException $e) { - return __autoload_failed($classname, $e->getMessage()); - } - } - - public static function wholeClassCache($classname) - { - // we must duplicate this one here, otherwise any fail will be silent - require_once dirname(__FILE__).DIRECTORY_SEPARATOR.'BaseException'.EXT_MOD; - - static $path = null; - static $checksum = null; - static $included = array(); - - if (strpos($classname, "\0") !== false) { - /* are you sane? */ - return; - } - - $currentPath = get_include_path(); - - if ($currentPath != $path) { - $checksum = crc32($currentPath.ONPHP_VERSION); - $path = $currentPath; - } - - $cacheFile = ONPHP_CLASS_CACHE.$checksum.'.occ'; - - if (!isset($included[$cacheFile])) { - try { - include $cacheFile; - $included[$cacheFile] = true; - } catch (BaseException $e) { - /* ignore */ - } - } - - if (!class_exists($classname)) { - static $pid = null; - - if (!$pid) { - $pid = getmypid(); - - register_shutdown_function(array('Autoloader', 'autoloadCleanup')); - } - - try { - $classPath = null; - - foreach ( - explode(PATH_SEPARATOR, get_include_path()) - as $directory - ) { - $location = $directory.'/'.$classname.EXT_CLASS; - - if (is_readable($location)) { - $classPath = $location; - break; - } - } - - if (!$classPath) - throw new BaseException('failed to find requested class'); - - $class = file_get_contents($classPath); - - eval('?>'.$class); - } catch (BaseException $e) { - return __autoload_failed($classname, $e->getMessage()); - } - - file_put_contents($cacheFile.'-'.$pid, $class, FILE_APPEND); - - $included[$cacheFile] = true; - } - } - - public static function autoloadCleanup() - { - $pid = getmypid(); - - if ($paths = glob(ONPHP_CLASS_CACHE.'*-'.$pid, GLOB_NOSORT)) { - foreach ($paths as $file) { - rename($file, ONPHP_CLASS_CACHE.basename($file, '-'.$pid)); - } - } - } - - - } -?> \ No newline at end of file diff --git a/test/AllTests.php b/test/AllTests.php index 71a0f205a1..4f8e126fe4 100644 --- a/test/AllTests.php +++ b/test/AllTests.php @@ -19,15 +19,12 @@ mb_internal_encoding(ENCODING); mb_regex_encoding(ENCODING); - set_include_path( - // current path - get_include_path().PATH_SEPARATOR - .ONPHP_TEST_PATH.'misc'.PATH_SEPARATOR - ); + AutoloaderPool::get('onPHP')->addPath(ONPHP_TEST_PATH.'misc'); $testPathes = array( ONPHP_TEST_PATH.'core'.DIRECTORY_SEPARATOR, ONPHP_TEST_PATH.'main'.DIRECTORY_SEPARATOR, + ONPHP_TEST_PATH.'main'.DIRECTORY_SEPARATOR.'Autoloader'.DIRECTORY_SEPARATOR, ONPHP_TEST_PATH.'main'.DIRECTORY_SEPARATOR.'Ip'.DIRECTORY_SEPARATOR, ONPHP_TEST_PATH.'main'.DIRECTORY_SEPARATOR.'Net'.DIRECTORY_SEPARATOR, ONPHP_TEST_PATH.'main'.DIRECTORY_SEPARATOR.'Utils'.DIRECTORY_SEPARATOR, @@ -86,17 +83,15 @@ public static function suite() include $path; - // provide paths to autogenerated stuff - set_include_path( - get_include_path().PATH_SEPARATOR - .ONPHP_META_AUTO_BUSINESS_DIR.PATH_SEPARATOR - .ONPHP_META_AUTO_DAO_DIR.PATH_SEPARATOR - .ONPHP_META_AUTO_PROTO_DIR.PATH_SEPARATOR - - .ONPHP_META_DAO_DIR.PATH_SEPARATOR - .ONPHP_META_BUSINESS_DIR.PATH_SEPARATOR - .ONPHP_META_PROTO_DIR - ); + AutoloaderPool::get('onPHP')->addPaths(array( + ONPHP_META_AUTO_BUSINESS_DIR, + ONPHP_META_AUTO_DAO_DIR, + ONPHP_META_AUTO_PROTO_DIR, + + ONPHP_META_DAO_DIR, + ONPHP_META_BUSINESS_DIR, + ONPHP_META_PROTO_DIR + )); $dBCreator = DBTestCreator::create()-> setSchemaPath(ONPHP_META_AUTO_DIR.'schema.php')-> diff --git a/test/core/PrimitiveClassTest.class.php b/test/core/PrimitiveClassTest.class.php index a242bfe926..491dfb758c 100644 --- a/test/core/PrimitiveClassTest.class.php +++ b/test/core/PrimitiveClassTest.class.php @@ -21,7 +21,7 @@ public function testOf() try { $prm->of('InExIsNaNtClass'); $this->fail(); - } catch (ClassNotFoundException $e) { + } catch (WrongArgumentException $e) { // pass } diff --git a/test/main/Autoloader/AutoloaderClassPathCacheTest.class.php b/test/main/Autoloader/AutoloaderClassPathCacheTest.class.php new file mode 100644 index 0000000000..3dedc2b317 --- /dev/null +++ b/test/main/Autoloader/AutoloaderClassPathCacheTest.class.php @@ -0,0 +1,142 @@ +spawnService(); + + //simple autoload, will cache data to file + $service->autoload('Form'); + + //second autoload call must not require to reload cache + $service->setNamespaceResolver($this->spawnResolver(array('getClassPathListCount' => 0))); + $service->autoload('Sub\Form'); + + //but if we ask force recache it will reload + $service->setNamespaceResolver($this->spawnResolver()); + $service->autoload('Sub\Form', true); + } + + public function testWithBaseException() + { + $service = $this->spawnService(); + $counter = 0; + $callback = function() use (&$counter) { + switch ($counter++) { + case 0: return null; + case 1: throw new BaseException('include exception'); + case 2: return null; + default: Assert::isUnreachable($counter - 1); + } + }; + + $service->expects($this->exactly(3))-> + method('includeFile')-> + will($this->returnCallback($callback)); + + //autoload without error, it's allow us to cache data + $service->autoload('Form'); + + define('DEBUG', true); + //second autoload and here we throw error + $service->setNamespaceResolver($this->spawnResolver(array( + 'getPathsCount' => 2, + 'getClassPathListCount' => 1, + ))); + $service->autoload('Form'); + } + + public function testRecacheOnChangedPath() + { + //setup + $service = $this->spawnService(); + + //simple autoload, will cache data to file + $service->autoload('Form'); + + //chang path list and expect recache + $service->setNamespaceResolver($this->spawnResolver(array( + 'getPaths' => array('' => array('path1')) + ))); + $service->autoload('Form'); + } + + /** + * @return AutoloaderClassPathCache + */ + private function spawnService(array $options = array()) + { + $service = $this->getMockBuilder('AutoloaderClassPathCache')-> + setMethods(array('includeFile', 'register', 'unregister'))-> + getMock(); + + /* @var $service AutoloaderClassPathCache */ + $service-> + setNamespaceResolver($this->spawnResolver($options))-> + setClassCachePath($this->spawnCacheDir()); + + return $service; + } + + /** + * @return NamespaceResolver + */ + private function spawnResolver(array $options = array()) + { + $options += array( + 'getPaths' => array('' => array('path1', 'path2')), + 'getPathsCount' => 1, + + 'getClassExtension' => EXT_CLASS, + + 'getClassPathList' => array( + 0 => 'path1/', + '\Form' => 0, + 1 => 'path1/path2/', + '\Sub\Form' => 1, + ), + 'getClassPathListCount' => 1, + ); + $mock = $this->getMock('NamespaceResolver'); + + $mock->expects($this->any())-> + method('getClassExtension')-> + will($this->returnValue($options['getClassExtension'])); + + $mock->expects($this->exactly($options['getPathsCount']))-> + method('getPaths')-> + will($this->returnValue($options['getPaths'])); + + $mock->expects($this->exactly($options['getClassPathListCount']))-> + method('getClassPathList')-> + will($this->returnValue($options['getClassPathList'])); + + return $mock; + } + + private function spawnCacheDir() + { + $cachePath = ONPHP_CLASS_CACHE.'testCache/'; + if (file_exists($cachePath)) { + if (is_file($cachePath)) + unlink($cachePath); + elseif (is_dir($cachePath)) { + FileUtils::removeDirectory($cachePath, true); + } + } + mkdir($cachePath, 0777, true); + return $cachePath; + } + } +?> \ No newline at end of file diff --git a/test/main/Autoloader/NamespaceResolverTest.class.php b/test/main/Autoloader/NamespaceResolverTest.class.php new file mode 100644 index 0000000000..24241acdf3 --- /dev/null +++ b/test/main/Autoloader/NamespaceResolverTest.class.php @@ -0,0 +1,226 @@ + + addPath($this->getBasePath().'onPHP'); + //expectation + $result = array( + 0 => $this->getBasePath().'onPHP/', + '\MyForm' => 0, + ); + //execution + $this->assertEquals($result, $resolver->getClassPathList()); + $this->assertEquals($this->getBasePath().'onPHP/MyForm.class.php', $resolver->getClassPath('MyForm')); + $this->assertNull($resolver->getClassPath('MyFormSub')); + $this->assertNull($resolver->getClassPath('\onPHP\MyFormSub')); + $this->assertNull($resolver->getClassPath('\onPHP\MyFormSup')); + + //setup + $resolver->addPaths( + array($this->getBasePath().'onPHP/Sub/', $this->getBasePath().'onPHP/Up/'), + 'onPHP' + ); + //expectation + $result[1] = $this->getBasePath().'onPHP/Sub/'; + $result['\onPHP\MyFormSub'] = 1; + $result[2] = $this->getBasePath().'onPHP/Up/'; + $result['\onPHP\MyFormUp'] = 2; + //execution + $this->assertEquals($result, $resolver->getClassPathList()); + $this->assertEquals($this->getBasePath().'onPHP/MyForm.class.php', $resolver->getClassPath('\MyForm')); + $this->assertNull($resolver->getClassPath('MyFormSub')); + $this->assertEquals( + $this->getBasePath().'onPHP/Sub/MyFormSub.class.php', + $resolver->getClassPath('\onPHP\MyFormSub') + ); + $this->assertNull($resolver->getClassPath('\onPHP\MyFormSup')); + + //setup + $resolver->setClassExtension('.clazz.php'); + //expecation + $result = array( + 0 => $this->getBasePath().'onPHP/', + 1 => $this->getBasePath().'onPHP/Sub/', + '\\onPHP\\MyFormSup' => 1, + 2 => $this->getBasePath().'onPHP/Up/', + ); + //execution + $this->assertEquals($result, $resolver->getClassPathList()); + $this->assertNull($resolver->getClassPath('\MyForm')); + $this->assertNull($resolver->getClassPath('MyFormSub')); + $this->assertNull($resolver->getClassPath('\onPHP\MyFormSub')); + $this->assertEquals( + $this->getBasePath().'onPHP/Sub/MyFormSup.clazz.php', + $resolver->getClassPath('\onPHP\MyFormSup') + ); + } + + public function testPSR0ResolverEmptyBaseNamespace() + { + //setup + $resolver = NamespaceResolverPSR0::create()-> + addPath($this->getBasePath()); + + //expectation + $result = array( + 0 => $this->getBasePath(), + 1 => $this->getBasePath().'MyNS/', + '\MyNS\\Class1' => 1, + 2 => $this->getBasePath().'MyNS/Sub/', + '\\MyNS\Sub\Class2' => 2, + 3 => $this->getBasePath().'onPHP/', + 4 => $this->getBasePath().'onPHP/Sub/', + 5 => $this->getBasePath().'onPHP/Up/', + '\onPHP\MyForm' => 3, + '\onPHP\Sub\MyFormSub' => 4, + '\onPHP\Up\MyFormUp' => 5, + ); + //execution + $this->assertEquals($result, $resolver->getClassPathList()); + $this->assertEquals( + $this->getBasePath().'MyNS/Sub/Class2.class.php', + $resolver->getClassPath('\MyNS\\Sub\Class2') + ); + $this->assertNull($resolver->getClassPath('\MyNS\\Sub\Class1')); + $this->assertNull($resolver->getClassPath('\onPHP\Sub\MyFormSup')); + + //setup + $resolver->setClassExtension('.clazz.php'); + //expectation + $result = array( + 0 => $this->getBasePath(), + 1 => $this->getBasePath().'MyNS/', + 2 => $this->getBasePath().'MyNS/Sub/', + 3 => $this->getBasePath().'onPHP/', + 4 => $this->getBasePath().'onPHP/Sub/', + '\onPHP\Sub\MyFormSup' => 4, + 5 => $this->getBasePath().'onPHP/Up/', + ); + //execution + $this->assertEquals($result, $resolver->getClassPathList()); + $this->assertNull($resolver->getClassPath('\MyNS\Sub\Class2')); + $this->assertEquals( + $this->getBasePath().'onPHP/Sub/MyFormSup.clazz.php', + $resolver->getClassPath('\onPHP\Sub\MyFormSup') + ); + } + + public function testPSR0ResolverStartWithNamespace() + { + //setup + $resolver = NamespaceResolverPSR0::create()-> + addPath($this->getBasePath().'onPHP', '\onPHP\\'); + //expectation + $result = array( + 0 => $this->getBasePath().'onPHP/', + '\onPHP\MyForm' => 0, + 1 => $this->getBasePath().'onPHP/Sub/', + '\onPHP\Sub\MyFormSub' => 1, + 2 => $this->getBasePath().'onPHP/Up/', + '\onPHP\Up\MyFormUp' => 2, + ); + //execution + $this->assertEquals($result, $resolver->getClassPathList()); + $this->assertEquals( + $this->getBasePath().'onPHP/Up/MyFormUp.class.php', + $resolver->getClassPath('onPHP\Up\MyFormUp') + ); + $this->assertNull($resolver->getClassPath('\MyNS\\Sub\Class1')); + $this->assertNull($resolver->getClassPath('\onPHP\Sub\MyFormSup')); + } + + public function testPSR0WithUnderlineNoBaseNamespace() + { + //setup + $resolver = NamespaceResolverPSR0::create()-> + setAllowedUnderline(true)-> + addPath($this->getBasePath(true)); + + //expectation + $this->assertEquals( + $this->getBasePath(true).'Under/Class.class.php', + $resolver->getClassPath('\Under_Class') + ); + $this->assertEquals( + $this->getBasePath(true).'Under/Class.class.php', + $resolver->getClassPath('\Under\Class') + ); + + $result = array( + 0 => $this->getBasePath(true), + 1 => $this->getBasePath(true).'Under/', + '\Under\Class' => 1, + '\Under_Class' => 1, + ); + $this->assertEquals($result, $resolver->getClassPathList()); + + //re-setup + $resolver->setAllowedUnderline(false); + $this->assertNull($resolver->getClassPath('\Under_Class')); + $this->assertEquals( + $this->getBasePath(true).'Under/Class.class.php', + $resolver->getClassPath('\Under\Class') + ); + } + + public function testPSR0WithUnderlineWithBaseNamespace() + { + //setup + $resolver = NamespaceResolverPSR0::create()-> + setAllowedUnderline(true)-> + addPath($this->getBasePath(true), 'My\base_package'); + + //expectation + $this->assertEquals( + $this->getBasePath(true).'Under/Class.class.php', + $resolver->getClassPath('\My\base_package\Under_Class') + ); + $this->assertEquals( + $this->getBasePath(true).'Under/Class.class.php', + $resolver->getClassPath('\My\base_package\Under\Class') + ); + $this->assertNull($resolver->getClassPath('\Under\Class')); + + $result = array( + 0 => $this->getBasePath(true), + 1 => $this->getBasePath(true).'Under/', + '\My\base_package\Under\Class' => 1, + '\My\base_package\Under_Class' => 1, + ); + $this->assertEquals($result, $resolver->getClassPathList()); + + //re-setup + $resolver->setAllowedUnderline(false); + $this->assertNull($resolver->getClassPath('\My\base_package\Under_Class')); + $this->assertEquals( + $this->getBasePath(true).'Under/Class.class.php', + $resolver->getClassPath('\My\base_package\Under\Class') + ); + } + + private function getBasePath($isUnderline = false) + { + return ONPHP_TEST_PATH.( + $isUnderline + ? 'main/data/namespace_ul/' + : 'main/data/namespace/' + ); + } + } +?> \ No newline at end of file diff --git a/test/main/data/namespace/MyNS/Class1.class.php b/test/main/data/namespace/MyNS/Class1.class.php new file mode 100644 index 0000000000..fe5d918394 --- /dev/null +++ b/test/main/data/namespace/MyNS/Class1.class.php @@ -0,0 +1 @@ +nothing here, just for tests autoloaders \ No newline at end of file diff --git a/test/main/data/namespace/MyNS/Sub/Class2.class.php b/test/main/data/namespace/MyNS/Sub/Class2.class.php new file mode 100644 index 0000000000..fe5d918394 --- /dev/null +++ b/test/main/data/namespace/MyNS/Sub/Class2.class.php @@ -0,0 +1 @@ +nothing here, just for tests autoloaders \ No newline at end of file diff --git a/test/main/data/namespace/onPHP/MyForm.class.php b/test/main/data/namespace/onPHP/MyForm.class.php new file mode 100644 index 0000000000..fe5d918394 --- /dev/null +++ b/test/main/data/namespace/onPHP/MyForm.class.php @@ -0,0 +1 @@ +nothing here, just for tests autoloaders \ No newline at end of file diff --git a/test/main/data/namespace/onPHP/Sub/MyFormSub.class.php b/test/main/data/namespace/onPHP/Sub/MyFormSub.class.php new file mode 100644 index 0000000000..fe5d918394 --- /dev/null +++ b/test/main/data/namespace/onPHP/Sub/MyFormSub.class.php @@ -0,0 +1 @@ +nothing here, just for tests autoloaders \ No newline at end of file diff --git a/test/main/data/namespace/onPHP/Sub/MyFormSup.clazz.php b/test/main/data/namespace/onPHP/Sub/MyFormSup.clazz.php new file mode 100644 index 0000000000..fe5d918394 --- /dev/null +++ b/test/main/data/namespace/onPHP/Sub/MyFormSup.clazz.php @@ -0,0 +1 @@ +nothing here, just for tests autoloaders \ No newline at end of file diff --git a/test/main/data/namespace/onPHP/Up/MyFormUp.class.php b/test/main/data/namespace/onPHP/Up/MyFormUp.class.php new file mode 100644 index 0000000000..fe5d918394 --- /dev/null +++ b/test/main/data/namespace/onPHP/Up/MyFormUp.class.php @@ -0,0 +1 @@ +nothing here, just for tests autoloaders \ No newline at end of file diff --git a/test/main/data/namespace_ul/Under/Class.class.php b/test/main/data/namespace_ul/Under/Class.class.php new file mode 100644 index 0000000000..fe5d918394 --- /dev/null +++ b/test/main/data/namespace_ul/Under/Class.class.php @@ -0,0 +1 @@ +nothing here, just for tests autoloaders \ No newline at end of file