anonymous//src/MiddlewareTrait.php$1   A
last analyzed

Complexity

Total Complexity 3

Size/Duplication

Total Lines 20
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
dl 0
loc 20
rs 10
c 1
b 0
f 1
wmc 3
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace HnrAzevedo\Router;
6
7
use HnrAzevedo\Http\Factory;
8
use HnrAzevedo\Http\ServerRequest;
9
use Psr\Http\Server\RequestHandlerInterface;
10
use Psr\Http\Message\ServerRequestInterface;
11
use Psr\Http\Message\ResponseInterface;
12
13
trait MiddlewareTrait
14
{
15
    use Helper,
16
        CurrentTrait,
17
        RunInTrait;
18
19
    protected array $globalMiddlewares = [];
20
    protected ServerRequest $serverRequest;
21
    protected array $currentMiddlewares = [];
22
23
    public static function globalMiddlewares(?array $middlewares = null): array
24
    {
25
        if(null !== $middlewares) {
26
            foreach($middlewares as $middleware){
27
                if(!class_exists($middleware)) {
28
                    throw new \RuntimeException("Middleware class {$middleware} not exists");
29
                }
30
            }
31
            self::getInstance()->setGlobalMiddlewares($middlewares);
32
        }
33
        return self::getInstance()->getGlobalMiddlewares();
34
    }
35
36
    protected function getGlobalMiddlewares(): array
37
    {
38
        return $this->globalMiddlewares;
39
    }
40
41
    protected function setGlobalMiddlewares(array $middlewares): void
42
    {
43
        $this->globalMiddlewares = $middlewares;
44
    }
45
46
    public static function middleware(array $middlewares): RouterInterface
47
    {
48
        $route = self::getInstance()->inSave();
49
        $route['middlewares'] = (is_array($route['middlewares'])) ? array_merge($route['middlewares'], $middlewares) : $middlewares;
50
        self::getInstance()->updateRoute($route, array_key_last(self::getInstance()->getRoutes()));
51
        return self::getInstance();
52
    }
53
54
    public static function groupMiddlewares(array $middlewares, ?array $excepts = null): RouterInterface
55
    {
56
        $excepts = (is_array($excepts)) ? $excepts : [];
57
        $group = self::getInstance()->inSave()['group'];
58
        foreach(self::getInstance()->getRoutes() as $r => $route){
59
            if($route['group'] !== $group || in_array($route['name'], $excepts)) {
60
                continue;
61
            }
62
63
            $route['middlewares'] = array_merge($route['middlewares'], $middlewares);
64
            self::getInstance()->updateRoute($route, $r);
65
        }
66
        return self::getInstance();
67
    }
68
69
    private static function existMiddleware(string $name): void
70
    {
71
        if(!class_exists($name) && !array_key_exists($name, self::$globalMiddlewares)) {
72
            throw new \RuntimeException("Middleware {$name} does not exist");
73
        }
74
    }
75
76
    protected function handleMiddlewares(): void
77
    {
78
        $factory = new Factory();
79
80
        $requestMethod = (isset($_REQUEST['REQUEST_METHOD'])) ? $_REQUEST['REQUEST_METHOD'] : $_SERVER['REQUEST_METHOD'];
81
82
        $this->serverRequest = (!isset($this->serverRequest)) ? $factory->createServerRequest($requestMethod, unserialize($this->current()['uri']), ['route' => $this->current()]) : $this->serverRequest;
83
        
84
        foreach ($this->current()['middlewares'] as $middleware){
85
            $this->currentMiddlewares[] = (class_exists($middleware)) ? new $middleware() : new $this->globalMiddlewares[$middleware]();
86
        }
87
88
        $this->process(
89
            $this->serverRequest, new class implements RequestHandlerInterface {
90
                public function handle(ServerRequestInterface $request): ResponseInterface
91
                {
92
                    return (new Factory())->createResponse(200);
93
                }
94
            }
95
        );
96
97
    }
98
99
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
100
    {
101
        if(!$this->getInstance()->loaded()) {
102
            $this->getInstance()->load();
103
        }
104
105
        $route = $this->getInstance()->current();
106
        if(!empty($route)) {
107
108
            $route['action'] = function () {
109
                $this->getInstance()->executeBefore();
110
                $this->getInstance()->executeRouteAction(unserialize($this->getInstance()->current()['action']));
111
                $this->getInstance()->executeAfter();
112
            };
113
        }
114
115
        return $this->next($handler)->handle($request->withAttribute('route', $route));
116
    }
117
118
    private function next(RequestHandlerInterface $defaultHandler): RequestHandlerInterface
119
    {
120
        return new class ($this->currentMiddlewares, $defaultHandler) implements RequestHandlerInterface {
121
            private RequestHandlerInterface $handler;
122
            private array $pipeline;
123
124
            public function __construct(array $pipeline, RequestHandlerInterface $handler)
125
            {
126
                $this->handler = $handler;
127
                $this->pipeline = $pipeline;
128
            }
129
130
            public function handle(ServerRequestInterface $request): ResponseInterface
131
            {
132
                if (!$middleware = array_shift($this->pipeline)) {
133
                    return $this->handler->handle($request);
134
                }
135
136
                $next = clone $this;
137
                $this->pipeline = [];
138
139
                return $middleware->process($request, $next);
140
            }
141
        };
142
    }
143
    
144
}
145