Passed
Push — master ( 5762bf...48d630 )
by Alexander
04:11 queued 01:44
created

MiddlewareStack::reset()   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 2
Bugs 0 Features 0
Metric Value
eloc 1
c 2
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Middleware\Dispatcher;
6
7
use Psr\EventDispatcher\EventDispatcherInterface;
8
use Psr\Http\Message\ResponseInterface;
9
use Psr\Http\Message\ServerRequestInterface;
10
use Psr\Http\Server\MiddlewareInterface;
11
use Psr\Http\Server\RequestHandlerInterface;
12
use RuntimeException;
13
use Yiisoft\Middleware\Dispatcher\Event\AfterMiddleware;
14
use Yiisoft\Middleware\Dispatcher\Event\BeforeMiddleware;
15
16
final class MiddlewareStack implements RequestHandlerInterface
17
{
18
    /**
19
     * Contains a stack of middleware wrapped in handlers.
20
     * Each handler points to the handler of middleware that will be processed next.
21
     *
22
     * @var RequestHandlerInterface|null stack of middleware
23
     */
24
    private ?RequestHandlerInterface $stack = null;
25
    private EventDispatcherInterface $eventDispatcher;
26
    private RequestHandlerInterface $fallbackHandler;
27
    private array $middlewares;
28
29
    /**
30
     * @param MiddlewareInterface[] $middlewares Middlewares.
31
     * @param RequestHandlerInterface $fallbackHandler Fallback handler
32
     * @param EventDispatcherInterface $eventDispatcher Event dispatcher to use for triggering before/after middleware
33
     * events.
34
     */
35 8
    public function __construct(array $middlewares, RequestHandlerInterface $fallbackHandler, EventDispatcherInterface $eventDispatcher)
36
    {
37 8
        if ($middlewares === []) {
38 1
            throw new RuntimeException('Stack is empty.');
39
        }
40
41 7
        $this->middlewares = $middlewares;
42 7
        $this->fallbackHandler = $fallbackHandler;
43 7
        $this->eventDispatcher = $eventDispatcher;
44 7
    }
45
46 7
    public function handle(ServerRequestInterface $request): ResponseInterface
47
    {
48 7
        if ($this->stack === null) {
49 7
            $this->build();
50
        }
51
52
        /** @psalm-suppress PossiblyNullReference */
53 7
        return $this->stack->handle($request);
0 ignored issues
show
Bug introduced by
The method handle() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

53
        return $this->stack->/** @scrutinizer ignore-call */ handle($request);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
54
    }
55
56 7
    private function build(): void
57
    {
58 7
        $handler = $this->fallbackHandler;
59
60
        /** @var  MiddlewareInterface $middleware */
61 7
        foreach ($this->middlewares as $middleware) {
62 7
            $handler = $this->wrap($middleware, $handler);
63
        }
64
65 7
        $this->stack = $handler;
66 7
    }
67
68
    /**
69
     * Wrap handler by middlewares.
70
     */
71 7
    private function wrap(MiddlewareInterface $middleware, RequestHandlerInterface $handler): RequestHandlerInterface
72
    {
73 7
        return new class($middleware, $handler, $this->eventDispatcher) implements RequestHandlerInterface {
74
            private MiddlewareInterface $middleware;
75
            private RequestHandlerInterface $handler;
76
            private EventDispatcherInterface $eventDispatcher;
77
78
            public function __construct(
79
                MiddlewareInterface $middleware,
80
                RequestHandlerInterface $handler,
81
                EventDispatcherInterface $eventDispatcher
82
            ) {
83 7
                $this->middleware = $middleware;
84 7
                $this->handler = $handler;
85 7
                $this->eventDispatcher = $eventDispatcher;
86 7
            }
87
88
            public function handle(ServerRequestInterface $request): ResponseInterface
89
            {
90 7
                $this->eventDispatcher->dispatch(new BeforeMiddleware($this->middleware, $request));
91
92
                try {
93 7
                    return $response = $this->middleware->process($request, $this->handler);
94
                } finally {
95 7
                    $this->eventDispatcher->dispatch(new AfterMiddleware($this->middleware, $response ?? null));
96
                }
97
            }
98
        };
99
    }
100
}
101