Passed
Push — 8.0 ( 4448c2...81f206 )
by liu
02:14
created

Route::checkDomain()   F

Complexity

Conditions 15
Paths 388

Size

Total Lines 49
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 32.0416

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 15
eloc 25
c 1
b 0
f 0
nc 388
nop 0
dl 0
loc 49
ccs 15
cts 26
cp 0.5769
crap 32.0416
rs 2.7333

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2023 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\exception\RouteNotFoundException;
17
use think\route\Dispatch;
18
use think\route\Domain;
19
use think\route\Resource;
20
use think\route\ResourceRegister;
21
use think\route\Rule;
22
use think\route\RuleGroup;
23
use think\route\RuleItem;
24
use think\route\RuleName;
25
use think\route\Url as UrlBuild;
26
27
/**
28
 * 路由管理类
29
 * @package think
30
 */
31
class Route
32
{
33
    /**
34
     * REST定义
35
     * @var array
36
     */
37
    protected $rest = [
38
        'index'  => ['get', '', 'index'],
39
        'create' => ['get', '/create', 'create'],
40
        'edit'   => ['get', '/<id>/edit', 'edit'],
41
        'read'   => ['get', '/<id>', 'read'],
42
        'save'   => ['post', '', 'save'],
43
        'update' => ['put', '/<id>', 'update'],
44
        'delete' => ['delete', '/<id>', 'delete'],
45
    ];
46
47
    /**
48
     * 配置参数
49
     * @var array
50
     */
51
    protected $config = [
52
        // pathinfo分隔符
53
        'pathinfo_depr'         => '/',
54
        // 是否开启路由延迟解析
55
        'url_lazy_route'        => false,
56
        // 是否强制使用路由
57
        'url_route_must'        => false,
58
        // 是否区分大小写
59
        'url_case_sensitive'    => 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
        'default_route_pattern' => '[\w\.]+',
70
        // URL伪静态后缀
71
        'url_html_suffix'       => 'html',
72
        // 访问控制器层名称
73
        'controller_layer'      => 'controller',
74
        // 空控制器名
75
        'empty_controller'      => 'Error',
76
        // 是否使用控制器后缀
77
        'controller_suffix'     => false,
78
        // 默认路由 [路由规则, 路由地址]
79
        'default_route'         => [],
80
        // 默认模块名
81
        'default_module'        => 'index',
82
        // 默认控制器名
83
        'default_controller'    => 'Index',
84
        // 默认操作名
85
        'default_action'        => 'index',
86
        // 操作方法后缀
87
        'action_suffix'         => '',
88
        // 非路由变量是否使用普通参数方式(用于URL生成)
89
        'url_common_param'      => true,
90
    ];
91
92
    /**
93
     * 请求对象
94
     * @var Request
95
     */
96
    protected $request;
97
98
    /**
99
     * @var RuleName
100
     */
101
    protected $ruleName;
102
103
    /**
104
     * 当前HOST
105
     * @var string
106
     */
107
    protected $host;
108
109
    /**
110
     * 当前分组对象
111
     * @var RuleGroup
112
     */
113
    protected $group;
114
115
    /**
116
     * 路由绑定
117
     * @var array
118
     */
119
    protected $bind = [];
120
121
    /**
122
     * 域名对象
123
     * @var Domain[]
124
     */
125
    protected $domains = [];
126
127
    /**
128
     * 跨域路由规则
129
     * @var RuleGroup
130
     */
131
    protected $cross;
132
133
    /**
134
     * 路由是否延迟解析
135
     * @var bool
136
     */
137
    protected $lazy = false;
138
139
    /**
140
     * (分组)路由规则是否合并解析
141
     * @var bool
142
     */
143
    protected $mergeRuleRegex = false;
144
145
    /**
146
     * 是否去除URL最后的斜线
147
     * @var bool
148
     */
149
    protected $removeSlash = false;
150
151 27
    public function __construct(protected App $app)
152
    {
153 27
        $this->ruleName = new RuleName();
154 27
        $this->setDefaultDomain();
155
156 27
        if (is_file($this->app->getRuntimePath() . 'route.php')) {
157
            // 读取路由映射文件
158
            $this->import(include $this->app->getRuntimePath() . 'route.php');
159
        }
160
161 27
        $this->config = array_merge($this->config, $this->app->config->get('route'));
0 ignored issues
show
Bug introduced by
It seems like $this->app->config->get('route') can also be of type null; however, parameter $arrays of array_merge() does only seem to accept array, 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

161
        $this->config = array_merge($this->config, /** @scrutinizer ignore-type */ $this->app->config->get('route'));
Loading history...
162
163 27
        $this->init();
164
    }
165
166 27
    protected function init()
167
    {
168 27
        if (!empty($this->config['middleware'])) {
169
            $this->app->middleware->import($this->config['middleware'], 'route');
170
        }
171
172 27
        $this->lazy($this->config['url_lazy_route']);
173 27
        $this->mergeRuleRegex = $this->config['route_rule_merge'];
174 27
        $this->removeSlash    = $this->config['remove_slash'];
175
176 27
        $this->group->removeSlash($this->removeSlash);
177
178
        // 注册全局MISS路由
179 27
        $this->miss(function () {
180 3
            return Response::create('', 'html', 204)->header(['Allow' => 'GET, POST, PUT, DELETE']);
181 27
        }, 'options');
182
    }
183
184 27
    public function config(?string $name = null)
185
    {
186 27
        if (is_null($name)) {
187
            return $this->config;
188
        }
189
190 27
        return $this->config[$name] ?? null;
191
    }
192
193
    /**
194
     * 设置路由域名及分组(包括资源路由)是否延迟解析
195
     * @access public
196
     * @param bool $lazy 路由是否延迟解析
197
     * @return $this
198
     */
199 27
    public function lazy(bool $lazy = true)
200
    {
201 27
        $this->lazy = $lazy;
202 27
        return $this;
203
    }
204
205
    /**
206
     * 设置路由域名及分组(包括资源路由)是否合并解析
207
     * @access public
208
     * @param bool $merge 路由是否合并解析
209
     * @return $this
210
     */
211
    public function mergeRuleRegex(bool $merge = true)
212
    {
213
        $this->mergeRuleRegex = $merge;
214
        $this->group->mergeRuleRegex($merge);
215
216
        return $this;
217
    }
218
219
    /**
220
     * 初始化默认域名
221
     * @access protected
222
     * @return void
223
     */
224 27
    protected function setDefaultDomain(): void
225
    {
226
        // 注册默认域名
227 27
        $domain = new Domain($this);
228
229 27
        $this->domains['-'] = $domain;
230
231
        // 默认分组
232 27
        $this->group = $domain;
233
    }
234
235
    /**
236
     * 设置当前分组
237
     * @access public
238
     * @param RuleGroup $group 域名
239
     * @return void
240
     */
241 27
    public function setGroup(RuleGroup $group): void
242
    {
243 27
        $this->group = $group;
244
    }
245
246
    /**
247
     * 获取指定标识的路由分组 不指定则获取当前分组
248
     * @access public
249
     * @param string $name 分组标识
250
     * @return RuleGroup
251
     */
252 27
    public function getGroup(?string $name = null)
253
    {
254 27
        return $name ? $this->ruleName->getGroup($name) : $this->group;
255
    }
256
257
    /**
258
     * 注册变量规则
259
     * @access public
260
     * @param array $pattern 变量规则
261
     * @return $this
262
     */
263
    public function pattern(array $pattern)
264
    {
265
        $this->group->pattern($pattern);
266
267
        return $this;
268
    }
269
270
    /**
271
     * 注册路由参数
272
     * @access public
273
     * @param array $option 参数
274
     * @return $this
275
     */
276
    public function option(array $option)
277
    {
278
        $this->group->option($option);
279
280
        return $this;
281
    }
282
283
    /**
284
     * 注册域名路由
285
     * @access public
286
     * @param string|array $name 子域名
287
     * @param mixed        $rule 路由规则
288
     * @return Domain
289
     */
290 3
    public function domain(string | array $name, $rule = null): Domain
291
    {
292
        // 支持多个域名使用相同路由规则
293 3
        $domainName = is_array($name) ? array_shift($name) : $name;
0 ignored issues
show
introduced by
The condition is_array($name) is always true.
Loading history...
294
295 3
        if (!isset($this->domains[$domainName])) {
296 3
            $domain = (new Domain($this, $domainName, $rule, $this->lazy))
297 3
                ->removeSlash($this->removeSlash)
298 3
                ->mergeRuleRegex($this->mergeRuleRegex);
299
300 3
            $this->domains[$domainName] = $domain;
301
        } else {
302
            $domain = $this->domains[$domainName];
303
            $domain->parseGroupRule($rule);
304
        }
305
306 3
        if (is_array($name) && !empty($name)) {
307
            foreach ($name as $item) {
308
                $this->domains[$item] = $domainName;
309
            }
310
        }
311
312
        // 返回域名对象
313 3
        return $domain;
314
    }
315
316
    /**
317
     * 获取域名
318
     * @access public
319
     * @return array
320
     */
321
    public function getDomains(): array
322
    {
323
        return $this->domains;
324
    }
325
326
    /**
327
     * 获取RuleName对象
328
     * @access public
329
     * @return RuleName
330
     */
331
    public function getRuleName(): RuleName
332
    {
333
        return $this->ruleName;
334
    }
335
336
    /**
337
     * 设置路由绑定
338
     * @access public
339
     * @param string $bind   绑定信息
340
     * @param string $domain 域名
341
     * @return $this
342
     */
343
    public function bind(string $bind, ?string $domain = null)
344
    {
345
        $domain = is_null($domain) ? '-' : $domain;
346
347
        $this->bind[$domain] = $bind;
348
349
        return $this;
350
    }
351
352
    /**
353
     * 读取路由绑定信息
354
     * @access public
355
     * @return array
356
     */
357
    public function getBind(): array
358
    {
359
        return $this->bind;
360
    }
361
362
    /**
363
     * 读取路由绑定
364
     * @access public
365
     * @param string $domain 域名
366
     * @return string|null
367
     */
368 27
    public function getDomainBind(?string $domain = null)
369
    {
370 27
        if (is_null($domain)) {
371 24
            $domain = $this->host;
372 3
        } elseif (!str_contains($domain, '.') && $this->request) {
373 3
            $domain .= '.' . $this->request->rootDomain();
374
        }
375
376 27
        if ($this->request) {
377 27
            $subDomain = $this->request->subDomain();
378
379 27
            if (str_contains($subDomain, '.')) {
380
                $name = '*' . strstr($subDomain, '.');
381
            }
382
        }
383
384 27
        if (isset($this->bind[$domain])) {
385
            $result = $this->bind[$domain];
386 27
        } elseif (isset($name) && isset($this->bind[$name])) {
387
            $result = $this->bind[$name];
388 27
        } elseif (!empty($subDomain) && isset($this->bind['*'])) {
389
            $result = $this->bind['*'];
390
        } else {
391 27
            $result = null;
392
        }
393
394 27
        return $result;
395
    }
396
397
    /**
398
     * 读取路由标识
399
     * @access public
400
     * @param string $name   路由标识
401
     * @param string $domain 域名
402
     * @param string $method 请求类型
403
     * @return array
404
     */
405
    public function getName(?string $name = null, ?string $domain = null, string $method = '*'): array
406
    {
407
        return $this->ruleName->getName($name, $domain, $method);
408
    }
409
410
    /**
411
     * 批量导入路由标识
412
     * @access public
413
     * @param array $name 路由标识
414
     * @return void
415
     */
416
    public function import(array $name): void
417
    {
418
        $this->ruleName->import($name);
419
    }
420
421
    /**
422
     * 注册路由标识
423
     * @access public
424
     * @param string   $name     路由标识
425
     * @param RuleItem $ruleItem 路由规则
426
     * @param bool     $first    是否优先
427
     * @return void
428
     */
429 12
    public function setName(string $name, RuleItem $ruleItem, bool $first = false): void
430
    {
431 12
        $this->ruleName->setName($name, $ruleItem, $first);
432
    }
433
434
    /**
435
     * 保存路由规则
436
     * @access public
437
     * @param string   $rule     路由规则
438
     * @param RuleItem $ruleItem RuleItem对象
439
     * @return void
440
     */
441 27
    public function setRule(string $rule, ?RuleItem $ruleItem = null): void
442
    {
443 27
        $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

443
        $this->ruleName->setRule($rule, /** @scrutinizer ignore-type */ $ruleItem);
Loading history...
444
    }
445
446
    /**
447
     * 读取路由
448
     * @access public
449
     * @param string $rule 路由规则
450
     * @return RuleItem[]
451
     */
452
    public function getRule(string $rule): array
453
    {
454
        return $this->ruleName->getRule($rule);
455
    }
456
457
    /**
458
     * 读取路由列表
459
     * @access public
460
     * @return array
461
     */
462
    public function getRuleList(): array
463
    {
464
        return $this->ruleName->getRuleList();
465
    }
466
467
    /**
468
     * 清空路由规则
469
     * @access public
470
     * @return void
471
     */
472
    public function clear(): void
473
    {
474
        $this->ruleName->clear();
475
476
        if ($this->group) {
477
            $this->group->clear();
478
        }
479
    }
480
481
    /**
482
     * 注册路由规则
483
     * @access public
484
     * @param string $rule   路由规则
485
     * @param mixed  $route  路由地址
486
     * @param string $method 请求类型
487
     * @return RuleItem
488
     */
489 24
    public function rule(string $rule, $route = null, string $method = '*'): RuleItem
490
    {
491 24
        return $this->group->addRule($rule, $route, $method);
492
    }
493
494
    /**
495
     * 设置路由规则全局有效
496
     * @access public
497
     * @param Rule   $rule   路由规则
498
     * @return $this
499
     */
500
    public function setCrossDomainRule(Rule $rule)
501
    {
502
        if (!isset($this->cross)) {
503
            $this->cross = (new RuleGroup($this))->mergeRuleRegex($this->mergeRuleRegex);
504
        }
505
506
        $this->cross->addRuleItem($rule);
507
508
        return $this;
509
    }
510
511
    /**
512
     * 注册路由分组
513
     * @access public
514
     * @param string|Closure $name  分组名称或者参数
515
     * @param mixed           $route 分组路由
516
     * @return RuleGroup
517
     */
518 3
    public function group(string | Closure $name, $route = null): RuleGroup
519
    {
520 3
        if ($name instanceof Closure) {
521 3
            $route = $name;
522 3
            $name  = '';
523
        }
524
525 3
        return (new RuleGroup($this, $this->group, $name, $route, $this->lazy))
526 3
            ->removeSlash($this->removeSlash)
527 3
            ->mergeRuleRegex($this->mergeRuleRegex);
528
    }
529
530
    /**
531
     * 注册路由
532
     * @access public
533
     * @param string $rule  路由规则
534
     * @param mixed  $route 路由地址
535
     * @return RuleItem
536
     */
537
    public function any(string $rule, $route): RuleItem
538
    {
539
        return $this->rule($rule, $route, '*');
540
    }
541
542
    /**
543
     * 注册GET路由
544
     * @access public
545
     * @param string $rule  路由规则
546
     * @param mixed  $route 路由地址
547
     * @return RuleItem
548
     */
549 18
    public function get(string $rule, $route): RuleItem
550
    {
551 18
        return $this->rule($rule, $route, 'GET');
552
    }
553
554
    /**
555
     * 注册POST路由
556
     * @access public
557
     * @param string $rule  路由规则
558
     * @param mixed  $route 路由地址
559
     * @return RuleItem
560
     */
561 3
    public function post(string $rule, $route): RuleItem
562
    {
563 3
        return $this->rule($rule, $route, 'POST');
564
    }
565
566
    /**
567
     * 注册PUT路由
568
     * @access public
569
     * @param string $rule  路由规则
570
     * @param mixed  $route 路由地址
571
     * @return RuleItem
572
     */
573 3
    public function put(string $rule, $route): RuleItem
574
    {
575 3
        return $this->rule($rule, $route, 'PUT');
576
    }
577
578
    /**
579
     * 注册DELETE路由
580
     * @access public
581
     * @param string $rule  路由规则
582
     * @param mixed  $route 路由地址
583
     * @return RuleItem
584
     */
585
    public function delete(string $rule, $route): RuleItem
586
    {
587
        return $this->rule($rule, $route, 'DELETE');
588
    }
589
590
    /**
591
     * 注册PATCH路由
592
     * @access public
593
     * @param string $rule  路由规则
594
     * @param mixed  $route 路由地址
595
     * @return RuleItem
596
     */
597
    public function patch(string $rule, $route): RuleItem
598
    {
599
        return $this->rule($rule, $route, 'PATCH');
600
    }
601
602
    /**
603
     * 注册HEAD路由
604
     * @access public
605
     * @param string $rule  路由规则
606
     * @param mixed  $route 路由地址
607
     * @return RuleItem
608
     */
609
    public function head(string $rule, $route): RuleItem
610
    {
611
        return $this->rule($rule, $route, 'HEAD');
612
    }
613
614
    /**
615
     * 注册OPTIONS路由
616
     * @access public
617
     * @param string $rule  路由规则
618
     * @param mixed  $route 路由地址
619
     * @return RuleItem
620
     */
621
    public function options(string $rule, $route): RuleItem
622
    {
623
        return $this->rule($rule, $route, 'OPTIONS');
624
    }
625
626
    /**
627
     * 注册资源路由
628
     * @access public
629
     * @param string $rule  路由规则
630
     * @param string $route 路由地址
631
     * @return Resource|ResourceRegister
632
     */
633
    public function resource(string $rule, string $route)
634
    {
635
        $resource = new Resource($this, $this->group, $rule, $route, $this->rest);
636
637
        if (!$this->lazy) {
638
            return new ResourceRegister($resource);
639
        }
640
641
        return $resource;
642
    }
643
644
    /**
645
     * 注册视图路由
646
     * @access public
647
     * @param string $rule     路由规则
648
     * @param string $template 路由模板地址
649
     * @param array  $vars     模板变量
650
     * @return RuleItem
651
     */
652 3
    public function view(string $rule, string $template = '', array $vars = []): RuleItem
653
    {
654 3
        return $this->rule($rule, function () use ($vars, $template) {
655 3
            return Response::create($template, 'view')->assign($vars);
0 ignored issues
show
Bug introduced by
The method assign() does not exist on think\Response. It seems like you code against a sub-type of think\Response such as think\response\View. ( Ignorable by Annotation )

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

655
            return Response::create($template, 'view')->/** @scrutinizer ignore-call */ assign($vars);
Loading history...
656 3
        }, 'GET');
657
    }
658
659
    /**
660
     * 注册重定向路由
661
     * @access public
662
     * @param string $rule   路由规则
663
     * @param string $route  路由地址
664
     * @param int    $status 状态码
665
     * @return RuleItem
666
     */
667 3
    public function redirect(string $rule, string $route = '', int $status = 301): RuleItem
668
    {
669 3
        return $this->rule($rule, function (Request $request) use ($status, $route) {
670 3
            $search  = $replace  = [];
671 3
            $matches = $request->rule()->getVars();
672
673 3
            foreach ($matches as $key => $value) {
674
                $search[]  = '<' . $key . '>';
675
                $replace[] = $value;
676
677
                $search[]  = ':' . $key;
678
                $replace[] = $value;
679
            }
680
681 3
            $route = str_replace($search, $replace, $route);
682 3
            return Response::create($route, 'redirect')->code($status);
683 3
        }, '*');
684
    }
685
686
    /**
687
     * rest方法定义和修改
688
     * @access public
689
     * @param string|array $name     方法名称
690
     * @param array|bool   $resource 资源
691
     * @return $this
692
     */
693
    public function rest(string | array $name, array | bool $resource = [])
694
    {
695
        if (is_array($name)) {
0 ignored issues
show
introduced by
The condition is_array($name) is always true.
Loading history...
696
            $this->rest = $resource ? $name : array_merge($this->rest, $name);
697
        } else {
698
            $this->rest[$name] = $resource;
699
        }
700
701
        return $this;
702
    }
703
704
    /**
705
     * 获取rest方法定义的参数
706
     * @access public
707
     * @param string $name 方法名称
708
     * @return array|null
709
     */
710
    public function getRest(?string $name = null)
711
    {
712
        if (is_null($name)) {
713
            return $this->rest;
714
        }
715
716
        return $this->rest[$name] ?? null;
717
    }
718
719
    /**
720
     * 注册未匹配路由规则后的处理
721
     * @access public
722
     * @param string|Closure $route  路由地址
723
     * @param string         $method 请求类型
724
     * @return RuleItem
725
     */
726 27
    public function miss(string | Closure $route, string $method = '*'): RuleItem
727
    {
728 27
        return $this->group->miss($route, $method);
729
    }
730
731
    /**
732
     * 路由调度
733
     * @param Request $request
734
     * @param Closure|bool $withRoute
735
     * @return Response
736
     */
737 27
    public function dispatch(Request $request, Closure | bool $withRoute = true)
738
    {
739 27
        $this->request = $request;
740 27
        $this->host    = $this->request->host(true);
741 27
        $completeMatch = (bool) $this->config['route_complete_match'];
742
743 27
        if ($withRoute) {
744
            //加载路由
745 27
            if ($withRoute instanceof Closure) {
746
                $withRoute();
747
            }
748 27
            $dispatch = $this->check($completeMatch);
749
        } else {
750
            $dispatch = $this->autoUrl($this->config['default_route'])
751
                ->check($this->request, $this->path(), $completeMatch);
752
        }
753
754 27
        $dispatch->init($this->app);
755
756 27
        return $this->app->middleware->pipeline('route')
757 27
            ->send($request)
758 27
            ->then(function () use ($dispatch) {
759 27
                return $dispatch->run();
760 27
            });
761
    }
762
763
    /**
764
     * 检测URL路由
765
     * @access public
766
     * @param  bool $completeMatch
767
     * @return Dispatch|false
768
     * @throws RouteNotFoundException
769
     */
770 27
    public function check(bool $completeMatch = false)
771
    {
772
        // 自动检测域名路由
773 27
        $url = str_replace($this->config['pathinfo_depr'], '|', $this->path());
774
775 27
        $result = $this->checkDomain()->check($this->request, $url, $completeMatch);
776
777 27
        if (false === $result && !empty($this->cross)) {
778
            // 检测跨域路由
779
            $result = $this->cross->check($this->request, $url, $completeMatch);
780
        }
781
782 27
        if (false !== $result) {
783 24
            return $result;
784 3
        } elseif ($this->config['url_route_must']) {
785
            throw new RouteNotFoundException();
786
        }
787 3
        return $this->autoUrl($this->config['default_route'])
788 3
            ->check($this->request, $url, $completeMatch);
789
    }
790
791
    /**
792
     * 获取当前请求URL的pathinfo信息(不含URL后缀)
793
     * @access protected
794
     * @return string
795
     */
796 27
    protected function path(): string
797
    {
798 27
        $suffix   = $this->config['url_html_suffix'];
799 27
        $pathinfo = $this->request->pathinfo();
800
801 27
        if (false === $suffix) {
802
            // 禁止伪静态访问
803
            $path = $pathinfo;
804 27
        } elseif ($suffix) {
805
            // 去除正常的URL后缀
806 27
            $path = preg_replace('/\.(' . ltrim($suffix, '.') . ')$/i', '', $pathinfo);
807
        } else {
808
            // 允许任何后缀访问
809
            $path = preg_replace('/\.' . $this->request->ext() . '$/i', '', $pathinfo);
810
        }
811
812 27
        return $path;
813
    }
814
815
    /**
816
     * 自动多模块URL路由 如使用多模块在路由定义文件最后定义
817
     * @access public
818
     * @param  string $rule    路由规则
819
     * @param  mixed  $route   路由地址
820
     * @return RuleItem
821
     */
822
    public function auto(string $rule = '[:module]/[:controller]/[:action]', $route = ':module/:controller/:action'): RuleItem
823
    {
824
        return $this->rule($rule, $route)
825
            ->pattern([
826
                'module'     => '[A-Za-z0-9\.\_]+',
827
                'controller' => '[A-Za-z0-9\.\_]+',
828
                'action'     => '[A-Za-z0-9\_]+',
829
            ])->default([
830
                'module'     => $this->config['default_module'],
831
                'controller' => $this->config['default_controller'],
832
                'action'     => $this->config['default_action'],
833
            ]);
834
    }
835
836
    /**
837
     * 注册分组默认URL解析路由
838
     * @access public
839
     * @param  array     $option 解析规则
840
     * @return RuleItem
841
     */
842 3
    protected function autoUrl(array $option = []): RuleItem
843
    {
844 3
        return $this->group->autoUrl($option);
845
    }
846
847
    /**
848
     * 检测域名的路由规则
849
     * @access protected
850
     * @return Domain
851
     */
852 27
    protected function checkDomain(): Domain
853
    {
854 27
        $item = false;
855
856 27
        if (count($this->domains) > 1) {
857
            // 获取当前子域名
858 3
            $subDomain = $this->request->subDomain();
859
860 3
            $domain  = $subDomain ? explode('.', $subDomain) : [];
861 3
            $domain2 = $domain ? array_pop($domain) : '';
862
863 3
            if ($domain) {
864
                // 存在三级域名
865
                $domain3 = array_pop($domain);
866
            }
867
868 3
            if (isset($this->domains[$this->host])) {
869
                // 子域名配置
870
                $item = $this->domains[$this->host];
871 3
            } elseif (isset($this->domains[$subDomain])) {
872 3
                $item = $this->domains[$subDomain];
873
            } elseif (isset($this->domains['*.' . $domain2]) && !empty($domain3)) {
874
                // 泛三级域名
875
                $item      = $this->domains['*.' . $domain2];
876
                $panDomain = $domain3;
877
            } elseif (isset($this->domains['*']) && !empty($domain2)) {
878
                // 泛二级域名
879
                if ('www' != $domain2) {
880
                    $item      = $this->domains['*'];
881
                    $panDomain = $domain2;
882
                }
883
            }
884
885 3
            if (isset($panDomain)) {
886
                // 保存当前泛域名
887
                $this->request->setPanDomain($panDomain);
888
            }
889
        }
890
891 27
        if (false === $item) {
892
            // 检测全局域名规则
893 24
            $item = $this->domains['-'];
894
        }
895
896 27
        if (is_string($item)) {
897
            $item = $this->domains[$item];
898
        }
899
900 27
        return $item;
901
    }
902
903
    /**
904
     * URL生成 支持路由反射
905
     * @access public
906
     * @param string $url  路由地址
907
     * @param array  $vars 参数 ['a'=>'val1', 'b'=>'val2']
908
     * @return UrlBuild
909
     */
910
    public function buildUrl(string $url = '', array $vars = []): UrlBuild
911
    {
912
        return $this->app->make(UrlBuild::class, [$this, $this->app, $url, $vars], true);
913
    }
914
915
    /**
916
     * 设置全局的路由分组参数
917
     * @access public
918
     * @param string $method 方法名
919
     * @param array  $args   调用参数
920
     * @return RuleGroup
921
     */
922
    public function __call($method, $args)
923
    {
924
        return call_user_func_array([$this->group, $method], $args);
925
    }
926
}
927