Completed
Push — 6.0 ( 037a27...bcbbbf )
by liu
02:39
created

Http::runWithRequest()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 24
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 11
nc 8
nop 1
dl 0
loc 24
ccs 11
cts 11
cp 1
crap 4
rs 9.9
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\Handle;
16
use think\exception\HttpException;
17
use Throwable;
18
19
/**
20
 * Web应用管理类
21
 */
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...
22
class Http
23
{
24
25
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
26
     * @var App
27
     */
28
    protected $app;
29
30
    /**
31
     * 应用路径
32
     * @var string
33
     */
34
    protected $path;
35
36
    /**
37
     * 是否多应用模式
38
     * @var bool
39
     */
40
    protected $multi = false;
41
42
    /**
43
     * 是否域名绑定应用
44
     * @var bool
45
     */
46
    protected $bindDomain = false;
47
48
    /**
49
     * 应用名称
50
     * @var string
51
     */
52
    protected $name;
53
54 9
    public function __construct(App $app)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
55
    {
56 9
        $this->app   = $app;
57 9
        $this->multi = is_dir($this->app->getBasePath() . 'controller') ? false : true;
58 9
    }
59
60
    /**
61
     * 是否域名绑定应用
62
     * @access public
63
     * @return bool
64
     */
65 2
    public function isBindDomain(): bool
66
    {
67 2
        return $this->bindDomain;
68
    }
69
70
    /**
71
     * 设置应用模式
72
     * @access public
73
     * @param bool $multi
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
74
     * @return $this
75
     */
76 1
    public function multi(bool $multi)
77
    {
78 1
        $this->multi = $multi;
79 1
        return $this;
80
    }
81
82
    /**
83
     * 是否为多应用模式
84
     * @access public
85
     * @return bool
86
     */
87 7
    public function isMulti(): bool
88
    {
89 7
        return $this->multi;
90
    }
91
92
    /**
93
     * 设置应用名称
94
     * @access public
95
     * @param string $name 应用名称
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
96
     * @return $this
97
     */
98 1
    public function name(string $name)
99
    {
100 1
        $this->name = $name;
101 1
        return $this;
102
    }
103
104
    /**
105
     * 获取应用名称
106
     * @access public
107
     * @return string
108
     */
109 5
    public function getName(): string
110
    {
111 5
        return $this->name ?: '';
112
    }
113
114
    /**
115
     * 设置应用目录
116
     * @access public
117
     * @param string $path 应用目录
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
118
     * @return $this
119
     */
120 1
    public function path(string $path)
121
    {
122 1
        $this->path = $path;
123 1
        return $this;
124
    }
125
126
    /**
127
     * 执行应用程序
128
     * @access public
129
     * @param Request|null $request
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
130
     * @return Response
131
     */
132 8
    public function run(Request $request = null): Response
133
    {
134
        //自动创建request对象
135 8
        $request = $request ?? $this->app->make('request', [], true);
136 8
        $this->app->instance('request', $request);
137
138
        try {
139 8
            $response = $this->runWithRequest($request);
140 2
        } catch (Throwable $e) {
141 2
            $this->reportException($e);
142
143 2
            $response = $this->renderException($request, $e);
144
        }
145
146 8
        return $response->setCookie($this->app->cookie);
147
    }
148
149
    /**
150
     * 初始化
151
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
152 7
    protected function initialize()
153
    {
154 7
        if (!$this->app->initialized()) {
155 7
            $this->app->initialize();
156
        }
157 7
    }
158
159
    /**
160
     * 执行应用程序
161
     * @param Request $request
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
162
     * @return mixed
163
     */
164 7
    protected function runWithRequest(Request $request)
165
    {
166 7
        $this->initialize();
167
168
        // 加载全局中间件
169 7
        if (is_file($this->app->getBasePath() . 'middleware.php')) {
170 7
            $this->app->middleware->import(include $this->app->getBasePath() . 'middleware.php');
171
        }
172
173 7
        if ($this->multi) {
174 6
            $this->parseMultiApp();
175
        }
176
177
        // 设置开启事件机制
178 6
        $this->app->event->withEvent($this->app->config->get('app.with_event', true));
0 ignored issues
show
Bug introduced by
It seems like $this->app->config->get('app.with_event', true) can also be of type array and array; however, parameter $event of think\Event::withEvent() does only seem to accept boolean, 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

178
        $this->app->event->withEvent(/** @scrutinizer ignore-type */ $this->app->config->get('app.with_event', true));
Loading history...
179
180
        // 监听HttpRun
181 6
        $this->app->event->trigger('HttpRun');
182
183
        $withRoute = $this->app->config->get('app.with_route', true) ? function () {
184 6
            $this->loadRoutes();
185 6
        } : null;
186
187 6
        return $this->app->route->dispatch($request, $withRoute);
188
    }
189
190
    /**
191
     * 加载路由
192
     * @access protected
193
     * @return void
194
     */
195 6
    protected function loadRoutes(): void
196
    {
197
        // 加载路由定义
198 6
        if (is_dir($this->getRoutePath())) {
199 1
            $files = glob($this->getRoutePath() . '*.php');
200 1
            foreach ($files as $file) {
201
                include $file;
202
            }
203
        }
204
205 6
        if ($this->app->route->config('route_annotation')) {
206
            // 自动生成注解路由定义
207 6
            if ($this->app->isDebug()) {
208 6
                $this->app->console->call('route:build', [$this->name]);
209
            }
210
211 6
            $filename = $this->app->getRuntimePath() . 'build_route.php';
212
213 6
            if (is_file($filename)) {
214
                include $filename;
215
            }
216
        }
217 6
    }
218
219
    /**
220
     * 获取路由目录
221
     * @access protected
222
     * @return string
223
     */
224 6
    protected function getRoutePath(): string
225
    {
226 6
        return $this->app->getRootPath() . 'route' . DIRECTORY_SEPARATOR . ($this->isMulti() ? $this->getName() . DIRECTORY_SEPARATOR : '');
227
    }
228
229
    /**
230
     * Report the exception to the exception handler.
231
     *
232
     * @param Throwable $e
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
233
     * @return void
234
     */
235 1
    protected function reportException(Throwable $e)
236
    {
237 1
        $this->app->make(Handle::class)->report($e);
238 1
    }
239
240
    /**
241
     * Render the exception to a response.
242
     *
243
     * @param Request   $request
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
244
     * @param Throwable $e
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
245
     * @return Response
246
     */
247 1
    protected function renderException($request, Throwable $e)
248
    {
249 1
        return $this->app->make(Handle::class)->render($request, $e);
250
    }
251
252
    /**
253
     * 获取当前运行入口名称
254
     * @access protected
1 ignored issue
show
Coding Style introduced by
Tag value for @access tag indented incorrectly; expected 13 spaces but found 1
Loading history...
255
     * @codeCoverageIgnore
256
     * @return string
1 ignored issue
show
Coding Style introduced by
Tag value for @return tag indented incorrectly; expected 13 spaces but found 1
Loading history...
257
     */
258
    protected function getScriptName(): string
259
    {
260
        if (isset($_SERVER['SCRIPT_FILENAME'])) {
261
            $file = $_SERVER['SCRIPT_FILENAME'];
262
        } elseif (isset($_SERVER['argv'][0])) {
263
            $file = realpath($_SERVER['argv'][0]);
264
        }
265
266
        return isset($file) ? pathinfo($file, PATHINFO_FILENAME) : '';
267
    }
268
269
    /**
270
     * 解析多应用
271
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
272 6
    protected function parseMultiApp(): void
273
    {
274 6
        if ($this->app->config->get('app.auto_multi_app', false)) {
275
            // 自动多应用识别
276 5
            $this->bindDomain = false;
277
278 5
            $bind = $this->app->config->get('app.domain_bind', []);
279
280 5
            if (!empty($bind)) {
281
                // 获取当前子域名
282 5
                $subDomain = $this->app->request->subDomain();
283 5
                $domain    = $this->app->request->host(true);
284
285 5
                if (isset($bind[$domain])) {
286 1
                    $appName          = $bind[$domain];
287 1
                    $this->bindDomain = true;
288 4
                } elseif (isset($bind[$subDomain])) {
289 1
                    $appName          = $bind[$subDomain];
290 1
                    $this->bindDomain = true;
291
                }
292
            }
293
294 5
            if (!$this->bindDomain) {
295 3
                $map  = $this->app->config->get('app.app_map', []);
296 3
                $path = $this->app->request->pathinfo();
297 3
                $name = current(explode('/', $path));
298
299 3
                if (isset($map[$name])) {
300 1
                    $appName = $map[$name];
301 2
                } elseif ($name && false !== array_search($name, $map)) {
302 1
                    throw new HttpException(404, 'app not exists:' . $name);
303
                } else {
304 1
                    $appName = $name;
305
                }
306
307 2
                if ($name) {
308 2
                    $this->app->request->setRoot($name);
309 4
                    $this->app->request->setPathinfo(strpos($path, '/') ? ltrim(strstr($path, '/'), '/') : '');
310
                }
311
            }
312
        } else {
313 1
            $appName = $this->name ?: $this->getScriptName();
314
        }
315
316 5
        $this->loadApp($appName ?: $this->app->config->get('app.default_app', 'index'));
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...
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

316
        $this->loadApp(/** @scrutinizer ignore-type */ $appName ?: $this->app->config->get('app.default_app', 'index'));
Loading history...
317 5
    }
318
319
    /**
320
     * 加载应用文件
321
     * @param string $appName 应用名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
322
     * @return void
323
     */
324 5
    protected function loadApp(string $appName): void
325
    {
326 5
        $this->name = $appName;
327 5
        $this->app->request->setApp($appName);
328 5
        $this->app->setAppPath($this->path ?: $this->app->getBasePath() . $appName . DIRECTORY_SEPARATOR);
329 5
        $this->app->setRuntimePath($this->app->getRootPath() . 'runtime' . DIRECTORY_SEPARATOR . $appName . DIRECTORY_SEPARATOR);
330
331
        //加载app文件
332 5
        if (is_dir($this->app->getAppPath())) {
333 1
            if (is_file($this->app->getRuntimePath() . 'init.php')) {
334
                //直接加载缓存
335
                include $this->app->getRuntimePath() . 'init.php';
336
            } else {
337 1
                $appPath = $this->app->getAppPath();
338
339 1
                if (is_file($appPath . 'common.php')) {
340 1
                    include_once $appPath . 'common.php';
341
                }
342
343 1
                $configPath = $this->app->getConfigPath();
344
345 1
                $files = [];
346
347 1
                if (is_dir($configPath . $appName)) {
348 1
                    $files = array_merge($files, glob($configPath . $appName . DIRECTORY_SEPARATOR . '*' . $this->app->getConfigExt()));
0 ignored issues
show
Bug introduced by
It seems like glob($configPath . $appN...s->app->getConfigExt()) can also be of type false; however, parameter $array2 of array_merge() does only seem to accept array|null, 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

348
                    $files = array_merge($files, /** @scrutinizer ignore-type */ glob($configPath . $appName . DIRECTORY_SEPARATOR . '*' . $this->app->getConfigExt()));
Loading history...
349
                } elseif (is_dir($appPath . 'config')) {
350
                    $files = array_merge($files, glob($appPath . 'config' . DIRECTORY_SEPARATOR . '*' . $this->app->getConfigExt()));
351
                }
352
353 1
                foreach ($files as $file) {
354
                    $this->app->config->load($file, pathinfo($file, PATHINFO_FILENAME));
355
                }
356
357 1
                if (is_file($appPath . 'event.php')) {
358 1
                    $this->app->loadEvent(include $appPath . 'event.php');
359
                }
360
361 1
                if (is_file($appPath . 'middleware.php')) {
362 1
                    $this->app->middleware->import(include $appPath . 'middleware.php');
363
                }
364
365 1
                if (is_file($appPath . 'provider.php')) {
366 1
                    $this->app->bind(include $appPath . 'provider.php');
367
                }
368
            }
369
        }
370
371 5
        $this->app->setNamespace($this->app->config->get('app.app_namespace') ?: 'app\\' . $appName);
0 ignored issues
show
Bug introduced by
It seems like $this->app->config->get(...') ?: 'app\' . $appName can also be of type array; however, parameter $namespace of think\App::setNamespace() 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

371
        $this->app->setNamespace(/** @scrutinizer ignore-type */ $this->app->config->get('app.app_namespace') ?: 'app\\' . $appName);
Loading history...
372 5
    }
373
374
    /**
375
     * HttpEnd
376
     * @param Response $response
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
377
     * @return void
378
     */
379 1
    public function end(Response $response): void
380
    {
381 1
        $this->app->event->trigger('HttpEnd', $response);
382
383
        // 写入日志
384 1
        $this->app->log->save();
385
        // 写入Session
386 1
        $this->app->session->save();
387 1
    }
388
}
389