Passed
Push — 5.2 ( 14f2ed...c4c2c8 )
by liu
02:25
created

App::controllerLayer()   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\ClassNotFoundException;
16
use think\exception\HttpResponseException;
17
use think\route\Dispatch;
18
19
/**
20
 * App 应用管理
21
 * @property Route $route
22
 * @property Config $config
23
 * @property Cache $cache
24
 * @property Request $request
25
 * @property Env $env
26
 * @property Debug $debug
27
 * @property Event $event
28
 * @property Middleware $middleware
29
 * @property Log $log
30
 * @property Lang $lang
31
 * @property Db $db
32
 * @property Cookie $cookie
33
 * @property Session $session
34
 * @property Url $url
35
 * @property Validate $validate
36
 * @property Build $build
37
 * @property \think\route\RuleName $rule_name
38
 */
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...
39
class App extends Base
40
{
41
    const VERSION = '5.2.0RC1';
42
43
    /**
44
     * 默认应用名(多应用模式)
45
     * @var string
46
     */
47
    protected $defaultApp = 'index';
48
49
    /**
50
     * 路由目录
51
     * @var string
52
     */
53
    protected $routePath = '';
54
55
    /**
56
     * URL
57
     * @var string
58
     */
59
    protected $urlPath = '';
60
61
    /**
62
     * 是否需要使用路由
63
     * @var bool
64
     */
65
    protected $withRoute = true;
66
67
    /**
68
     * 访问控制器层名称
69
     * @var string
70
     */
71
    protected $controllerLayer = 'controller';
72
73
    /**
74
     * 是否使用控制器类库后缀
75
     * @var bool
76
     */
77
    protected $controllerSuffix = false;
78
79
    /**
80
     * 空控制器名称
81
     * @var string
82
     */
83
    protected $emptyController = 'Error';
84
85
    /**
86
     * 架构方法
87
     * @access public
88
     * @param  string $rootPath 应用根目录
89
     */
90
    public function __construct(string $rootPath = '')
91
    {
92
        $this->thinkPath = dirname(__DIR__) . DIRECTORY_SEPARATOR;
93
        $this->rootPath  = $rootPath ? realpath($rootPath) . DIRECTORY_SEPARATOR : $this->getDefaultRootPath();
94
        $this->basePath  = $this->rootPath . 'app' . DIRECTORY_SEPARATOR;
95
96
        $this->multi = is_dir($this->basePath . 'controller') ? false : true;
97
98
        static::setInstance($this);
99
100
        $this->instance('app', $this);
101
102
        // 注册错误和异常处理机制
103
        Error::register();
104
    }
105
106
    /**
107
     * 自动多应用访问
108
     * @access public
109
     * @param  array $map 应用路由映射
110
     * @return $this
111
     */
112
    public function autoMulti(array $map = [])
113
    {
114
        $this->multi = true;
115
        $this->auto  = true;
116
        $this->map   = $map;
117
118
        return $this;
119
    }
120
121
    /**
122
     * 是否为自动多应用模式
123
     * @access public
124
     * @return bool
125
     */
126
    public function isAutoMulti(): bool
127
    {
128
        return $this->auto;
129
    }
130
131
    /**
132
     * 设置应用模式
133
     * @access public
134
     * @param  bool $multi
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
135
     * @return $this
136
     */
137
    public function multi(bool $multi)
138
    {
139
        $this->multi = $multi;
140
        return $this;
141
    }
142
143
    /**
144
     * 是否为多应用模式
145
     * @access public
146
     * @return bool
147
     */
148
    public function isMulti(): bool
149
    {
150
        return $this->multi;
151
    }
152
153
    /**
154
     * 设置是否使用路由
155
     * @access public
156
     * @param  bool $route
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
157
     * @return $this
158
     */
159
    public function withRoute(bool $route)
160
    {
161
        $this->withRoute = $route;
162
        return $this;
163
    }
164
165
    /**
166
     * 设置默认应用(对多应用有效)
167
     * @access public
168
     * @param  string $name 应用名
169
     * @return $this
170
     */
171
    public function defaultApp(string $name)
172
    {
173
        $this->defaultApp = $name;
174
        return $this;
175
    }
176
177
    /**
178
     * 设置控制器层名称
179
     * @access public
180
     * @param  string $layer 控制器层名称
181
     * @return $this
182
     */
183
    public function controllerLayer(string $layer)
184
    {
185
        $this->controllerLayer = $layer;
186
        return $this;
187
    }
188
189
    /**
190
     * 设置空控制器名称
191
     * @access public
192
     * @param  string $empty 空控制器名称
193
     * @return $this
194
     */
195
    public function emptyController(string $empty)
196
    {
197
        $this->emptyController = $empty;
198
        return $this;
199
    }
200
201
    /**
202
     * 设置是否启用控制器类库后缀
203
     * @access public
204
     * @param  bool  $suffix 启用控制器类库后缀
205
     * @return $this
206
     */
207
    public function controllerSuffix(bool $suffix = true)
208
    {
209
        $this->controllerSuffix = $suffix;
210
        return $this;
211
    }
212
213
    /**
214
     * 是否启用控制器类库后缀
215
     * @access public
216
     * @return bool
217
     */
218
    public function hasControllerSuffix(): bool
219
    {
220
        return $this->controllerSuffix;
221
    }
222
223
    /**
224
     * 获取控制器层名称
225
     * @access public
226
     * @return string
227
     */
228
    public function getControllerLayer(): string
229
    {
230
        return $this->controllerLayer;
231
    }
232
233
    /**
234
     * 执行应用程序
235
     * @access public
236
     * @return Response
237
     * @throws Exception
238
     */
239
    public function run(): Response
240
    {
241
        try {
242
            if ($this->withRoute) {
243
                $dispatch = $this->routeCheck()->init();
244
            } else {
245
                $dispatch = $this->route->url($this->getRealPath())->init();
246
            }
247
248
            // 监听AppBegin
249
            $this->event->trigger('AppBegin');
250
251
            $data = null;
252
        } catch (HttpResponseException $exception) {
253
            $dispatch = null;
254
            $data     = $exception->getResponse();
255
        }
256
257
        $this->middleware->add(function (Request $request, $next) use ($dispatch, $data) {
0 ignored issues
show
Unused Code introduced by
The parameter $next is not used and could be removed. ( Ignorable by Annotation )

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

257
        $this->middleware->add(function (Request $request, /** @scrutinizer ignore-unused */ $next) use ($dispatch, $data) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

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

257
        $this->middleware->add(function (/** @scrutinizer ignore-unused */ Request $request, $next) use ($dispatch, $data) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
258
            return is_null($data) ? $dispatch->run() : $data;
259
        });
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...
260
261
        $response = $this->middleware->dispatch($this->request);
262
263
        // 监听AppEnd
264
        $this->event->trigger('AppEnd', $response);
265
266
        return $response;
267
    }
268
269
    /**
270
     * 实例化访问控制器
271
     * @access public
272
     * @param  string $name 资源地址
273
     * @return object
274
     * @throws ClassNotFoundException
275
     */
276
    public function controller(string $name)
277
    {
278
        $suffix = $this->controllerSuffix ? 'Controller' : '';
279
        $class  = $this->parseClass($this->controllerLayer, $name . $suffix);
280
281
        if (class_exists($class)) {
282
            return $this->make($class, [], true);
283
        } elseif ($this->emptyController && class_exists($emptyClass = $this->parseClass($this->controllerLayer, $this->emptyController . $suffix))) {
284
            return $this->make($emptyClass, [], true);
285
        }
286
287
        throw new ClassNotFoundException('class not exists:' . $class, $class);
288
    }
289
290
    /**
291
     * 路由初始化(路由规则注册)
292
     * @access protected
293
     * @return void
294
     */
295
    protected function routeInit(): void
296
    {
297
        // 加载路由定义
298
        if (is_dir($this->routePath)) {
299
            $files = glob($this->routePath . DIRECTORY_SEPARATOR . '*.php');
300
            foreach ($files as $file) {
301
                include $file;
302
            }
303
        }
304
305
        if ($this->route->config('route_annotation')) {
306
            // 自动生成注解路由定义
307
            if ($this->isDebug()) {
308
                $this->build->buildRoute();
309
            }
310
311
            $filename = $this->runtimePath . 'build_route.php';
312
313
            if (is_file($filename)) {
314
                include $filename;
315
            }
316
        }
317
    }
318
319
    /**
320
     * URL路由检测(根据PATH_INFO)
321
     * @access protected
322
     * @return Dispatch
323
     */
324
    protected function routeCheck(): Dispatch
325
    {
326
        // 检测路由缓存
327
        if (!$this->isDebug() && $this->route->config('route_check_cache')) {
328
            $routeKey = $this->getRouteCacheKey();
329
            $option   = $this->route->config('route_cache_option');
330
331
            if ($option && $this->cache->connect($option)->has($routeKey)) {
332
                return $this->cache->connect($option)->get($routeKey);
333
            } elseif ($this->cache->has($routeKey)) {
334
                return $this->cache->get($routeKey);
335
            }
336
        }
337
338
        $this->routeInit();
339
340
        // 路由检测
341
        $dispatch = $this->route->check($this->getRealPath());
342
343
        if (!empty($routeKey)) {
344
            try {
345
                if (!empty($option)) {
346
                    $this->cache->connect($option)->tag('route_cache')->set($routeKey, $dispatch);
347
                } else {
348
                    $this->cache->tag('route_cache')->set($routeKey, $dispatch);
349
                }
350
            } catch (\Exception $e) {
351
                // 存在闭包的时候缓存无效
352
            }
353
        }
354
355
        return $dispatch;
356
    }
357
358
    /**
359
     * 获取路由缓存Key
360
     * @access protected
361
     * @return string
362
     */
363
    protected function getRouteCacheKey(): string
364
    {
365
        if ($this->route->config('route_check_cache_key')) {
366
            $closure  = $this->route->config('route_check_cache_key');
367
            $routeKey = $closure($this->request);
368
        } else {
369
            $routeKey = md5($this->request->baseUrl(true) . ':' . $this->request->method());
370
        }
371
372
        return $routeKey;
373
    }
374
375
}
376