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

MiddlewareDispatcher   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 83
Duplicated Lines 0 %

Test Coverage

Coverage 70%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 29
dl 0
loc 83
ccs 21
cts 30
cp 0.7
rs 10
c 4
b 0
f 0
wmc 12

6 Methods

Rating   Name   Duplication   Size   Complexity  
A add() 0 8 3
A __construct() 0 18 3
A process() 0 4 1
A addCallable() 0 3 1
A handle() 0 13 3
A dispatch() 0 4 1
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