1
|
|
|
<?php |
2
|
|
|
namespace nebula; |
3
|
|
|
|
4
|
|
|
use nebula\application\Route; |
5
|
|
|
use nebula\application\Debugger; |
6
|
|
|
use nebula\application\Resource; |
7
|
|
|
use nebula\component\debug\Debug; |
8
|
|
|
use nebula\component\loader\Path; |
9
|
|
|
use nebula\application\Application; |
10
|
|
|
use nebula\component\loader\Loader; |
11
|
|
|
use nebula\application\config\Config; |
12
|
|
|
use nebula\component\request\Request; |
13
|
|
|
use nebula\application\cache\FileCache; |
14
|
|
|
use nebula\component\runnable\Runnable; |
15
|
|
|
use nebula\application\filesystem\FileSystem; |
16
|
|
|
use nebula\component\cacheable\CacheInterface; |
17
|
|
|
use nebula\component\debug\log\AbstractLogger; |
18
|
|
|
use nebula\component\debug\log\logger\FileLogger; |
19
|
|
|
use nebula\component\debug\log\logger\NullLogger; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* 应用 |
23
|
|
|
* |
24
|
|
|
*/ |
25
|
|
|
class NebulaApplication |
26
|
|
|
{ |
27
|
|
|
/** |
28
|
|
|
* 应用路径 |
29
|
|
|
* |
30
|
|
|
* @var string |
31
|
|
|
*/ |
32
|
|
|
protected $path; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* 数据路径 |
36
|
|
|
* |
37
|
|
|
* @var string |
38
|
|
|
*/ |
39
|
|
|
protected $dataPath; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* 类加载器 |
43
|
|
|
* |
44
|
|
|
* @var Loader |
45
|
|
|
*/ |
46
|
|
|
protected $classLoader; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* 调试工具 |
50
|
|
|
* |
51
|
|
|
* @var Debug |
52
|
|
|
*/ |
53
|
|
|
protected $debugger; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* 路由 |
57
|
|
|
* |
58
|
|
|
* @var Route |
59
|
|
|
*/ |
60
|
|
|
protected $route; |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* 配置信息 |
64
|
|
|
* |
65
|
|
|
* @var Config |
66
|
|
|
*/ |
67
|
|
|
protected $config; |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* 应用引用程序 |
71
|
|
|
* |
72
|
|
|
* @var Application |
73
|
|
|
*/ |
74
|
|
|
protected $application; |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* 请求封装 |
78
|
|
|
* |
79
|
|
|
* @var Request |
80
|
|
|
*/ |
81
|
|
|
protected $request; |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* 缓存 |
85
|
|
|
* |
86
|
|
|
* @var CacheInterface |
87
|
|
|
*/ |
88
|
|
|
protected $cache; |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* 静态实例 |
92
|
|
|
* |
93
|
|
|
* @var NebulaApplication |
94
|
|
|
*/ |
95
|
|
|
protected static $instance; |
96
|
|
|
|
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* 返回实例 |
100
|
|
|
* |
101
|
|
|
* @return NebulaApplication |
102
|
|
|
*/ |
103
|
|
|
public static function instance() |
104
|
|
|
{ |
105
|
|
|
if (isset(static::$instance)) { |
106
|
|
|
return static::$instance; |
107
|
|
|
} |
108
|
|
|
return static::$instance = new static; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* Get 类加载器 |
113
|
|
|
* |
114
|
|
|
* @return Loader |
115
|
|
|
*/ |
116
|
|
|
public function getClassLoader() |
117
|
|
|
{ |
118
|
|
|
return $this->classLoader; |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
/** |
122
|
|
|
* Set 类加载器 |
123
|
|
|
* |
124
|
|
|
* @param Loader $classLoader 类加载器 |
125
|
|
|
* |
126
|
|
|
* @return self |
127
|
|
|
*/ |
128
|
|
|
public function setClassLoader(Loader $classLoader) |
129
|
|
|
{ |
130
|
|
|
$this->classLoader = $classLoader; |
131
|
|
|
|
132
|
|
|
return $this; |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Get 调试工具 |
137
|
|
|
* |
138
|
|
|
* @return Debug |
139
|
|
|
*/ |
140
|
|
|
public function getDebugger() |
141
|
|
|
{ |
142
|
|
|
return $this->debugger; |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* Set 调试工具 |
147
|
|
|
* |
148
|
|
|
* @param Debug $debugger 调试工具 |
149
|
|
|
* |
150
|
|
|
* @return self |
151
|
|
|
*/ |
152
|
|
|
public function setDebugger(Debug $debugger) |
153
|
|
|
{ |
154
|
|
|
$this->debugger = $debugger; |
155
|
|
|
|
156
|
|
|
return $this; |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
|
160
|
|
|
/** |
161
|
|
|
* Get 配置信息 |
162
|
|
|
* |
163
|
|
|
* @return Config |
164
|
|
|
*/ |
165
|
|
|
public function getConfig() |
166
|
|
|
{ |
167
|
|
|
return $this->config; |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* Set 配置信息 |
172
|
|
|
* |
173
|
|
|
* @param Config $config 配置信息 |
174
|
|
|
* |
175
|
|
|
* @return self |
176
|
|
|
*/ |
177
|
|
|
public function setConfig(Config $config) |
178
|
|
|
{ |
179
|
|
|
$this->config = $config; |
180
|
|
|
|
181
|
|
|
return $this; |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* Get 路由 |
186
|
|
|
* |
187
|
|
|
* @return Route |
188
|
|
|
*/ |
189
|
|
|
public function getRoute() |
190
|
|
|
{ |
191
|
|
|
return $this->route; |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
/** |
195
|
|
|
* Set 路由 |
196
|
|
|
* |
197
|
|
|
* @param Route $route 路由 |
198
|
|
|
* |
199
|
|
|
* @return self |
200
|
|
|
*/ |
201
|
|
|
public function setRoute(Route $route) |
202
|
|
|
{ |
203
|
|
|
$this->route = $route; |
204
|
|
|
|
205
|
|
|
return $this; |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
public static function configuration(string $path) |
209
|
|
|
{ |
210
|
|
|
$nebula = static::instance(); |
211
|
|
|
$nebula->path = $path; |
212
|
|
|
if (!FileSystem::exist($path)) { |
213
|
|
|
FileSystem::copyDir(NEBULA_RESOURCE.'/application', $path); |
214
|
|
|
} |
215
|
|
|
$config = new Config; |
216
|
|
|
$manifast = $config->loadConfig($path.'/manifast.json'); |
217
|
|
|
$config->set('app', $manifast); |
218
|
|
|
$nebula->setConfig($config); |
219
|
|
|
$nebula->initialization(); |
220
|
|
|
$nebula->dataPath = Path::toAbsolutePath(defined('NEBULA_DATA') ? constant('NEBULA_DATA') : '~/nebula-data'); |
221
|
|
|
return $nebula; |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
/** |
225
|
|
|
* 初始化操作 |
226
|
|
|
* |
227
|
|
|
* @return void |
228
|
|
|
*/ |
229
|
|
|
protected function initialization() |
230
|
|
|
{ |
231
|
|
|
$request = Request::buildFromServer(); |
232
|
|
|
$request->apply(true); |
233
|
|
|
$this->setRequest($request); |
234
|
|
|
$this->initBaseConfig(); |
235
|
|
|
$this->initDebugger(); |
236
|
|
|
$this->initCache(); |
237
|
|
|
$this->getDebugger()->info('initialized nebula application'); |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
|
241
|
|
|
/** |
242
|
|
|
* 初始化基本配置 |
243
|
|
|
* |
244
|
|
|
* @return void |
245
|
|
|
*/ |
246
|
|
|
private function initBaseConfig() |
247
|
|
|
{ |
248
|
|
|
if (!$this->config->has('app.route.active')) { |
249
|
|
|
$this->config->set('app.route.active', ['default']); |
250
|
|
|
} |
251
|
|
|
if (defined('NEBULA_ROUTE_GROUPS')) { |
252
|
|
|
$this->config->set('app.route.active', \explode(',', constant('NEBULA_ROUTE_GROUPS'))); |
253
|
|
|
} |
254
|
|
|
if (!$this->config->has('app.import')) { |
255
|
|
|
$this->config->set('app.import', [ |
256
|
|
|
0 => \constant('NEBULA_APP').'/' .'share', |
257
|
|
|
]); |
258
|
|
|
} |
259
|
|
|
if (!$this->config->has('app.resource')) { |
260
|
|
|
$this->config->set('app.resource', [ |
261
|
|
|
0 => \constant('NEBULA_APP').'/' .'resource', |
262
|
|
|
]); |
263
|
|
|
} |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
|
267
|
|
|
/** |
268
|
|
|
* 初始化调试工具 |
269
|
|
|
* |
270
|
|
|
* @return void |
271
|
|
|
*/ |
272
|
|
|
private function initDebugger() |
273
|
|
|
{ |
274
|
|
|
$logger = (new Runnable($this->getConfig()->get('app.logger-build', [$this, 'buildLogger'])))->run(); |
275
|
|
|
$debugger = new Debugger; |
276
|
|
|
$debugger->applyConfig([ |
277
|
|
|
'start-time' => \constant('NEBULA_START_TIME'), |
278
|
|
|
'start-memory' => \constant('NEBULA_START_MEMORY'), |
279
|
|
|
]); |
280
|
|
|
$debugger->setLogger($logger); |
281
|
|
|
$this->setDebugger($debugger); |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
/** |
285
|
|
|
* 构建日志记录器 |
286
|
|
|
* |
287
|
|
|
* @return AbstractLogger |
288
|
|
|
*/ |
289
|
|
|
private function buildLogger(): AbstractLogger |
290
|
|
|
{ |
291
|
|
|
$dataPath = $this->dataPath; |
292
|
|
|
if (\is_writable(dirname($dataPath))) { |
293
|
|
|
return new FileLogger( |
294
|
|
|
[ |
295
|
|
|
'log-level' => defined('NEBULA_DEBUG_LEVEL') ? defined('NEBULA_DEBUG_LEVEL') : 'debug', |
296
|
|
|
'save-path' => $dataPath.'/logs', |
297
|
|
|
'save-zip-path' => $dataPath.'/logs/zip', |
298
|
|
|
'log-format' => '%message%', |
299
|
|
|
'save-pack-path' => $dataPath.'/logs/dump', |
300
|
|
|
] |
301
|
|
|
); |
302
|
|
|
FileSystem::makes($dataPath.'/logs/zip'); |
|
|
|
|
303
|
|
|
FileSystem::makes($dataPath.'/logs/dump'); |
304
|
|
|
} |
305
|
|
|
return new NullLogger; |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
/** |
309
|
|
|
* 初始化缓存器 |
310
|
|
|
* |
311
|
|
|
* @return void |
312
|
|
|
*/ |
313
|
|
|
private function initCache() |
314
|
|
|
{ |
315
|
|
|
$cache = (new Runnable($this->getConfig()->get('app.cache-build', [$this, 'buildCache'])))->run(); |
316
|
|
|
$this->cache = $cache; |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
/** |
320
|
|
|
* 构建文件缓存 |
321
|
|
|
* |
322
|
|
|
* @return CacheInterface |
323
|
|
|
*/ |
324
|
|
|
private function buildCache(): CacheInterface |
325
|
|
|
{ |
326
|
|
|
$dataPath = $this->dataPath.'/cache'; |
327
|
|
|
FileSystem::makes($dataPath); |
328
|
|
|
return new FileCache($dataPath); |
329
|
|
|
} |
330
|
|
|
|
331
|
|
|
/** |
332
|
|
|
* Get 应用引用程序 |
333
|
|
|
* |
334
|
|
|
* @return Application |
335
|
|
|
*/ |
336
|
|
|
public function getApplication() |
337
|
|
|
{ |
338
|
|
|
return $this->application; |
339
|
|
|
} |
340
|
|
|
|
341
|
|
|
/** |
342
|
|
|
* Set 应用引用程序 |
343
|
|
|
* |
344
|
|
|
* @param Application $application 应用引用程序 |
345
|
|
|
* |
346
|
|
|
* @return self |
347
|
|
|
*/ |
348
|
|
|
public function setApplication(Application $application) |
349
|
|
|
{ |
350
|
|
|
$this->application = $application; |
351
|
|
|
|
352
|
|
|
return $this; |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
/** |
356
|
|
|
* 运行应用 |
357
|
|
|
* |
358
|
|
|
* @return void |
359
|
|
|
*/ |
360
|
|
|
public function run() |
361
|
|
|
{ |
362
|
|
|
$className = $this->config->get('app.application', Application::class); |
363
|
|
|
$this->application = Runnable::newClassInstance($className); |
364
|
|
|
$this->application->setNebula($this); |
365
|
|
|
$this->application->initialization(); |
366
|
|
|
$this->application->onRequest($this->getRequest()); |
367
|
|
|
$this->getDebugger()->info('nebula application shutdown'); |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
/** |
371
|
|
|
* Get 请求封装 |
372
|
|
|
* |
373
|
|
|
* @return Request |
374
|
|
|
*/ |
375
|
|
|
public function getRequest() |
376
|
|
|
{ |
377
|
|
|
return $this->request; |
378
|
|
|
} |
379
|
|
|
|
380
|
|
|
/** |
381
|
|
|
* Set 请求封装 |
382
|
|
|
* |
383
|
|
|
* @param Request $request 请求封装 |
384
|
|
|
* |
385
|
|
|
* @return self |
386
|
|
|
*/ |
387
|
|
|
public function setRequest(Request $request) |
388
|
|
|
{ |
389
|
|
|
$this->request = $request; |
390
|
|
|
|
391
|
|
|
return $this; |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
/** |
395
|
|
|
* Get 缓存 |
396
|
|
|
* |
397
|
|
|
* @return CacheInterface |
398
|
|
|
*/ |
399
|
|
|
public function getCache() |
400
|
|
|
{ |
401
|
|
|
return $this->cache; |
402
|
|
|
} |
403
|
|
|
|
404
|
|
|
/** |
405
|
|
|
* Set 缓存 |
406
|
|
|
* |
407
|
|
|
* @param CacheInterface $cache 缓存 |
408
|
|
|
* |
409
|
|
|
* @return self |
410
|
|
|
*/ |
411
|
|
|
public function setCache(CacheInterface $cache) |
412
|
|
|
{ |
413
|
|
|
$this->cache = $cache; |
414
|
|
|
|
415
|
|
|
return $this; |
416
|
|
|
} |
417
|
|
|
} |
418
|
|
|
|
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.
Unreachable code is most often the result of
return
,die
orexit
statements that have been added for debug purposes.In the above example, the last
return false
will never be executed, because a return statement has already been met in every possible execution path.