Passed
Push — 8.0 ( d0e1cd...7f09d5 )
by liu
02:13
created

Url::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 4
c 0
b 0
f 0
nc 1
nop 3
dl 0
loc 8
ccs 0
cts 5
cp 0
crap 2
rs 10
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\route\dispatch;
14
15
use think\exception\HttpException;
16
use think\helper\Str;
17
use think\Request;
18
use think\route\Rule;
19
20
/**
21
 * Url Dispatcher
22
 */
23
class Url extends Controller
24
{
25
26
    public function __construct(Request $request, Rule $rule, $dispatch)
27
    {
28
        $this->request = $request;
29
        $this->rule    = $rule;
30
        // 解析默认的URL规则
31
        $dispatch = $this->parseUrl($dispatch);
32
33
        parent::__construct($request, $rule, $dispatch, $this->param);
34
    }
35
36
    /**
37
     * 解析URL地址
38
     * @access protected
39
     * @param  string $url URL
40
     * @return array
41
     */
42
    protected function parseUrl(string $url): array
43
    {
44
        $depr = $this->rule->config('pathinfo_depr');
45
        $bind = $this->rule->getRouter()->getDomainBind();
46
47
        if ($bind && preg_match('/^[a-z]/is', $bind)) {
48
            $bind = str_replace('/', $depr, $bind);
49
            // 如果有域名绑定
50
            $url = $bind . (!str_ends_with($bind, '.') ? $depr : '') . ltrim($url, $depr);
0 ignored issues
show
Bug introduced by
It seems like $depr can also be of type null; however, parameter $characters of ltrim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

50
            $url = $bind . (!str_ends_with($bind, '.') ? $depr : '') . ltrim($url, /** @scrutinizer ignore-type */ $depr);
Loading history...
51
        }
52
53
        $path = $this->rule->parseUrlPath($url);
54
        if (empty($path)) {
55
            return [null, null];
56
        }
57
58
        // 解析控制器
59
        $controller = !empty($path) ? array_shift($path) : null;
60
61
        if ($controller && !preg_match('/^[A-Za-z0-9][\w|\.]*$/', $controller)) {
62
            throw new HttpException(404, 'controller not exists:' . $controller);
63
        }
64
65
        // 解析操作
66
        $action = !empty($path) ? array_shift($path) : null;
67
        $var    = [];
68
69
        // 解析额外参数
70
        if ($path) {
71
            preg_replace_callback('/(\w+)\|([^\|]+)/', function ($match) use (&$var) {
72
                $var[$match[1]] = strip_tags($match[2]);
73
            }, implode('|', $path));
74
        }
75
76
        $panDomain = $this->request->panDomain();
77
        if ($panDomain && $key = array_search('*', $var)) {
78
            // 泛域名赋值
79
            $var[$key] = $panDomain;
80
        }
81
82
        // 设置当前请求的参数
83
        $this->param = $var;
84
85
        // 封装路由
86
        $route = [$controller, $action];
87
88
        if ($this->hasDefinedRoute($route)) {
89
            throw new HttpException(404, 'invalid request:' . str_replace('|', $depr, $url));
90
        }
91
92
        return $route;
93
    }
94
95
    /**
96
     * 检查URL是否已经定义过路由
97
     * @access protected
98
     * @param  array $route 路由信息
99
     * @return bool
100
     */
101
    protected function hasDefinedRoute(array $route): bool
102
    {
103
        [$controller, $action] = $route;
104
105
        // 检查地址是否被定义过路由
106
        $name = strtolower(Str::studly($controller) . '/' . $action);
107
108
        $host   = $this->request->host(true);
109
        $method = $this->request->method();
110
111
        if ($this->rule->getRouter()->getName($name, $host, $method)) {
112
            return true;
113
        }
114
115
        return false;
116
    }
117
}
118