Completed
Push — 6.0 ( 9c5c55...31860d )
by liu
03:11
created

Route   F

Complexity

Total Complexity 96

Size/Duplication

Total Lines 880
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 222
dl 0
loc 880
ccs 0
cts 226
cp 0
rs 2
c 0
b 0
f 0
wmc 96

47 Methods

Rating   Name   Duplication   Size   Complexity  
A getRuleList() 0 3 1
A setRule() 0 3 1
A isTest() 0 3 1
A option() 0 5 1
F checkDomain() 0 49 15
A getDomains() 0 3 1
A get() 0 3 1
A group() 0 10 2
A import() 0 3 1
A setName() 0 3 1
A bind() 0 7 2
A rest() 0 9 3
A setDefaultDomain() 0 9 1
A __construct() 0 22 4
A getRest() 0 7 2
A getGroup() 0 3 2
A getRuleName() 0 3 1
A resource() 0 4 1
A dispatch() 0 35 4
A put() 0 3 1
A patch() 0 3 1
A lazy() 0 4 1
A getBind() 0 3 1
A redirect() 0 3 1
A getRule() 0 3 1
A any() 0 3 1
A path() 0 17 3
A post() 0 3 1
A url() 0 3 1
A miss() 0 3 1
A delete() 0 3 1
A setGroup() 0 3 1
A clear() 0 6 2
A check() 0 21 5
A domain() 0 24 6
A view() 0 3 1
A mergeRuleRegex() 0 6 1
A rule() 0 3 1
A getName() 0 3 1
A getRouteCacheKey() 0 10 2
A __call() 0 3 1
A setTestMode() 0 3 1
A setCrossDomainRule() 0 9 2
A buildUrl() 0 3 1
B getDomainBind() 0 25 9
A config() 0 7 2
A pattern() 0 5 1

How to fix   Complexity   

Complex Class

Complex classes like Route often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Route, and based on these observations, apply Extract Interface, too.

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 Closure;
16
use think\cache\Driver;
17
use think\exception\HttpResponseException;
18
use think\exception\RouteNotFoundException;
19
use think\route\Dispatch;
20
use think\route\dispatch\Url as UrlDispatch;
21
use think\route\Domain;
22
use think\route\Resource;
23
use think\route\Rule;
24
use think\route\RuleGroup;
25
use think\route\RuleItem;
26
use think\route\RuleName;
27
use think\route\Url as UrlBuild;
28
29
/**
30
 * 路由管理类
31
 */
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...
32
class Route
33
{
34
    /**
35
     * REST定义
36
     * @var array
37
     */
38
    protected $rest = [
39
        'index'  => ['get', '', 'index'],
40
        'create' => ['get', '/create', 'create'],
41
        'edit'   => ['get', '/<id>/edit', 'edit'],
42
        'read'   => ['get', '/<id>', 'read'],
43
        'save'   => ['post', '', 'save'],
44
        'update' => ['put', '/<id>', 'update'],
45
        'delete' => ['delete', '/<id>', 'delete'],
46
    ];
47
48
    /**
49
     * 配置参数
50
     * @var array
51
     */
52
    protected $config = [
53
        // pathinfo分隔符
54
        'pathinfo_depr'         => '/',
55
        // 是否开启路由延迟解析
56
        'url_lazy_route'        => false,
57
        // 是否强制使用路由
58
        'url_route_must'        => false,
59
        // 合并路由规则
60
        'route_rule_merge'      => false,
61
        // 路由是否完全匹配
62
        'route_complete_match'  => false,
63
        // 使用注解路由
64
        'route_annotation'      => false,
65
        // 路由缓存设置
66
        'route_check_cache'     => false,
67
        'route_cache_option'    => [],
68
        'route_check_cache_key' => '',
69
        // 是否自动转换URL中的控制器和操作名
70
        'url_convert'           => true,
71
        // 默认的路由变量规则
72
        'default_route_pattern' => '[\w\.]+',
73
        // URL伪静态后缀
74
        'url_html_suffix'       => 'html',
75
        // 访问控制器层名称
76
        'controller_layer'      => 'controller',
77
        // 空控制器名
78
        'empty_controller'      => 'Error',
79
        // 是否使用控制器后缀
80
        'controller_suffix'     => false,
81
        // 默认控制器名
82
        'default_controller'    => 'Index',
83
        // 默认操作名
84
        'default_action'        => 'index',
85
        // 操作方法后缀
86
        'action_suffix'         => '',
87
        // 是否开启路由检测缓存
88
        'route_check_cache'     => false,
89
        // 非路由变量是否使用普通参数方式(用于URL生成)
90
        'url_common_param'      => true,
91
    ];
92
93
    /**
94
     * 当前应用
95
     * @var App
96
     */
97
    protected $app;
98
99
    /**
100
     * 请求对象
101
     * @var Request
102
     */
103
    protected $request;
104
105
    /**
106
     * 缓存
107
     * @var Driver
108
     */
109
    protected $cache;
110
111
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
112
     * @var RuleName
113
     */
114
    protected $ruleName;
115
116
    /**
117
     * 当前HOST
118
     * @var string
119
     */
120
    protected $host;
121
122
    /**
123
     * 当前分组对象
124
     * @var RuleGroup
125
     */
126
    protected $group;
127
128
    /**
129
     * 路由绑定
130
     * @var array
131
     */
132
    protected $bind = [];
133
134
    /**
135
     * 域名对象
136
     * @var array
137
     */
138
    protected $domains = [];
139
140
    /**
141
     * 跨域路由规则
142
     * @var RuleGroup
143
     */
144
    protected $cross;
145
146
    /**
147
     * 路由是否延迟解析
148
     * @var bool
149
     */
150
    protected $lazy = true;
151
152
    /**
153
     * 路由是否测试模式
154
     * @var bool
155
     */
156
    protected $isTest = false;
157
158
    /**
159
     * (分组)路由规则是否合并解析
160
     * @var bool
161
     */
162
    protected $mergeRuleRegex = false;
163
164
    public function __construct(App $app)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
165
    {
166
        $this->app      = $app;
167
        $this->config   = array_merge($this->config, $app->config->get('route'));
168
        $this->ruleName = new RuleName();
169
170
        $this->lazy($this->config['url_lazy_route']);
171
172
        if ($this->config['route_check_cache']) {
173
            if (!empty($this->config['route_cache_option'])) {
174
                $this->cache = $app->cache->connect($this->config['route_cache_option']);
175
            } else {
176
                $this->cache = $app->cache->init();
177
            }
178
        }
179
180
        if (is_file($app->getRuntimePath() . 'route.php')) {
181
            // 读取路由映射文件
182
            $this->import(include $app->getRuntimePath() . 'route.php');
183
        }
184
185
        $this->setDefaultDomain();
186
    }
187
188
    public function config(string $name = null)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function config()
Loading history...
189
    {
190
        if (is_null($name)) {
191
            return $this->config;
192
        }
193
194
        return $this->config[$name] ?? null;
195
    }
196
197
    /**
198
     * 设置路由域名及分组(包括资源路由)是否延迟解析
199
     * @access public
200
     * @param bool $lazy 路由是否延迟解析
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
201
     * @return $this
202
     */
203
    public function lazy(bool $lazy = true)
204
    {
205
        $this->lazy = $lazy;
206
        return $this;
207
    }
208
209
    /**
210
     * 设置路由为测试模式
211
     * @access public
212
     * @param bool $test 路由是否测试模式
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
213
     * @return void
214
     */
215
    public function setTestMode(bool $test): void
216
    {
217
        $this->isTest = $test;
218
    }
219
220
    /**
221
     * 检查路由是否为测试模式
222
     * @access public
223
     * @return bool
224
     */
225
    public function isTest(): bool
226
    {
227
        return $this->isTest;
228
    }
229
230
    /**
231
     * 设置路由域名及分组(包括资源路由)是否合并解析
232
     * @access public
233
     * @param bool $merge 路由是否合并解析
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
234
     * @return $this
235
     */
236
    public function mergeRuleRegex(bool $merge = true)
237
    {
238
        $this->mergeRuleRegex = $merge;
239
        $this->group->mergeRuleRegex($merge);
240
241
        return $this;
242
    }
243
244
    /**
245
     * 初始化默认域名
246
     * @access protected
247
     * @return void
248
     */
249
    protected function setDefaultDomain(): void
250
    {
251
        // 注册默认域名
252
        $domain = new Domain($this);
253
254
        $this->domains['-'] = $domain;
255
256
        // 默认分组
257
        $this->group = $domain;
258
    }
259
260
    /**
261
     * 设置当前分组
262
     * @access public
263
     * @param RuleGroup $group 域名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
264
     * @return void
265
     */
266
    public function setGroup(RuleGroup $group): void
267
    {
268
        $this->group = $group;
269
    }
270
271
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $name should have a doc-comment as per coding-style.
Loading history...
272
     * 获取指定标识的路由分组 不指定则获取当前分组
273
     * @access public
274
     * @return RuleGroup
275
     */
276
    public function getGroup(string $name = null)
277
    {
278
        return $name ? $this->ruleName->getGroup($name) : $this->group;
279
    }
280
281
    /**
282
     * 注册变量规则
283
     * @access public
284
     * @param array $pattern 变量规则
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
285
     * @return $this
286
     */
287
    public function pattern(array $pattern)
288
    {
289
        $this->group->pattern($pattern);
290
291
        return $this;
292
    }
293
294
    /**
295
     * 注册路由参数
296
     * @access public
297
     * @param array $option 参数
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
298
     * @return $this
299
     */
300
    public function option(array $option)
301
    {
302
        $this->group->option($option);
303
304
        return $this;
305
    }
306
307
    /**
308
     * 注册域名路由
309
     * @access public
310
     * @param string|array $name 子域名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
311
     * @param mixed        $rule 路由规则
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
312
     * @return Domain
313
     */
314
    public function domain($name, $rule = null): Domain
315
    {
316
        // 支持多个域名使用相同路由规则
317
        $domainName = is_array($name) ? array_shift($name) : $name;
318
319
        if (!isset($this->domains[$domainName])) {
320
            $domain = (new Domain($this, $domainName, $rule))
321
                ->lazy($this->lazy)
322
                ->mergeRuleRegex($this->mergeRuleRegex);
323
324
            $this->domains[$domainName] = $domain;
325
        } else {
326
            $domain = $this->domains[$domainName];
327
            $domain->parseGroupRule($rule);
328
        }
329
330
        if (is_array($name) && !empty($name)) {
331
            foreach ($name as $item) {
332
                $this->domains[$item] = $domainName;
333
            }
334
        }
335
336
        // 返回域名对象
337
        return $domain;
338
    }
339
340
    /**
341
     * 获取域名
342
     * @access public
343
     * @return array
344
     */
345
    public function getDomains(): array
346
    {
347
        return $this->domains;
348
    }
349
350
    /**
351
     * 获取RuleName对象
352
     * @access public
353
     * @return RuleName
354
     */
355
    public function getRuleName(): RuleName
356
    {
357
        return $this->ruleName;
358
    }
359
360
    /**
361
     * 设置路由绑定
362
     * @access public
363
     * @param string $bind   绑定信息
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
364
     * @param string $domain 域名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
365
     * @return $this
366
     */
367
    public function bind(string $bind, string $domain = null)
368
    {
369
        $domain = is_null($domain) ? '-' : $domain;
370
371
        $this->bind[$domain] = $bind;
372
373
        return $this;
374
    }
375
376
    /**
377
     * 读取路由绑定信息
378
     * @access public
379
     * @return array
380
     */
381
    public function getBind(): array
382
    {
383
        return $this->bind;
384
    }
385
386
    /**
387
     * 读取路由绑定
388
     * @access public
389
     * @param string $domain 域名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
390
     * @return string|null
391
     */
392
    public function getDomainBind(string $domain = null)
393
    {
394
        if (is_null($domain)) {
395
            $domain = $this->host;
396
        } elseif (false === strpos($domain, '.')) {
397
            $domain .= '.' . $this->request->rootDomain();
398
        }
399
400
        $subDomain = $this->request->subDomain();
401
402
        if (strpos($subDomain, '.')) {
403
            $name = '*' . strstr($subDomain, '.');
404
        }
405
406
        if (isset($this->bind[$domain])) {
407
            $result = $this->bind[$domain];
408
        } elseif (isset($name) && isset($this->bind[$name])) {
409
            $result = $this->bind[$name];
410
        } elseif (!empty($subDomain) && isset($this->bind['*'])) {
411
            $result = $this->bind['*'];
412
        } else {
413
            $result = null;
414
        }
415
416
        return $result;
417
    }
418
419
    /**
420
     * 读取路由标识
421
     * @access public
422
     * @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...
423
     * @param string $domain 域名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
424
     * @param string $method 请求类型
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
425
     * @return RuleItem[]
426
     */
427
    public function getName(string $name = null, string $domain = null, string $method = '*'): array
428
    {
429
        return $this->ruleName->getName($name, $domain, $method);
430
    }
431
432
    /**
433
     * 批量导入路由标识
434
     * @access public
435
     * @param array $name 路由标识
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
436
     * @return $this
437
     */
438
    public function import(array $name): void
439
    {
440
        $this->ruleName->import($name);
441
    }
442
443
    /**
444
     * 注册路由标识
445
     * @access public
446
     * @param string   $name  路由标识
1 ignored issue
show
Coding Style introduced by
Expected 5 spaces after parameter name; 2 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
447
     * @param RuleItem $ruleItem 路由规则
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
448
     * @param bool     $first 是否优先
1 ignored issue
show
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
449
     * @return void
450
     */
451
    public function setName(string $name, RuleItem $ruleItem, bool $first = false): void
452
    {
453
        $this->ruleName->setName($name, $ruleItem, $first);
454
    }
455
456
    /**
457
     * 保存路由规则
458
     * @access public
459
     * @param string $rule   路由规则
1 ignored issue
show
Coding Style introduced by
Expected 5 spaces after parameter name; 3 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
460
     * @param RuleItem $ruleItem RuleItem对象
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
461
     * @return void
462
     */
463
    public function setRule(string $rule, RuleItem $ruleItem = null): void
464
    {
465
        $this->ruleName->setRule($rule, $ruleItem);
0 ignored issues
show
Bug introduced by
It seems like $ruleItem can also be of type null; however, parameter $ruleItem of think\route\RuleName::setRule() does only seem to accept think\route\RuleItem, 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

465
        $this->ruleName->setRule($rule, /** @scrutinizer ignore-type */ $ruleItem);
Loading history...
466
    }
467
468
    /**
469
     * 读取路由
470
     * @access public
471
     * @param string $rule   路由规则
1 ignored issue
show
Coding Style introduced by
Expected 1 spaces after parameter name; 3 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
472
     * @return RuleItem[]
473
     */
474
    public function getRule(string $rule): array
475
    {
476
        return $this->ruleName->getRule($rule);
477
    }
478
479
    /**
480
     * 读取路由列表
481
     * @access public
482
     * @return array
483
     */
484
    public function getRuleList(): array
485
    {
486
        return $this->ruleName->getRuleList();
487
    }
488
489
    /**
490
     * 清空路由规则
491
     * @access public
492
     * @return void
493
     */
494
    public function clear(): void
495
    {
496
        $this->ruleName->clear();
497
498
        if ($this->group) {
499
            $this->group->clear();
500
        }
501
    }
502
503
    /**
504
     * 注册路由规则
505
     * @access public
506
     * @param string $rule   路由规则
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
507
     * @param mixed  $route  路由地址
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
508
     * @param string $method 请求类型
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
509
     * @return RuleItem
510
     */
511
    public function rule(string $rule, $route = null, string $method = '*'): RuleItem
512
    {
513
        return $this->group->addRule($rule, $route, $method);
514
    }
515
516
    /**
517
     * 设置跨域有效路由规则
518
     * @access public
519
     * @param Rule   $rule   路由规则
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
520
     * @param string $method 请求类型
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
521
     * @return $this
522
     */
523
    public function setCrossDomainRule(Rule $rule, string $method = '*')
524
    {
525
        if (!isset($this->cross)) {
526
            $this->cross = (new RuleGroup($this))->mergeRuleRegex($this->mergeRuleRegex);
527
        }
528
529
        $this->cross->addRuleItem($rule, $method);
530
531
        return $this;
532
    }
533
534
    /**
535
     * 注册路由分组
536
     * @access public
537
     * @param string|\Closure $name  分组名称或者参数
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
538
     * @param mixed           $route 分组路由
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
539
     * @return RuleGroup
540
     */
541
    public function group($name, $route = null): RuleGroup
542
    {
543
        if ($name instanceof \Closure) {
544
            $route = $name;
545
            $name  = '';
546
        }
547
548
        return (new RuleGroup($this, $this->group, $name, $route))
549
            ->lazy($this->lazy)
550
            ->mergeRuleRegex($this->mergeRuleRegex);
551
    }
552
553
    /**
554
     * 注册路由
555
     * @access public
556
     * @param string $rule  路由规则
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
557
     * @param mixed  $route 路由地址
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
558
     * @return RuleItem
559
     */
560
    public function any(string $rule, $route): RuleItem
561
    {
562
        return $this->rule($rule, $route, '*');
563
    }
564
565
    /**
566
     * 注册GET路由
567
     * @access public
568
     * @param string $rule  路由规则
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
569
     * @param mixed  $route 路由地址
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
570
     * @return RuleItem
571
     */
572
    public function get(string $rule, $route): RuleItem
573
    {
574
        return $this->rule($rule, $route, 'GET');
575
    }
576
577
    /**
578
     * 注册POST路由
579
     * @access public
580
     * @param string $rule  路由规则
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
581
     * @param mixed  $route 路由地址
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
582
     * @return RuleItem
583
     */
584
    public function post(string $rule, $route): RuleItem
585
    {
586
        return $this->rule($rule, $route, 'POST');
587
    }
588
589
    /**
590
     * 注册PUT路由
591
     * @access public
592
     * @param string $rule  路由规则
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
593
     * @param mixed  $route 路由地址
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
594
     * @return RuleItem
595
     */
596
    public function put(string $rule, $route): RuleItem
597
    {
598
        return $this->rule($rule, $route, 'PUT');
599
    }
600
601
    /**
602
     * 注册DELETE路由
603
     * @access public
604
     * @param string $rule  路由规则
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
605
     * @param mixed  $route 路由地址
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
606
     * @return RuleItem
607
     */
608
    public function delete(string $rule, $route): RuleItem
609
    {
610
        return $this->rule($rule, $route, 'DELETE');
611
    }
612
613
    /**
614
     * 注册PATCH路由
615
     * @access public
616
     * @param string $rule  路由规则
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
617
     * @param mixed  $route 路由地址
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
618
     * @return RuleItem
619
     */
620
    public function patch(string $rule, $route): RuleItem
621
    {
622
        return $this->rule($rule, $route, 'PATCH');
623
    }
624
625
    /**
626
     * 注册资源路由
627
     * @access public
628
     * @param string $rule  路由规则
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
629
     * @param string $route 路由地址
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
630
     * @return Resource
631
     */
632
    public function resource(string $rule, string $route): Resource
633
    {
634
        return (new Resource($this, $this->group, $rule, $route, $this->rest))
635
            ->lazy($this->lazy);
636
    }
637
638
    /**
639
     * 注册视图路由
640
     * @access public
641
     * @param string|array $rule     路由规则
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
642
     * @param string       $template 路由模板地址
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
643
     * @param array        $vars     模板变量
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
644
     * @return RuleItem
645
     */
646
    public function view(string $rule, string $template = '', array $vars = []): RuleItem
647
    {
648
        return $this->rule($rule, $template, 'GET')->view($vars);
649
    }
650
651
    /**
652
     * 注册重定向路由
653
     * @access public
654
     * @param string|array $rule   路由规则
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
655
     * @param string       $route  路由地址
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
656
     * @param int          $status 状态码
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
657
     * @return RuleItem
658
     */
659
    public function redirect(string $rule, string $route = '', int $status = 301): RuleItem
660
    {
661
        return $this->rule($rule, $route, '*')->redirect()->status($status);
662
    }
663
664
    /**
665
     * rest方法定义和修改
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
666
     * @access public
667
     * @param string|array $name     方法名称
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
668
     * @param array|bool   $resource 资源
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
669
     * @return $this
670
     */
671
    public function rest($name, $resource = [])
672
    {
673
        if (is_array($name)) {
674
            $this->rest = $resource ? $name : array_merge($this->rest, $name);
675
        } else {
676
            $this->rest[$name] = $resource;
677
        }
678
679
        return $this;
680
    }
681
682
    /**
683
     * 获取rest方法定义的参数
684
     * @access public
685
     * @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...
686
     * @return array|null
687
     */
688
    public function getRest(string $name = null)
689
    {
690
        if (is_null($name)) {
691
            return $this->rest;
692
        }
693
694
        return $this->rest[$name] ?? null;
695
    }
696
697
    /**
698
     * 注册未匹配路由规则后的处理
699
     * @access public
700
     * @param string|Closure $route  路由地址
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
701
     * @param string         $method 请求类型
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
702
     * @return RuleItem
703
     */
704
    public function miss($route, string $method = '*'): RuleItem
705
    {
706
        return $this->group->miss($route, $method);
707
    }
708
709
    /**
710
     * 路由调度
711
     * @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...
712
     * @param Closure $withRoute
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...
713
     * @return Response
714
     */
715
    public function dispatch(Request $request, $withRoute = null)
716
    {
717
        $this->request = $request;
718
        $this->host    = $this->request->host(true);
719
720
        if ($withRoute) {
721
            $checkCallback = function () use ($request, $withRoute) {
0 ignored issues
show
Unused Code introduced by
The import $request is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
722
                //加载路由
723
                $withRoute();
724
                return $this->check();
725
            };
726
727
            if ($this->config['route_check_cache']) {
728
                $dispatch = $this->cache
729
                    ->tag('route_cache')
730
                    ->remember($this->getRouteCacheKey($request), $checkCallback);
731
            } else {
732
                $dispatch = $checkCallback();
733
            }
734
        } else {
735
            $dispatch = $this->url($this->path());
736
        }
737
738
        $dispatch->init($this->app);
739
740
        $this->app->middleware->add(function () use ($dispatch) {
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...
741
            try {
742
                $response = $dispatch->run();
743
            } catch (HttpResponseException $exception) {
744
                $response = $exception->getResponse();
745
            }
746
            return $response;
747
        });
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...
748
749
        return $this->app->middleware->dispatch($request);
750
    }
751
752
    /**
753
     * 获取路由缓存Key
754
     * @access protected
755
     * @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...
756
     * @return string
757
     */
758
    protected function getRouteCacheKey(Request $request): string
759
    {
760
        if (!empty($this->config['route_check_cache_key'])) {
761
            $closure  = $this->config['route_check_cache_key'];
762
            $routeKey = $closure($request);
763
        } else {
764
            $routeKey = md5($request->baseUrl(true) . ':' . $request->method());
765
        }
766
767
        return $routeKey;
768
    }
769
770
    /**
771
     * 检测URL路由
772
     * @access public
773
     * @return Dispatch
774
     * @throws RouteNotFoundException
775
     */
776
    public function check(): Dispatch
777
    {
778
        // 自动检测域名路由
779
        $url = str_replace($this->config['pathinfo_depr'], '|', $this->path());
780
781
        $completeMatch = $this->config['route_complete_match'];
782
783
        $result = $this->checkDomain()->check($this->request, $url, $completeMatch);
784
785
        if (false === $result && !empty($this->cross)) {
786
            // 检测跨域路由
787
            $result = $this->cross->check($this->request, $url, $completeMatch);
788
        }
789
790
        if (false !== $result) {
791
            return $result;
792
        } elseif ($this->config['url_route_must']) {
793
            throw new RouteNotFoundException();
794
        }
795
796
        return $this->url($url);
797
    }
798
799
    /**
800
     * 获取当前请求URL的pathinfo信息(不含URL后缀)
801
     * @access protected
802
     * @return string
803
     */
804
    protected function path(): string
805
    {
806
        $suffix   = $this->config['url_html_suffix'];
807
        $pathinfo = $this->request->pathinfo();
808
809
        if (false === $suffix) {
810
            // 禁止伪静态访问
811
            $path = $pathinfo;
812
        } elseif ($suffix) {
813
            // 去除正常的URL后缀
814
            $path = preg_replace('/\.(' . ltrim($suffix, '.') . ')$/i', '', $pathinfo);
815
        } else {
816
            // 允许任何后缀访问
817
            $path = preg_replace('/\.' . $this->request->ext() . '$/i', '', $pathinfo);
818
        }
819
820
        return $path;
821
    }
822
823
    /**
824
     * 默认URL解析
825
     * @access public
826
     * @param string $url URL地址
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
827
     * @return Dispatch
828
     */
829
    public function url(string $url): UrlDispatch
830
    {
831
        return new UrlDispatch($this->request, $this->group, $url);
832
    }
833
834
    /**
835
     * 检测域名的路由规则
836
     * @access protected
837
     * @return Domain
838
     */
839
    protected function checkDomain(): Domain
840
    {
841
        $item = false;
842
843
        if (count($this->domains) > 1) {
844
            // 获取当前子域名
845
            $subDomain = $this->request->subDomain();
846
847
            $domain  = $subDomain ? explode('.', $subDomain) : [];
848
            $domain2 = $domain ? array_pop($domain) : '';
849
850
            if ($domain) {
851
                // 存在三级域名
852
                $domain3 = array_pop($domain);
853
            }
854
855
            if (isset($this->domains[$this->host])) {
856
                // 子域名配置
857
                $item = $this->domains[$this->host];
858
            } elseif (isset($this->domains[$subDomain])) {
859
                $item = $this->domains[$subDomain];
860
            } elseif (isset($this->domains['*.' . $domain2]) && !empty($domain3)) {
861
                // 泛三级域名
862
                $item      = $this->domains['*.' . $domain2];
863
                $panDomain = $domain3;
864
            } elseif (isset($this->domains['*']) && !empty($domain2)) {
865
                // 泛二级域名
866
                if ('www' != $domain2) {
867
                    $item      = $this->domains['*'];
868
                    $panDomain = $domain2;
869
                }
870
            }
871
872
            if (isset($panDomain)) {
873
                // 保存当前泛域名
874
                $this->request->setPanDomain($panDomain);
875
            }
876
        }
877
878
        if (false === $item) {
879
            // 检测全局域名规则
880
            $item = $this->domains['-'];
881
        }
882
883
        if (is_string($item)) {
884
            $item = $this->domains[$item];
885
        }
886
887
        return $item;
888
    }
889
890
    /**
891
     * URL生成 支持路由反射
892
     * @access public
893
     * @param  string $url 路由地址
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 1 found
Loading history...
894
     * @param  array  $vars 参数 ['a'=>'val1', 'b'=>'val2']
895
     * @return UrlBuild
896
     */
897
    public function buildUrl(string $url = '', array $vars = []): UrlBuild
898
    {
899
        return new UrlBuild($this, $this->app, $url, $vars);
900
    }
901
902
    /**
903
     * 设置全局的路由分组参数
904
     * @access public
905
     * @param string $method 方法名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
906
     * @param array  $args   调用参数
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
907
     * @return RuleGroup
908
     */
909
    public function __call($method, $args)
910
    {
911
        return call_user_func_array([$this->group, $method], $args);
912
    }
913
}
914