Completed
Push — 6.0 ( 987184...59032c )
by liu
02:49
created

Route::setRule()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
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 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->ruleName = new RuleName();
168
        $this->setDefaultDomain();
169
    }
170
171
    protected function init()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function init()
Loading history...
172
    {
173
        $this->config = array_merge($this->config, $this->app->config->get('route'));
174
175
        $this->lazy($this->config['url_lazy_route']);
176
177
        if ($this->config['route_check_cache']) {
178
            if (!empty($this->config['route_cache_option'])) {
179
                $this->cache = $this->app->cache->connect($this->config['route_cache_option']);
180
            } else {
181
                $this->cache = $this->app->cache->init();
182
            }
183
        }
184
185
        if (is_file($this->app->getRuntimePath() . 'route.php')) {
186
            // 读取路由映射文件
187
            $this->import(include $this->app->getRuntimePath() . 'route.php');
188
        }
189
    }
190
191
    public function config(string $name = null)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function config()
Loading history...
192
    {
193
        if (is_null($name)) {
194
            return $this->config;
195
        }
196
197
        return $this->config[$name] ?? null;
198
    }
199
200
    /**
201
     * 设置路由域名及分组(包括资源路由)是否延迟解析
202
     * @access public
203
     * @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...
204
     * @return $this
205
     */
206
    public function lazy(bool $lazy = true)
207
    {
208
        $this->lazy = $lazy;
209
        return $this;
210
    }
211
212
    /**
213
     * 设置路由为测试模式
214
     * @access public
215
     * @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...
216
     * @return void
217
     */
218
    public function setTestMode(bool $test): void
219
    {
220
        $this->isTest = $test;
221
    }
222
223
    /**
224
     * 检查路由是否为测试模式
225
     * @access public
226
     * @return bool
227
     */
228
    public function isTest(): bool
229
    {
230
        return $this->isTest;
231
    }
232
233
    /**
234
     * 设置路由域名及分组(包括资源路由)是否合并解析
235
     * @access public
236
     * @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...
237
     * @return $this
238
     */
239
    public function mergeRuleRegex(bool $merge = true)
240
    {
241
        $this->mergeRuleRegex = $merge;
242
        $this->group->mergeRuleRegex($merge);
243
244
        return $this;
245
    }
246
247
    /**
248
     * 初始化默认域名
249
     * @access protected
250
     * @return void
251
     */
252
    protected function setDefaultDomain(): void
253
    {
254
        // 注册默认域名
255
        $domain = new Domain($this);
256
257
        $this->domains['-'] = $domain;
258
259
        // 默认分组
260
        $this->group = $domain;
261
    }
262
263
    /**
264
     * 设置当前分组
265
     * @access public
266
     * @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...
267
     * @return void
268
     */
269
    public function setGroup(RuleGroup $group): void
270
    {
271
        $this->group = $group;
272
    }
273
274
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $name should have a doc-comment as per coding-style.
Loading history...
275
     * 获取指定标识的路由分组 不指定则获取当前分组
276
     * @access public
277
     * @return RuleGroup
278
     */
279
    public function getGroup(string $name = null)
280
    {
281
        return $name ? $this->ruleName->getGroup($name) : $this->group;
282
    }
283
284
    /**
285
     * 注册变量规则
286
     * @access public
287
     * @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...
288
     * @return $this
289
     */
290
    public function pattern(array $pattern)
291
    {
292
        $this->group->pattern($pattern);
293
294
        return $this;
295
    }
296
297
    /**
298
     * 注册路由参数
299
     * @access public
300
     * @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...
301
     * @return $this
302
     */
303
    public function option(array $option)
304
    {
305
        $this->group->option($option);
306
307
        return $this;
308
    }
309
310
    /**
311
     * 注册域名路由
312
     * @access public
313
     * @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...
314
     * @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...
315
     * @return Domain
316
     */
317
    public function domain($name, $rule = null): Domain
318
    {
319
        // 支持多个域名使用相同路由规则
320
        $domainName = is_array($name) ? array_shift($name) : $name;
321
322
        if (!isset($this->domains[$domainName])) {
323
            $domain = (new Domain($this, $domainName, $rule))
324
                ->lazy($this->lazy)
325
                ->mergeRuleRegex($this->mergeRuleRegex);
326
327
            $this->domains[$domainName] = $domain;
328
        } else {
329
            $domain = $this->domains[$domainName];
330
            $domain->parseGroupRule($rule);
331
        }
332
333
        if (is_array($name) && !empty($name)) {
334
            foreach ($name as $item) {
335
                $this->domains[$item] = $domainName;
336
            }
337
        }
338
339
        // 返回域名对象
340
        return $domain;
341
    }
342
343
    /**
344
     * 获取域名
345
     * @access public
346
     * @return array
347
     */
348
    public function getDomains(): array
349
    {
350
        return $this->domains;
351
    }
352
353
    /**
354
     * 获取RuleName对象
355
     * @access public
356
     * @return RuleName
357
     */
358
    public function getRuleName(): RuleName
359
    {
360
        return $this->ruleName;
361
    }
362
363
    /**
364
     * 设置路由绑定
365
     * @access public
366
     * @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...
367
     * @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...
368
     * @return $this
369
     */
370
    public function bind(string $bind, string $domain = null)
371
    {
372
        $domain = is_null($domain) ? '-' : $domain;
373
374
        $this->bind[$domain] = $bind;
375
376
        return $this;
377
    }
378
379
    /**
380
     * 读取路由绑定信息
381
     * @access public
382
     * @return array
383
     */
384
    public function getBind(): array
385
    {
386
        return $this->bind;
387
    }
388
389
    /**
390
     * 读取路由绑定
391
     * @access public
392
     * @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...
393
     * @return string|null
394
     */
395
    public function getDomainBind(string $domain = null)
396
    {
397
        if (is_null($domain)) {
398
            $domain = $this->host;
399
        } elseif (false === strpos($domain, '.')) {
400
            $domain .= '.' . $this->request->rootDomain();
401
        }
402
403
        $subDomain = $this->request->subDomain();
404
405
        if (strpos($subDomain, '.')) {
406
            $name = '*' . strstr($subDomain, '.');
407
        }
408
409
        if (isset($this->bind[$domain])) {
410
            $result = $this->bind[$domain];
411
        } elseif (isset($name) && isset($this->bind[$name])) {
412
            $result = $this->bind[$name];
413
        } elseif (!empty($subDomain) && isset($this->bind['*'])) {
414
            $result = $this->bind['*'];
415
        } else {
416
            $result = null;
417
        }
418
419
        return $result;
420
    }
421
422
    /**
423
     * 读取路由标识
424
     * @access public
425
     * @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...
426
     * @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...
427
     * @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...
428
     * @return RuleItem[]
429
     */
430
    public function getName(string $name = null, string $domain = null, string $method = '*'): array
431
    {
432
        return $this->ruleName->getName($name, $domain, $method);
433
    }
434
435
    /**
436
     * 批量导入路由标识
437
     * @access public
438
     * @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...
439
     * @return $this
440
     */
441
    public function import(array $name): void
442
    {
443
        $this->ruleName->import($name);
444
    }
445
446
    /**
447
     * 注册路由标识
448
     * @access public
449
     * @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...
450
     * @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...
451
     * @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...
452
     * @return void
453
     */
454
    public function setName(string $name, RuleItem $ruleItem, bool $first = false): void
455
    {
456
        $this->ruleName->setName($name, $ruleItem, $first);
457
    }
458
459
    /**
460
     * 保存路由规则
461
     * @access public
462
     * @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...
463
     * @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...
464
     * @return void
465
     */
466
    public function setRule(string $rule, RuleItem $ruleItem = null): void
467
    {
468
        $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

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