Passed
Push — master ( 8fb003...dae8ba )
by Divine Niiquaye
11:39
created

MiddlewareTrait::addRecursiveMiddleware()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.0416

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 5
c 3
b 0
f 0
dl 0
loc 10
ccs 5
cts 6
cp 0.8333
rs 10
cc 3
nc 3
nop 1
crap 3.0416
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 Psr\Container\NotFoundExceptionInterface;
25
use Psr\Http\Server\MiddlewareInterface;
26
use Psr\Http\Server\RequestHandlerInterface;
27
28
/**
29
 * Provides ability to manage set of middleware.
30
 */
31
trait MiddlewareTrait
32
{
33
    /**
34
     * Set of route middleware to be used in $middlewares
35
     * Stack, if string name is equal to a given middleware.
36
     *
37
     * @var array<string,mixed>
38
     */
39
    protected $nameMiddlewares = [];
40
41
    /**
42
     * Add new middleware(s) at the end of chain.
43
     *
44
     * Example (in bootstrap):
45
     * $this->addMiddleware(new ProxyMiddleware());
46
     *
47
     * @param array<string,mixed>|callable|MiddlewareInterface|RequestHandlerInterface|string ...$middlewares
48
     */
49 40
    public function addMiddleware(...$middlewares): void
50
    {
51 40
        foreach ($middlewares as $middleware) {
52 17
            if (\is_array($middleware) && !\is_callable($middleware)) {
53 3
                $this->addRecursiveMiddleware($middleware);
54
55 3
                continue;
56
            }
57
58 15
            $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

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