Completed
Pull Request — master (#186)
by Alexander
02:08
created

MiddlewareDispatcher::dispatch()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1.037

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 4
ccs 2
cts 3
cp 0.6667
crap 1.037
rs 10
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
    private $pointer = 0;
18
19
    /**
20
     * @var MiddlewareInterface[]
21
     */
22
    private $middlewares = [];
23
24
    /**
25
     * @var RequestHandlerInterface|null
26
     */
27
    private $nextHandler;
28
29
    /**
30
     * @var ContainerInterface
31
     */
32
    private $container;
33
34 3
    public function __construct(
35
        array $middlewares,
36
        ContainerInterface $container,
37
        RequestHandlerInterface $nextHandler = null
38
    ) {
39 3
        if ($middlewares === []) {
40 1
            throw new \InvalidArgumentException('Middlewares should be defined.');
41
        }
42
43 3
        $this->container = $container;
44
45 3
        foreach ($middlewares as $middleware) {
46 3
            $this->add($middleware);
47
        }
48
49 3
        $responseFactory = $container->get(ResponseFactoryInterface::class);
50
51 3
        $this->nextHandler = $nextHandler ?? new NotFoundHandler($responseFactory);
52
    }
53
54
    private function addCallable(callable $callback): void
55
    {
56
        $this->middlewares[] = new Callback($callback, $this->container);
57
    }
58
59 3
    public function add($middleware): void
60
    {
61 3
        if (is_callable($middleware)) {
62
            $this->addCallable($middleware);
63 3
        } elseif ($middleware instanceof MiddlewareInterface) {
64 3
            $this->middlewares[] = $middleware;
65
        } else {
66 1
            throw new \InvalidArgumentException('Middleware should be either callable or MiddlewareInterface instance. ' . get_class($middleware) . ' given.');
67
        }
68
    }
69
70 1
    public function dispatch(ServerRequestInterface $request): ResponseInterface
71
    {
72 1
        $this->pointer = 0;
73
        return $this->handle($request);
74
    }
75
76 1
    /**
77
     * @internal Please use {@see dispatch()} instead
78
     * @param ServerRequestInterface $request
79
     * @return ResponseInterface
80
     */
81
    public function handle(ServerRequestInterface $request): ResponseInterface
82
    {
83
        if ($this->isLastMiddlewareCalled()) {
84
            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

84
            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...
85
        }
86
87
        return $this->middlewares[$this->pointer++]->process($request, $this);
88
    }
89
90 1
    /**
91
     * Last middleware in the queue has been called on the request handler
92 1
     */
93
    private function isLastMiddlewareCalled(): bool
94
    {
95
        return $this->pointer === \count($this->middlewares);
96
    }
97
98
    public function process(ServerRequestInterface $request, RequestHandlerInterface $nextHandler): ResponseInterface
99
    {
100
        $this->nextHandler = $nextHandler;
101
        return $this->dispatch($request);
102
    }
103
}
104