Completed
Push — 6.0 ( 9f671b...4e2ba0 )
by yun
05:44
created

Middleware::controller()   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
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
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 = 'route'): 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 = 'route'): 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 controller($middleware): void
81
    {
82 1
        $this->add($middleware, 'controller');
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
     * @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 1
    public function unshift($middleware, string $type = 'route')
92
    {
93 1
        $middleware = $this->buildMiddleware($middleware, $type);
94
95 1
        if (!empty($middleware)) {
96 1
            array_unshift($this->queue[$type], $middleware);
97
        }
98 1
    }
99
100
    /**
101
     * 获取注册的中间件
102
     * @access public
103
     * @param string $type 中间件类型
104
     * @return array
105
     */
106 1
    public function all(string $type = 'route'): array
107
    {
108 1
        return $this->queue[$type] ?? [];
109
    }
110
111
    /**
112
     * 调度管道
113
     * @access public
114
     * @param string $type 中间件类型
115
     * @return Pipeline
116
     */
117 1
    public function pipeline(string $type = 'route')
118
    {
119 1
        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 1
                    list($call, $param) = $middleware;
123 1
                    if (is_array($call) && is_string($call[0])) {
124 1
                        $call = [$this->app->make($call[0]), $call[1]];
125
                    }
126 1
                    $response = call_user_func($call, $request, $next, $param);
127
128 1
                    if (!$response instanceof Response) {
129
                        throw new LogicException('The middleware must return Response instance');
130
                    }
131 1
                    return $response;
132 1
                };
133 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...
134 1
            ->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 2
    public function end(Response $response)
142
    {
143 2
        foreach ($this->queue as $queue) {
144 1
            foreach ($queue as $middleware) {
145 1
                list($call, ) = $middleware;
146 1
                if (is_array($call) && is_string($call[0])) {
147 1
                    $instance = $this->app->make($call[0]);
148 1
                    if (method_exists($instance, 'end')) {
149 1
                        $instance->end($response);
150
                    }
151
                }
152
            }
153
        }
154 2
    }
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 1
    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 1
        $handler = $this->app->make(Handle::class);
166
167 1
        $handler->report($e);
168
169 1
        $response = $handler->render($passable, $e);
170
171 1
        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 2
    protected function buildMiddleware($middleware, string $type = 'route'): array
182
    {
183 2
        if (is_array($middleware)) {
184 1
            list($middleware, $param) = $middleware;
185
        }
186
187 2
        if ($middleware instanceof Closure) {
188 2
            return [$middleware, $param ?? null];
189
        }
190
191 2
        if (!is_string($middleware)) {
192
            throw new InvalidArgumentException('The middleware is invalid');
193
        }
194
195
        //中间件别名检查
196 2
        $alias = $this->app->config->get('middleware.alias', []);
197
198 2
        if (isset($alias[$middleware])) {
199 1
            $middleware = $alias[$middleware];
200
        }
201
202 2
        if (is_array($middleware)) {
203 1
            $this->import($middleware, $type);
204 1
            return [];
205
        }
206
207 2
        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 1
    protected function sortMiddleware(array $middlewares)
216
    {
217 1
        $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 1
            $aPriority = $this->getMiddlewarePriority($priority, $a);
220 1
            $bPriority = $this->getMiddlewarePriority($priority, $b);
221 1
            return $bPriority - $aPriority;
222 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...
223
224 1
        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 1
    protected function getMiddlewarePriority($priority, $middleware)
234
    {
235 1
        list($call, ) = $middleware;
236 1
        if (is_array($call) && is_string($call[0])) {
237 1
            $index = array_search($call[0], array_reverse($priority));
238 1
            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 1
        return -1;
241
    }
242
243
}
244