Completed
Push — 6.0 ( 4bea3d...c65c26 )
by liu
05:50
created

Route   F

Complexity

Total Complexity 112

Size/Duplication

Total Lines 958
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 11
Bugs 0 Features 0
Metric Value
eloc 249
dl 0
loc 958
ccs 0
cts 240
cp 0
rs 2
c 11
b 0
f 0
wmc 112

51 Methods

Rating   Name   Duplication   Size   Complexity  
A getRuleList() 0 3 1
A isTest() 0 3 1
A setRule() 0 3 1
F checkDomain() 0 49 15
A option() 0 5 1
A getDomains() 0 3 1
A init() 0 12 3
A get() 0 3 1
A import() 0 3 1
A group() 0 12 2
A setName() 0 3 1
A rest() 0 9 3
A bind() 0 7 2
A __construct() 0 9 2
A setDefaultDomain() 0 9 1
A getRest() 0 7 2
A getGroup() 0 3 2
A getRuleName() 0 3 1
A resource() 0 5 1
A dispatch() 0 30 3
A put() 0 3 1
A patch() 0 3 1
A lazy() 0 4 1
A getBind() 0 3 1
A getRule() 0 3 1
A redirect() 0 3 1
A any() 0 3 1
A post() 0 3 1
A path() 0 17 3
C url() 0 33 14
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 25 6
A view() 0 3 1
A mergeRuleRegex() 0 6 1
A setAppName() 0 3 1
A rule() 0 3 1
A getName() 0 3 1
A getRouteCacheKey() 0 10 2
A options() 0 3 1
A __call() 0 3 1
A setCrossDomainRule() 0 9 2
A setTestMode() 0 3 1
A buildUrl() 0 3 1
B getDomainBind() 0 25 9
A app() 0 3 1
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
// +----------------------------------------------------------------------
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\HttpException;
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
 * @package think
0 ignored issues
show
Coding Style introduced by
Package name "think" is not valid; consider "Think" instead
Loading history...
32
 */
33
class Route
34
{
35
    /**
36
     * REST定义
37
     * @var array
38
     */
39
    protected $rest = [
40
        'index'  => ['get', '', 'index'],
41
        'create' => ['get', '/create', 'create'],
42
        'edit'   => ['get', '/<id>/edit', 'edit'],
43
        'read'   => ['get', '/<id>', 'read'],
44
        'save'   => ['post', '', 'save'],
45
        'update' => ['put', '/<id>', 'update'],
46
        'delete' => ['delete', '/<id>', 'delete'],
47
    ];
48
49
    /**
50
     * 配置参数
51
     * @var array
52
     */
53
    protected $config = [
54
        // pathinfo分隔符
55
        'pathinfo_depr'         => '/',
56
        // 是否开启路由延迟解析
57
        'url_lazy_route'        => false,
58
        // 是否强制使用路由
59
        'url_route_must'        => false,
60
        // 合并路由规则
61
        'route_rule_merge'      => false,
62
        // 路由是否完全匹配
63
        'route_complete_match'  => false,
64
        // 去除斜杠
65
        'remove_slash'          => false,
66
        // 使用注解路由
67
        'route_annotation'      => false,
68
        // 路由缓存设置
69
        'route_check_cache'     => false,
70
        'route_check_cache_key' => '',
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
        // 非路由变量是否使用普通参数方式(用于URL生成)
88
        'url_common_param'      => true,
89
    ];
90
91
    /**
92
     * 当前应用
93
     * @var App
94
     */
95
    protected $app;
96
97
    /**
98
     * 请求对象
99
     * @var Request
100
     */
101
    protected $request;
102
103
    /**
104
     * 缓存
105
     * @var Driver
106
     */
107
    protected $cache;
108
109
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
110
     * @var RuleName
111
     */
112
    protected $ruleName;
113
114
    /**
115
     * 当前HOST
116
     * @var string
117
     */
118
    protected $host;
119
120
    /**
121
     * 当前分组对象
122
     * @var RuleGroup
123
     */
124
    protected $group;
125
126
    /**
127
     * 路由绑定
128
     * @var array
129
     */
130
    protected $bind = [];
131
132
    /**
133
     * 域名对象
134
     * @var array
135
     */
136
    protected $domains = [];
137
138
    /**
139
     * 跨域路由规则
140
     * @var RuleGroup
141
     */
142
    protected $cross;
143
144
    /**
145
     * 路由是否延迟解析
146
     * @var bool
147
     */
148
    protected $lazy = true;
149
150
    /**
151
     * 路由是否测试模式
152
     * @var bool
153
     */
154
    protected $isTest = false;
155
156
    /**
157
     * (分组)路由规则是否合并解析
158
     * @var bool
159
     */
160
    protected $mergeRuleRegex = false;
161
162
    /**
163
     * 是否去除URL最后的斜线
164
     * @var bool
165
     */
166
    protected $removeSlash = false;
167
168
    /**
169
     * 当前路由所属应用
170
     * @var string
171
     */
172
    protected $appName = '';
173
174
    public function __construct(App $app)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
175
    {
176
        $this->app      = $app;
177
        $this->ruleName = new RuleName();
178
        $this->setDefaultDomain();
179
180
        if (is_file($this->app->getRuntimePath() . 'route.php')) {
181
            // 读取路由映射文件
182
            $this->import(include $this->app->getRuntimePath() . 'route.php');
183
        }
184
    }
185
186
    protected function init()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function init()
Loading history...
187
    {
188
        $this->config = array_merge($this->config, $this->app->config->get('route'));
189
190
        $this->lazy($this->config['url_lazy_route']);
191
        $this->mergeRuleRegex = $this->config['route_rule_merge'];
192
        $this->removeSlash    = $this->config['remove_slash'];
193
194
        $this->group->removeSlash($this->removeSlash);
195
196
        if ($this->config['route_check_cache']) {
197
            $this->cache = $this->app->cache->store(true === $this->config['route_check_cache'] ? '' : $this->config['route_check_cache']);
198
        }
199
    }
200
201
    public function config(string $name = null)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function config()
Loading history...
202
    {
203
        if (is_null($name)) {
204
            return $this->config;
205
        }
206
207
        return $this->config[$name] ?? null;
208
    }
209
210
    /**
211
     * 设置路由域名及分组(包括资源路由)是否延迟解析
212
     * @access public
213
     * @param bool $lazy 路由是否延迟解析
214
     * @return $this
215
     */
216
    public function lazy(bool $lazy = true)
217
    {
218
        $this->lazy = $lazy;
219
        return $this;
220
    }
221
222
    /**
223
     * 设置路由为测试模式
224
     * @access public
225
     * @param bool $test 路由是否测试模式
226
     * @return void
227
     */
228
    public function setTestMode(bool $test): void
229
    {
230
        $this->isTest = $test;
231
    }
232
233
    /**
234
     * 检查路由是否为测试模式
235
     * @access public
236
     * @return bool
237
     */
238
    public function isTest(): bool
239
    {
240
        return $this->isTest;
241
    }
242
243
    /**
244
     * 设置路由域名及分组(包括资源路由)是否合并解析
245
     * @access public
246
     * @param bool $merge 路由是否合并解析
247
     * @return $this
248
     */
249
    public function mergeRuleRegex(bool $merge = true)
250
    {
251
        $this->mergeRuleRegex = $merge;
252
        $this->group->mergeRuleRegex($merge);
253
254
        return $this;
255
    }
256
257
    /**
258
     * 初始化默认域名
259
     * @access protected
260
     * @return void
261
     */
262
    protected function setDefaultDomain(): void
263
    {
264
        // 注册默认域名
265
        $domain = new Domain($this);
266
267
        $this->domains['-'] = $domain;
268
269
        // 默认分组
270
        $this->group = $domain;
271
    }
272
273
    /**
274
     * 设置当前应用名
275
     * @access public
276
     * @param string $name 应用名
277
     * @return void
278
     */
279
    public function setAppName(string $name): void
280
    {
281
        $this->appName = $name;
282
    }
283
284
    /**
285
     * 设置当前分组
286
     * @access public
287
     * @param RuleGroup $group 域名
288
     * @return void
289
     */
290
    public function setGroup(RuleGroup $group): void
291
    {
292
        $this->group = $group;
293
    }
294
295
    /**
296
     * 获取指定标识的路由分组 不指定则获取当前分组
297
     * @access public
298
     * @param string $name 分组标识
299
     * @return RuleGroup
300
     */
301
    public function getGroup(string $name = null)
302
    {
303
        return $name ? $this->ruleName->getGroup($name) : $this->group;
304
    }
305
306
    /**
307
     * 注册变量规则
308
     * @access public
309
     * @param array $pattern 变量规则
310
     * @return $this
311
     */
312
    public function pattern(array $pattern)
313
    {
314
        $this->group->pattern($pattern);
315
316
        return $this;
317
    }
318
319
    /**
320
     * 注册路由参数
321
     * @access public
322
     * @param array $option 参数
323
     * @return $this
324
     */
325
    public function option(array $option)
326
    {
327
        $this->group->option($option);
328
329
        return $this;
330
    }
331
332
    /**
333
     * 注册域名路由
334
     * @access public
335
     * @param string|array $name 子域名
336
     * @param mixed        $rule 路由规则
337
     * @return Domain
338
     */
339
    public function domain($name, $rule = null): Domain
340
    {
341
        // 支持多个域名使用相同路由规则
342
        $domainName = is_array($name) ? array_shift($name) : $name;
343
344
        if (!isset($this->domains[$domainName])) {
345
            $domain = (new Domain($this, $domainName, $rule))
346
                ->lazy($this->lazy)
347
                ->removeSlash($this->removeSlash)
348
                ->mergeRuleRegex($this->mergeRuleRegex);
349
350
            $this->domains[$domainName] = $domain;
351
        } else {
352
            $domain = $this->domains[$domainName];
353
            $domain->parseGroupRule($rule);
354
        }
355
356
        if (is_array($name) && !empty($name)) {
357
            foreach ($name as $item) {
358
                $this->domains[$item] = $domainName;
359
            }
360
        }
361
362
        // 返回域名对象
363
        return $domain;
364
    }
365
366
    /**
367
     * 获取域名
368
     * @access public
369
     * @return array
370
     */
371
    public function getDomains(): array
372
    {
373
        return $this->domains;
374
    }
375
376
    /**
377
     * 获取RuleName对象
378
     * @access public
379
     * @return RuleName
380
     */
381
    public function getRuleName(): RuleName
382
    {
383
        return $this->ruleName;
384
    }
385
386
    /**
387
     * 设置路由绑定
388
     * @access public
389
     * @param string $bind   绑定信息
390
     * @param string $domain 域名
391
     * @return $this
392
     */
393
    public function bind(string $bind, string $domain = null)
394
    {
395
        $domain = is_null($domain) ? '-' : $domain;
396
397
        $this->bind[$domain] = $bind;
398
399
        return $this;
400
    }
401
402
    /**
403
     * 读取路由绑定信息
404
     * @access public
405
     * @return array
406
     */
407
    public function getBind(): array
408
    {
409
        return $this->bind;
410
    }
411
412
    /**
413
     * 读取路由绑定
414
     * @access public
415
     * @param string $domain 域名
416
     * @return string|null
417
     */
418
    public function getDomainBind(string $domain = null)
419
    {
420
        if (is_null($domain)) {
421
            $domain = $this->host;
422
        } elseif (false === strpos($domain, '.')) {
423
            $domain .= '.' . $this->request->rootDomain();
424
        }
425
426
        $subDomain = $this->request->subDomain();
427
428
        if (strpos($subDomain, '.')) {
429
            $name = '*' . strstr($subDomain, '.');
430
        }
431
432
        if (isset($this->bind[$domain])) {
433
            $result = $this->bind[$domain];
434
        } elseif (isset($name) && isset($this->bind[$name])) {
435
            $result = $this->bind[$name];
436
        } elseif (!empty($subDomain) && isset($this->bind['*'])) {
437
            $result = $this->bind['*'];
438
        } else {
439
            $result = null;
440
        }
441
442
        return $result;
443
    }
444
445
    /**
446
     * 读取路由标识
447
     * @access public
448
     * @param string $name   路由标识
449
     * @param string $domain 域名
450
     * @param string $method 请求类型
451
     * @return RuleItem[]
452
     */
453
    public function getName(string $name = null, string $domain = null, string $method = '*'): array
454
    {
455
        return $this->ruleName->getName($name, $domain, $method);
456
    }
457
458
    /**
459
     * 批量导入路由标识
460
     * @access public
461
     * @param array $name 路由标识
462
     * @return $this
463
     */
464
    public function import(array $name): void
465
    {
466
        $this->ruleName->import($name);
467
    }
468
469
    /**
470
     * 注册路由标识
471
     * @access public
472
     * @param string   $name     路由标识
473
     * @param RuleItem $ruleItem 路由规则
474
     * @param bool     $first    是否优先
475
     * @return void
476
     */
477
    public function setName(string $name, RuleItem $ruleItem, bool $first = false): void
478
    {
479
        $this->ruleName->setName($name, $ruleItem, $first);
480
    }
481
482
    /**
483
     * 保存路由规则
484
     * @access public
485
     * @param string   $rule     路由规则
486
     * @param RuleItem $ruleItem RuleItem对象
487
     * @return void
488
     */
489
    public function setRule(string $rule, RuleItem $ruleItem = null): void
490
    {
491
        $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

491
        $this->ruleName->setRule($rule, /** @scrutinizer ignore-type */ $ruleItem);
Loading history...
492
    }
493
494
    /**
495
     * 读取路由
496
     * @access public
497
     * @param string $rule 路由规则
498
     * @return RuleItem[]
499
     */
500
    public function getRule(string $rule): array
501
    {
502
        return $this->ruleName->getRule($rule);
503
    }
504
505
    /**
506
     * 读取路由列表
507
     * @access public
508
     * @return array
509
     */
510
    public function getRuleList(): array
511
    {
512
        return $this->ruleName->getRuleList();
513
    }
514
515
    /**
516
     * 清空路由规则
517
     * @access public
518
     * @return void
519
     */
520
    public function clear(): void
521
    {
522
        $this->ruleName->clear();
523
524
        if ($this->group) {
525
            $this->group->clear();
526
        }
527
    }
528
529
    /**
530
     * 注册路由规则
531
     * @access public
532
     * @param string $rule   路由规则
533
     * @param mixed  $route  路由地址
534
     * @param string $method 请求类型
535
     * @return RuleItem
536
     */
537
    public function rule(string $rule, $route = null, string $method = '*'): RuleItem
538
    {
539
        return $this->group->addRule($rule, $route, $method)->app($this->appName);
540
    }
541
542
    /**
543
     * 设置跨域有效路由规则
544
     * @access public
545
     * @param Rule   $rule   路由规则
546
     * @param string $method 请求类型
547
     * @return $this
548
     */
549
    public function setCrossDomainRule(Rule $rule, string $method = '*')
550
    {
551
        if (!isset($this->cross)) {
552
            $this->cross = (new RuleGroup($this))->mergeRuleRegex($this->mergeRuleRegex);
553
        }
554
555
        $this->cross->addRuleItem($rule, $method);
556
557
        return $this;
558
    }
559
560
    /**
561
     * 注册应用路由
562
     * @access public
563
     * @param string  $name  应用名称
564
     * @param Closure $route 应用路由
565
     * @return RuleGroup
566
     */
567
    public function app($name, Closure $route): RuleGroup
568
    {
569
        return $this->group('', $route)->app($name);
570
    }
571
572
    /**
573
     * 注册路由分组
574
     * @access public
575
     * @param string|\Closure $name  分组名称或者参数
576
     * @param mixed           $route 分组路由
577
     * @return RuleGroup
578
     */
579
    public function group($name, $route = null): RuleGroup
580
    {
581
        if ($name instanceof Closure) {
582
            $route = $name;
583
            $name  = '';
584
        }
585
586
        return (new RuleGroup($this, $this->group, $name, $route))
587
            ->lazy($this->lazy)
588
            ->removeSlash($this->removeSlash)
589
            ->mergeRuleRegex($this->mergeRuleRegex)
590
            ->app($this->appName);
591
    }
592
593
    /**
594
     * 注册路由
595
     * @access public
596
     * @param string $rule  路由规则
597
     * @param mixed  $route 路由地址
598
     * @return RuleItem
599
     */
600
    public function any(string $rule, $route): RuleItem
601
    {
602
        return $this->rule($rule, $route, '*');
603
    }
604
605
    /**
606
     * 注册GET路由
607
     * @access public
608
     * @param string $rule  路由规则
609
     * @param mixed  $route 路由地址
610
     * @return RuleItem
611
     */
612
    public function get(string $rule, $route): RuleItem
613
    {
614
        return $this->rule($rule, $route, 'GET');
615
    }
616
617
    /**
618
     * 注册POST路由
619
     * @access public
620
     * @param string $rule  路由规则
621
     * @param mixed  $route 路由地址
622
     * @return RuleItem
623
     */
624
    public function post(string $rule, $route): RuleItem
625
    {
626
        return $this->rule($rule, $route, 'POST');
627
    }
628
629
    /**
630
     * 注册PUT路由
631
     * @access public
632
     * @param string $rule  路由规则
633
     * @param mixed  $route 路由地址
634
     * @return RuleItem
635
     */
636
    public function put(string $rule, $route): RuleItem
637
    {
638
        return $this->rule($rule, $route, 'PUT');
639
    }
640
641
    /**
642
     * 注册DELETE路由
643
     * @access public
644
     * @param string $rule  路由规则
645
     * @param mixed  $route 路由地址
646
     * @return RuleItem
647
     */
648
    public function delete(string $rule, $route): RuleItem
649
    {
650
        return $this->rule($rule, $route, 'DELETE');
651
    }
652
653
    /**
654
     * 注册PATCH路由
655
     * @access public
656
     * @param string $rule  路由规则
657
     * @param mixed  $route 路由地址
658
     * @return RuleItem
659
     */
660
    public function patch(string $rule, $route): RuleItem
661
    {
662
        return $this->rule($rule, $route, 'PATCH');
663
    }
664
665
    /**
666
     * 注册OPTIONS路由
667
     * @access public
668
     * @param string $rule  路由规则
669
     * @param mixed  $route 路由地址
670
     * @return RuleItem
671
     */
672
    public function options(string $rule, $route): RuleItem
673
    {
674
        return $this->rule($rule, $route, 'OPTIONS');
675
    }
676
677
    /**
678
     * 注册资源路由
679
     * @access public
680
     * @param string $rule  路由规则
681
     * @param string $route 路由地址
682
     * @return Resource
683
     */
684
    public function resource(string $rule, string $route): Resource
685
    {
686
        return (new Resource($this, $this->group, $rule, $route, $this->rest))
687
            ->lazy($this->lazy)
688
            ->app($this->appName);
689
    }
690
691
    /**
692
     * 注册视图路由
693
     * @access public
694
     * @param string $rule     路由规则
695
     * @param string $template 路由模板地址
696
     * @param array  $vars     模板变量
697
     * @return RuleItem
698
     */
699
    public function view(string $rule, string $template = '', array $vars = []): RuleItem
700
    {
701
        return $this->rule($rule, $template, 'GET')->view($vars);
702
    }
703
704
    /**
705
     * 注册重定向路由
706
     * @access public
707
     * @param string $rule   路由规则
708
     * @param string $route  路由地址
709
     * @param int    $status 状态码
710
     * @return RuleItem
711
     */
712
    public function redirect(string $rule, string $route = '', int $status = 301): RuleItem
713
    {
714
        return $this->rule($rule, $route, '*')->redirect()->status($status);
715
    }
716
717
    /**
718
     * rest方法定义和修改
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
719
     * @access public
720
     * @param string|array $name     方法名称
721
     * @param array|bool   $resource 资源
722
     * @return $this
723
     */
724
    public function rest($name, $resource = [])
725
    {
726
        if (is_array($name)) {
727
            $this->rest = $resource ? $name : array_merge($this->rest, $name);
728
        } else {
729
            $this->rest[$name] = $resource;
730
        }
731
732
        return $this;
733
    }
734
735
    /**
736
     * 获取rest方法定义的参数
737
     * @access public
738
     * @param string $name 方法名称
739
     * @return array|null
740
     */
741
    public function getRest(string $name = null)
742
    {
743
        if (is_null($name)) {
744
            return $this->rest;
745
        }
746
747
        return $this->rest[$name] ?? null;
748
    }
749
750
    /**
751
     * 注册未匹配路由规则后的处理
752
     * @access public
753
     * @param string|Closure $route  路由地址
754
     * @param string         $method 请求类型
755
     * @return RuleItem
756
     */
757
    public function miss($route, string $method = '*'): RuleItem
758
    {
759
        return $this->group->miss($route, $method);
760
    }
761
762
    /**
763
     * 路由调度
764
     * @param Request $request
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
765
     * @param Closure $withRoute
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
766
     * @return Response
767
     */
768
    public function dispatch(Request $request, $withRoute = null)
769
    {
770
        $this->request = $request;
771
        $this->host    = $this->request->host(true);
772
        $this->init();
773
774
        return $this->app->middleware->pipeline()
775
            ->send($request)
776
            ->then(function ($request) use ($withRoute) {
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...
777
                if ($withRoute) {
778
                    $checkCallback = function () use ($withRoute) {
779
                        //加载路由
780
                        $withRoute();
781
                        return $this->check();
782
                    };
783
784
                    if ($this->config['route_check_cache']) {
785
                        $dispatch = $this->cache
786
                            ->tag('route_cache')
787
                            ->remember($this->getRouteCacheKey($request), $checkCallback);
788
                    } else {
789
                        $dispatch = $checkCallback();
790
                    }
791
                } else {
792
                    $dispatch = $this->url($this->path());
793
                }
794
795
                $dispatch->init($this->app);
796
797
                return $dispatch->run();
798
            });
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...
799
    }
800
801
    /**
802
     * 获取路由缓存Key
803
     * @access protected
804
     * @param Request $request
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
805
     * @return string
806
     */
807
    protected function getRouteCacheKey(Request $request): string
808
    {
809
        if (!empty($this->config['route_check_cache_key'])) {
810
            $closure  = $this->config['route_check_cache_key'];
811
            $routeKey = $closure($request);
812
        } else {
813
            $routeKey = md5($request->baseUrl(true) . ':' . $request->method());
814
        }
815
816
        return $routeKey;
817
    }
818
819
    /**
820
     * 检测URL路由
821
     * @access public
822
     * @return Dispatch
823
     * @throws RouteNotFoundException
824
     */
825
    public function check(): Dispatch
826
    {
827
        // 自动检测域名路由
828
        $url = str_replace($this->config['pathinfo_depr'], '|', $this->path());
829
830
        $completeMatch = $this->config['route_complete_match'];
831
832
        $result = $this->checkDomain()->check($this->request, $url, $completeMatch);
833
834
        if (false === $result && !empty($this->cross)) {
835
            // 检测跨域路由
836
            $result = $this->cross->check($this->request, $url, $completeMatch);
837
        }
838
839
        if (false !== $result) {
840
            return $result;
841
        } elseif ($this->config['url_route_must']) {
842
            throw new RouteNotFoundException();
843
        }
844
845
        return $this->url($url);
846
    }
847
848
    /**
849
     * 获取当前请求URL的pathinfo信息(不含URL后缀)
850
     * @access protected
851
     * @return string
852
     */
853
    protected function path(): string
854
    {
855
        $suffix   = $this->config['url_html_suffix'];
856
        $pathinfo = $this->request->pathinfo();
857
858
        if (false === $suffix) {
859
            // 禁止伪静态访问
860
            $path = $pathinfo;
861
        } elseif ($suffix) {
862
            // 去除正常的URL后缀
863
            $path = preg_replace('/\.(' . ltrim($suffix, '.') . ')$/i', '', $pathinfo);
864
        } else {
865
            // 允许任何后缀访问
866
            $path = preg_replace('/\.' . $this->request->ext() . '$/i', '', $pathinfo);
867
        }
868
869
        return $path;
870
    }
871
872
    /**
873
     * 默认URL解析
874
     * @access public
875
     * @param string $url URL地址
876
     * @return Dispatch
877
     */
878
    public function url(string $url): UrlDispatch
879
    {
880
        if ($this->app->http->isMulti() && !$this->app->http->getName()) {
881
            $path = $this->app->request->pathinfo();
882
            $map  = $this->app->config->get('app.app_map', []);
883
            $deny = $this->app->config->get('app.deny_app_list', []);
884
            $name = current(explode('|', $url));
885
886
            if (isset($map[$name])) {
887
                if ($map[$name] instanceof Closure) {
888
                    $result  = call_user_func_array($map[$name], [$this]);
889
                    $appName = $result ?: $name;
890
                } else {
891
                    $appName = $map[$name];
892
                }
893
            } elseif ($name && (false !== array_search($name, $map) || in_array($name, $deny))) {
894
                throw new HttpException(404, 'app not exists:' . $name);
895
            } elseif ($name && isset($map['*'])) {
896
                $appName = $map['*'];
897
            } else {
898
                $appName = $name;
899
            }
900
901
            if ($name) {
902
                $this->request->setRoot('/' . $name);
903
                $url = strpos($path, '/') ? ltrim(strstr($path, '/'), '/') : '';
904
                $this->request->setPathinfo($url);
905
            }
906
907
            $this->app->http->setApp($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; however, parameter $appName of think\Http::setApp() 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

907
            $this->app->http->setApp(/** @scrutinizer ignore-type */ $appName ?: $this->app->config->get('app.default_app', 'index'));
Loading history...
908
        }
909
910
        return new UrlDispatch($this->request, $this->group, $url);
911
    }
912
913
    /**
914
     * 检测域名的路由规则
915
     * @access protected
916
     * @return Domain
917
     */
918
    protected function checkDomain(): Domain
919
    {
920
        $item = false;
921
922
        if (count($this->domains) > 1) {
923
            // 获取当前子域名
924
            $subDomain = $this->request->subDomain();
925
926
            $domain  = $subDomain ? explode('.', $subDomain) : [];
927
            $domain2 = $domain ? array_pop($domain) : '';
928
929
            if ($domain) {
930
                // 存在三级域名
931
                $domain3 = array_pop($domain);
932
            }
933
934
            if (isset($this->domains[$this->host])) {
935
                // 子域名配置
936
                $item = $this->domains[$this->host];
937
            } elseif (isset($this->domains[$subDomain])) {
938
                $item = $this->domains[$subDomain];
939
            } elseif (isset($this->domains['*.' . $domain2]) && !empty($domain3)) {
940
                // 泛三级域名
941
                $item      = $this->domains['*.' . $domain2];
942
                $panDomain = $domain3;
943
            } elseif (isset($this->domains['*']) && !empty($domain2)) {
944
                // 泛二级域名
945
                if ('www' != $domain2) {
946
                    $item      = $this->domains['*'];
947
                    $panDomain = $domain2;
948
                }
949
            }
950
951
            if (isset($panDomain)) {
952
                // 保存当前泛域名
953
                $this->request->setPanDomain($panDomain);
954
            }
955
        }
956
957
        if (false === $item) {
958
            // 检测全局域名规则
959
            $item = $this->domains['-'];
960
        }
961
962
        if (is_string($item)) {
963
            $item = $this->domains[$item];
964
        }
965
966
        return $item;
967
    }
968
969
    /**
970
     * URL生成 支持路由反射
971
     * @access public
972
     * @param string $url  路由地址
973
     * @param array  $vars 参数 ['a'=>'val1', 'b'=>'val2']
974
     * @return UrlBuild
975
     */
976
    public function buildUrl(string $url = '', array $vars = []): UrlBuild
977
    {
978
        return new UrlBuild($this, $this->app, $url, $vars);
979
    }
980
981
    /**
982
     * 设置全局的路由分组参数
983
     * @access public
984
     * @param string $method 方法名
985
     * @param array  $args   调用参数
986
     * @return RuleGroup
987
     */
988
    public function __call($method, $args)
989
    {
990
        return call_user_func_array([$this->group, $method], $args);
991
    }
992
}
993