Completed
Push — 6.0 ( 9db11b...892b87 )
by yun
06:42
created

Middleware::all()   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
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 0
cp 0
crap 2
rs 10
c 0
b 0
f 0
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
    public function __construct(App $app)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
40
    {
41
        $this->app = $app;
42
    }
43 7
44
    /**
45 7
     * 导入中间件
46 7
     * @access public
47
     * @param array  $middlewares
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
48 7
     * @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 7
     */
51
    public function import(array $middlewares = [], string $type = 'route'): void
52
    {
53
        foreach ($middlewares as $middleware) {
54
            $this->add($middleware, $type);
55
        }
56
    }
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 7
     */
65
    public function add($middleware, string $type = 'route'): void
66 7
    {
67 7
        $middleware = $this->buildMiddleware($middleware, $type);
68
69
        if ($middleware) {
70
            $this->queue[$type][] = $middleware;
71
        }
72
    }
73
74
    /**
75
     * 注册控制器中间件
76
     * @access public
77 7
     * @param mixed $middleware
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
78
     * @return void
79 7
     */
80
    public function controller($middleware): void
81
    {
82 7
        $this->add($middleware, 'controller');
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
     * @param string $type 中间件类型
0 ignored issues
show
Coding Style introduced by
Expected 7 spaces after parameter name; 1 found
Loading history...
90
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
91
    public function unshift($middleware, string $type = 'route')
92
    {
93
        $middleware = $this->buildMiddleware($middleware, $type);
94
95
        if (!empty($middleware)) {
96
            array_unshift($this->queue[$type], $middleware);
97
        }
98
    }
99
100
    /**
101
     * 获取注册的中间件
102
     * @access public
103
     * @param string $type 中间件类型
104
     * @return array
105
     */
106
    public function all(string $type = 'route'): array
107
    {
108
        return $this->queue[$type] ?? [];
109
    }
110
111
    /**
112
     * 调度管道
113
     * @access public
114
     * @param string $type 中间件类型
115
     * @return Pipeline
116
     */
117
    public function pipeline(string $type = 'route')
118
    {
119
        return (new Pipeline())
120
            ->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...
121
                return function ($request, $next) use ($middleware) {
122
                    list($call, $param) = $middleware;
123
                    if (is_array($call) && is_string($call[0])) {
124
                        $call = [$this->app->make($call[0]), $call[1]];
125
                    }
126
                    $response = call_user_func($call, $request, $next, $param);
127
128
                    if (!$response instanceof Response) {
129
                        throw new LogicException('The middleware must return Response instance');
130
                    }
131
                    return $response;
132
                };
133
            }, $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...
134
            ->whenException([$this, 'handleException']);
135
    }
136
137
    /**
138
     * 结束调度
139
     * @param Response $response
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
140
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
141
    public function end(Response $response)
142
    {
143
        foreach ($this->queue as $queue) {
144
            foreach ($queue as $middleware) {
145
                list($call,) = $middleware;
146
                if (is_array($call) && is_string($call[0])) {
147
                    $instance = $this->app->make($call[0]);
148
                    if (method_exists($instance, 'end')) {
149
                        $instance->end($response);
150
                    }
151
                }
152
            }
153
        }
154
    }
155
156
    /**
157
     * 异常处理
158
     * @param Request   $passable
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
159
     * @param Throwable $e
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
160
     * @return Response
161
     */
162
    public function handleException($passable, Throwable $e)
163
    {
164
        /** @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...
165
        $handler = $this->app->make(Handle::class);
166
167
        $handler->report($e);
168
169
        $response = $handler->render($passable, $e);
170
171
        return $response;
172
    }
173
174
    /**
175
     * 解析中间件
176
     * @access protected
177
     * @param mixed  $middleware
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
178
     * @param string $type 中间件类型
0 ignored issues
show
Coding Style introduced by
Expected 7 spaces after parameter name; 1 found
Loading history...
179
     * @return array
180
     */
181
    protected function buildMiddleware($middleware, string $type = 'route'): array
182
    {
183
        if (is_array($middleware)) {
184
            list($middleware, $param) = $middleware;
185
        }
186
187
        if ($middleware instanceof Closure) {
188
            return [$middleware, $param ?? null];
189
        }
190
191
        if (!is_string($middleware)) {
192
            throw new InvalidArgumentException('The middleware is invalid');
193
        }
194
195
        //中间件别名检查
196
        $alias = $this->app->config->get('middleware.alias', []);
197
198
        if (isset($alias[$middleware])) {
199
            $middleware = $alias[$middleware];
200
        }
201
202
        if (is_array($middleware)) {
203
            $this->import($middleware, $type);
204
            return [];
205
        }
206
207
        return [[$middleware, 'handle'], $param ?? null];
208
    }
209
210
    /**
211
     * 中间件排序
212
     * @param array $middlewares
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
213
     * @return array
214
     */
215
    protected function sortMiddleware(array $middlewares)
216
    {
217
        $priority = $this->app->config->get('middleware.priority', []);
218
        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...
219
            $aPriority = $this->getMiddlewarePriority($priority, $a);
220
            $bPriority = $this->getMiddlewarePriority($priority, $b);
221
            return $bPriority - $aPriority;
222
        });
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...
223
224
        return $middlewares;
225
    }
226
227
    /**
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...
228
     * 获取中间件优先级
229
     * @param $priority
0 ignored issues
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
230
     * @param $middleware
0 ignored issues
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
231
     * @return int
232
     */
233
    protected function getMiddlewarePriority($priority, $middleware)
234
    {
235
        list($call,) = $middleware;
236
        if (is_array($call) && is_string($call[0])) {
237
            $index = array_search($call[0], array_reverse($priority));
238
            return $index === false ? -1 : $index;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $index === false ? -1 : $index also could return the type string which is incompatible with the documented return type integer.
Loading history...
239
        }
240
        return -1;
241
    }
242
243
}
244