Passed
Push — 5.2 ( 94f706...1b9ee1 )
by liu
03:53
created

Http::withRoute()   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 bool
61
     */
62
    protected $withRoute = true;
63
64
    public function __construct(App $app)
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
65
    {
66
        $this->app   = $app;
67
        $this->multi = is_dir($this->app->getBasePath() . 'controller') ? false : true;
68
    }
69
70
    /**
71
     * 自动多应用访问
72
     * @access public
73
     * @param  array $map 应用路由映射
74
     * @return $this
75
     */
76
    public function autoMulti(array $map = [])
77
    {
78
        $this->multi = true;
79
        $this->auto  = true;
80
        $this->map   = $map;
81
82
        return $this;
83
    }
84
85
    /**
86
     * 是否为自动多应用模式
87
     * @access public
88
     * @return bool
89
     */
90
    public function isAutoMulti(): bool
91
    {
92
        return $this->auto;
93
    }
94
95
    /**
96
     * 设置应用模式
97
     * @access public
98
     * @param  bool $multi
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
99
     * @return $this
100
     */
101
    public function multi(bool $multi)
102
    {
103
        $this->multi = $multi;
104
        return $this;
105
    }
106
107
    /**
108
     * 是否为多应用模式
109
     * @access public
110
     * @return bool
111
     */
112
    public function isMulti(): bool
113
    {
114
        return $this->multi;
115
    }
116
117
    /**
118
     * 设置默认应用(对多应用有效)
119
     * @access public
120
     * @param  string $name 应用名
121
     * @return $this
122
     */
123
    public function defaultApp(string $name)
124
    {
125
        $this->defaultApp = $name;
126
        return $this;
127
    }
128
129
    /**
130
     * 设置应用名称
131
     * @access public
132
     * @param  string $name 应用名称
133
     * @return $this
134
     */
135
    public function name(string $name)
136
    {
137
        $this->name = $name;
138
        return $this;
139
    }
140
141
    /**
142
     * 获取应用名称
143
     * @access public
144
     * @return string
145
     */
146
    public function getName(): string
147
    {
148
        return $this->name ?: '';
149
    }
150
151
    /**
152
     * 设置是否使用路由
153
     * @access public
154
     * @param  bool $route
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
155
     * @return $this
156
     */
157
    public function withRoute(bool $route)
158
    {
159
        $this->withRoute = $route;
160
        return $this;
161
    }
162
163
    /**
164
     * 执行应用程序
165
     * @access public
166
     * @param  Request|null $request
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
167
     * @return Response
168
     */
169
    public function run(Request $request = null): Response
170
    {
171
        //自动创建request对象
172
        $request = $request ?? $this->app->make('request', [], true);
173
        $this->app->instance('request', $request);
174
175
        try {
176
            $response = $this->runWithRequest($request);
177
        } catch (\Throwable $e) {
178
            $this->reportException($e);
179
180
            $response = $this->renderException($request, $e);
181
        }
182
183
        return $response;
184
    }
185
186
    /**
187
     * 执行应用程序
188
     * @param  Request $request
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
189
     * @return mixed
190
     */
191
    protected function runWithRequest(Request $request)
192
    {
193
        $this->app->initialize();
194
195
        if ($this->multi) {
196
            $this->parseMultiApp();
197
        }
198
199
        $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...
200
201
            $withRoute = $this->withRoute ? function () {
202
                $this->loadRoutes();
203
            } : null;
204
205
            return $this->app->route->dispatch($request, $withRoute);
206
        });
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...
207
208
        return $this->app->middleware->dispatch($request);
209
    }
210
211
    /**
212
     * 加载路由
213
     * @access protected
214
     * @return void
215
     */
216
    protected function loadRoutes(): void
217
    {
218
        // 加载路由定义
219
        if (is_dir($this->getRoutePath())) {
220
            $files = glob($this->getRoutePath() . DIRECTORY_SEPARATOR . '*.php');
221
            foreach ($files as $file) {
222
                include $file;
223
            }
224
        }
225
226
        if ($this->app->route->config('route_annotation')) {
227
            // 自动生成注解路由定义
228
            if ($this->app->isDebug()) {
229
                $this->app->build->buildRoute();
230
            }
231
232
            $filename = $this->app->getRuntimePath() . 'build_route.php';
233
234
            if (is_file($filename)) {
235
                include $filename;
236
            }
237
        }
238
    }
239
240
    /**
241
     * 获取路由目录
242
     * @access protected
243
     * @return string
244
     */
245
    protected function getRoutePath(): string
246
    {
247
        return $this->app->getRootPath() . 'route' . DIRECTORY_SEPARATOR . ($this->isMulti() ? $this->getName() . DIRECTORY_SEPARATOR : '');
248
    }
249
250
    /**
251
     * Report the exception to the exception handler.
252
     *
253
     * @param  \Throwable $e
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
254
     * @return void
255
     */
256
    protected function reportException(\Throwable $e)
257
    {
258
        $this->app['error_handle']->report($e);
259
    }
260
261
    /**
262
     * Render the exception to a response.
263
     *
264
     * @param  Request    $request
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
265
     * @param  \Throwable $e
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
266
     * @return Response
267
     */
268
    protected function renderException($request, \Throwable $e)
269
    {
270
        return $this->app['error_handle']->render($request, $e);
271
    }
272
273
    /**
274
     * 获取当前运行入口名称
275
     * @access protected
276
     * @return string
277
     */
278
    protected function getScriptName(): string
279
    {
280
        if (isset($_SERVER['SCRIPT_FILENAME'])) {
281
            $file = $_SERVER['SCRIPT_FILENAME'];
282
        } elseif (isset($_SERVER['argv'][0])) {
283
            $file = realpath($_SERVER['argv'][0]);
284
        }
285
286
        return isset($file) ? pathinfo($file, PATHINFO_FILENAME) : $this->defaultApp;
287
    }
288
289
    /**
290
     * 解析多应用
291
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
292
    protected function parseMultiApp(): void
293
    {
294
        if ($this->auto) {
295
            // 自动多应用识别
296
            $path = $this->app->request->path();
297
            $name = current(explode('/', $path));
298
299
            if (isset($this->map[$name])) {
300
                if ($this->map[$name] instanceof \Closure) {
301
                    call_user_func_array($this->map[$name], [$this]);
302
                } else {
303
                    $appName = $this->map[$name];
304
                }
305
            } elseif ($name && false !== array_search($name, $this->map)) {
306
                throw new HttpException(404, 'app not exists:' . $name);
307
            } else {
308
                $appName = $name ?: $this->defaultApp;
309
            }
310
311
            if ($name) {
312
                $this->app->request->setPathinfo(preg_replace('/^' . $name . '\//', '', $this->app->request->pathinfo()));
313
                $this->app->request->setRoot($name);
314
            }
315
        } else {
316
            $appName = $this->name ?: $this->getScriptName();
317
        }
318
319
        $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...
320
    }
321
322
    protected function loadApp(string $appName): void
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
323
    {
324
        $this->name = $appName;
325
        $this->app->request->setApp($appName);
326
        $this->app->setNamespace($this->app->getRootNamespace() . '\\' . $appName);
327
        $this->app->setAppPath($this->app->getBasePath() . $appName . DIRECTORY_SEPARATOR);
328
        $this->app->setRuntimePath($this->app->getRootPath() . 'runtime' . DIRECTORY_SEPARATOR . $appName . DIRECTORY_SEPARATOR);
329
330
        //加载app文件
331
        if (is_file($this->app->getRuntimePath() . 'init.php')) {
332
            //直接加载缓存
333
            include $this->app->getRuntimePath() . 'init.php';
334
        } else {
335
            $appPath = $this->app->getAppPath();
336
337
            if (is_file($appPath . 'common.php')) {
338
                include_once $appPath . 'common.php';
339
            }
340
341
            $configPath = $this->app->getConfigPath();
342
343
            $files = [];
344
345
            if (is_dir($appPath . 'config')) {
346
                $files = array_merge($files, glob($appPath . 'config' . DIRECTORY_SEPARATOR . '*' . $this->app->getConfigExt()));
347
            } elseif (is_dir($configPath . $appName)) {
348
                $files = array_merge($files, glob($configPath . $appName . DIRECTORY_SEPARATOR . '*' . $this->app->getConfigExt()));
349
            }
350
351
            foreach ($files as $file) {
352
                $this->app->config->load($file, pathinfo($file, PATHINFO_FILENAME));
353
            }
354
355
            if (is_file($appPath . 'event.php')) {
356
                $this->app->loadEvent(include $appPath . 'event.php');
357
            }
358
359
            if (is_file($appPath . 'middleware.php')) {
360
                $this->app->middleware->import(include $appPath . 'middleware.php');
361
            }
362
363
            if (is_file($appPath . 'provider.php')) {
364
                $this->app->bind(include $appPath . 'provider.php');
365
            }
366
        }
367
    }
368
}
369