Completed
Push — 6.0 ( fe454f...4b767c )
by liu
05:27
created

Middleware::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
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 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 1
    public function route($middleware): void
81
    {
82 1
        $this->add($middleware, 'route');
83 1
    }
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
    }
95 1
96 1
    /**
97
     * 注册中间件到开始位置
98 1
     * @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
    public function unshift($middleware, string $type = 'global')
103
    {
104
        $middleware = $this->buildMiddleware($middleware, $type);
105
106 1
        if (!empty($middleware)) {
107
            array_unshift($this->queue[$type], $middleware);
108 1
        }
109
    }
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 1
    /**
123 1
     * 调度管道
124 1
     * @access public
125
     * @param string $type 中间件类型
126 1
     * @return Pipeline
127
     */
128 1
    public function pipeline(string $type = 'global')
129
    {
130
        return (new Pipeline())
131 1
            ->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 1
                return function ($request, $next) use ($middleware) {
133 1
                    list($call, $param) = $middleware;
134 1
                    if (is_array($call) && is_string($call[0])) {
135
                        $call = [$this->app->make($call[0]), $call[1]];
136
                    }
137
                    $response = call_user_func($call, $request, $next, $param);
138
139
                    if (!$response instanceof Response) {
140
                        throw new LogicException('The middleware must return Response instance');
141 2
                    }
142
                    return $response;
143 2
                };
144 1
            }, $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 1
            ->whenException([$this, 'handleException']);
146 1
    }
147 1
148 1
    /**
149 1
     * 结束调度
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
    public function end(Response $response)
153
    {
154 2
        foreach ($this->queue as $queue) {
155
            foreach ($queue as $middleware) {
156
                list($call) = $middleware;
157
                if (is_array($call) && is_string($call[0])) {
158
                    $instance = $this->app->make($call[0]);
159
                    if (method_exists($instance, 'end')) {
160
                        $instance->end($response);
161
                    }
162 1
                }
163
            }
164
        }
165 1
    }
166
167 1
    /**
168
     * 异常处理
169 1
     * @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 1
     * @return Response
172
     */
173
    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
        $handler = $this->app->make(Handle::class);
177
178
        $handler->report($e);
179
180
        $response = $handler->render($passable, $e);
181 2
182
        return $response;
183 2
    }
184 1
185
    /**
186
     * 解析中间件
187 2
     * @access protected
188 2
     * @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 2
     */
192
    protected function buildMiddleware($middleware, string $type): array
193
    {
194
        if (is_array($middleware)) {
195
            list($middleware, $param) = $middleware;
196 2
        }
197
198 2
        if ($middleware instanceof Closure) {
199 1
            return [$middleware, $param ?? null];
200
        }
201
202 2
        if (!is_string($middleware)) {
203 1
            throw new InvalidArgumentException('The middleware is invalid');
204 1
        }
205
206
        //中间件别名检查
207 2
        $alias = $this->app->config->get('middleware.alias', []);
208
209
        if (isset($alias[$middleware])) {
210
            $middleware = $alias[$middleware];
211
        }
212
213
        if (is_array($middleware)) {
214
            $this->import($middleware, $type);
215 1
            return [];
216
        }
217 1
218
        return [[$middleware, 'handle'], $param ?? null];
219 1
    }
220 1
221 1
    /**
222 1
     * 中间件排序
223
     * @param array $middlewares
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
224 1
     * @return array
225
     */
226
    protected function sortMiddleware(array $middlewares)
227
    {
228
        $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
            $aPriority = $this->getMiddlewarePriority($priority, $a);
231
            $bPriority = $this->getMiddlewarePriority($priority, $b);
232
            return $bPriority - $aPriority;
233 1
        });
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 1
        return $middlewares;
236 1
    }
237 1
238 1
    /**
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 1
     * @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
    protected function getMiddlewarePriority($priority, $middleware)
245
    {
246
        list($call) = $middleware;
247
        if (is_array($call) && is_string($call[0])) {
248
            $index = array_search($call[0], array_reverse($priority));
249
            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
        return -1;
252
    }
253
254
}
255