Completed
Push — 6.0 ( e89165...09da7f )
by liu
06:38 queued 15s
created

Middleware::route()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
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: Slince <[email protected]>
10
// +----------------------------------------------------------------------
11
declare (strict_types = 1);
12
13
namespace think;
14
15
use Closure;
16
use InvalidArgumentException;
17
use LogicException;
18
use think\exception\Handle;
19
use Throwable;
20
21
/**
22
 * 中间件管理类
23
 * @package think
0 ignored issues
show
Coding Style introduced by
Package name "think" is not valid; consider "Think" instead
Loading history...
24
 */
25
class Middleware
26
{
27
    /**
28
     * 中间件执行队列
29
     * @var array
30
     */
31
    protected $queue = [];
32
33
    /**
34
     * 应用对象
35
     * @var App
36
     */
37
    protected $app;
38
39 10
    public function __construct(App $app)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
40
    {
41 10
        $this->app = $app;
42 10
    }
43
44
    /**
45
     * 导入中间件
46
     * @access public
47
     * @param array  $middlewares
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
48
     * @param string $type 中间件类型
0 ignored issues
show
Coding Style introduced by
Expected 8 spaces after parameter name; 1 found
Loading history...
49
     * @return void
50
     */
51 9
    public function import(array $middlewares = [], string $type = 'global'): void
52
    {
53 9
        foreach ($middlewares as $middleware) {
54 2
            $this->add($middleware, $type);
55
        }
56 9
    }
57
58
    /**
59
     * 注册中间件
60
     * @access public
61
     * @param mixed  $middleware
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
62
     * @param string $type 中间件类型
0 ignored issues
show
Coding Style introduced by
Expected 7 spaces after parameter name; 1 found
Loading history...
63
     * @return void
64
     */
65 2
    public function add($middleware, string $type = 'global'): void
66
    {
67 2
        $middleware = $this->buildMiddleware($middleware, $type);
68
69 2
        if ($middleware) {
70 2
            $this->queue[$type][] = $middleware;
71
        }
72 2
    }
73
74
    /**
75
     * 注册路由中间件
76
     * @access public
77
     * @param mixed $middleware
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
78
     * @return void
79
     */
80
    public function route($middleware): void
81
    {
82
        $this->add($middleware, 'route');
83
    }
84
85
    /**
86
     * 注册控制器中间件
87
     * @access public
88
     * @param mixed $middleware
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
89
     * @return void
90
     */
91 1
    public function controller($middleware): void
92
    {
93 1
        $this->add($middleware, 'controller');
94 1
    }
95
96
    /**
97
     * 注册中间件到开始位置
98
     * @access public
99
     * @param mixed  $middleware
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
100
     * @param string $type 中间件类型
0 ignored issues
show
Coding Style introduced by
Expected 7 spaces after parameter name; 1 found
Loading history...
101
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
102 1
    public function unshift($middleware, string $type = 'global')
103
    {
104 1
        $middleware = $this->buildMiddleware($middleware, $type);
105
106 1
        if (!empty($middleware)) {
107 1
            array_unshift($this->queue[$type], $middleware);
108
        }
109 1
    }
110
111
    /**
112
     * 获取注册的中间件
113
     * @access public
114
     * @param string $type 中间件类型
115
     * @return array
116
     */
117 1
    public function all(string $type = 'global'): array
118
    {
119 1
        return $this->queue[$type] ?? [];
120
    }
121
122
    /**
123
     * 调度管道
124
     * @access public
125
     * @param string $type 中间件类型
126
     * @return Pipeline
127
     */
128 7
    public function pipeline(string $type = 'global')
129
    {
130 7
        return (new Pipeline())
131
            ->through(array_map(function ($middleware) {
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...
132
                return function ($request, $next) use ($middleware) {
133 1
                    list($call, $param) = $middleware;
134 1
                    if (is_array($call) && is_string($call[0])) {
135 1
                        $call = [$this->app->make($call[0]), $call[1]];
136
                    }
137 1
                    $response = call_user_func($call, $request, $next, $param);
138
139 1
                    if (!$response instanceof Response) {
140
                        throw new LogicException('The middleware must return Response instance');
141
                    }
142 1
                    return $response;
143 1
                };
144 7
            }, $this->sortMiddleware($this->queue[$type] ?? [])))
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...
145 7
            ->whenException([$this, 'handleException']);
146
    }
147
148
    /**
149
     * 结束调度
150
     * @param Response $response
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
151
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
152 2
    public function end(Response $response)
153
    {
154 2
        foreach ($this->queue as $queue) {
155 1
            foreach ($queue as $middleware) {
156 1
                list($call) = $middleware;
157 1
                if (is_array($call) && is_string($call[0])) {
158 1
                    $instance = $this->app->make($call[0]);
159 1
                    if (method_exists($instance, 'end')) {
160 1
                        $instance->end($response);
161
                    }
162
                }
163
            }
164
        }
165 2
    }
166
167
    /**
168
     * 异常处理
169
     * @param Request   $passable
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
170
     * @param Throwable $e
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
171
     * @return Response
172
     */
173 1
    public function handleException($passable, Throwable $e)
174
    {
175
        /** @var Handle $handler */
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...
176 1
        $handler = $this->app->make(Handle::class);
177
178 1
        $handler->report($e);
179
180 1
        $response = $handler->render($passable, $e);
181
182 1
        return $response;
183
    }
184
185
    /**
186
     * 解析中间件
187
     * @access protected
188
     * @param mixed  $middleware
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
189
     * @param string $type 中间件类型
0 ignored issues
show
Coding Style introduced by
Expected 7 spaces after parameter name; 1 found
Loading history...
190
     * @return array
191
     */
192 2
    protected function buildMiddleware($middleware, string $type): array
193
    {
194 2
        if (is_array($middleware)) {
195 1
            list($middleware, $param) = $middleware;
196
        }
197
198 2
        if ($middleware instanceof Closure) {
199 2
            return [$middleware, $param ?? null];
200
        }
201
202 2
        if (!is_string($middleware)) {
203
            throw new InvalidArgumentException('The middleware is invalid');
204
        }
205
206
        //中间件别名检查
207 2
        $alias = $this->app->config->get('middleware.alias', []);
208
209 2
        if (isset($alias[$middleware])) {
210 1
            $middleware = $alias[$middleware];
211
        }
212
213 2
        if (is_array($middleware)) {
214 1
            $this->import($middleware, $type);
215 1
            return [];
216
        }
217
218 2
        return [[$middleware, 'handle'], $param ?? null];
219
    }
220
221
    /**
222
     * 中间件排序
223
     * @param array $middlewares
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
224
     * @return array
225
     */
226 7
    protected function sortMiddleware(array $middlewares)
227
    {
228 7
        $priority = $this->app->config->get('middleware.priority', []);
229
        uasort($middlewares, function ($a, $b) use ($priority) {
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...
230 1
            $aPriority = $this->getMiddlewarePriority($priority, $a);
231 1
            $bPriority = $this->getMiddlewarePriority($priority, $b);
232 1
            return $bPriority - $aPriority;
233 7
        });
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...
234
235 7
        return $middlewares;
236
    }
237
238
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $priority should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $middleware should have a doc-comment as per coding-style.
Loading history...
239
     * 获取中间件优先级
240
     * @param $priority
0 ignored issues
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
241
     * @param $middleware
0 ignored issues
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
242
     * @return int
243
     */
244 1
    protected function getMiddlewarePriority($priority, $middleware)
245
    {
246 1
        list($call) = $middleware;
247 1
        if (is_array($call) && is_string($call[0])) {
248 1
            $index = array_search($call[0], array_reverse($priority));
249 1
            return false === $index ? -1 : $index;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false === $index ? -1 : $index also could return the type string which is incompatible with the documented return type integer.
Loading history...
250
        }
251 1
        return -1;
252
    }
253
254
}
255