Completed
Push — master ( 712098...4bb528 )
by Rasmus
13:19
created

Dispatcher::resolve()   C

Complexity

Conditions 7
Paths 2

Size

Total Lines 39
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 7.1782

Importance

Changes 0
Metric Value
dl 0
loc 39
ccs 22
cts 26
cp 0.8462
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 24
nc 2
nop 1
crap 7.1782
1
<?php
2
3
namespace mindplay\middleman;
4
5
use Interop\Http\Middleware\DelegateInterface;
6
use Interop\Http\Middleware\MiddlewareInterface;
7
use Interop\Http\Middleware\ServerMiddlewareInterface;
8
use InvalidArgumentException;
9
use LogicException;
10
use mindplay\readable;
11
use Psr\Http\Message\RequestInterface;
12
use Psr\Http\Message\ResponseInterface;
13
14
/**
15
 * PSR-7 / PSR-15 middleware dispatcher
16
 */
17
class Dispatcher implements MiddlewareInterface
18
{
19
    /**
20
     * @var callable middleware resolver
21
     */
22
    private $resolver;
23
24
    /**
25
     * @var mixed[] unresolved middleware stack
26
     */
27
    private $stack;
28
29
    /**
30
     * @param (callable|MiddlewareInterface|mixed)[] $stack middleware stack (with at least one middleware component)
31
     * @param callable|null $resolver optional middleware resolver:
32
     *                                function (string $name): MiddlewareInterface
33
     *
34
     * @throws InvalidArgumentException if an empty middleware stack was given
35
     */
36 1
    public function __construct($stack, callable $resolver = null)
37
    {
38 1
        if (count($stack) === 0) {
39 1
            throw new InvalidArgumentException("an empty middleware stack was given");
40
        }
41
42 1
        $this->stack = $stack;
43 1
        $this->resolver = $resolver;
44 1
    }
45
46
    /**
47
     * Dispatches the middleware stack and returns the resulting `ResponseInterface`.
48
     *
49
     * @param RequestInterface $request
50
     *
51
     * @return ResponseInterface
52
     *
53
     * @throws LogicException on unexpected result from any middleware on the stack
54
     */
55 1
    public function dispatch(RequestInterface $request)
56
    {
57 1
        $resolved = $this->resolve(0);
58
59 1
        return $resolved($request);
60
    }
61
62
    /**
63
     * @inheritdoc
64
     */
65 1
    public function process(RequestInterface $request, DelegateInterface $delegate)
66
    {
67
        $this->stack[] = function (RequestInterface $request) use ($delegate) {
68 1
            return $delegate->process($request);
69
        };
70
71 1
        $response = $this->dispatch($request);
72
73 1
        array_pop($this->stack);
74
75 1
        return $response;
76
    }
77
78
    /**
79
     * @param int $index middleware stack index
80
     *
81
     * @return Delegate
82
     */
83 1
    private function resolve($index)
84
    {
85 1
        if (isset($this->stack[$index])) {
86
            return new Delegate(function (RequestInterface $request) use ($index) {
87 1
                $middleware = $this->resolver
88 1
                    ? call_user_func($this->resolver, $this->stack[$index])
89 1
                    : $this->stack[$index]; // as-is
90
91 1
                switch (true) {
92 1
                    case $middleware instanceof MiddlewareInterface:
93 1
                    case $middleware instanceof ServerMiddlewareInterface:
94 1
                        $result = $middleware->process($request, $this->resolve($index + 1));
0 ignored issues
show
Documentation introduced by
$request is of type object<Psr\Http\Message\RequestInterface>, but the function expects a object<Psr\Http\Message\ServerRequestInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
95 1
                        break;
96
97 1
                    case is_callable($middleware):
98 1
                        $result = $middleware($request, $this->resolve($index + 1));
99 1
                        break;
100
101
                    default:
102
                        $given = readable::callback($middleware);
103
104
                        throw new LogicException("unsupported middleware type: {$given}");
105
                }
106
107 1
                if (! $result instanceof ResponseInterface) {
108 1
                    $given = readable::value($result);
109 1
                    $source = readable::callback($middleware);
110
111 1
                    throw new LogicException("unexpected middleware result: {$given} returned by: {$source}");
112
                }
113
114 1
                return $result;
115 1
            });
116
        }
117
118 1
        return new Delegate(function () {
119 1
            throw new LogicException("unresolved request: middleware stack exhausted with no result");
120 1
        });
121
    }
122
}
123