|
@@ -1,415 +0,0 @@
|
|
-<?php
|
|
|
|
-namespace \Qii\Autoloader;
|
|
|
|
-
|
|
|
|
-/**
|
|
|
|
- * Psr4 规范
|
|
|
|
- *
|
|
|
|
- */
|
|
|
|
-class Psr4
|
|
|
|
-{
|
|
|
|
- /**
|
|
|
|
- * 将查找过的文件放入缓存
|
|
|
|
- */
|
|
|
|
- protected static $cachedFiles = array();
|
|
|
|
- /**
|
|
|
|
- * 是否使用namespace
|
|
|
|
- */
|
|
|
|
- protected $useNamespace = array();
|
|
|
|
- /**
|
|
|
|
- * 添加namespace前缀对应的目录,只要是以这个前缀开头的文件都在指定目录中去查找
|
|
|
|
- * 前缀可以对应多个目录,找的时候会去遍历数组
|
|
|
|
- * @var array
|
|
|
|
- */
|
|
|
|
- protected $prefixes = array();
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 当前class的初始化
|
|
|
|
- */
|
|
|
|
- private static $_instance = null;
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @var APP_LOAD_PREFIX 保存类到以APP_LOAD_PREFIX开头的key中
|
|
|
|
- */
|
|
|
|
- const APP_LOAD_PREFIX = '__qii_psr4_instance';
|
|
|
|
- /**
|
|
|
|
- * @var $_loadedClass 保存加载过的类
|
|
|
|
- */
|
|
|
|
- protected static $_loadedClass = array();
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @var $_realpath 将转换后的路径存放到此变量中
|
|
|
|
- */
|
|
|
|
- protected static $_realpath = array();
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 最后一次没有加载到文件的错误路径
|
|
|
|
- * @var array $lastErrorLoadedFile
|
|
|
|
- */
|
|
|
|
- protected static $lastErrorLoadedFile = array();
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 注册自动加载类
|
|
|
|
- *
|
|
|
|
- */
|
|
|
|
- private function __construct()
|
|
|
|
- {
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 单例模式
|
|
|
|
- */
|
|
|
|
- public static function getInstance()
|
|
|
|
- {
|
|
|
|
- if (self::$_instance == null) {
|
|
|
|
- self::$_instance = new self();
|
|
|
|
- }
|
|
|
|
- return self::$_instance;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 注册自动加载类
|
|
|
|
- *
|
|
|
|
- * @return void
|
|
|
|
- */
|
|
|
|
- public function register()
|
|
|
|
- {
|
|
|
|
- spl_autoload_register(array($this, 'loadFileByClass'));
|
|
|
|
- return $this;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Setting is use namespace for class
|
|
|
|
- *
|
|
|
|
- * @param $prefix 以prefix前缀开头的使用namespace
|
|
|
|
- * @param bool $useNamespace
|
|
|
|
- * @return object $this
|
|
|
|
- */
|
|
|
|
- public function setUseNamespace($prefix, $useNamespace = true)
|
|
|
|
- {
|
|
|
|
- $this->useNamespace[$prefix] = $useNamespace;
|
|
|
|
- return $this;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Adds a base directory for a namespace prefix.
|
|
|
|
- *
|
|
|
|
- * @param string $prefix The namespace prefix.
|
|
|
|
- * @param string $baseDir A base directory for class files in the
|
|
|
|
- * namespace.
|
|
|
|
- * @param bool $prepend If true, prepend the base directory to the stack
|
|
|
|
- * instead of appending it; this causes it to be searched first rather
|
|
|
|
- * than last.
|
|
|
|
- * @return void
|
|
|
|
- */
|
|
|
|
- public function addNamespace($prefix, $baseDir, $prepend = false)
|
|
|
|
- {
|
|
|
|
- // normalize namespace prefix
|
|
|
|
- $prefix = trim($prefix, '\\') . '\\';
|
|
|
|
-
|
|
|
|
- // normalize the base directory with a trailing separator
|
|
|
|
- $baseDir = rtrim($baseDir, '/') . DIRECTORY_SEPARATOR;
|
|
|
|
- $baseDir = rtrim($baseDir, DIRECTORY_SEPARATOR) . '/';
|
|
|
|
-
|
|
|
|
- // initialize the namespace prefix array
|
|
|
|
- if (isset($this->prefixes[$prefix]) === false) {
|
|
|
|
- $this->prefixes[$prefix] = array();
|
|
|
|
- }
|
|
|
|
- if (in_array($baseDir, $this->prefixes[$prefix])) {
|
|
|
|
- return $this;
|
|
|
|
- }
|
|
|
|
- // retain the base directory for the namespace prefix
|
|
|
|
- if ($prepend) {
|
|
|
|
- array_unshift($this->prefixes[$prefix], $baseDir);
|
|
|
|
- } else {
|
|
|
|
- array_push($this->prefixes[$prefix], $baseDir);
|
|
|
|
- }
|
|
|
|
- return $this;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 移除某一个namespace下的指定路径
|
|
|
|
- * @param string $prefix 前缀
|
|
|
|
- * @param string $baseDir 路径
|
|
|
|
- * @return array
|
|
|
|
- */
|
|
|
|
- public function removeNameSpace($prefix, $baseDir)
|
|
|
|
- {
|
|
|
|
- // normalize namespace prefix
|
|
|
|
- $prefix = trim($prefix, '\\') . '\\';
|
|
|
|
-
|
|
|
|
- // normalize the base directory with a trailing separator
|
|
|
|
- $baseDir = rtrim($baseDir, '/') . DIRECTORY_SEPARATOR;
|
|
|
|
- $baseDir = rtrim($baseDir, DIRECTORY_SEPARATOR) . '/';
|
|
|
|
- // initialize the namespace prefix array
|
|
|
|
- if (isset($this->prefixes[$prefix]) === false) {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
- foreach ($this->prefixes[$prefix] AS $key => $dir) {
|
|
|
|
- if ($dir == $baseDir) unset($this->prefixes[$prefix][$key]);
|
|
|
|
- }
|
|
|
|
- return $this->prefixes;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 返回namespace路径
|
|
|
|
- */
|
|
|
|
- public function getNamespace($prefix)
|
|
|
|
- {
|
|
|
|
- // normalize namespace prefix
|
|
|
|
- $prefix = trim($prefix, '\\') . '\\';
|
|
|
|
- if (isset($this->prefixes[$prefix])) return $this->prefixes[$prefix];
|
|
|
|
- return '';
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 通过文件名返回路径
|
|
|
|
- * @param string $fileName 文件名
|
|
|
|
- * @return string
|
|
|
|
- */
|
|
|
|
- public function getFileByPrefix($fileName)
|
|
|
|
- {
|
|
|
|
- $fileName = str_replace(array('/', '\\'), DS, $fileName);
|
|
|
|
- $prefixes = explode(DS, $fileName, 2);
|
|
|
|
- $dirs = isset($this->prefixes['workspace\\']) ? $this->prefixes['workspace\\'] : array();
|
|
|
|
- if (count($prefixes) == 2) {
|
|
|
|
- if (isset($this->prefixes[$prefixes[0]])) $dirs = $this->prefixes[$prefixes[0]];
|
|
|
|
- }
|
|
|
|
- foreach ($dirs as $baseDir) {
|
|
|
|
- if (is_file($baseDir . DS . $fileName)) {
|
|
|
|
- return $baseDir . DS . $fileName;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return $fileName;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 获取指定文件夹路径
|
|
|
|
- * @param string $folder 路径
|
|
|
|
- * @return string 路径
|
|
|
|
- */
|
|
|
|
- public function getFolderByPrefix($folder)
|
|
|
|
- {
|
|
|
|
- $fileName = str_replace(array('/', '\\'), DS, $folder);
|
|
|
|
- $prefixes = explode(DS, $fileName, 2);
|
|
|
|
- $dirs = isset($this->prefixes['workspace\\']) ? $this->prefixes['workspace\\'] : array();
|
|
|
|
- if (count($prefixes) == 2) {
|
|
|
|
- if (isset($this->prefixes[$prefixes[0]])) $dirs = $this->prefixes[$prefixes[0]];
|
|
|
|
- }
|
|
|
|
- foreach ($dirs as $baseDir) {
|
|
|
|
- return $baseDir . DS . $folder;
|
|
|
|
- }
|
|
|
|
- return $folder;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 通过类名加载文件
|
|
|
|
- * @param string $class 类名
|
|
|
|
- * @return string 文件路径
|
|
|
|
- */
|
|
|
|
- public function loadFileByClass($class)
|
|
|
|
- {
|
|
|
|
- // the current namespace prefix
|
|
|
|
- //replace "_" to "\" use common method to load class
|
|
|
|
- $class = str_replace("_", "\\", $class);
|
|
|
|
- $prefix = $class;
|
|
|
|
- // work backwards through the namespace names of the fully-qualified
|
|
|
|
- // class name to find a mapped file name
|
|
|
|
- while (false !== $pos = strrpos($prefix, '\\')) {
|
|
|
|
- // retain the trailing namespace separator in the prefix
|
|
|
|
- $prefix = substr($class, 0, $pos + 1);
|
|
|
|
-
|
|
|
|
- // the rest is the relative class name
|
|
|
|
- $relativeClass = substr($class, $pos + 1);
|
|
|
|
-
|
|
|
|
- // try to load a mapped file for the prefix and relative class
|
|
|
|
- $mappedFile = $this->loadMappedFile($prefix, $relativeClass);
|
|
|
|
- if ($mappedFile) {
|
|
|
|
- return $mappedFile;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // remove the trailing namespace separator for the next iteration
|
|
|
|
- // of strrpos()
|
|
|
|
- $prefix = rtrim($prefix, '\\');
|
|
|
|
- };
|
|
|
|
- //如果没有找到就在workspace中去找对应的文件 额外添加的方法
|
|
|
|
- $mappedFile = $this->loadMappedFile('workspace\\', $class);
|
|
|
|
- if ($mappedFile) {
|
|
|
|
- return $mappedFile;
|
|
|
|
- }
|
|
|
|
- $notLoaded = isset(self::$lastErrorLoadedFile[$class]) ? self::$lastErrorLoadedFile[$class] : self::getClassName($class);
|
|
|
|
- throw new \Qii\Exceptions\FileNotFound(\Qii::i(1405, $notLoaded), __LINE__);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * loadClass返回真正的类名
|
|
|
|
- *
|
|
|
|
- * @param string $class 类名
|
|
|
|
- */
|
|
|
|
- public function getClassName($class)
|
|
|
|
- {
|
|
|
|
- //如果是不使用namespace,就将namespace转换成下划线的形式
|
|
|
|
- $useNamespace = false;
|
|
|
|
- //将_隔开的统一替换成namespace方式,如果不使用namespace就再替换回来
|
|
|
|
- $class = str_replace('_', '\\', $class);
|
|
|
|
- if (stristr($class, '\\')) {
|
|
|
|
- $prefix = explode('\\', ltrim($class, '\\'))[0];
|
|
|
|
- $useNamespace = isset($this->useNamespace[$prefix]) && $this->useNamespace[$prefix] ? true : false;
|
|
|
|
- }
|
|
|
|
- if (!$useNamespace) {
|
|
|
|
- $class = str_replace('\\', '_', $class);
|
|
|
|
- }
|
|
|
|
- return $class;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Loads the class file for a given class name.
|
|
|
|
- *
|
|
|
|
- * @param string $class The fully-qualified class name.
|
|
|
|
- * @return mixed The mapped file name on success, or boolean false on
|
|
|
|
- * failure.
|
|
|
|
- */
|
|
|
|
- public function loadClass($class)
|
|
|
|
- {
|
|
|
|
- $args = func_get_args();
|
|
|
|
- //去掉第一个斜杠
|
|
|
|
- $class = array_shift($args);
|
|
|
|
- $class = preg_replace("/^\\\\/", "", $class);
|
|
|
|
- $class = $this->getClassName($class);
|
|
|
|
- array_unshift($args, $class);
|
|
|
|
-
|
|
|
|
- if (class_exists($class, false)) {
|
|
|
|
- return call_user_func_array(array($this, 'instance'), $args);
|
|
|
|
- }
|
|
|
|
- if ($this->loadFileByClass($class)) {
|
|
|
|
- return call_user_func_array(array($this, 'instance'), $args);
|
|
|
|
- }
|
|
|
|
- throw new \Qii\Exceptions\ClassNotFound(\Qii::i(1103, $class), __LINE__);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 调用静态的方法
|
|
|
|
- * @param string $class 类名
|
|
|
|
- * @param string $method 方法名
|
|
|
|
- * @return mixed
|
|
|
|
- */
|
|
|
|
- public static function loadStatic($class, $method)
|
|
|
|
- {
|
|
|
|
- $args = func_get_args();
|
|
|
|
- $class = \Qii\Autoloader\Psr4::getInstance()->getClassName(array_shift($args));
|
|
|
|
- $method = array_shift($args);
|
|
|
|
- return call_user_func_array(array($class, $method), $args);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 获取文件的绝对路径
|
|
|
|
- * @param string $path
|
|
|
|
- * @param bool $exists 是否使用realpath
|
|
|
|
- * @return string 真实路径
|
|
|
|
- */
|
|
|
|
- public static function realpath($path)
|
|
|
|
- {
|
|
|
|
- if (isset(self::$_realpath[$path])) return self::$_realpath[$path];
|
|
|
|
- $drive = '';
|
|
|
|
- if (OS === 'WIN') {
|
|
|
|
- $path = preg_replace('/[\\\\\/]/', DIRECTORY_SEPARATOR, $path);
|
|
|
|
- if (preg_match('/(phar\:\\\\|[a-zA-Z]\:)(.*)/', $path, $matches)) {
|
|
|
|
- list(, $drive, $path) = $matches;
|
|
|
|
- } else {
|
|
|
|
- $cwd = getcwd();
|
|
|
|
- $drive = substr($cwd, 0, 2);
|
|
|
|
- if (substr($path, 0, 1) != DIRECTORY_SEPARATOR) {
|
|
|
|
- $path = substr($cwd, 3) . DIRECTORY_SEPARATOR . $path;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- } elseif (substr($path, 0, 1) != DIRECTORY_SEPARATOR) {
|
|
|
|
- $path = getcwd() . DIRECTORY_SEPARATOR . $path;
|
|
|
|
- }
|
|
|
|
- $stack = array();
|
|
|
|
- $parts = explode(DIRECTORY_SEPARATOR, $path);
|
|
|
|
- foreach ($parts as $dir) {
|
|
|
|
- if (strlen($dir) && $dir !== '.') {
|
|
|
|
- if ($dir == '..') {
|
|
|
|
- array_pop($stack);
|
|
|
|
- } else {
|
|
|
|
- array_push($stack, $dir);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- $realPath = str_replace(DIRECTORY_SEPARATOR, '/', $drive . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $stack));
|
|
|
|
- self::$_realpath[$path] = $realPath;
|
|
|
|
- return $realPath;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Load the mapped file for a namespace prefix and relative class.
|
|
|
|
- *
|
|
|
|
- * @param string $prefix The namespace prefix.
|
|
|
|
- * @param string $relativeClass The relative class name.
|
|
|
|
- * @return mixed Boolean false if no mapped file can be loaded, or the
|
|
|
|
- * name of the mapped file that was loaded.
|
|
|
|
- */
|
|
|
|
- protected function loadMappedFile($prefix, $relativeClass)
|
|
|
|
- {
|
|
|
|
- if (isset(self::$cachedFiles[$prefix . '_' . $relativeClass])) return self::$cachedFiles[$prefix . '_' . $relativeClass];
|
|
|
|
- // are there any base directories for this namespace prefix?
|
|
|
|
- if (isset($this->prefixes[$prefix]) === false) {
|
|
|
|
- //if there any base directories , add self to prefix
|
|
|
|
- $this->addNamespace($prefix, $prefix);
|
|
|
|
- //return false;
|
|
|
|
- }
|
|
|
|
- $prefix = trim($prefix, '\\') . '\\';
|
|
|
|
- $file = '';
|
|
|
|
- // look through base directories for this namespace prefix
|
|
|
|
- foreach ($this->prefixes[$prefix] as $baseDir) {
|
|
|
|
- $file = str_replace("/", DS, $baseDir
|
|
|
|
- . str_replace('\\', DS, $relativeClass)
|
|
|
|
- . '.php');
|
|
|
|
- // if the mapped file exists, require it
|
|
|
|
- if ($this->requireFile($file)) {
|
|
|
|
- self::$cachedFiles[$prefix . '_' . $relativeClass] = $file;
|
|
|
|
- return $file;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- self::$lastErrorLoadedFile[$relativeClass] = $file;
|
|
|
|
- // never found it
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * If a file exists, require it from the file system.
|
|
|
|
- *
|
|
|
|
- * @param string $file The file to require.
|
|
|
|
- * @return bool True if the file exists, false if not.
|
|
|
|
- */
|
|
|
|
- protected function requireFile($file)
|
|
|
|
- {
|
|
|
|
- return \Qii\Autoloader\Import::requires($file);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * instance class
|
|
|
|
- * @param string $class
|
|
|
|
- * @return object
|
|
|
|
- */
|
|
|
|
- public function instance()
|
|
|
|
- {
|
|
|
|
- $args = func_get_args();
|
|
|
|
- $class = array_shift($args);
|
|
|
|
- $className = $this->getClassName($class);
|
|
|
|
- if (isset(self::$_loadedClass[$className])) return self::$_loadedClass[$className];
|
|
|
|
- if (!class_exists($className, false)) {
|
|
|
|
- throw new \Qii\Exceptions\CallUndefinedClass(\Qii\Application::i('1105', $className), __LINE__);
|
|
|
|
- }
|
|
|
|
- $loader = new \ReflectionClass($className);
|
|
|
|
- //try {
|
|
|
|
- self::$_loadedClass[$className] = $instance = $loader->newInstanceArgs($args);
|
|
|
|
- //如果有_initialize方法就自动调用_initialize方法,并将参数传递给_initialize方法
|
|
|
|
- if ($loader->hasMethod('_initialize')) {
|
|
|
|
- call_user_func_array(array($instance, '_initialize'), $args);
|
|
|
|
- }
|
|
|
|
- return $instance;
|
|
|
|
- /*} catch (Exception $e) {
|
|
|
|
- throw new \Exception($e->getMessage(), __LINE__);
|
|
|
|
- }*/
|
|
|
|
- }
|
|
|
|
-}
|
|
|