Completed
Push — master ( 6d34b5...1a2ea1 )
by Rasmus
46s queued 10s
created

Dispatcher::handle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace mindplay\middleman;
4
5
use Interop\Http\Server\MiddlewareInterface as LegacyMiddlewareInterface;
6
use InvalidArgumentException;
7
use LogicException;
8
use mindplay\readable;
9
use Psr\Http\Message\ResponseInterface;
10
use Psr\Http\Message\ServerRequestInterface;
11
use Psr\Http\Server\MiddlewareInterface as PsrMiddlewareInterface;
12
use Psr\Http\Server\RequestHandlerInterface;
13
14
/**
15
 * PSR-7 / PSR-15 middleware dispatcher
16
 */
17
class Dispatcher implements LegacyMiddlewareInterface, RequestHandlerInterface
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 ServerRequestInterface $request
50
     *
51
     * @return ResponseInterface
52
     *
53
     * @throws LogicException on unexpected result from any middleware on the stack
54
     */
55 1
    public function handle(ServerRequestInterface $request): ResponseInterface
56
    {
57 1
        $resolved = $this->resolve(0);
58
59 1
        return $resolved->handle($request);
60
    }
61
62
    /**
63
     * Dispatches the middleware stack and returns the resulting `ResponseInterface`.
64
     *
65
     * @deprecated in favor of identical PSR-15 method `RequestHandlerInterface::handle()`
66
     * 
67
     * @param ServerRequestInterface $request
68
     *
69
     * @return ResponseInterface
70
     *
71
     * @throws LogicException on unexpected result from any middleware on the stack
72
     */
73 1
    public function dispatch(ServerRequestInterface $request): ResponseInterface
74
    {
75 1
        return $this->handle($request);
76
    }
77
78
    /**
79
     * @inheritdoc
80
     */
81 1
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
82
    {
83 1
        $this->stack[] = function (ServerRequestInterface $request) use ($handler) {
84 1
            return $handler->handle($request);
85
        };
86
87 1
        $response = $this->dispatch($request);
0 ignored issues
show
Deprecated Code introduced by
The method mindplay\middleman\Dispatcher::dispatch() has been deprecated with message: in favor of identical PSR-15 method `RequestHandlerInterface::handle()`

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
88
89 1
        array_pop($this->stack);
90
91 1
        return $response;
92
    }
93
94
    /**
95
     * @param int $index middleware stack index
96
     *
97
     * @return RequestHandlerInterface
98
     */
99 1
    private function resolve($index): RequestHandlerInterface
100
    {
101 1
        if (isset($this->stack[$index])) {
102 1
            return new Delegate(function (ServerRequestInterface $request) use ($index) {
103 1
                $middleware = $this->resolver
104 1
                    ? call_user_func($this->resolver, $this->stack[$index])
105 1
                    : $this->stack[$index]; // as-is
106
107
                switch (true) {
108 1
                    case $middleware instanceof PsrMiddlewareInterface:
109 1
                    case $middleware instanceof LegacyMiddlewareInterface:
110 1
                        $result = $middleware->process($request, $this->resolve($index + 1));
111 1
                        break;
112
113 1
                    case is_callable($middleware):
114 1
                        $result = $middleware($request, $this->resolve($index + 1));
115 1
                        break;
116
117
                    default:
118
                        $given = readable::callback($middleware);
119
120
                        throw new LogicException("unsupported middleware type: {$given}");
121
                }
122
123 1
                if (! $result instanceof ResponseInterface) {
124 1
                    $given = readable::value($result);
125 1
                    $source = readable::callback($middleware);
126
127 1
                    throw new LogicException("unexpected middleware result: {$given} returned by: {$source}");
128
                }
129
130 1
                return $result;
131 1
            });
132
        }
133
134 1
        return new Delegate(function () {
135 1
            throw new LogicException("unresolved request: middleware stack exhausted with no result");
136 1
        });
137
    }
138
}
139