MiddlewareStack::resolve()   A
last analyzed

Complexity

Conditions 4
Paths 1

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 11
c 1
b 0
f 0
dl 0
loc 22
rs 9.9
cc 4
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 Psr\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 (! $middleware instanceof MiddlewareInterface &&
53
            ! is_callable($middleware)
54
        ) {
55
            throw new InvalidArgumentException(
56
                "Middleware stack accepts only MiddlewareInterface object or callable"
57
            );
58
        }
59
60
        array_push($this->middlewareStack, $middleware);
61
        return $this;
62
    }
63
64
    /**
65
     * Processes all the middleware stack
66
     *
67
     * @param ServerRequestInterface $request
68
     *
69
     * @return \Psr\Http\Message\ResponseInterface
70
     */
71
    public function process(ServerRequestInterface $request)
72
    {
73
        $handler = $this->resolve(0);
74
        return $handler->handle($request);
75
    }
76
77
    /**
78
     * Creates a request handler for middleware at the position defined by $index
79
     *
80
     * @param int $index
81
     *
82
     * @return RequestHandler
83
     *
84
     * @throws UnexpectedValueException If the return form a middleware is not a ResponseInterface
85
     */
86
    private function resolve($index)
87
    {
88
        return new RequestHandler(function (ServerRequestInterface $request) use ($index) {
89
90
            $middleware = isset($this->middlewareStack[$index])
91
                ? $this->middlewareStack[$index]
92
                : new CallableMiddleware(function () {
93
                });
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