Route::checkDomain()   F
last analyzed

Complexity

Conditions 15
Paths 388

Size

Total Lines 49
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 68.3647

Importance

Changes 0
Metric Value
cc 15
eloc 25
nc 388
nop 0
dl 0
loc 49
ccs 8
cts 21
cp 0.381
crap 68.3647
rs 2.7333
c 0
b 0
f 0

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~2021 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\dispatch\Callback;
19
use think\route\dispatch\Url as UrlDispatch;
20
use think\route\Domain;
21
use think\route\Resource;
22
use think\route\Rule;
23
use think\route\RuleGroup;
24
use think\route\RuleItem;
25
use think\route\RuleName;
26
use think\route\Url as UrlBuild;
27
28
/**
29
 * 路由管理类
30
 * @package think
31
 */
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
        'remove_slash'          => false,
65
        // 使用注解路由
66
        'route_annotation'      => false,
67
        // 默认的路由变量规则
68
        'default_route_pattern' => '[\w\.]+',
69
        // URL伪静态后缀
70
        'url_html_suffix'       => 'html',
71
        // 访问控制器层名称
72
        'controller_layer'      => 'controller',
73
        // 空控制器名
74
        'empty_controller'      => 'Error',
75
        // 是否使用控制器后缀
76
        'controller_suffix'     => false,
77
        // 默认控制器名
78
        'default_controller'    => 'Index',
79
        // 默认操作名
80
        'default_action'        => 'index',
81
        // 操作方法后缀
82
        'action_suffix'         => '',
83
        // 非路由变量是否使用普通参数方式(用于URL生成)
84
        'url_common_param'      => true,
85
    ];
86
87
    /**
88
     * 当前应用
89
     * @var App
90
     */
91
    protected $app;
92
93
    /**
94
     * 请求对象
95
     * @var Request
96
     */
97
    protected $request;
98
99
    /**
100
     * @var RuleName
101
     */
102
    protected $ruleName;
103
104
    /**
105
     * 当前HOST
106
     * @var string
107
     */
108
    protected $host;
109
110
    /**
111
     * 当前分组对象
112
     * @var RuleGroup
113
     */
114
    protected $group;
115
116
    /**
117
     * 路由绑定
118
     * @var array
119
     */
120
    protected $bind = [];
121
122
    /**
123
     * 域名对象
124
     * @var Domain[]
125
     */
126
    protected $domains = [];
127
128
    /**
129
     * 跨域路由规则
130
     * @var RuleGroup
131
     */
132
    protected $cross;
133
134
    /**
135
     * 路由是否延迟解析
136
     * @var bool
137
     */
138
    protected $lazy = false;
139
140
    /**
141
     * 路由是否测试模式
142
     * @var bool
143
     */
144
    protected $isTest = false;
145
146
    /**
147
     * (分组)路由规则是否合并解析
148
     * @var bool
149
     */
150
    protected $mergeRuleRegex = false;
151
152
    /**
153
     * 是否去除URL最后的斜线
154
     * @var bool
155
     */
156
    protected $removeSlash = false;
157
158 33
    public function __construct(App $app)
159
    {
160 33
        $this->app      = $app;
161 33
        $this->ruleName = new RuleName();
162 33
        $this->setDefaultDomain();
163
164 33
        if (is_file($this->app->getRuntimePath() . 'route.php')) {
165
            // 读取路由映射文件
166
            $this->import(include $this->app->getRuntimePath() . 'route.php');
167
        }
168
169 33
        $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

169
        $this->config = array_merge($this->config, /** @scrutinizer ignore-type */ $this->app->config->get('route'));
Loading history...
170 33
171
        $this->init();
172 33
    }
173
174 33
    protected function init()
175
    {
176
        if (!empty($this->config['middleware'])) {
177
            $this->app->middleware->import($this->config['middleware'], 'route');
178 33
        }
179 33
180 33
        $this->lazy($this->config['url_lazy_route']);
181
        $this->mergeRuleRegex = $this->config['route_rule_merge'];
182 33
        $this->removeSlash    = $this->config['remove_slash'];
183 33
184
        $this->group->removeSlash($this->removeSlash);
185 33
    }
186
187 33
    public function config(string $name = null)
188
    {
189
        if (is_null($name)) {
190
            return $this->config;
191 33
        }
192
193
        return $this->config[$name] ?? null;
194
    }
195
196
    /**
197
     * 设置路由域名及分组(包括资源路由)是否延迟解析
198
     * @access public
199
     * @param bool $lazy 路由是否延迟解析
200 33
     * @return $this
201
     */
202 33
    public function lazy(bool $lazy = true)
203 33
    {
204
        $this->lazy = $lazy;
205
        return $this;
206
    }
207
208
    /**
209
     * 设置路由为测试模式
210
     * @access public
211
     * @param bool $test 路由是否测试模式
212
     * @return void
213
     */
214
    public function setTestMode(bool $test): void
215
    {
216
        $this->isTest = $test;
217
    }
218
219
    /**
220
     * 检查路由是否为测试模式
221
     * @access public
222 6
     * @return bool
223
     */
224 6
    public function isTest(): bool
225
    {
226
        return $this->isTest;
227
    }
228
229
    /**
230
     * 设置路由域名及分组(包括资源路由)是否合并解析
231
     * @access public
232
     * @param bool $merge 路由是否合并解析
233
     * @return $this
234
     */
235
    public function mergeRuleRegex(bool $merge = true)
236
    {
237
        $this->mergeRuleRegex = $merge;
238
        $this->group->mergeRuleRegex($merge);
239
240
        return $this;
241
    }
242
243
    /**
244
     * 初始化默认域名
245
     * @access protected
246 33
     * @return void
247
     */
248
    protected function setDefaultDomain(): void
249 33
    {
250
        // 注册默认域名
251 33
        $domain = new Domain($this);
252
253
        $this->domains['-'] = $domain;
254 33
255 33
        // 默认分组
256
        $this->group = $domain;
257
    }
258
259
    /**
260
     * 设置当前分组
261
     * @access public
262
     * @param RuleGroup $group 域名
263 33
     * @return void
264
     */
265 33
    public function setGroup(RuleGroup $group): void
266 33
    {
267
        $this->group = $group;
268
    }
269
270
    /**
271
     * 获取指定标识的路由分组 不指定则获取当前分组
272
     * @access public
273
     * @param string $name 分组标识
274 33
     * @return RuleGroup
275
     */
276 33
    public function getGroup(string $name = null)
277
    {
278
        return $name ? $this->ruleName->getGroup($name) : $this->group;
279
    }
280
281
    /**
282
     * 注册变量规则
283
     * @access public
284
     * @param array $pattern 变量规则
285
     * @return $this
286
     */
287
    public function pattern(array $pattern)
288
    {
289
        $this->group->pattern($pattern);
290
291
        return $this;
292
    }
293
294
    /**
295
     * 注册路由参数
296
     * @access public
297
     * @param array $option 参数
298
     * @return $this
299
     */
300
    public function option(array $option)
301
    {
302
        $this->group->option($option);
303
304
        return $this;
305
    }
306
307
    /**
308
     * 注册域名路由
309
     * @access public
310
     * @param string|array $name 子域名
311
     * @param mixed        $rule 路由规则
312 3
     * @return Domain
313
     */
314
    public function domain($name, $rule = null): Domain
315 3
    {
316
        // 支持多个域名使用相同路由规则
317 3
        $domainName = is_array($name) ? array_shift($name) : $name;
318 3
319 3
        if (!isset($this->domains[$domainName])) {
320 3
            $domain = (new Domain($this, $domainName, $rule))
321 3
                ->lazy($this->lazy)
322
                ->removeSlash($this->removeSlash)
323 3
                ->mergeRuleRegex($this->mergeRuleRegex);
324
325
            $this->domains[$domainName] = $domain;
326
        } else {
327
            $domain = $this->domains[$domainName];
328
            $domain->parseGroupRule($rule);
329 3
        }
330
331
        if (is_array($name) && !empty($name)) {
332
            foreach ($name as $item) {
333
                $this->domains[$item] = $domainName;
334
            }
335
        }
336 3
337
        // 返回域名对象
338
        return $domain;
339
    }
340
341
    /**
342
     * 获取域名
343
     * @access public
344
     * @return array
345
     */
346
    public function getDomains(): array
347
    {
348
        return $this->domains;
349
    }
350
351
    /**
352
     * 获取RuleName对象
353
     * @access public
354 3
     * @return RuleName
355
     */
356 3
    public function getRuleName(): RuleName
357
    {
358
        return $this->ruleName;
359
    }
360
361
    /**
362
     * 设置路由绑定
363
     * @access public
364
     * @param string $bind   绑定信息
365
     * @param string $domain 域名
366
     * @return $this
367
     */
368
    public function bind(string $bind, string $domain = null)
369
    {
370
        $domain = is_null($domain) ? '-' : $domain;
371
372
        $this->bind[$domain] = $bind;
373
374
        return $this;
375
    }
376
377
    /**
378
     * 读取路由绑定信息
379
     * @access public
380
     * @return array
381
     */
382
    public function getBind(): array
383
    {
384
        return $this->bind;
385
    }
386
387
    /**
388
     * 读取路由绑定
389
     * @access public
390
     * @param string $domain 域名
391 33
     * @return string|null
392
     */
393 33
    public function getDomainBind(string $domain = null)
394 30
    {
395 3
        if (is_null($domain)) {
396 3
            $domain = $this->host;
397
        } elseif (false === strpos($domain, '.') && $this->request) {
398
            $domain .= '.' . $this->request->rootDomain();
399 33
        }
400 33
401
        if ($this->request) {
402 33
            $subDomain = $this->request->subDomain();
403
404
            if (strpos($subDomain, '.')) {
405
                $name = '*' . strstr($subDomain, '.');
406
            }
407 33
        }
408
409 33
        if (isset($this->bind[$domain])) {
410
            $result = $this->bind[$domain];
411 33
        } elseif (isset($name) && isset($this->bind[$name])) {
412
            $result = $this->bind[$name];
413
        } elseif (!empty($subDomain) && isset($this->bind['*'])) {
414 33
            $result = $this->bind['*'];
415
        } else {
416
            $result = null;
417 33
        }
418
419
        return $result;
420
    }
421
422
    /**
423
     * 读取路由标识
424
     * @access public
425
     * @param string $name   路由标识
426
     * @param string $domain 域名
427
     * @param string $method 请求类型
428 3
     * @return array
429
     */
430 3
    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 路由标识
439
     * @return void
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     路由标识
450
     * @param RuleItem $ruleItem 路由规则
451
     * @param bool     $first    是否优先
452 12
     * @return void
453
     */
454 12
    public function setName(string $name, RuleItem $ruleItem, bool $first = false): void
455 12
    {
456
        $this->ruleName->setName($name, $ruleItem, $first);
457
    }
458
459
    /**
460
     * 保存路由规则
461
     * @access public
462
     * @param string   $rule     路由规则
463
     * @param RuleItem $ruleItem RuleItem对象
464 30
     * @return void
465
     */
466 30
    public function setRule(string $rule, RuleItem $ruleItem = null): void
467 30
    {
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 路由规则
475 3
     * @return RuleItem[]
476
     */
477 3
    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   路由规则
510
     * @param mixed  $route  路由地址
511
     * @param string $method 请求类型
512 30
     * @return RuleItem
513
     */
514 30
    public function rule(string $rule, $route = null, string $method = '*'): RuleItem
515
    {
516
        if ($route instanceof Response) {
517 3
            // 兼容之前的路由到响应对象,感觉不需要,使用场景很少,闭包就能实现
518 3
            $route = function () use ($route) {
519
                return $route;
520 30
            };
521
        }
522
        return $this->group->addRule($rule, $route, $method);
523
    }
524
525
    /**
526
     * 设置跨域有效路由规则
527
     * @access public
528
     * @param Rule   $rule   路由规则
529
     * @param string $method 请求类型
530
     * @return $this
531
     */
532
    public function setCrossDomainRule(Rule $rule, string $method = '*')
533
    {
534
        if (!isset($this->cross)) {
535
            $this->cross = (new RuleGroup($this))->mergeRuleRegex($this->mergeRuleRegex);
536
        }
537
538
        $this->cross->addRuleItem($rule, $method);
539
540
        return $this;
541
    }
542
543
    /**
544
     * 注册路由分组
545
     * @access public
546
     * @param string|\Closure $name  分组名称或者参数
547
     * @param mixed           $route 分组路由
548 6
     * @return RuleGroup
549
     */
550 6
    public function group($name, $route = null): RuleGroup
551 6
    {
552 6
        if ($name instanceof Closure) {
553
            $route = $name;
554
            $name  = '';
555 6
        }
556 6
557 6
        return (new RuleGroup($this, $this->group, $name, $route))
558 6
            ->lazy($this->lazy)
559
            ->removeSlash($this->removeSlash)
560
            ->mergeRuleRegex($this->mergeRuleRegex);
561
    }
562
563
    /**
564
     * 注册路由
565
     * @access public
566
     * @param string $rule  路由规则
567
     * @param mixed  $route 路由地址
568
     * @return RuleItem
569
     */
570
    public function any(string $rule, $route): RuleItem
571
    {
572
        return $this->rule($rule, $route, '*');
573
    }
574
575
    /**
576
     * 注册GET路由
577
     * @access public
578
     * @param string $rule  路由规则
579
     * @param mixed  $route 路由地址
580 24
     * @return RuleItem
581
     */
582 24
    public function get(string $rule, $route): RuleItem
583
    {
584
        return $this->rule($rule, $route, 'GET');
585
    }
586
587
    /**
588
     * 注册POST路由
589
     * @access public
590
     * @param string $rule  路由规则
591
     * @param mixed  $route 路由地址
592 6
     * @return RuleItem
593
     */
594 6
    public function post(string $rule, $route): RuleItem
595
    {
596
        return $this->rule($rule, $route, 'POST');
597
    }
598
599
    /**
600
     * 注册PUT路由
601
     * @access public
602
     * @param string $rule  路由规则
603
     * @param mixed  $route 路由地址
604 6
     * @return RuleItem
605
     */
606 6
    public function put(string $rule, $route): RuleItem
607
    {
608
        return $this->rule($rule, $route, 'PUT');
609
    }
610
611
    /**
612
     * 注册DELETE路由
613
     * @access public
614
     * @param string $rule  路由规则
615
     * @param mixed  $route 路由地址
616
     * @return RuleItem
617
     */
618
    public function delete(string $rule, $route): RuleItem
619
    {
620
        return $this->rule($rule, $route, 'DELETE');
621
    }
622
623
    /**
624
     * 注册PATCH路由
625
     * @access public
626
     * @param string $rule  路由规则
627
     * @param mixed  $route 路由地址
628
     * @return RuleItem
629
     */
630
    public function patch(string $rule, $route): RuleItem
631
    {
632
        return $this->rule($rule, $route, 'PATCH');
633
    }
634
635
    /**
636
     * 注册HEAD路由
637
     * @access public
638
     * @param string $rule  路由规则
639
     * @param mixed  $route 路由地址
640
     * @return RuleItem
641
     */
642
    public function head(string $rule, $route): RuleItem
643
    {
644
        return $this->rule($rule, $route, 'HEAD');
645
    }
646
647
    /**
648
     * 注册OPTIONS路由
649
     * @access public
650
     * @param string $rule  路由规则
651
     * @param mixed  $route 路由地址
652 3
     * @return RuleItem
653
     */
654 3
    public function options(string $rule, $route): RuleItem
655 3
    {
656
        return $this->rule($rule, $route, 'OPTIONS');
657
    }
658
659
    /**
660
     * 注册资源路由
661
     * @access public
662
     * @param string $rule  路由规则
663
     * @param string $route 路由地址
664
     * @return Resource
665
     */
666 3
    public function resource(string $rule, string $route): Resource
667
    {
668
        return (new Resource($this, $this->group, $rule, $route, $this->rest))
669 3
            ->lazy($this->lazy);
670 3
    }
671
672
    /**
673
     * 注册视图路由
674
     * @access public
675
     * @param string $rule     路由规则
676
     * @param string $template 路由模板地址
677
     * @param array  $vars     模板变量
678
     * @return RuleItem
679
     */
680
    public function view(string $rule, string $template = '', array $vars = []): RuleItem
681 3
    {
682
        return $this->rule($rule, function () use ($vars, $template) {
683
            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

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