Completed
Push — master ( 6b8416...c520c0 )
by Filipe
02:12
created

MiddlewareStack::resolve()   B

Complexity

Conditions 4
Paths 1

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 8.6845
c 0
b 0
f 0
cc 4
eloc 12
nc 1
nop 1
1
<?php
2
3
/**
4
 * This file is part of slick/http
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace Slick\Http\Server;
11
12
use Interop\Http\Server\MiddlewareInterface;
13
use Psr\Http\Message\ResponseInterface;
14
use Psr\Http\Message\ServerRequestInterface;
15
use Slick\Http\Server\Exception\InvalidArgumentException;
16
use Slick\Http\Server\Exception\UnexpectedValueException;
17
use Slick\Http\Server\Middleware\CallableMiddleware;
18
19
/**
20
 * MiddlewareStack
21
 *
22
 * @package Slick\Http\Server
23
 */
24
class MiddlewareStack
25
{
26
    /**
27
     * @var array|MiddlewareInterface[]
28
     */
29
    private $middlewareStack = [];
30
31
    /**
32
     * Creates a Middleware Stack
33
     *
34
     * @param MiddlewareInterface[]|callable[] $middlewareStack
35
     */
36
    public function __construct(array $middlewareStack)
37
    {
38
        foreach ($middlewareStack as $middleware) {
39
            $this->push($middleware);
40
        }
41
    }
42
43
    /**
44
     * Pushes a middleware to the stack
45
     *
46
     * @param MiddlewareInterface|callable $middleware
47
     *
48
     * @return MiddlewareStack
49
     */
50
    public function push($middleware)
51
    {
52
        if (
53
            ! $middleware instanceof MiddlewareInterface &&
54
            ! is_callable($middleware)
55
        ) {
56
            throw new InvalidArgumentException(
57
                "Middleware stack accepts only MiddlewareInterface object or callable"
58
            );
59
        }
60
61
        array_push($this->middlewareStack, $middleware);
62
        return $this;
63
    }
64
65
    /**
66
     * Processes all the middleware stack
67
     *
68
     * @param ServerRequestInterface $request
69
     *
70
     * @return \Psr\Http\Message\ResponseInterface
71
     */
72
    public function process(ServerRequestInterface $request)
73
    {
74
        $handler = $this->resolve(0);
75
        return $handler->handle($request);
76
    }
77
78
    /**
79
     * Creates a request handler for middleware at the position defined by $index
80
     *
81
     * @param int $index
82
     *
83
     * @return RequestHandler
84
     *
85
     * @throws UnexpectedValueException If the return form a middleware is not a ResponseInterface
86
     */
87
    private function resolve($index)
88
    {
89
        return new RequestHandler(function(ServerRequestInterface $request) use ($index) {
90
91
            $middleware = isset($this->middlewareStack[$index])
92
                ? $this->middlewareStack[$index]
93
                : new CallableMiddleware(function () {});
94
95
            if ($middleware instanceof \Closure) {
96
                $middleware = new CallableMiddleware($middleware);
97
            }
98
99
            $response = $middleware->process($request, $this->resolve($index + 1));
100
101
            if (!($response instanceof ResponseInterface)) {
102
                throw new UnexpectedValueException(
103
                    sprintf('The middleware must return an instance of %s', ResponseInterface::class)
104
                );
105
            }
106
107
            return $response;
108
        });
109
110
    }
111
}