Passed
Push — master ( 1f40d1...402cf9 )
by Alexander
02:17
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 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
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 MiddlewareStackInterface
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
26
    private EventDispatcherInterface $eventDispatcher;
27
28 13
    public function __construct(EventDispatcherInterface $eventDispatcher)
29
    {
30 13
        $this->eventDispatcher = $eventDispatcher;
31 13
    }
32
33 9
    public function build(array $middlewares, RequestHandlerInterface $fallbackHandler): MiddlewareStackInterface
34
    {
35 9
        $handler = $fallbackHandler;
36 9
        foreach ($middlewares as $middleware) {
37 8
            $handler = $this->wrap($middleware, $handler);
38
        }
39
40 9
        $new = clone $this;
41 9
        $new->stack = $handler;
42
43 9
        return $new;
44
    }
45
46 9
    public function handle(ServerRequestInterface $request): ResponseInterface
47
    {
48 9
        if ($this->isEmpty()) {
49 1
            throw new RuntimeException('Stack is empty.');
50
        }
51
52
        /** @psalm-suppress PossiblyNullReference */
53 8
        return $this->stack->handle($request);
54
    }
55
56 11
    public function reset(): void
57
    {
58 11
        $this->stack = null;
59 11
    }
60
61 9
    public function isEmpty(): bool
62
    {
63 9
        return $this->stack === null;
64
    }
65
66
    /**
67
     * Wraps handler by middlewares
68
     */
69 8
    private function wrap(MiddlewareInterface $middleware, RequestHandlerInterface $handler): RequestHandlerInterface
70
    {
71 8
        return new class($middleware, $handler, $this->eventDispatcher) implements RequestHandlerInterface {
72
            private MiddlewareInterface $middleware;
73
            private RequestHandlerInterface $handler;
74
            private EventDispatcherInterface $eventDispatcher;
75
76
            public function __construct(MiddlewareInterface $middleware, RequestHandlerInterface $handler, EventDispatcherInterface $eventDispatcher)
77
            {
78 8
                $this->middleware = $middleware;
79 8
                $this->handler = $handler;
80 8
                $this->eventDispatcher = $eventDispatcher;
81 8
            }
82
83
            public function handle(ServerRequestInterface $request): ResponseInterface
84
            {
85 8
                $this->eventDispatcher->dispatch(new BeforeMiddleware($this->middleware, $request));
86
87 8
                $response = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $response is dead and can be removed.
Loading history...
88
                try {
89 8
                    return $response = $this->middleware->process($request, $this->handler);
90
                } finally {
91 8
                    $this->eventDispatcher->dispatch(new AfterMiddleware($this->middleware, $response));
92
                }
93
            }
94
        };
95
    }
96
}
97