Passed
Push — 8.0 ( bf2321...08f6c8 )
by liu
25:06 queued 10:10
created

Route::checkDomain()   F

Complexity

Conditions 15
Paths 388

Size

Total Lines 49
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 34.1663

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 14
cts 25
cp 0.56
crap 34.1663
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\dispatch\Callback;
19
use think\route\Domain;
20
use think\route\Resource;
21
use think\route\ResourceRegister;
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
use think\route\UrlRuleItem;
28
29
/**
30
 * 路由管理类
31
 * @package think
32
 */
33
class Route
34
{
35
    /**
36
     * REST定义
37
     * @var array
38
     */
39
    protected $rest = [
40
        'index'  => ['get', '', 'index'],
41
        'create' => ['get', '/create', 'create'],
42
        'edit'   => ['get', '/<id>/edit', 'edit'],
43
        'read'   => ['get', '/<id>', 'read'],
44
        'save'   => ['post', '', 'save'],
45
        'update' => ['put', '/<id>', 'update'],
46
        'delete' => ['delete', '/<id>', 'delete'],
47
    ];
48
49
    /**
50
     * 配置参数
51
     * @var array
52
     */
53
    protected $config = [
54
        // pathinfo分隔符
55
        'pathinfo_depr'         => '/',
56
        // 是否开启路由延迟解析
57
        'url_lazy_route'        => false,
58
        // 是否强制使用路由
59
        'url_route_must'        => false,
60
        // 是否区分大小写
61
        'url_case_sensitive'    => false,
62
        // 合并路由规则
63
        'route_rule_merge'      => false,
64
        // 路由是否完全匹配
65
        'route_complete_match'  => false,
66
        // 去除斜杠
67
        'remove_slash'          => false,
68
        // 使用注解路由
69
        'route_annotation'      => false,
70
        // 默认的路由变量规则
71
        'default_route_pattern' => '[\w\.]+',
72
        // URL伪静态后缀
73
        'url_html_suffix'       => 'html',
74
        // 访问控制器层名称
75
        'controller_layer'      => 'controller',
76
        // 空控制器名
77
        'empty_controller'      => 'Error',
78
        // 是否使用控制器后缀
79
        'controller_suffix'     => false,
80
        // 默认控制器名
81
        'default_controller'    => 'Index',
82
        // 默认操作名
83
        'default_action'        => 'index',
84
        // 操作方法后缀
85
        'action_suffix'         => '',
86
        // 非路由变量是否使用普通参数方式(用于URL生成)
87
        'url_common_param'      => true,
88
    ];
89
90
    /**
91
     * 请求对象
92
     * @var Request
93
     */
94
    protected $request;
95
96
    /**
97
     * @var RuleName
98
     */
99
    protected $ruleName;
100
101
    /**
102
     * 当前HOST
103
     * @var string
104
     */
105
    protected $host;
106
107
    /**
108
     * 当前分组对象
109
     * @var RuleGroup
110
     */
111
    protected $group;
112
113
    /**
114
     * 路由绑定
115
     * @var array
116
     */
117
    protected $bind = [];
118
119
    /**
120
     * 域名对象
121
     * @var Domain[]
122
     */
123
    protected $domains = [];
124
125
    /**
126
     * 跨域路由规则
127
     * @var RuleGroup
128
     */
129
    protected $cross;
130
131
    /**
132
     * 路由是否延迟解析
133
     * @var bool
134
     */
135
    protected $lazy = false;
136
137
    /**
138
     * (分组)路由规则是否合并解析
139
     * @var bool
140
     */
141
    protected $mergeRuleRegex = false;
142
143
    /**
144
     * 是否去除URL最后的斜线
145
     * @var bool
146
     */
147
    protected $removeSlash = false;
148
149
    public function __construct(protected App $app)
150
    {
151
        $this->ruleName = new RuleName();
152 27
        $this->setDefaultDomain();
153
154 27
        if (is_file($this->app->getRuntimePath() . 'route.php')) {
155 27
            // 读取路由映射文件
156
            $this->import(include $this->app->getRuntimePath() . 'route.php');
157 27
        }
158
159
        $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

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

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

653
            return Response::create($template, 'view')->/** @scrutinizer ignore-call */ assign($vars);
Loading history...
654
        }, 'GET');
655 3
    }
656 3
657 3
    /**
658
     * 注册重定向路由
659
     * @access public
660
     * @param string $rule   路由规则
661
     * @param string $route  路由地址
662
     * @param int    $status 状态码
663
     * @return RuleItem
664
     */
665
    public function redirect(string $rule, string $route = '', int $status = 301): RuleItem
666
    {
667
        return $this->rule($rule, function (Request $request) use ($status, $route) {
668 3
            $search  = $replace  = [];
669
            $matches = $request->rule()->getVars();
670 3
671 3
            foreach ($matches as $key => $value) {
672 3
                $search[]  = '<' . $key . '>';
673
                $replace[] = $value;
674 3
675
                $search[]  = ':' . $key;
676
                $replace[] = $value;
677
            }
678
679
            $route = str_replace($search, $replace, $route);
680
            return Response::create($route, 'redirect')->code($status);
681
        }, '*');
682 3
    }
683 3
684 3
    /**
685
     * rest方法定义和修改
686
     * @access public
687
     * @param string|array $name     方法名称
688
     * @param array|bool   $resource 资源
689
     * @return $this
690
     */
691
    public function rest(string | array $name, array | bool $resource = [])
692
    {
693
        if (is_array($name)) {
0 ignored issues
show
introduced by
The condition is_array($name) is always true.
Loading history...
694
            $this->rest = $resource ? $name : array_merge($this->rest, $name);
695
        } else {
696
            $this->rest[$name] = $resource;
697
        }
698
699
        return $this;
700
    }
701
702
    /**
703
     * 获取rest方法定义的参数
704
     * @access public
705
     * @param string $name 方法名称
706
     * @return array|null
707
     */
708
    public function getRest(?string $name = null)
709
    {
710
        if (is_null($name)) {
711
            return $this->rest;
712
        }
713
714
        return $this->rest[$name] ?? null;
715
    }
716
717
    /**
718
     * 注册未匹配路由规则后的处理
719
     * @access public
720
     * @param string|Closure $route  路由地址
721
     * @param string         $method 请求类型
722
     * @return RuleItem
723
     */
724
    public function miss(string | Closure $route, string $method = '*'): RuleItem
725
    {
726
        return $this->group->miss($route, $method);
727 27
    }
728
729 27
    /**
730
     * 路由调度
731
     * @param Request $request
732
     * @param Closure|bool $withRoute
733
     * @return Response
734
     */
735
    public function dispatch(Request $request, Closure | bool $withRoute = true)
736
    {
737
        $this->request = $request;
738 27
        $this->host    = $this->request->host(true);
739
        $completeMatch = (bool) $this->config['route_complete_match'];
740 27
741 27
        if ($withRoute) {
742 27
            //加载路由
743
            if ($withRoute instanceof Closure) {
744 27
                $withRoute();
745
            }
746 27
            $dispatch = $this->check($completeMatch);
747
        } else {
748
            $dispatch = $this->url()->check($this->request, $this->path(), $completeMatch);
749 27
        }
750
751
        $dispatch->init($this->app);
752
753
        return $this->app->middleware->pipeline('route')
754 27
            ->send($request)
755
            ->then(function () use ($dispatch) {
756 27
                return $dispatch->run();
757 27
            });
758 27
    }
759 27
760 27
    /**
761
     * 检测URL路由
762
     * @access public
763
     * @param  bool $completeMatch
764
     * @return Dispatch|false
765
     * @throws RouteNotFoundException
766
     */
767
    public function check(bool $completeMatch = false)
768
    {
769
        // 自动检测域名路由
770 27
        $url = str_replace($this->config['pathinfo_depr'], '|', $this->path());
771
772
        $result = $this->checkDomain()->check($this->request, $url, $completeMatch);
773 27
774
        if (false === $result && !empty($this->cross)) {
775 27
            // 检测跨域路由
776
            $result = $this->cross->check($this->request, $url, $completeMatch);
777 27
        }
778
779
        if (false !== $result) {
780
            return $result;
781
        } elseif ($this->config['url_route_must']) {
782 27
            throw new RouteNotFoundException();
783 24
        }
784 3
        return $this->url()->check($this->request, $url, $completeMatch);
785
    }
786
787 3
    /**
788
     * 获取当前请求URL的pathinfo信息(不含URL后缀)
789
     * @access protected
790
     * @return string
791
     */
792
    protected function path(): string
793
    {
794
        $suffix   = $this->config['url_html_suffix'];
795 27
        $pathinfo = $this->request->pathinfo();
796
797 27
        if (false === $suffix) {
798 27
            // 禁止伪静态访问
799
            $path = $pathinfo;
800 27
        } elseif ($suffix) {
801
            // 去除正常的URL后缀
802
            $path = preg_replace('/\.(' . ltrim($suffix, '.') . ')$/i', '', $pathinfo);
803 27
        } else {
804
            // 允许任何后缀访问
805 27
            $path = preg_replace('/\.' . $this->request->ext() . '$/i', '', $pathinfo);
806
        }
807
808
        return $path;
809
    }
810
811 27
    /**
812
     * 自动多模块路由解析
813
     * @access public
814
     * @param  string $default 默认模块
815
     * @return RuleItem
816
     */
817
    public function autoMultiModule(string $default = '') 
818
    {
819
        $this->group(':module')->pattern([
820 3
            'module' => '[A-Za-z0-9\.\_]+',
821
        ])->useUrlDispatch();
822 3
823
        if ($default) {
824
            $this->get('/', $default . '/' . $this->config['default_controller'] . '/' . $this->config['default_action']);            
825
        }
826
    }
827
828
    /**
829 3
     * 注册默认URL解析路由
830
     * @access public
831 3
     * @param  string|array $option 解析规则
832
     * @return RuleItem
833
     */
834
    public function url(string | array $option = ''): RuleItem
835 3
    {
836 3
        if (is_array($option)) {
837
            [$rule, $route] = $option;
838
        } else {
839 3
            $rule  = ($option ? $option . '/' : '') . '[:controller]/[:action]';
840
            $route = ($option ? $option . '/' : '') . ':controller/:action';
0 ignored issues
show
Bug introduced by
Are you sure $option of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

840
            $route = ($option ? /** @scrutinizer ignore-type */ $option . '/' : '') . ':controller/:action';
Loading history...
841 3
        }
842 3
843 3
        $ruleItem = new UrlRuleItem($this, $this->group, '_default_route_', $rule, $route, '*');
844 3
845 3
        return $ruleItem->default([
846 3
            'controller' => $this->config['default_controller'],
847 3
            'action'     => $this->config['default_action'],
848 3
        ])->pattern([
849 3
            'controller' => '[A-Za-z0-9\.\_]+',
850
            'action'     => '[A-Za-z0-9\_]+',
851
        ]);
852
    }
853
854
    /**
855
     * 检测域名的路由规则
856
     * @access protected
857 27
     * @return Domain
858
     */
859 27
    protected function checkDomain(): Domain
860
    {
861 27
        $item = false;
862
863 3
        if (count($this->domains) > 1) {
864
            // 获取当前子域名
865 3
            $subDomain = $this->request->subDomain();
866 3
867
            $domain  = $subDomain ? explode('.', $subDomain) : [];
868 3
            $domain2 = $domain ? array_pop($domain) : '';
869
870
            if ($domain) {
871
                // 存在三级域名
872
                $domain3 = array_pop($domain);
873 3
            }
874
875
            if (isset($this->domains[$this->host])) {
876 3
                // 子域名配置
877 3
                $item = $this->domains[$this->host];
878
            } elseif (isset($this->domains[$subDomain])) {
879
                $item = $this->domains[$subDomain];
880
            } elseif (isset($this->domains['*.' . $domain2]) && !empty($domain3)) {
881
                // 泛三级域名
882
                $item      = $this->domains['*.' . $domain2];
883
                $panDomain = $domain3;
884
            } elseif (isset($this->domains['*']) && !empty($domain2)) {
885
                // 泛二级域名
886
                if ('www' != $domain2) {
887
                    $item      = $this->domains['*'];
888
                    $panDomain = $domain2;
889
                }
890 3
            }
891
892
            if (isset($panDomain)) {
893
                // 保存当前泛域名
894
                $this->request->setPanDomain($panDomain);
895
            }
896 27
        }
897
898 24
        if (false === $item) {
899
            // 检测全局域名规则
900
            $item = $this->domains['-'];
901 27
        }
902
903
        if (is_string($item)) {
904
            $item = $this->domains[$item];
905 27
        }
906
907
        return $item;
908
    }
909
910
    /**
911
     * URL生成 支持路由反射
912
     * @access public
913
     * @param string $url  路由地址
914
     * @param array  $vars 参数 ['a'=>'val1', 'b'=>'val2']
915
     * @return UrlBuild
916
     */
917
    public function buildUrl(string $url = '', array $vars = []): UrlBuild
918
    {
919
        return $this->app->make(UrlBuild::class, [$this, $this->app, $url, $vars], true);
920
    }
921
922
    /**
923
     * 设置全局的路由分组参数
924
     * @access public
925
     * @param string $method 方法名
926
     * @param array  $args   调用参数
927
     * @return RuleGroup
928
     */
929
    public function __call($method, $args)
930
    {
931
        return call_user_func_array([$this->group, $method], $args);
932
    }
933
}
934