Test Failed
Push — master ( d3660e...c7a4a9 )
by Divine Niiquaye
10:08
created

MiddlewareTrait   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 105
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 5
Bugs 0 Features 0
Metric Value
wmc 20
eloc 32
c 5
b 0
f 0
dl 0
loc 105
rs 10
ccs 25
cts 25
cp 1

4 Methods

Rating   Name   Duplication   Size   Complexity  
B resolveMiddleware() 0 27 9
A addMiddleware() 0 10 4
A addRecursiveMiddleware() 0 10 3
A resolveMiddlewares() 0 15 4
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Flight Routing.
7
 *
8
 * PHP version 7.1 and above required
9
 *
10
 * @author    Divine Niiquaye Ibok <[email protected]>
11
 * @copyright 2019 Biurad Group (https://biurad.com/)
12
 * @license   https://opensource.org/licenses/BSD-3-Clause License
13
 *
14
 * For the full copyright and license information, please view the LICENSE
15
 * file that was distributed with this source code.
16
 */
17
18
namespace Flight\Routing\Traits;
19
20
use Flight\Routing\Exceptions\InvalidMiddlewareException;
21
use Flight\Routing\Route;
22
use Laminas\Stratigility\Middleware\CallableMiddlewareDecorator;
23
use Laminas\Stratigility\Middleware\RequestHandlerMiddleware;
24
use Laminas\Stratigility\MiddlewarePipeInterface;
25
use Psr\Container\NotFoundExceptionInterface;
26
use Psr\Http\Server\MiddlewareInterface;
27
use Psr\Http\Server\RequestHandlerInterface;
28
29
/**
30
 * Provides ability to manage set of middleware.
31
 */
32
trait MiddlewareTrait
33
{
34
    /**
35
     * Set of route middleware to be used in $middlewares
36
     * Stack, if string name is equal to a given middleware.
37
     *
38
     * @var array<string,mixed>
39
     */
40
    protected $nameMiddlewares = [];
41
42
    /**
43
     * Add new middleware(s) at the end of chain.
44
     *
45
     * Example (in bootstrap):
46
     * $this->addMiddleware(new ProxyMiddleware());
47
     *
48
     * @param array<string,mixed>|callable|MiddlewareInterface|RequestHandlerInterface|string ...$middlewares
49
     */
50
    public function addMiddleware(...$middlewares): void
51
    {
52
        foreach ($middlewares as $middleware) {
53
            if (\is_array($middleware) && !\is_callable($middleware)) {
54
                $this->addRecursiveMiddleware($middleware);
55 20
56
                continue;
57 20
            }
58 20
59 4
            $this->pipe($middleware);
0 ignored issues
show
Bug introduced by
It seems like pipe() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

59
            $this->/** @scrutinizer ignore-call */ 
60
                   pipe($middleware);
Loading history...
60
        }
61 4
    }
62
63
    /**
64 17
     * @param array<int|string,mixed> $middlewares
65
     */
66 17
    protected function addRecursiveMiddleware(array $middlewares): void
67 1
    {
68
        foreach ($middlewares as $index => $middleware) {
69
            if (\is_string($index)) {
70 17
                $this->nameMiddlewares[$index] = $middleware;
71
72 20
                continue;
73
            }
74
75
            $this->addMiddleware($middleware);
76
        }
77
    }
78
79 39
    /**
80
     * Add a new middleware to the stack.
81 39
     *
82
     * Middleware are organized as a stack. That means middleware
83
     * that have been added before will be executed after the newly
84
     * added one (last in, first out).
85
     *
86
     * @param mixed $middleware
87 4
     *
88
     * @throws InvalidMiddlewareException if argument is not one of
89 4
     *                                    the specified types
90 4
     *
91 4
     * @return MiddlewareInterface
92
     */
93 4
    private function resolveMiddleware($middleware): MiddlewareInterface
94
    {
95
        if (\is_string($middleware) && null !== $container = $this->resolver->getContainer()) {
96 1
            try {
97
                $middleware = $container->get($middleware);
98 4
            } catch (NotFoundExceptionInterface $e) {
99
                // ... handled at the end
100
            }
101
        }
102
103
        if (\is_string($middleware) && \class_exists($middleware)) {
104
            $middleware = new $middleware();
105 17
        }
106
107 17
        if ($middleware instanceof RequestHandlerInterface) {
108 17
            return new RequestHandlerMiddleware($middleware);
109
        }
110
111 3
        if (\is_callable($middleware)) {
112 1
            return new CallableMiddlewareDecorator($middleware);
113
        }
114
115 3
        if (!$middleware instanceof MiddlewareInterface) {
116
            throw InvalidMiddlewareException::forMiddleware($middleware);
117
        }
118
119
        return $middleware;
120
    }
121
122
    private function resolveMiddlewares(MiddlewarePipeInterface $pipeline, Route $route): MiddlewarePipeInterface
123
    {
124
        $middlewares = $route->getMiddlewares();
125
126
        foreach ($middlewares as $middleware) {
127
            if (\is_string($middleware) && isset($this->nameMiddlewares[$middleware])) {
128
                $pipeline->pipe($this->resolveMiddleware($this->nameMiddlewares[$middleware]));
129
130
                continue;
131
            }
132
133
            $pipeline->pipe($this->resolveMiddleware($middleware));
134
        }
135
136
        return $pipeline;
137
    }
138
}
139