Completed
Pull Request — master (#188)
by Alexander
04:45
created

MiddlewareDispatcher::dispatch()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
namespace Yiisoft\Yii\Web;
3
4
use Psr\Container\ContainerInterface;
5
use Psr\Http\Message\ResponseFactoryInterface;
6
use Psr\Http\Message\ResponseInterface;
7
use Psr\Http\Message\ServerRequestInterface;
8
use Psr\Http\Server\MiddlewareInterface;
9
use Psr\Http\Server\RequestHandlerInterface;
10
use Yiisoft\Yii\Web\Middleware\Callback;
11
12
/**
13
 * MiddlewareDispatcher
14
 */
15
final class MiddlewareDispatcher implements RequestHandlerInterface, MiddlewareInterface
16
{
17
    /**
18
     * @var MiddlewareInterface[]
19
     */
20
    private $middlewares = [];
21
22
    /**
23
     * @var RequestHandlerInterface|null
24
     */
25
    private $nextHandler;
26
27
    /**
28
     * @var ContainerInterface
29
     */
30
    private $container;
31
32 3
    public function __construct(
33
        array $middlewares,
34
        ContainerInterface $container,
35
        RequestHandlerInterface $nextHandler = null
36
    ) {
37 3
        if ($middlewares === []) {
38 1
            throw new \InvalidArgumentException('Middlewares should be defined.');
39
        }
40
41 3
        $this->container = $container;
42
43 3
        foreach ($middlewares as $middleware) {
44 3
            $this->add($middleware);
45
        }
46
47 3
        $responseFactory = $container->get(ResponseFactoryInterface::class);
48
49 3
        $this->nextHandler = $nextHandler ?? new NotFoundHandler($responseFactory);
50
    }
51
52
    private function addCallable(callable $callback): void
53
    {
54
        $this->middlewares[] = new Callback($callback, $this->container);
55
    }
56
57 3
    public function add($middleware): void
58
    {
59 3
        if (is_callable($middleware)) {
60
            $this->addCallable($middleware);
61 3
        } elseif ($middleware instanceof MiddlewareInterface) {
62 3
            $this->middlewares[] = $middleware;
63
        } else {
64 1
            throw new \InvalidArgumentException('Middleware should be either callable or MiddlewareInterface instance. ' . get_class($middleware) . ' given.');
65
        }
66
    }
67
68 1
    public function dispatch(ServerRequestInterface $request): ResponseInterface
69
    {
70 1
        reset($this->middlewares);
71 1
        return $this->handle($request);
72
    }
73
74
    /**
75
     * @internal Please use {@see dispatch()} or {@see process()} instead
76
     * @param ServerRequestInterface $request
77
     * @return ResponseInterface
78
     */
79 1
    public function handle(ServerRequestInterface $request): ResponseInterface
80
    {
81 1
        $middleware = current($this->middlewares);
82 1
        next($this->middlewares);
83 1
        if ($middleware === false) {
84
            if ($this->nextHandler !== null) {
85
                return $this->nextHandler->handle($request);
86
            }
87
88
            throw new \LogicException('Middleware stack exhausted');
89
        }
90
91 1
        return $middleware->process($request, $this);
92
    }
93
94
    public function process(ServerRequestInterface $request, RequestHandlerInterface $nextHandler): ResponseInterface
95
    {
96
        $this->nextHandler = $nextHandler;
97
        return $this->dispatch($request);
98
    }
99
}
100