Test Failed
Pull Request — master (#28)
by Alexander
01:59
created

MiddlewareStack::isEmpty()   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 InvalidArgumentException;
8
use Psr\EventDispatcher\EventDispatcherInterface;
9
use Psr\Http\Message\ResponseInterface;
10
use Psr\Http\Message\ServerRequestInterface;
11
use Psr\Http\Server\MiddlewareInterface;
12
use Psr\Http\Server\RequestHandlerInterface;
13
use Yiisoft\Middleware\Dispatcher\Event\AfterMiddleware;
14
use Yiisoft\Middleware\Dispatcher\Event\BeforeMiddleware;
15
16
final class MiddlewareStack implements MiddlewarePipelineInterface
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
    private array $middlewares;
29
    private RequestHandlerInterface $fallbackHandler;
30
31
    /**
32 12
     * @param EventDispatcherInterface $eventDispatcher Event dispatcher to use for triggering before/after middleware
33
     * events.
34 12
     */
35 12
    public function __construct(array $middlewares, RequestHandlerInterface $fallbackHandler, EventDispatcherInterface $eventDispatcher)
36
    {
37 8
        if ($middlewares === []) {
38
            throw new InvalidArgumentException('No middleware defined.');
39 8
        }
40 8
41 7
        $this->eventDispatcher = $eventDispatcher;
42
        $this->middlewares = $middlewares;
43
        $this->fallbackHandler = $fallbackHandler;
44 8
    }
45 8
46
    private function build(): MiddlewarePipelineInterface
47 8
    {
48
        $handler = $this->fallbackHandler;
49
        foreach ($this->middlewares as $middleware) {
50 8
            $handler = $this->wrap($middleware, $handler);
51
        }
52 8
53 1
        $new = clone $this;
54
        $new->stack = $handler;
55
56
        return $new;
57 7
    }
58
59
    public function handle(ServerRequestInterface $request): ResponseInterface
60
    {
61
        if ($this->stack === null) {
62
            $this->build();
63 10
        }
64
65 10
        /** @psalm-suppress PossiblyNullReference */
66 10
        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

66
        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...
67
    }
68
69
    /**
70
     * Reset the stack.
71 8
     */
72
    public function reset(): void
73 8
    {
74
        $this->stack = null;
75
    }
76
77
    /**
78
     * Wrap handler by middlewares.
79 7
     */
80
    private function wrap(MiddlewareInterface $middleware, RequestHandlerInterface $handler): RequestHandlerInterface
81 7
    {
82
        return new class($middleware, $handler, $this->eventDispatcher) implements RequestHandlerInterface {
83
            private MiddlewareInterface $middleware;
84
            private RequestHandlerInterface $handler;
85
            private EventDispatcherInterface $eventDispatcher;
86
87
            public function __construct(MiddlewareInterface $middleware, RequestHandlerInterface $handler, EventDispatcherInterface $eventDispatcher)
88 7
            {
89 7
                $this->middleware = $middleware;
90 7
                $this->handler = $handler;
91 7
                $this->eventDispatcher = $eventDispatcher;
92
            }
93
94
            public function handle(ServerRequestInterface $request): ResponseInterface
95 7
            {
96
                $this->eventDispatcher->dispatch(new BeforeMiddleware($this->middleware, $request));
97
98 7
                try {
99
                    return $response = $this->middleware->process($request, $this->handler);
100 7
                } finally {
101
                    $this->eventDispatcher->dispatch(new AfterMiddleware($this->middleware, $response ?? null));
102
                }
103
            }
104
        };
105
    }
106
}
107