1 <?php
2 3 4 5 6 7
8 namespace Cross\Core;
9
10 use Cross\Exception\CoreException;
11
12 13 14 15 16
17 class Loader
18 {
19 20 21
22 private static $instance;
23
24 25 26 27 28
29 private static $namespace;
30
31 32 33 34 35
36 private static $loaded = array();
37
38 39 40
41 private function __construct()
42 {
43 spl_autoload_register(array($this, 'loadClass'));
44 spl_autoload_register(array($this, 'loadPSRClass'));
45 }
46
47 48 49 50 51
52 static function init()
53 {
54 if (!self::$instance) {
55 self::$instance = new self();
56 }
57
58 return self::$instance;
59 }
60
61 62 63 64 65 66 67
68 static function import($file)
69 {
70 return self::requireFile(PROJECT_REAL_PATH . $file, true);
71 }
72
73 74 75 76 77 78 79 80
81 static function read($file, $get_file_content = false)
82 {
83 if (!file_exists($file)) {
84 throw new CoreException("{$file} 文件不存在");
85 }
86
87 static $cache = null;
88 $flag = (int)$get_file_content;
89 if (isset($cache[$file][$flag])) {
90 return $cache[$file][$flag];
91 }
92
93 if (is_readable($file)) {
94 if ($get_file_content) {
95 $file_content = file_get_contents($file);
96 $cache[$file][$flag] = $file_content;
97 return $file_content;
98 }
99
100 switch (Helper::getExt($file)) {
101 case 'php' :
102 $data = require $file;
103 $cache[$file][$flag] = $data;
104 break;
105
106 case 'json' :
107 $data = json_decode(file_get_contents($file), true);
108 $cache[$file][$flag] = $data;
109 break;
110
111 case 'ini':
112 $data = parse_ini_file($file, true);
113 $cache[$file][$flag] = $data;
114 break;
115
116 default :
117 throw new CoreException('不支持的解析格式');
118 }
119
120 return $data;
121 } else {
122 throw new CoreException("读取文件失败:{$file}");
123 }
124 }
125
126 127 128 129 130
131 static function getNamespaceMap()
132 {
133 return self::$namespace;
134 }
135
136 137 138 139 140 141 142
143 static function registerNamespace($prefix, $base_dir, $prepend = false)
144 {
145 $prefix = trim($prefix, '\\') . '\\';
146 $base_dir = rtrim($base_dir, DIRECTORY_SEPARATOR) . '/';
147 if (isset(self::$namespace[$prefix]) === false) {
148 self::$namespace[$prefix] = array();
149 }
150
151 if ($prepend) {
152 array_unshift(self::$namespace[$prefix], $base_dir);
153 } else {
154 array_push(self::$namespace[$prefix], $base_dir);
155 }
156 }
157
158 159 160 161 162 163 164
165 private function loadClass($class_name)
166 {
167 $prefix = '';
168 $pos = strpos($class_name, '\\');
169 if (false !== $pos) {
170 $prefix = substr($class_name, 0, $pos);
171 $class_name = str_replace('\\', DIRECTORY_SEPARATOR, $class_name);
172 }
173
174 $check_file_exists = true;
175 if ('' !== $prefix && 0 === strcasecmp($prefix, 'cross')) {
176 $check_file_exists = false;
177 $class_file = CP_PATH . substr($class_name, $pos + 1) . '.php';
178 } else {
179 $class_file = PROJECT_REAL_PATH . $class_name . '.php';
180 }
181
182 $this->requireFile($class_file, false, $check_file_exists);
183 return $class_file;
184 }
185
186 187 188 189 190 191 192
193 private function loadPSRClass($class)
194 {
195 $prefix = $class;
196 while (false !== $pos = strrpos($prefix, '\\')) {
197 $prefix = substr($class, 0, $pos + 1);
198 $relative_class = substr($class, $pos + 1);
199
200 $mapped_file = $this->loadMappedFile($prefix, $relative_class);
201 if ($mapped_file) {
202 return $mapped_file;
203 }
204 $prefix = rtrim($prefix, '\\');
205 }
206
207 return false;
208 }
209
210 211 212 213 214 215 216 217
218 private function loadMappedFile($prefix, $relative_class)
219 {
220 if (isset(self::$namespace[$prefix]) === false) {
221 return false;
222 }
223
224 foreach (self::$namespace[$prefix] as $base_dir) {
225 $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
226 if ($this->requireFile($file)) {
227 return $file;
228 }
229 }
230
231 return false;
232 }
233
234 235 236 237 238 239 240 241 242
243 private static function requireFile($file, $throw_exception = false, $check_file_exists = true)
244 {
245 if (isset(self::$loaded[$file])) {
246 return true;
247 } elseif ($check_file_exists === false) {
248 require $file;
249 self::$loaded[$file] = true;
250 return true;
251 } elseif (is_file($file)) {
252 require $file;
253 self::$loaded[$file] = true;
254 return true;
255 } elseif ($throw_exception) {
256 throw new CoreException("未找到要载入的文件:{$file}");
257 } else {
258 return false;
259 }
260 }
261
262 }
263