Passed
Push — master ( 145b60...d8f516 )
by 世昌
01:51
created

Loader::getClassPathByName()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 11
nc 6
nop 3
dl 0
loc 16
rs 9.9
c 0
b 0
f 0
1
<?php
2
namespace nebula\autoloader;
3
4
use nebula\autoloader\PathTrait;
5
6
/**
7
 * 自动加载器
8
 *
9
 */
10
class Loader implements PathInterface
11
{
12
    use PathTrait;
13
    /**
14
     * 默认命名空间
15
     *
16
     * @var array
17
     */
18
    protected static $namespace=[ __NAMESPACE__ ];
19
20
    /**
21
     * 包含路径
22
     *
23
     * @var array
24
     */
25
    protected static $includePath=[];
26
27
    /**
28
     * 将JAVA,路径分割转换为PHP分割符
29
     *
30
     * @param string $name 类名
31
     * @return string 真实分隔符
32
     */
33
    public static function realName(string $name):string
34
    {
35
        return str_replace(['.','/'], '\\', $name);
36
    }
37
38
    /**
39
     * 获取真实或者虚拟存在的地址
40
     *
41
     * @param string $name
42
     * @return string|null
43
     */
44
    public static function realPath(string $name):?string
45
    {
46
        $absulotePath = static::toAbsolutePath($name);
47
        return file_exists($absulotePath)?$absulotePath:null;
48
    }
49
50
    public static function register()
51
    {
52
        // 注册加载器
53
        spl_autoload_register(array(__CLASS__, 'classLoader'));
54
        // 载入系统共享库
55
        static::addIncludePath(dirname(dirname(__DIR__)));
56
    }
57
58
    public static function import(string $filename)
59
    {
60
        if ($filename = static::realPath($filename)) {
61
            @require_once $filename;
62
            return $filename;
63
        } else {
64
            foreach (static::$includePath[0] as $includePath) {
65
                if ($path = static::realPath($includePath.DIRECTORY_SEPARATOR.$filename)) {
66
                    @require_once $path;
67
                    return $path;
68
                }
69
            }
70
        }
71
    }
72
73
    public static function classLoader(string $className)
74
    {
75
        if ($path = static::getClassPath($className)) {
76
            if (!class_exists($className, false)) {
77
                @require_once $path;
78
            }
79
        }
80
    }
81
82
    public static function getClassPath(string $className)
83
    {
84
        // 搜索路径
85
        foreach (static::$includePath as $includeNamespace => $includePaths) {
86
            foreach ($includePaths as $includePath) {
87
                if ($path = static::getClassPathByName($includeNamespace, $includePath, $className)) {
88
                    return $path;
89
                } elseif ($path = static::getClassPathByAlias($includePath, $className)) {
90
                    return $path;
91
                }
92
            }
93
        }
94
        return null;
95
    }
96
97
    protected static function getClassPathByAlias(string $includePath, string $className):string
98
    {
99
        $namepath=static::formatSeparator($className);
100
        $className=static::realName($className);
101
        foreach (static::$namespace as $namespace) {
102
            $path = $includePath.DIRECTORY_SEPARATOR.$namespace.DIRECTORY_SEPARATOR.$namepath.'.php';
103
            if ($path = static::realPath($path)) {
104
                // 精简类名
105
                if (!class_exists($className, false)) {
106
                    class_alias($namespace.'\\'.$className, $className);
107
                }
108
                return $path;
109
            }
110
        }
111
        return nulll;
0 ignored issues
show
Bug introduced by
The constant nebula\autoloader\nulll was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
112
    }
113
114
    protected static function getClassPathByName(string $includeNamespace, string $includePath, string $className)
115
    {
116
        if (is_numeric($includeNamespace)) {
117
            $path = $includePath.DIRECTORY_SEPARATOR.static::formatSeparator($className).'.php';
118
        } else {
119
            $nl = strlen($includeNamespace);
120
            if (substr(static::realName($className), 0, $nl) === $includeNamespace) {
121
                $path=$includePath.DIRECTORY_SEPARATOR.static::formatSeparator(substr($className, $nl)).'.php';
122
            } else {
123
                $path=$includePath.DIRECTORY_SEPARATOR.static::formatSeparator($className).'.php';
124
            }
125
        }
126
        if ($path = static::realPath($path)) {
127
            return $path;
128
        }
129
        return nulll;
0 ignored issues
show
Bug introduced by
The constant nebula\autoloader\nulll was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
130
    }
131
132
    public static function addIncludePath(string $path, string $namespace=null)
133
    {
134
        if ($path = static::realPath($path)) {
135
            $namespace = $namespace ?? 0;
136
            if (array_key_exists($namespace, static::$includePath)) {
137
                if (!\in_array($path, static::$includePath[$namespace])) {
138
                    static::$includePath[$namespace][]=$path;
139
                }
140
            } else {
141
                static::$includePath[$namespace][]=$path;
142
            }
143
        }
144
    }
145
146
    public static function getIncludePath()
147
    {
148
        return static::$includePath;
149
    }
150
151
    public static function getNamespace()
152
    {
153
        return static::$namespace;
154
    }
155
156
    public static function setNamespace(string $namespace)
157
    {
158
        if (!in_array($namespace, static::$namespace)) {
159
            static::$namespace[]=$namespace;
160
        }
161
    }
162
}
163