Passed
Push — 5.2 ( ed7db6...79cd5f )
by liu
02:29
created

Http::runWithRequest()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 4
nop 1
dl 0
loc 13
rs 10
c 0
b 0
f 0
1
<?php
2
// +----------------------------------------------------------------------
1 ignored issue
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: liu21st <[email protected]>
10
// +----------------------------------------------------------------------
11
declare (strict_types = 1);
12
13
namespace think;
14
15
use think\exception\HttpException;
16
17
/**
18
 * Web应用管理类
19
 */
5 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @author tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
20
class Http
21
{
22
23
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
24
     * @var App
25
     */
26
    protected $app;
27
28
    /**
29
     * 是否多应用模式
30
     * @var bool
31
     */
32
    protected $multi = false;
33
34
    /**
35
     * 是否自动多应用
36
     * @var bool
37
     */
38
    protected $auto = false;
39
40
    /**
41
     * 是否域名绑定应用
42
     * @var bool
43
     */
44
    protected $bindDomain = false;
45
46
    /**
47
     * 默认应用名(多应用模式)
48
     * @var string
49
     */
50
    protected $defaultApp = 'index';
51
52
    /**
53
     * 应用名称
54
     * @var string
55
     */
56
    protected $name;
57
58
    /**
59
     * 应用映射
60
     * @var array
61
     */
62
    protected $map = [];
63
64
    /**
65
     * 域名映射
66
     * @var array
67
     */
68
    protected $domain = [];
69
70
    /**
71
     * 是否需要使用路由
72
     * @var bool
73
     */
74
    protected $withRoute = true;
75
76
    public function __construct(App $app)
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
77
    {
78
        $this->app   = $app;
79
        $this->multi = is_dir($this->app->getBasePath() . 'controller') ? false : true;
80
    }
81
82
    /**
83
     * 自动多应用访问
84
     * @access public
85
     * @param array $map 应用路由映射
1 ignored issue
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
86
     * @return $this
87
     */
88
    public function autoMulti(array $map = [])
89
    {
90
        $this->multi = true;
91
        $this->auto  = true;
92
        $this->map   = $map;
93
94
        return $this;
95
    }
96
97
    /**
98
     * 域名应用映射
99
     * @access public
100
     * @param  array $map 应用域名映射
101
     * @return $this
102
     */
103
    public function domain(array $map)
104
    {
105
        $this->domain = $map;
106
        return $this;
107
    }
108
109
    /**
110
     * 域名绑定应用
111
     * @access public
112
     * @return array
113
     */
114
    public function getDomain(): array
115
    {
116
        return $this->domain;
117
    }
118
119
    /**
120
     * 是否域名绑定应用
121
     * @access public
122
     * @return bool
123
     */
124
    public function isBindDomain(): bool
125
    {
126
        return $this->bindDomain;
127
    }
128
129
    /**
130
     * 是否为自动多应用模式
131
     * @access public
132
     * @return bool
133
     */
134
    public function isAutoMulti(): bool
135
    {
136
        return $this->auto;
137
    }
138
139
    /**
140
     * 设置应用模式
141
     * @access public
142
     * @param bool $multi
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
143
     * @return $this
144
     */
145
    public function multi(bool $multi)
146
    {
147
        $this->multi = $multi;
148
        return $this;
149
    }
150
151
    /**
152
     * 是否为多应用模式
153
     * @access public
154
     * @return bool
155
     */
156
    public function isMulti(): bool
157
    {
158
        return $this->multi;
159
    }
160
161
    /**
162
     * 设置默认应用(对多应用有效)
163
     * @access public
164
     * @param string $name 应用名
1 ignored issue
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
165
     * @return $this
166
     */
167
    public function defaultApp(string $name)
168
    {
169
        $this->defaultApp = $name;
170
        return $this;
171
    }
172
173
    /**
174
     * 设置应用名称
175
     * @access public
176
     * @param string $name 应用名称
1 ignored issue
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
177
     * @return $this
178
     */
179
    public function name(string $name)
180
    {
181
        $this->name = $name;
182
        return $this;
183
    }
184
185
    /**
186
     * 获取应用名称
187
     * @access public
188
     * @return string
189
     */
190
    public function getName(): string
191
    {
192
        return $this->name ?: '';
193
    }
194
195
    /**
196
     * 设置是否使用路由
197
     * @access public
198
     * @param bool $route
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
199
     * @return $this
200
     */
201
    public function withRoute(bool $route)
202
    {
203
        $this->withRoute = $route;
204
        return $this;
205
    }
206
207
    /**
208
     * 执行应用程序
209
     * @access public
210
     * @param Request|null $request
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
211
     * @return Response
212
     */
213
    public function run(Request $request = null): Response
214
    {
215
        //自动创建request对象
216
        $request = $request ?? $this->app->make('request', [], true);
217
        $this->app->instance('request', $request);
218
219
        try {
220
            $response = $this->runWithRequest($request);
221
        } catch (\Throwable $e) {
222
            $this->reportException($e);
223
224
            $response = $this->renderException($request, $e);
225
        }
226
227
        return $response;
228
    }
229
230
    /**
231
     * 执行应用程序
232
     * @param Request $request
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
233
     * @return mixed
234
     */
235
    protected function runWithRequest(Request $request)
236
    {
237
        $this->app->initialize();
238
239
        if ($this->multi) {
240
            $this->parseMultiApp();
241
        }
242
243
        $withRoute = $this->withRoute ? function () {
244
            $this->loadRoutes();
245
        } : null;
246
247
        return $this->app->route->dispatch($request, $withRoute);
248
    }
249
250
    /**
251
     * 加载路由
252
     * @access protected
253
     * @return void
254
     */
255
    protected function loadRoutes(): void
256
    {
257
        // 加载路由定义
258
        if (is_dir($this->getRoutePath())) {
259
            $files = glob($this->getRoutePath() . DIRECTORY_SEPARATOR . '*.php');
260
            foreach ($files as $file) {
261
                include $file;
262
            }
263
        }
264
265
        if ($this->app->route->config('route_annotation')) {
266
            // 自动生成注解路由定义
267
            if ($this->app->isDebug()) {
268
                $this->app->build->buildRoute();
269
            }
270
271
            $filename = $this->app->getRuntimePath() . 'build_route.php';
272
273
            if (is_file($filename)) {
274
                include $filename;
275
            }
276
        }
277
    }
278
279
    /**
280
     * 获取路由目录
281
     * @access protected
282
     * @return string
283
     */
284
    protected function getRoutePath(): string
285
    {
286
        return $this->app->getRootPath() . 'route' . DIRECTORY_SEPARATOR . ($this->isMulti() ? $this->getName() . DIRECTORY_SEPARATOR : '');
287
    }
288
289
    /**
290
     * Report the exception to the exception handler.
291
     *
292
     * @param \Throwable $e
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
293
     * @return void
294
     */
295
    protected function reportException(\Throwable $e)
296
    {
297
        $this->app['error_handle']->report($e);
298
    }
299
300
    /**
301
     * Render the exception to a response.
302
     *
303
     * @param Request    $request
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
304
     * @param \Throwable $e
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
305
     * @return Response
306
     */
307
    protected function renderException($request, \Throwable $e)
308
    {
309
        return $this->app['error_handle']->render($request, $e);
310
    }
311
312
    /**
313
     * 获取当前运行入口名称
314
     * @access protected
315
     * @return string
316
     */
317
    protected function getScriptName(): string
318
    {
319
        if (isset($_SERVER['SCRIPT_FILENAME'])) {
320
            $file = $_SERVER['SCRIPT_FILENAME'];
321
        } elseif (isset($_SERVER['argv'][0])) {
322
            $file = realpath($_SERVER['argv'][0]);
323
        }
324
325
        return isset($file) ? pathinfo($file, PATHINFO_FILENAME) : $this->defaultApp;
326
    }
327
328
    /**
329
     * 解析多应用
330
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
331
    protected function parseMultiApp(): void
332
    {
333
        if ($this->auto) {
334
            // 自动多应用识别
335
            // 获取当前子域名
336
            $subDomain = $this->app->request->subDomain();
337
            $domain    = $this->app->request->host();
338
339
            $this->bindDomain = false;
340
            if (isset($this->domain[$subDomain])) {
341
                $appName          = $this->domain[$subDomain];
342
                $this->bindDomain = true;
343
            } elseif (isset($this->domain[$domain])) {
344
                $appName          = $this->domain[$domain];
345
                $this->bindDomain = true;
346
            } else {
347
                $path = $this->app->request->pathinfo();
348
                $name = current(explode('/', $path));
349
350
                if (isset($this->map[$name])) {
351
                    if ($this->map[$name] instanceof \Closure) {
352
                        call_user_func_array($this->map[$name], [$this]);
353
                    } else {
354
                        $appName = $this->map[$name];
355
                    }
356
                } elseif ($name && false !== array_search($name, $this->map)) {
357
                    throw new HttpException(404, 'app not exists:' . $name);
358
                } else {
359
                    $appName = $name ?: $this->defaultApp;
360
                }
361
362
                if ($name) {
363
                    $this->app->request->setRoot($name);
364
                    $this->app->request->setPathinfo(strpos($path, '/') ? ltrim(strstr($path, '/'), '/') : '');
365
                }
366
            }
367
        } else {
368
            $appName = $this->name ?: $this->getScriptName();
369
        }
370
371
        $this->loadApp($appName);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $appName does not seem to be defined for all execution paths leading up to this point.
Loading history...
372
    }
373
374
    protected function loadApp(string $appName): void
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
375
    {
376
        $this->name = $appName;
377
        $this->app->request->setApp($appName);
378
        $this->app->setNamespace($this->app->getRootNamespace() . '\\' . $appName);
379
        $this->app->setAppPath($this->app->getBasePath() . $appName . DIRECTORY_SEPARATOR);
380
        $this->app->setRuntimePath($this->app->getRootPath() . 'runtime' . DIRECTORY_SEPARATOR . $appName . DIRECTORY_SEPARATOR);
381
382
        //加载app文件
383
        if (is_file($this->app->getRuntimePath() . 'init.php')) {
384
            //直接加载缓存
385
            include $this->app->getRuntimePath() . 'init.php';
386
        } else {
387
            $appPath = $this->app->getAppPath();
388
389
            if (is_file($appPath . 'common.php')) {
390
                include_once $appPath . 'common.php';
391
            }
392
393
            $configPath = $this->app->getConfigPath();
394
395
            $files = [];
396
397
            if (is_dir($appPath . 'config')) {
398
                $files = array_merge($files, glob($appPath . 'config' . DIRECTORY_SEPARATOR . '*' . $this->app->getConfigExt()));
399
            } elseif (is_dir($configPath . $appName)) {
400
                $files = array_merge($files, glob($configPath . $appName . DIRECTORY_SEPARATOR . '*' . $this->app->getConfigExt()));
401
            }
402
403
            foreach ($files as $file) {
404
                $this->app->config->load($file, pathinfo($file, PATHINFO_FILENAME));
405
            }
406
407
            if (is_file($appPath . 'event.php')) {
408
                $this->app->loadEvent(include $appPath . 'event.php');
409
            }
410
411
            if (is_file($appPath . 'middleware.php')) {
412
                $this->app->middleware->import(include $appPath . 'middleware.php');
413
            }
414
415
            if (is_file($appPath . 'provider.php')) {
416
                $this->app->bind(include $appPath . 'provider.php');
417
            }
418
        }
419
    }
420
}
421