Passed
Push — 5.2 ( 942813...8bccb0 )
by liu
02:30
created

Http::domain()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
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 string
43
     */
44
    protected $defaultApp = 'index';
45
46
    /**
47
     * 应用名称
48
     * @var string
49
     */
50
    protected $name;
51
52
    /**
53
     * 应用映射
54
     * @var array
55
     */
56
    protected $map = [];
57
58
    /**
59
     * 域名映射
60
     * @var array
61
     */
62
    protected $domain = [];
63
64
    /**
65
     * 是否需要使用路由
66
     * @var bool
67
     */
68
    protected $withRoute = true;
69
70
    public function __construct(App $app)
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
71
    {
72
        $this->app   = $app;
73
        $this->multi = is_dir($this->app->getBasePath() . 'controller') ? false : true;
74
    }
75
76
    /**
77
     * 自动多应用访问
78
     * @access public
79
     * @param  array $map 应用路由映射
80
     * @return $this
81
     */
82
    public function autoMulti(array $map = [])
83
    {
84
        $this->multi = true;
85
        $this->auto  = true;
86
        $this->map   = $map;
87
88
        return $this;
89
    }
90
91
    /**
92
     * 域名应用映射
93
     * @access public
94
     * @param  array $map 应用域名映射
95
     * @return $this
96
     */
97
    public function domain(array $map)
98
    {
99
        $this->domain = $map;
100
        return $this;
101
    }
102
103
    /**
104
     * 是否为自动多应用模式
105
     * @access public
106
     * @return bool
107
     */
108
    public function isAutoMulti(): bool
109
    {
110
        return $this->auto;
111
    }
112
113
    /**
114
     * 设置应用模式
115
     * @access public
116
     * @param  bool $multi
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
117
     * @return $this
118
     */
119
    public function multi(bool $multi)
120
    {
121
        $this->multi = $multi;
122
        return $this;
123
    }
124
125
    /**
126
     * 是否为多应用模式
127
     * @access public
128
     * @return bool
129
     */
130
    public function isMulti(): bool
131
    {
132
        return $this->multi;
133
    }
134
135
    /**
136
     * 设置默认应用(对多应用有效)
137
     * @access public
138
     * @param  string $name 应用名
139
     * @return $this
140
     */
141
    public function defaultApp(string $name)
142
    {
143
        $this->defaultApp = $name;
144
        return $this;
145
    }
146
147
    /**
148
     * 设置应用名称
149
     * @access public
150
     * @param  string $name 应用名称
151
     * @return $this
152
     */
153
    public function name(string $name)
154
    {
155
        $this->name = $name;
156
        return $this;
157
    }
158
159
    /**
160
     * 获取应用名称
161
     * @access public
162
     * @return string
163
     */
164
    public function getName(): string
165
    {
166
        return $this->name ?: '';
167
    }
168
169
    /**
170
     * 设置是否使用路由
171
     * @access public
172
     * @param  bool $route
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
173
     * @return $this
174
     */
175
    public function withRoute(bool $route)
176
    {
177
        $this->withRoute = $route;
178
        return $this;
179
    }
180
181
    /**
182
     * 执行应用程序
183
     * @access public
184
     * @param  Request|null $request
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
185
     * @return Response
186
     */
187
    public function run(Request $request = null): Response
188
    {
189
        //自动创建request对象
190
        $request = $request ?? $this->app->make('request', [], true);
191
        $this->app->instance('request', $request);
192
193
        try {
194
            $response = $this->runWithRequest($request);
195
        } catch (\Throwable $e) {
196
            $this->reportException($e);
197
198
            $response = $this->renderException($request, $e);
199
        }
200
201
        return $response;
202
    }
203
204
    /**
205
     * 执行应用程序
206
     * @param  Request $request
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
207
     * @return mixed
208
     */
209
    protected function runWithRequest(Request $request)
210
    {
211
        $this->app->initialize();
212
213
        if ($this->multi) {
214
            $this->parseMultiApp();
215
        }
216
217
        $this->app->middleware->add(function (Request $request) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
218
219
            $withRoute = $this->withRoute ? function () {
220
                $this->loadRoutes();
221
            } : null;
222
223
            return $this->app->route->dispatch($request, $withRoute);
224
        });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
225
226
        return $this->app->middleware->dispatch($request);
227
    }
228
229
    /**
230
     * 加载路由
231
     * @access protected
232
     * @return void
233
     */
234
    protected function loadRoutes(): void
235
    {
236
        // 加载路由定义
237
        if (is_dir($this->getRoutePath())) {
238
            $files = glob($this->getRoutePath() . DIRECTORY_SEPARATOR . '*.php');
239
            foreach ($files as $file) {
240
                include $file;
241
            }
242
        }
243
244
        if ($this->app->route->config('route_annotation')) {
245
            // 自动生成注解路由定义
246
            if ($this->app->isDebug()) {
247
                $this->app->build->buildRoute();
248
            }
249
250
            $filename = $this->app->getRuntimePath() . 'build_route.php';
251
252
            if (is_file($filename)) {
253
                include $filename;
254
            }
255
        }
256
    }
257
258
    /**
259
     * 获取路由目录
260
     * @access protected
261
     * @return string
262
     */
263
    protected function getRoutePath(): string
264
    {
265
        return $this->app->getRootPath() . 'route' . DIRECTORY_SEPARATOR . ($this->isMulti() ? $this->getName() . DIRECTORY_SEPARATOR : '');
266
    }
267
268
    /**
269
     * Report the exception to the exception handler.
270
     *
271
     * @param  \Throwable $e
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
272
     * @return void
273
     */
274
    protected function reportException(\Throwable $e)
275
    {
276
        $this->app['error_handle']->report($e);
277
    }
278
279
    /**
280
     * Render the exception to a response.
281
     *
282
     * @param  Request    $request
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
283
     * @param  \Throwable $e
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
284
     * @return Response
285
     */
286
    protected function renderException($request, \Throwable $e)
287
    {
288
        return $this->app['error_handle']->render($request, $e);
289
    }
290
291
    /**
292
     * 获取当前运行入口名称
293
     * @access protected
294
     * @return string
295
     */
296
    protected function getScriptName(): string
297
    {
298
        if (isset($_SERVER['SCRIPT_FILENAME'])) {
299
            $file = $_SERVER['SCRIPT_FILENAME'];
300
        } elseif (isset($_SERVER['argv'][0])) {
301
            $file = realpath($_SERVER['argv'][0]);
302
        }
303
304
        return isset($file) ? pathinfo($file, PATHINFO_FILENAME) : $this->defaultApp;
305
    }
306
307
    /**
308
     * 解析多应用
309
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
310
    protected function parseMultiApp(): void
311
    {
312
        if ($this->auto) {
313
            // 自动多应用识别
314
            // 获取当前子域名
315
            $subDomain = $this->app->request->subDomain();
316
            $domain    = $this->app->request->host();
317
318
            if (isset($this->domain[$subDomain])) {
319
                $appName = $this->domain[$subDomain];
320
            } elseif (isset($this->domain[$domain])) {
321
                $appName = $this->domain[$domain];
322
            } else {
323
                $path = $this->app->request->pathinfo();
324
                $name = current(explode('/', $path));
325
326
                if (isset($this->map[$name])) {
327
                    if ($this->map[$name] instanceof \Closure) {
328
                        call_user_func_array($this->map[$name], [$this]);
329
                    } else {
330
                        $appName = $this->map[$name];
331
                    }
332
                } elseif ($name && false !== array_search($name, $this->map)) {
333
                    throw new HttpException(404, 'app not exists:' . $name);
334
                } else {
335
                    $appName = $name ?: $this->defaultApp;
336
                }
337
338
                if ($name) {
339
                    $this->app->request->setRoot($name);
340
                    $this->app->request->setPathinfo(strpos($path, '/') ? ltrim(strstr($path, '/'), '/') : '');
341
                }
342
            }
343
        } else {
344
            $appName = $this->name ?: $this->getScriptName();
345
        }
346
347
        $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...
348
    }
349
350
    protected function loadApp(string $appName): void
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
351
    {
352
        $this->name = $appName;
353
        $this->app->request->setApp($appName);
354
        $this->app->setNamespace($this->app->getRootNamespace() . '\\' . $appName);
355
        $this->app->setAppPath($this->app->getBasePath() . $appName . DIRECTORY_SEPARATOR);
356
        $this->app->setRuntimePath($this->app->getRootPath() . 'runtime' . DIRECTORY_SEPARATOR . $appName . DIRECTORY_SEPARATOR);
357
358
        //加载app文件
359
        if (is_file($this->app->getRuntimePath() . 'init.php')) {
360
            //直接加载缓存
361
            include $this->app->getRuntimePath() . 'init.php';
362
        } else {
363
            $appPath = $this->app->getAppPath();
364
365
            if (is_file($appPath . 'common.php')) {
366
                include_once $appPath . 'common.php';
367
            }
368
369
            $configPath = $this->app->getConfigPath();
370
371
            $files = [];
372
373
            if (is_dir($appPath . 'config')) {
374
                $files = array_merge($files, glob($appPath . 'config' . DIRECTORY_SEPARATOR . '*' . $this->app->getConfigExt()));
375
            } elseif (is_dir($configPath . $appName)) {
376
                $files = array_merge($files, glob($configPath . $appName . DIRECTORY_SEPARATOR . '*' . $this->app->getConfigExt()));
377
            }
378
379
            foreach ($files as $file) {
380
                $this->app->config->load($file, pathinfo($file, PATHINFO_FILENAME));
381
            }
382
383
            if (is_file($appPath . 'event.php')) {
384
                $this->app->loadEvent(include $appPath . 'event.php');
385
            }
386
387
            if (is_file($appPath . 'middleware.php')) {
388
                $this->app->middleware->import(include $appPath . 'middleware.php');
389
            }
390
391
            if (is_file($appPath . 'provider.php')) {
392
                $this->app->bind(include $appPath . 'provider.php');
393
            }
394
        }
395
    }
396
}
397