Passed
Pull Request — master (#22)
by Evgeniy
07:40
created

MiddlewarePipeline::__construct()   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 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 1
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 MiddlewarePipeline implements MiddlewarePipelineInterface
17
{
18
    /**
19
     * Contains a middleware pipeline wrapped in handlers.
20
     * Each handler points to the handler of middleware that will be processed next.
21
     *
22
     * @var RequestHandlerInterface|null The middleware pipeline.
23
     */
24
    private ?RequestHandlerInterface $pipeline = null;
25
26
    private EventDispatcherInterface $eventDispatcher;
27
28 9
    public function __construct(EventDispatcherInterface $eventDispatcher)
29
    {
30 9
        $this->eventDispatcher = $eventDispatcher;
31 9
    }
32
33 8
    public function build(array $middlewares, RequestHandlerInterface $fallbackHandler): self
34
    {
35 8
        $handler = $fallbackHandler;
36
37 8
        foreach (array_reverse($middlewares) as $middleware) {
38 7
            $handler = $this->wrap($middleware, $handler);
39
        }
40
41 8
        $new = clone $this;
42 8
        $new->pipeline = $handler;
43
44 8
        return $new;
45
    }
46
47 8
    public function handle(ServerRequestInterface $request): ResponseInterface
48
    {
49 8
        if ($this->pipeline === null) {
50 1
            throw new RuntimeException('Pipeline is empty.');
51
        }
52
53 7
        return $this->pipeline->handle($request);
54
    }
55
56
    /**
57
     * Wraps handler by middlewares.
58
     */
59 7
    private function wrap(MiddlewareInterface $middleware, RequestHandlerInterface $handler): RequestHandlerInterface
60
    {
61 7
        return new class($middleware, $handler, $this->eventDispatcher) implements RequestHandlerInterface {
62
            private MiddlewareInterface $middleware;
63
            private RequestHandlerInterface $handler;
64
            private EventDispatcherInterface $eventDispatcher;
65
66
            public function __construct(MiddlewareInterface $middleware, RequestHandlerInterface $handler, EventDispatcherInterface $eventDispatcher)
67
            {
68 7
                $this->middleware = $middleware;
69 7
                $this->handler = $handler;
70 7
                $this->eventDispatcher = $eventDispatcher;
71 7
            }
72
73
            public function handle(ServerRequestInterface $request): ResponseInterface
74
            {
75 7
                $this->eventDispatcher->dispatch(new BeforeMiddleware($this->middleware, $request));
76
77
                try {
78 7
                    return $response = $this->middleware->process($request, $this->handler);
79
                } finally {
80 7
                    $this->eventDispatcher->dispatch(new AfterMiddleware($this->middleware, $response ?? null));
81
                }
82
            }
83
        };
84
    }
85
}
86