Passed
Branch master (72124e)
by Henri
03:20 queued 01:53
created

MiddlewareTrait::getGlobalMiddlewares()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

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
rs 10
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, array_key_last(self::getInstance()->getRoutes()));
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
        $this->serverRequest = (!isset($this->serverRequest)) ? $factory->createServerRequest($_SERVER['REQUEST_METHOD'], unserialize($this->current()['uri']),['route' => $this->current()]) : $this->serverRequest;
81
        
82
        foreach ($this->current()['middlewares'] as $middleware){
83
            $this->currentMiddlewares[] = (class_exists($middleware)) ? new $middleware() : new $this->globalMiddlewares[$middleware]();
84
        }
85
86
        $this->process($this->serverRequest, new class implements RequestHandlerInterface {
87
            public function handle(ServerRequestInterface $request): ResponseInterface
88
            {
89
                return (new Factory())->createResponse(200);
90
            }
91
        });
92
93
    }
94
95
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
96
    {
97
        if(!$this->getInstance()->loaded()){
98
            $this->getInstance()->load();
99
        }
100
101
        $route = $this->getInstance()->current();
102
        if(!empty($route)){
103
            $route['action'] = function(){
104
                $this->getInstance()->executeBefore();
105
                $this->getInstance()->executeRouteAction($this->getInstance()->current()['action']);
106
                $this->getInstance()->executeAfter();
107
            };
108
        }
109
110
        return $this->next($handler)->handle($request->withAttribute('route',$route));
111
    }
112
113
    private function next(RequestHandlerInterface $defaultHandler): RequestHandlerInterface
114
    {
115
        return new class ($this->currentMiddlewares, $defaultHandler) implements RequestHandlerInterface {
116
            private RequestHandlerInterface $handler;
117
            private array $pipeline;
118
119
            public function __construct(array $pipeline, RequestHandlerInterface $handler)
120
            {
121
                $this->handler = $handler;
122
                $this->pipeline = $pipeline;
123
            }
124
125
            public function handle(ServerRequestInterface $request): ResponseInterface
126
            {
127
                if (!$middleware = array_shift($this->pipeline)) {
128
                    return $this->handler->handle($request);
129
                }
130
131
                $next = clone $this;
132
                $this->pipeline = [];
133
134
                return $middleware->process($request, $next);
135
            }
136
        };
137
    }
138
    
139
}
140