| <?php |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| namespace think; |
|
|
| use think\exception\ClassNotFoundException; |
|
|
| class Loader |
| { |
| |
| |
| |
| protected static $instance = []; |
|
|
| |
| |
| |
| protected static $classMap = []; |
|
|
| |
| |
| |
| protected static $namespaceAlias = []; |
|
|
| |
| |
| |
| private static $prefixLengthsPsr4 = []; |
|
|
| |
| |
| |
| private static $prefixDirsPsr4 = []; |
|
|
| |
| |
| |
| private static $fallbackDirsPsr4 = []; |
|
|
| |
| |
| |
| private static $prefixesPsr0 = []; |
|
|
| |
| |
| |
| private static $fallbackDirsPsr0 = []; |
|
|
| |
| |
| |
| private static $files = []; |
|
|
| |
| |
| |
| |
| |
| |
| public static function autoload($class) |
| { |
| |
| if (!empty(self::$namespaceAlias)) { |
| $namespace = dirname($class); |
| if (isset(self::$namespaceAlias[$namespace])) { |
| $original = self::$namespaceAlias[$namespace] . '\\' . basename($class); |
| if (class_exists($original)) { |
| return class_alias($original, $class, false); |
| } |
| } |
| } |
|
|
| if ($file = self::findFile($class)) { |
| |
| if (!IS_WIN || pathinfo($file, PATHINFO_FILENAME) == pathinfo(realpath($file), PATHINFO_FILENAME)) { |
| __include_file($file); |
| return true; |
| } |
| } |
|
|
| return false; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| private static function findFile($class) |
| { |
| |
| if (!empty(self::$classMap[$class])) { |
| return self::$classMap[$class]; |
| } |
|
|
| |
| $logicalPathPsr4 = strtr($class, '\\', DS) . EXT; |
| $first = $class[0]; |
|
|
| if (isset(self::$prefixLengthsPsr4[$first])) { |
| foreach (self::$prefixLengthsPsr4[$first] as $prefix => $length) { |
| if (0 === strpos($class, $prefix)) { |
| foreach (self::$prefixDirsPsr4[$prefix] as $dir) { |
| if (is_file($file = $dir . DS . substr($logicalPathPsr4, $length))) { |
| return $file; |
| } |
| } |
| } |
| } |
| } |
|
|
| |
| foreach (self::$fallbackDirsPsr4 as $dir) { |
| if (is_file($file = $dir . DS . $logicalPathPsr4)) { |
| return $file; |
| } |
| } |
|
|
| |
| if (false !== $pos = strrpos($class, '\\')) { |
| |
| $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) |
| . strtr(substr($logicalPathPsr4, $pos + 1), '_', DS); |
| } else { |
| |
| $logicalPathPsr0 = strtr($class, '_', DS) . EXT; |
| } |
|
|
| if (isset(self::$prefixesPsr0[$first])) { |
| foreach (self::$prefixesPsr0[$first] as $prefix => $dirs) { |
| if (0 === strpos($class, $prefix)) { |
| foreach ($dirs as $dir) { |
| if (is_file($file = $dir . DS . $logicalPathPsr0)) { |
| return $file; |
| } |
| } |
| } |
| } |
| } |
|
|
| |
| foreach (self::$fallbackDirsPsr0 as $dir) { |
| if (is_file($file = $dir . DS . $logicalPathPsr0)) { |
| return $file; |
| } |
| } |
|
|
| |
| return self::$classMap[$class] = false; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| public static function addClassMap($class, $map = '') |
| { |
| if (is_array($class)) { |
| self::$classMap = array_merge(self::$classMap, $class); |
| } else { |
| self::$classMap[$class] = $map; |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| public static function addNamespace($namespace, $path = '') |
| { |
| if (is_array($namespace)) { |
| foreach ($namespace as $prefix => $paths) { |
| self::addPsr4($prefix . '\\', rtrim($paths, DS), true); |
| } |
| } else { |
| self::addPsr4($namespace . '\\', rtrim($path, DS), true); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| private static function addPsr0($prefix, $paths, $prepend = false) |
| { |
| if (!$prefix) { |
| self::$fallbackDirsPsr0 = $prepend ? |
| array_merge((array) $paths, self::$fallbackDirsPsr0) : |
| array_merge(self::$fallbackDirsPsr0, (array) $paths); |
| } else { |
| $first = $prefix[0]; |
|
|
| if (!isset(self::$prefixesPsr0[$first][$prefix])) { |
| self::$prefixesPsr0[$first][$prefix] = (array) $paths; |
| } else { |
| self::$prefixesPsr0[$first][$prefix] = $prepend ? |
| array_merge((array) $paths, self::$prefixesPsr0[$first][$prefix]) : |
| array_merge(self::$prefixesPsr0[$first][$prefix], (array) $paths); |
| } |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| private static function addPsr4($prefix, $paths, $prepend = false) |
| { |
| if (!$prefix) { |
| |
| self::$fallbackDirsPsr4 = $prepend ? |
| array_merge((array) $paths, self::$fallbackDirsPsr4) : |
| array_merge(self::$fallbackDirsPsr4, (array) $paths); |
|
|
| } elseif (!isset(self::$prefixDirsPsr4[$prefix])) { |
| |
| $length = strlen($prefix); |
| if ('\\' !== $prefix[$length - 1]) { |
| throw new \InvalidArgumentException( |
| "A non-empty PSR-4 prefix must end with a namespace separator." |
| ); |
| } |
|
|
| self::$prefixLengthsPsr4[$prefix[0]][$prefix] = $length; |
| self::$prefixDirsPsr4[$prefix] = (array) $paths; |
|
|
| } else { |
| self::$prefixDirsPsr4[$prefix] = $prepend ? |
| |
| array_merge((array) $paths, self::$prefixDirsPsr4[$prefix]) : |
| |
| array_merge(self::$prefixDirsPsr4[$prefix], (array) $paths); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| public static function addNamespaceAlias($namespace, $original = '') |
| { |
| if (is_array($namespace)) { |
| self::$namespaceAlias = array_merge(self::$namespaceAlias, $namespace); |
| } else { |
| self::$namespaceAlias[$namespace] = $original; |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public static function register($autoload = null) |
| { |
| |
| spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true); |
|
|
| |
| if (is_dir(VENDOR_PATH . 'composer')) { |
| if (PHP_VERSION_ID >= 50600 && is_file(VENDOR_PATH . 'composer' . DS . 'autoload_static.php')) { |
| require VENDOR_PATH . 'composer' . DS . 'autoload_static.php'; |
|
|
| $declaredClass = get_declared_classes(); |
| $composerClass = array_pop($declaredClass); |
|
|
| foreach (['prefixLengthsPsr4', 'prefixDirsPsr4', 'fallbackDirsPsr4', 'prefixesPsr0', 'fallbackDirsPsr0', 'classMap', 'files'] as $attr) { |
| if (property_exists($composerClass, $attr)) { |
| self::${$attr} = $composerClass::${$attr}; |
| } |
| } |
| } else { |
| self::registerComposerLoader(); |
| } |
| } |
|
|
| |
| self::addNamespace([ |
| 'think' => LIB_PATH . 'think' . DS, |
| 'behavior' => LIB_PATH . 'behavior' . DS, |
| 'traits' => LIB_PATH . 'traits' . DS, |
| ]); |
|
|
| |
| if (is_file(RUNTIME_PATH . 'classmap' . EXT)) { |
| self::addClassMap(__include_file(RUNTIME_PATH . 'classmap' . EXT)); |
| } |
|
|
| self::loadComposerAutoloadFiles(); |
|
|
| |
| self::$fallbackDirsPsr4[] = rtrim(EXTEND_PATH, DS); |
| } |
|
|
| |
| |
| |
| |
| |
| private static function registerComposerLoader() |
| { |
| if (is_file(VENDOR_PATH . 'composer/autoload_namespaces.php')) { |
| $map = require VENDOR_PATH . 'composer/autoload_namespaces.php'; |
| foreach ($map as $namespace => $path) { |
| self::addPsr0($namespace, $path); |
| } |
| } |
|
|
| if (is_file(VENDOR_PATH . 'composer/autoload_psr4.php')) { |
| $map = require VENDOR_PATH . 'composer/autoload_psr4.php'; |
| foreach ($map as $namespace => $path) { |
| self::addPsr4($namespace, $path); |
| } |
| } |
|
|
| if (is_file(VENDOR_PATH . 'composer/autoload_classmap.php')) { |
| $classMap = require VENDOR_PATH . 'composer/autoload_classmap.php'; |
| if ($classMap) { |
| self::addClassMap($classMap); |
| } |
| } |
|
|
| if (is_file(VENDOR_PATH . 'composer/autoload_files.php')) { |
| self::$files = require VENDOR_PATH . 'composer/autoload_files.php'; |
| } |
| } |
|
|
| |
| public static function loadComposerAutoloadFiles() |
| { |
| foreach (self::$files as $fileIdentifier => $file) { |
| if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { |
| __require_file($file); |
|
|
| $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; |
| } |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| public static function import($class, $baseUrl = '', $ext = EXT) |
| { |
| static $_file = []; |
| $key = $class . $baseUrl; |
| $class = str_replace(['.', '#'], [DS, '.'], $class); |
|
|
| if (isset($_file[$key])) { |
| return true; |
| } |
|
|
| if (empty($baseUrl)) { |
| list($name, $class) = explode(DS, $class, 2); |
|
|
| if (isset(self::$prefixDirsPsr4[$name . '\\'])) { |
| |
| $baseUrl = self::$prefixDirsPsr4[$name . '\\']; |
| } elseif ('@' == $name) { |
| |
| $baseUrl = App::$modulePath; |
| } elseif (is_dir(EXTEND_PATH . $name)) { |
| $baseUrl = EXTEND_PATH . $name . DS; |
| } else { |
| |
| $baseUrl = APP_PATH . $name . DS; |
| } |
| } elseif (substr($baseUrl, -1) != DS) { |
| $baseUrl .= DS; |
| } |
|
|
| |
| if (is_array($baseUrl)) { |
| foreach ($baseUrl as $path) { |
| if (is_file($filename = $path . DS . $class . $ext)) { |
| break; |
| } |
| } |
| } else { |
| $filename = $baseUrl . $class . $ext; |
| } |
|
|
| if (!empty($filename) && |
| is_file($filename) && |
| (!IS_WIN || pathinfo($filename, PATHINFO_FILENAME) == pathinfo(realpath($filename), PATHINFO_FILENAME)) |
| ) { |
| __include_file($filename); |
| $_file[$key] = true; |
|
|
| return true; |
| } |
|
|
| return false; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public static function model($name = '', $layer = 'model', $appendSuffix = false, $common = 'common') |
| { |
| $uid = $name . $layer; |
|
|
| if (isset(self::$instance[$uid])) { |
| return self::$instance[$uid]; |
| } |
|
|
| list($module, $class) = self::getModuleAndClass($name, $layer, $appendSuffix); |
|
|
| if (class_exists($class)) { |
| $model = new $class(); |
| } else { |
| $class = str_replace('\\' . $module . '\\', '\\' . $common . '\\', $class); |
|
|
| if (class_exists($class)) { |
| $model = new $class(); |
| } else { |
| throw new ClassNotFoundException('class not exists:' . $class, $class); |
| } |
| } |
|
|
| return self::$instance[$uid] = $model; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public static function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '') |
| { |
| list($module, $class) = self::getModuleAndClass($name, $layer, $appendSuffix); |
|
|
| if (class_exists($class)) { |
| return App::invokeClass($class); |
| } |
|
|
| if ($empty) { |
| $emptyClass = self::parseClass($module, $layer, $empty, $appendSuffix); |
|
|
| if (class_exists($emptyClass)) { |
| return new $emptyClass(Request::instance()); |
| } |
| } |
|
|
| throw new ClassNotFoundException('class not exists:' . $class, $class); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public static function validate($name = '', $layer = 'validate', $appendSuffix = false, $common = 'common') |
| { |
| $name = $name ?: Config::get('default_validate'); |
|
|
| if (empty($name)) { |
| return new Validate; |
| } |
|
|
| $uid = $name . $layer; |
| if (isset(self::$instance[$uid])) { |
| return self::$instance[$uid]; |
| } |
|
|
| list($module, $class) = self::getModuleAndClass($name, $layer, $appendSuffix); |
|
|
| if (class_exists($class)) { |
| $validate = new $class; |
| } else { |
| $class = str_replace('\\' . $module . '\\', '\\' . $common . '\\', $class); |
|
|
| if (class_exists($class)) { |
| $validate = new $class; |
| } else { |
| throw new ClassNotFoundException('class not exists:' . $class, $class); |
| } |
| } |
|
|
| return self::$instance[$uid] = $validate; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| protected static function getModuleAndClass($name, $layer, $appendSuffix) |
| { |
| if (false !== strpos($name, '\\')) { |
| $module = Request::instance()->module(); |
| $class = $name; |
| } else { |
| if (strpos($name, '/')) { |
| list($module, $name) = explode('/', $name, 2); |
| } else { |
| $module = Request::instance()->module(); |
| } |
|
|
| $class = self::parseClass($module, $layer, $name, $appendSuffix); |
| } |
|
|
| return [$module, $class]; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| public static function db($config = [], $name = false) |
| { |
| return Db::connect($config, $name); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public static function action($url, $vars = [], $layer = 'controller', $appendSuffix = false) |
| { |
| $info = pathinfo($url); |
| $action = $info['basename']; |
| $module = '.' != $info['dirname'] ? $info['dirname'] : Request::instance()->controller(); |
| $class = self::controller($module, $layer, $appendSuffix); |
|
|
| if ($class) { |
| if (is_scalar($vars)) { |
| if (strpos($vars, '=')) { |
| parse_str($vars, $vars); |
| } else { |
| $vars = [$vars]; |
| } |
| } |
|
|
| return App::invokeMethod([$class, $action . Config::get('action_suffix')], $vars); |
| } |
|
|
| return false; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public static function parseName($name, $type = 0, $ucfirst = true) |
| { |
| if ($type) { |
| $name = preg_replace_callback('/_([a-zA-Z])/', function ($match) { |
| return strtoupper($match[1]); |
| }, $name); |
|
|
| return $ucfirst ? ucfirst($name) : lcfirst($name); |
| } |
|
|
| return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_")); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public static function parseClass($module, $layer, $name, $appendSuffix = false) |
| { |
|
|
| $array = explode('\\', str_replace(['/', '.'], '\\', $name)); |
| $class = self::parseName(array_pop($array), 1); |
| $class = $class . (App::$suffix || $appendSuffix ? ucfirst($layer) : ''); |
| $path = $array ? implode('\\', $array) . '\\' : ''; |
|
|
| return App::$namespace . '\\' . |
| ($module ? $module . '\\' : '') . |
| $layer . '\\' . $path . $class; |
| } |
|
|
| |
| |
| |
| |
| |
| public static function clearInstance() |
| { |
| self::$instance = []; |
| } |
| } |
|
|
| |
|
|
| |
| |
| |
| |
| |
| function __include_file($file) |
| { |
| return include $file; |
| } |
|
|
| |
| |
| |
| |
| |
| function __require_file($file) |
| { |
| return require $file; |
| } |
|
|