Passed
Pull Request — master (#186)
by Alexander
09:08 queued 07:04
created

MiddlewareDispatcher::isLastMiddlewareCalled()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 0
cp 0
crap 2
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()} or {@see process()} instead
78
     * @param ServerRequestInterface $request
79
     * @return ResponseInterface
80
     */
81
    public function handle(ServerRequestInterface $request): ResponseInterface
82
    {
83
        if ($this->isLastMiddlewareCalled()) {
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 $this->middlewares[$this->pointer++]->process($request, $this);
92 1
    }
93
94
    /**
95
     * Last middleware in the queue has been called on the request handler
96
     */
97
    private function isLastMiddlewareCalled(): bool
98
    {
99
        return $this->pointer === \count($this->middlewares);
100
    }
101
102
    public function process(ServerRequestInterface $request, RequestHandlerInterface $nextHandler): ResponseInterface
103
    {
104
        $this->nextHandler = $nextHandler;
105
        return $this->dispatch($request);
106
    }
107
}
108