Completed
Push — 6.0 ( d30585...7d6f90 )
by yun
02:09
created

Url::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
c 0
b 0
f 0
nc 1
nop 5
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 1
rs 10
1
<?php
2
// +----------------------------------------------------------------------
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\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 3
    public function __construct(Request $request, Rule $rule, $dispatch, array $param = [], int $code = null)
27
    {
28 3
        $this->request = $request;
29 3
        $this->rule    = $rule;
30
        // 解析默认的URL规则
31 3
        $dispatch = $this->parseUrl($dispatch);
32
33 3
        parent::__construct($request, $rule, $dispatch, $this->param, $code);
34 3
    }
35
36
    /**
37
     * 解析URL地址
38
     * @access protected
39
     * @param  string $url URL
40
     * @return array
41
     */
42 3
    protected function parseUrl(string $url): array
43
    {
44 3
        $depr = $this->rule->config('pathinfo_depr');
45 3
        $bind = $this->rule->getRouter()->getDomainBind();
46
47 3
        if ($bind && preg_match('/^[a-z]/is', $bind)) {
48
            $bind = str_replace('/', $depr, $bind);
49
            // 如果有域名绑定
50
            $url = $bind . ('.' != substr($bind, -1) ? $depr : '') . ltrim($url, $depr);
51
        }
52
53 3
        $path = $this->rule->parseUrlPath($url);
54 3
        if (empty($path)) {
55
            return [null, null];
56
        }
57
58
        // 解析控制器
59 3
        $controller = !empty($path) ? array_shift($path) : null;
60
61 3
        if ($controller && !preg_match('/^[A-Za-z0-9][\w|\.]*$/', $controller)) {
62
            throw new HttpException(404, 'controller not exists:' . $controller);
63
        }
64
65
        // 解析操作
66 3
        $action = !empty($path) ? array_shift($path) : null;
67 3
        $var    = [];
68
69
        // 解析额外参数
70 3
        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 3
        $panDomain = $this->request->panDomain();
77 3
        if ($panDomain && $key = array_search('*', $var)) {
78
            // 泛域名赋值
79
            $var[$key] = $panDomain;
80
        }
81
82
        // 设置当前请求的参数
83 3
        $this->param = $var;
84
85
        // 封装路由
86 3
        $route = [$controller, $action];
87
88 3
        if ($this->hasDefinedRoute($route)) {
89
            throw new HttpException(404, 'invalid request:' . str_replace('|', $depr, $url));
90
        }
91
92 3
        return $route;
93
    }
94
95
    /**
96
     * 检查URL是否已经定义过路由
97
     * @access protected
98
     * @param  array $route 路由信息
99
     * @return bool
100
     */
101 3
    protected function hasDefinedRoute(array $route): bool
102
    {
103 3
        [$controller, $action] = $route;
104
105
        // 检查地址是否被定义过路由
106 3
        $name = strtolower(Str::studly($controller) . '/' . $action);
107
108 3
        $host   = $this->request->host(true);
109 3
        $method = $this->request->method();
110
111 3
        if ($this->rule->getRouter()->getName($name, $host, $method)) {
112
            return true;
113
        }
114
115 3
        return false;
116
    }
117
118
}
119