Completed
Push — 6.0 ( e7c66b...3b6853 )
by liu
02:54
created

Dispatch::setApp()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
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 setApp(App $app)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function setApp()
Loading history...
79
    {
80
        $this->app = $app;
81
        return $this;
82
    }
83
84
    public function init()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function init()
Loading history...
85
    {
86
        // 执行路由后置操作
87
        if ($this->rule->doAfter()) {
88
            // 设置请求的路由信息
89
            $this->request->setRoute($this->rule->getVars());
90
91
            // 设置当前请求的参数
92
            $this->request->routeInfo([
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
93
                'rule'   => $this->rule->getRule(),
94
                'route'  => $this->rule->getRoute(),
95
                'option' => $this->rule->getOption(),
96
                'var'    => $this->rule->getVars(),
97
            ]);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
98
99
            $this->doRouteAfter();
100
        }
101
    }
102
103
    /**
104
     * 执行路由调度
105
     * @access public
106
     * @return mixed
107
     */
108
    public function run(): Response
109
    {
110
        $this->init();
111
        $option = $this->rule->getOption();
112
113
        // 数据自动验证
114
        if (isset($option['validate'])) {
115
            $this->autoValidate($option['validate']);
116
        }
117
118
        $data = $this->exec();
119
120
        return $this->autoResponse($data);
121
    }
122
123
    protected function autoResponse($data): Response
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function autoResponse()
Loading history...
124
    {
125
        if ($data instanceof Response) {
126
            $response = $data;
127
        } elseif (!is_null($data)) {
128
            // 默认自动识别响应输出类型
129
            $type     = $this->request->isJson() ? 'json' : 'html';
130
            $response = Response::create($data, $type);
131
        } else {
132
            $data = ob_get_clean();
133
134
            $content  = false === $data ? '' : $data;
135
            $status   = false === $data ? 204 : 200;
136
            $response = Response::create($content, '', $status);
137
        }
138
139
        return $response;
140
    }
141
142
    /**
143
     * 检查路由后置操作
144
     * @access protected
145
     * @return void
146
     */
147
    protected function doRouteAfter(): void
148
    {
149
        // 记录匹配的路由信息
150
        $option  = $this->rule->getOption();
151
        $matches = $this->rule->getVars();
152
153
        // 添加中间件
154
        if (!empty($option['middleware'])) {
155
            $this->app['middleware']->import($option['middleware']);
156
        }
157
158
        // 绑定模型数据
159
        if (!empty($option['model'])) {
160
            $this->createBindModel($option['model'], $matches);
161
        }
162
163
        if (!empty($option['append'])) {
164
            $this->request->setRoute($option['append']);
165
        }
166
    }
167
168
    /**
169
     * 路由绑定模型实例
170
     * @access protected
171
     * @param  array $bindModel 绑定模型
172
     * @param  array $matches   路由变量
173
     * @return void
174
     */
175
    protected function createBindModel(array $bindModel, array $matches): void
176
    {
177
        foreach ($bindModel as $key => $val) {
178
            if ($val instanceof \Closure) {
179
                $result = $this->app->invokeFunction($val, $matches);
180
            } else {
181
                $fields = explode('&', $key);
182
183
                if (is_array($val)) {
184
                    list($model, $exception) = $val;
185
                } else {
186
                    $model     = $val;
187
                    $exception = true;
188
                }
189
190
                $where = [];
191
                $match = true;
192
193
                foreach ($fields as $field) {
194
                    if (!isset($matches[$field])) {
195
                        $match = false;
196
                        break;
197
                    } else {
198
                        $where[] = [$field, '=', $matches[$field]];
199
                    }
200
                }
201
202
                if ($match) {
203
                    $result = $model::where($where)->failException($exception)->find();
204
                }
205
            }
206
207
            if (!empty($result)) {
208
                // 注入容器
209
                $this->app->instance(get_class($result), $result);
210
            }
211
        }
212
    }
213
214
    /**
215
     * 验证数据
216
     * @access protected
217
     * @param  array $option
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
218
     * @return void
219
     * @throws \think\exception\ValidateException
220
     */
221
    protected function autoValidate(array $option): void
222
    {
223
        list($validate, $scene, $message, $batch) = $option;
224
225
        if (is_array($validate)) {
226
            // 指定验证规则
227
            $v = new Validate($validate, $message);
228
        } else {
229
            // 调用验证器
230
            /** @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...
231
            $class = $this->app->parseClass('validate', $validate);
232
            $v     = $class::make([], $message);
233
234
            if (!empty($scene)) {
235
                $v->scene($scene);
236
            }
237
        }
238
239
        $v->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

239
        $v->batch($batch)->failException(true)->check(/** @scrutinizer ignore-type */ $this->request->param());
Loading history...
240
    }
241
242
    public function convert(bool $convert)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function convert()
Loading history...
243
    {
244
        $this->convert = $convert;
245
246
        return $this;
247
    }
248
249
    public function getDispatch()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getDispatch()
Loading history...
250
    {
251
        return $this->dispatch;
252
    }
253
254
    public function getParam(): array
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getParam()
Loading history...
255
    {
256
        return $this->param;
257
    }
258
259
    abstract public function exec();
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function exec()
Loading history...
260
261
    public function __sleep()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __sleep()
Loading history...
262
    {
263
        return ['rule', 'dispatch', 'convert', 'param', 'code', 'controller', 'actionName'];
264
    }
265
266
    public function __wakeup()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __wakeup()
Loading history...
267
    {
268
        $this->app     = Container::pull('app');
269
        $this->request = $this->app->request;
270
    }
271
272
    public function __debugInfo()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __debugInfo()
Loading history...
273
    {
274
        return [
275
            'dispatch' => $this->dispatch,
276
            'param'    => $this->param,
277
            'code'     => $this->code,
278
        ];
279
    }
280
}
281