Completed
Push — 6.0 ( e48ed6...2a00ae )
by yun
04:03
created

Dispatch   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 238
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 83
dl 0
loc 238
ccs 0
cts 88
cp 0
rs 9.84
c 0
b 0
f 0
wmc 32

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 10 2
B createBindModel() 0 35 8
A __wakeup() 0 4 1
A __sleep() 0 3 1
A getDispatch() 0 3 1
A doRouteAfter() 0 17 4
A getParam() 0 3 1
A __debugInfo() 0 6 1
A autoValidate() 0 20 3
A run() 0 12 2
A convert() 0 5 1
A init() 0 5 1
A autoResponse() 0 17 6
1
<?php
2
// +----------------------------------------------------------------------
1 ignored issue
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
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;
14
15
use think\App;
16
use think\Container;
17
use think\Request;
18
use think\Response;
19
use think\Validate;
20
21
abstract class Dispatch
1 ignored issue
show
Coding Style introduced by
Missing doc comment for class Dispatch
Loading history...
22
{
23
    /**
24
     * 应用对象
25
     * @var \think\App
26
     */
27
    protected $app;
28
29
    /**
30
     * 请求对象
31
     * @var Request
32
     */
33
    protected $request;
34
35
    /**
36
     * 路由规则
37
     * @var Rule
38
     */
39
    protected $rule;
40
41
    /**
42
     * 调度信息
43
     * @var mixed
44
     */
45
    protected $dispatch;
46
47
    /**
48
     * 调度参数
49
     * @var array
50
     */
51
    protected $param;
52
53
    /**
54
     * 状态码
55
     * @var int
56
     */
57
    protected $code;
58
59
    /**
60
     * 是否进行大小写转换
61
     * @var bool
62
     */
63
    protected $convert;
64
65
    public function __construct(Request $request, Rule $rule, $dispatch, array $param = [], int $code = null)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
66
    {
67
        $this->request  = $request;
68
        $this->rule     = $rule;
69
        $this->dispatch = $dispatch;
70
        $this->param    = $param;
71
        $this->code     = $code;
72
73
        if (isset($param['convert'])) {
74
            $this->convert = $param['convert'];
75
        }
76
    }
77
78
    public function init(App $app)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function init()
Loading history...
79
    {
80
        $this->app = $app;
81
        // 执行路由后置操作
82
        $this->doRouteAfter();
83
    }
84
85
    /**
86
     * 执行路由调度
87
     * @access public
88
     * @return mixed
89
     */
90
    public function run(): Response
91
    {
92
        $option = $this->rule->getOption();
93
94
        // 数据自动验证
95
        if (isset($option['validate'])) {
96
            $this->autoValidate($option['validate']);
97
        }
98
99
        $data = $this->exec();
100
101
        return $this->autoResponse($data);
102
    }
103
104
    protected function autoResponse($data): Response
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function autoResponse()
Loading history...
105
    {
106
        if ($data instanceof Response) {
107
            $response = $data;
108
        } elseif (!is_null($data)) {
109
            // 默认自动识别响应输出类型
110
            $type     = $this->request->isJson() ? 'json' : 'html';
111
            $response = Response::create($data, $type);
112
        } else {
113
            $data = ob_get_clean();
114
115
            $content  = false === $data ? '' : $data;
116
            $status   = false === $data ? 204 : 200;
117
            $response = Response::create($content, '', $status);
118
        }
119
120
        return $response;
121
    }
122
123
    /**
124
     * 检查路由后置操作
125
     * @access protected
126
     * @return void
127
     */
128
    protected function doRouteAfter(): void
129
    {
130
        // 记录匹配的路由信息
131
        $option = $this->rule->getOption();
132
133
        // 添加中间件
134
        if (!empty($option['middleware'])) {
135
            $this->app['middleware']->import($option['middleware']);
136
        }
137
138
        // 绑定模型数据
139
        if (!empty($option['model'])) {
140
            $this->createBindModel($option['model'], $this->request->route());
0 ignored issues
show
Bug introduced by
$this->request->route() of type null|object is incompatible with the type array expected by parameter $matches of think\route\Dispatch::createBindModel(). ( Ignorable by Annotation )

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

140
            $this->createBindModel($option['model'], /** @scrutinizer ignore-type */ $this->request->route());
Loading history...
141
        }
142
143
        if (!empty($option['append'])) {
144
            $this->request->setRoute($option['append']);
145
        }
146
    }
147
148
    /**
149
     * 路由绑定模型实例
150
     * @access protected
151
     * @param array $bindModel 绑定模型
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
152
     * @param array $matches   路由变量
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
153
     * @return void
154
     */
155
    protected function createBindModel(array $bindModel, array $matches): void
156
    {
157
        foreach ($bindModel as $key => $val) {
158
            if ($val instanceof \Closure) {
159
                $result = $this->app->invokeFunction($val, $matches);
160
            } else {
161
                $fields = explode('&', $key);
162
163
                if (is_array($val)) {
164
                    list($model, $exception) = $val;
165
                } else {
166
                    $model     = $val;
167
                    $exception = true;
168
                }
169
170
                $where = [];
171
                $match = true;
172
173
                foreach ($fields as $field) {
174
                    if (!isset($matches[$field])) {
175
                        $match = false;
176
                        break;
177
                    } else {
178
                        $where[] = [$field, '=', $matches[$field]];
179
                    }
180
                }
181
182
                if ($match) {
183
                    $result = $model::where($where)->failException($exception)->find();
184
                }
185
            }
186
187
            if (!empty($result)) {
188
                // 注入容器
189
                $this->app->instance(get_class($result), $result);
190
            }
191
        }
192
    }
193
194
    /**
195
     * 验证数据
196
     * @access protected
197
     * @param array $option
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
198
     * @return void
199
     * @throws \think\exception\ValidateException
200
     */
201
    protected function autoValidate(array $option): void
202
    {
203
        list($validate, $scene, $message, $batch) = $option;
204
205
        if (is_array($validate)) {
206
            // 指定验证规则
207
            $v = new Validate();
208
            $v->rule($validate);
209
        } else {
210
            // 调用验证器
211
            /** @var Validate $class */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
212
            $class = $this->app->parseClass('validate', $validate);
213
            $v     = new $class();
214
215
            if (!empty($scene)) {
216
                $v->scene($scene);
217
            }
218
        }
219
220
        $v->message($message)->batch($batch)->failException(true)->check($this->request->param());
0 ignored issues
show
Bug introduced by
$this->request->param() of type null|object is incompatible with the type array expected by parameter $data of think\Validate::check(). ( Ignorable by Annotation )

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

220
        $v->message($message)->batch($batch)->failException(true)->check(/** @scrutinizer ignore-type */ $this->request->param());
Loading history...
221
    }
222
223
    public function convert(bool $convert)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function convert()
Loading history...
224
    {
225
        $this->convert = $convert;
226
227
        return $this;
228
    }
229
230
    public function getDispatch()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getDispatch()
Loading history...
231
    {
232
        return $this->dispatch;
233
    }
234
235
    public function getParam(): array
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getParam()
Loading history...
236
    {
237
        return $this->param;
238
    }
239
240
    abstract public function exec();
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function exec()
Loading history...
241
242
    public function __sleep()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __sleep()
Loading history...
243
    {
244
        return ['rule', 'dispatch', 'convert', 'param', 'code', 'controller', 'actionName'];
245
    }
246
247
    public function __wakeup()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __wakeup()
Loading history...
248
    {
249
        $this->app     = Container::pull('app');
250
        $this->request = $this->app->request;
251
    }
252
253
    public function __debugInfo()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __debugInfo()
Loading history...
254
    {
255
        return [
256
            'dispatch' => $this->dispatch,
257
            'param'    => $this->param,
258
            'code'     => $this->code,
259
        ];
260
    }
261
}
262