Passed
Push — master ( 022aa2...8d4f2f )
by Henri
04:23 queued 47s
created

MiddlewareTrait.php$0 ➔ handleMiddlewares()   A

Complexity

Conditions 1

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A MiddlewareTrait.php$0 ➔ handle() 0 3 1
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): RouterInterface
24
    {
25
        foreach($middlewares as $middleware){
26
            if(!class_exists($middleware)){
27
                throw new \RuntimeException("Middleware class {$middleware} not exists");
28
            }
29
        }
30
        self::getInstance()->setGlobalMiddlewares($middlewares);
31
        return self::getInstance();
32
    }
33
34
    protected function setGlobalMiddlewares(array $middlewares): void
35
    {
36
        $this->globalMiddlewares = $middlewares;
37
    }
38
39
    public static function middleware(array $middlewares): RouterInterface
40
    {
41
        $route = self::getInstance()->inSave();
42
        $route['middlewares'] = (is_array($route['middlewares'])) ? array_merge($route['middlewares'],$middlewares) : $middlewares;
43
        self::getInstance()->updateRoute($route,array_key_last(self::getInstance()->getRoutes()));
44
        return self::getInstance();
45
    }
46
47
    public static function groupMiddlewares(array $middlewares, array $excepts): RouterInterface
48
    {
49
        $group = self::getInstance()->inSave()['group'];
50
        foreach(self::getInstance()->getRoutes() as $r => $route){
51
            if($route['group'] !== $group || in_array($route['name'], $excepts)){
52
                continue;
53
            }
54
55
            $route['middlewares'] = array_merge($route['middlewares'], $middlewares);
56
            self::getInstance()->updateRoute($route, array_key_last(self::getInstance()->getRoutes()));
57
        }
58
        return self::getInstance();
59
    }
60
61
    private static function existMiddleware(string $name): void
62
    {
63
        if(!class_exists($name) && !array_key_exists($name,self::$globalMiddlewares)){
64
            throw new \RuntimeException("Middleware {$name} does not exist");
65
        }
66
    }
67
68
    protected function handleMiddlewares(): void
69
    {
70
        $factory = new Factory();
71
72
        $this->serverRequest = (!isset($this->serverRequest)) ? $factory->createServerRequest($_SERVER['REQUEST_METHOD'], $this->current()['uri'],['route' => $this->current()]) : $this->serverRequest;
73
        
74
        foreach ($this->current()['middlewares'] as $middleware){
75
            $this->currentMiddlewares[] = (class_exists($middleware)) ? new $middleware() : new $this->globalMiddlewares[$middleware]();
76
        }
77
78
        $this->process($this->serverRequest, new class implements RequestHandlerInterface {
79
            public function handle(ServerRequestInterface $request): ResponseInterface
80
            {
81
                return (new Factory())->createResponse(200);
82
            }
83
        });
84
85
    }
86
87
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
88
    {
89
        if(!$this->getInstance()->loaded()){
90
            $this->getInstance()->load();
91
        }
92
93
        $route = $this->getInstance()->current();
94
        if(!empty($route)){
95
            $route['action'] = function(){
96
                $this->getInstance()->executeBefore();
97
                $this->getInstance()->executeRouteAction($this->getInstance()->current()['action']);
98
                $this->getInstance()->executeAfter();
99
            };
100
        }
101
102
        return $this->next($handler)->handle($request->withAttribute('route',$route));
103
    }
104
105
    private function next(RequestHandlerInterface $defaultHandler): RequestHandlerInterface
106
    {
107
        return new class ($this->currentMiddlewares, $defaultHandler) implements RequestHandlerInterface {
108
            private RequestHandlerInterface $handler;
109
            private array $pipeline;
110
111
            public function __construct(array $pipeline, RequestHandlerInterface $handler)
112
            {
113
                $this->handler = $handler;
114
                $this->pipeline = $pipeline;
115
            }
116
117
            public function handle(ServerRequestInterface $request): ResponseInterface
118
            {
119
                if (!$middleware = array_shift($this->pipeline)) {
120
                    return $this->handler->handle($request);
121
                }
122
123
                $next = clone $this;
124
                $this->pipeline = [];
125
126
                return $middleware->process($request, $next);
127
            }
128
        };
129
    }
130
    
131
}
132