Completed
Push — master ( e12411...aa59ce )
by Alexander
02:02
created

MiddlewareDispatcher   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 83
Duplicated Lines 0 %

Test Coverage

Coverage 75%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 29
c 4
b 0
f 0
dl 0
loc 83
ccs 18
cts 24
cp 0.75
rs 10
wmc 12

6 Methods

Rating   Name   Duplication   Size   Complexity  
A add() 0 8 3
A __construct() 0 18 3
A addCallable() 0 3 1
A process() 0 4 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
    public function __construct(
33
        array $middlewares,
34 3
        ContainerInterface $container,
35
        RequestHandlerInterface $nextHandler = null
36
    ) {
37
        if ($middlewares === []) {
38
            throw new \InvalidArgumentException('Middlewares should be defined.');
39 3
        }
40 1
41
        $this->container = $container;
42
43 3
        foreach ($middlewares as $middleware) {
44
            $this->add($middleware);
45 3
        }
46 3
47
        $responseFactory = $container->get(ResponseFactoryInterface::class);
48
49 3
        $this->nextHandler = $nextHandler ?? new NotFoundHandler($responseFactory);
50
    }
51 3
52
    private function addCallable(callable $callback): void
53
    {
54
        $this->middlewares[] = new Callback($callback, $this->container);
55
    }
56
57
    public function add($middleware): void
58
    {
59 3
        if (is_callable($middleware)) {
60
            $this->addCallable($middleware);
61 3
        } elseif ($middleware instanceof MiddlewareInterface) {
62
            $this->middlewares[] = $middleware;
63 3
        } else {
64 3
            throw new \InvalidArgumentException('Middleware should be either callable or MiddlewareInterface instance. ' . get_class($middleware) . ' given.');
65
        }
66 1
    }
67
68
    public function dispatch(ServerRequestInterface $request): ResponseInterface
69
    {
70 1
        reset($this->middlewares);
71
        return $this->handle($request);
72 1
    }
73
74
    /**
75
     * @internal Please use {@see dispatch()} or {@see process()} instead
76 1
     * @param ServerRequestInterface $request
77
     * @return ResponseInterface
78
     */
79
    public function handle(ServerRequestInterface $request): ResponseInterface
80
    {
81
        $middleware = current($this->middlewares);
82
        next($this->middlewares);
83
        if ($middleware === false) {
84
            if (!$this->nextHandler !== null) {
0 ignored issues
show
introduced by
The condition ! $this->nextHandler !== null is always true.
Loading history...
85
                return $this->nextHandler->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

85
                return $this->nextHandler->/** @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...
86
            }
87
88
            throw new \LogicException('Middleware stack exhausted');
89
        }
90 1
91
        return $middleware->process($request, $this);
92 1
    }
93
94
    public function process(ServerRequestInterface $request, RequestHandlerInterface $nextHandler): ResponseInterface
95
    {
96
        $this->nextHandler = $nextHandler;
97
        return $this->dispatch($request);
98
    }
99
}
100