Passed
Push — 5.2 ( e9d7bb...682159 )
by liu
03:55
created

Http::defaultApp()   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 $bindDomain = false;
39
40
    /**
41
     * 应用名称
42
     * @var string
43
     */
44
    protected $name;
45
46
    public function __construct(App $app)
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
47
    {
48
        $this->app   = $app;
49
        $this->multi = is_dir($this->app->getBasePath() . 'controller') ? false : true;
50
    }
51
52
    /**
53
     * 是否域名绑定应用
54
     * @access public
55
     * @return bool
56
     */
57
    public function isBindDomain(): bool
58
    {
59
        return $this->bindDomain;
60
    }
61
62
    /**
63
     * 设置应用模式
64
     * @access public
65
     * @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...
66
     * @return $this
67
     */
68
    public function multi(bool $multi)
69
    {
70
        $this->multi = $multi;
71
        return $this;
72
    }
73
74
    /**
75
     * 是否为多应用模式
76
     * @access public
77
     * @return bool
78
     */
79
    public function isMulti(): bool
80
    {
81
        return $this->multi;
82
    }
83
84
    /**
85
     * 设置应用名称
86
     * @access public
87
     * @param string $name 应用名称
1 ignored issue
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
88
     * @return $this
89
     */
90
    public function name(string $name)
91
    {
92
        $this->name = $name;
93
        return $this;
94
    }
95
96
    /**
97
     * 获取应用名称
98
     * @access public
99
     * @return string
100
     */
101
    public function getName(): string
102
    {
103
        return $this->name ?: '';
104
    }
105
106
    /**
107
     * 执行应用程序
108
     * @access public
109
     * @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...
110
     * @return Response
111
     */
112
    public function run(Request $request = null): Response
113
    {
114
        //自动创建request对象
115
        $request = $request ?? $this->app->make('request', [], true);
116
        $this->app->instance('request', $request);
117
118
        try {
119
            $response = $this->runWithRequest($request);
120
        } catch (\Throwable $e) {
121
            $this->reportException($e);
122
123
            $response = $this->renderException($request, $e);
124
        }
125
126
        return $response;
127
    }
128
129
    /**
130
     * 执行应用程序
131
     * @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...
132
     * @return mixed
133
     */
134
    protected function runWithRequest(Request $request)
135
    {
136
        $this->app->initialize();
137
138
        if ($this->multi) {
139
            $this->parseMultiApp();
140
        }
141
142
        $withRoute = $this->app->config->get('app.with_route') ? function () {
143
            $this->loadRoutes();
144
        } : null;
145
146
        return $this->app->route->dispatch($request, $withRoute);
147
    }
148
149
    /**
150
     * 加载路由
151
     * @access protected
152
     * @return void
153
     */
154
    protected function loadRoutes(): void
155
    {
156
        // 加载路由定义
157
        if (is_dir($this->getRoutePath())) {
158
            $files = glob($this->getRoutePath() . DIRECTORY_SEPARATOR . '*.php');
159
            foreach ($files as $file) {
160
                include $file;
161
            }
162
        }
163
164
        if ($this->app->route->config('route_annotation')) {
165
            // 自动生成注解路由定义
166
            if ($this->app->isDebug()) {
167
                $this->app->build->buildRoute();
168
            }
169
170
            $filename = $this->app->getRuntimePath() . 'build_route.php';
171
172
            if (is_file($filename)) {
173
                include $filename;
174
            }
175
        }
176
    }
177
178
    /**
179
     * 获取路由目录
180
     * @access protected
181
     * @return string
182
     */
183
    protected function getRoutePath(): string
184
    {
185
        return $this->app->getRootPath() . 'route' . DIRECTORY_SEPARATOR . ($this->isMulti() ? $this->getName() . DIRECTORY_SEPARATOR : '');
186
    }
187
188
    /**
189
     * Report the exception to the exception handler.
190
     *
191
     * @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...
192
     * @return void
193
     */
194
    protected function reportException(\Throwable $e)
195
    {
196
        $this->app['error_handle']->report($e);
197
    }
198
199
    /**
200
     * Render the exception to a response.
201
     *
202
     * @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...
203
     * @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...
204
     * @return Response
205
     */
206
    protected function renderException($request, \Throwable $e)
207
    {
208
        return $this->app['error_handle']->render($request, $e);
209
    }
210
211
    /**
212
     * 获取当前运行入口名称
213
     * @access protected
214
     * @return string
215
     */
216
    protected function getScriptName(): string
217
    {
218
        if (isset($_SERVER['SCRIPT_FILENAME'])) {
219
            $file = $_SERVER['SCRIPT_FILENAME'];
220
        } elseif (isset($_SERVER['argv'][0])) {
221
            $file = realpath($_SERVER['argv'][0]);
222
        }
223
224
        return isset($file) ? pathinfo($file, PATHINFO_FILENAME) : '';
225
    }
226
227
    /**
228
     * 解析多应用
229
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
230
    protected function parseMultiApp(): void
231
    {
232
        if ($this->app->config->get('app.auto_multi_app', false)) {
233
            // 自动多应用识别
234
            $this->bindDomain = false;
235
236
            $bind = $this->app->config->get('app.domain_bind', []);
237
238
            if (!empty($bind)) {
239
                // 获取当前子域名
240
                $subDomain = $this->app->request->subDomain();
241
                $domain    = $this->app->request->host();
242
243
                if (isset($bind[$domain])) {
244
                    $appName          = $bind[$domain];
245
                    $this->bindDomain = true;
246
                } elseif (isset($bind[$subDomain])) {
247
                    $appName          = $bind[$subDomain];
248
                    $this->bindDomain = true;
249
                }
250
            }
251
252
            if (!$this->bindDomain) {
253
                $map  = $this->app->config->get('app.app_map', []);
254
                $path = $this->app->request->pathinfo();
255
                $name = current(explode('/', $path));
256
257
                if (isset($map[$name])) {
258
                    if ($map[$name] instanceof \Closure) {
259
                        call_user_func_array($map[$name], [$this->app]);
260
                    } else {
261
                        $appName = $map[$name];
262
                    }
263
                } elseif ($name && false !== array_search($name, $map)) {
264
                    throw new HttpException(404, 'app not exists:' . $name);
265
                } else {
266
                    $appName = $name;
267
                }
268
269
                if ($name) {
270
                    $this->app->request->setRoot($name);
271
                    $this->app->request->setPathinfo(strpos($path, '/') ? ltrim(strstr($path, '/'), '/') : '');
272
                }
273
            }
274
        } else {
275
            $appName = $this->name ?: $this->getScriptName();
276
        }
277
278
        $this->loadApp($appName ?: $this->app->config->get('app.default_app', 'index'));
0 ignored issues
show
Bug introduced by
It seems like $appName ?: $this->app->....default_app', 'index') can also be of type array and array; however, parameter $appName of think\Http::loadApp() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

278
        $this->loadApp(/** @scrutinizer ignore-type */ $appName ?: $this->app->config->get('app.default_app', 'index'));
Loading history...
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...
279
    }
280
281
    protected function loadApp(string $appName): void
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
282
    {
283
        $this->name = $appName;
284
        $this->app->request->setApp($appName);
285
        $this->app->setNamespace($this->app->getRootNamespace() . '\\' . $appName);
286
        $this->app->setAppPath($this->app->getBasePath() . $appName . DIRECTORY_SEPARATOR);
287
        $this->app->setRuntimePath($this->app->getRootPath() . 'runtime' . DIRECTORY_SEPARATOR . $appName . DIRECTORY_SEPARATOR);
288
289
        //加载app文件
290
        if (is_file($this->app->getRuntimePath() . 'init.php')) {
291
            //直接加载缓存
292
            include $this->app->getRuntimePath() . 'init.php';
293
        } else {
294
            $appPath = $this->app->getAppPath();
295
296
            if (is_file($appPath . 'common.php')) {
297
                include_once $appPath . 'common.php';
298
            }
299
300
            $configPath = $this->app->getConfigPath();
301
302
            $files = [];
303
304
            if (is_dir($appPath . 'config')) {
305
                $files = array_merge($files, glob($appPath . 'config' . DIRECTORY_SEPARATOR . '*' . $this->app->getConfigExt()));
306
            } elseif (is_dir($configPath . $appName)) {
307
                $files = array_merge($files, glob($configPath . $appName . DIRECTORY_SEPARATOR . '*' . $this->app->getConfigExt()));
308
            }
309
310
            foreach ($files as $file) {
311
                $this->app->config->load($file, pathinfo($file, PATHINFO_FILENAME));
312
            }
313
314
            if (is_file($appPath . 'event.php')) {
315
                $this->app->loadEvent(include $appPath . 'event.php');
316
            }
317
318
            if (is_file($appPath . 'middleware.php')) {
319
                $this->app->middleware->import(include $appPath . 'middleware.php');
320
            }
321
322
            if (is_file($appPath . 'provider.php')) {
323
                $this->app->bind(include $appPath . 'provider.php');
324
            }
325
        }
326
    }
327
}
328