Passed
Branch master (6a9c31)
by Henri
01:14
created

Router::setOnRoutes()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 3
eloc 4
c 1
b 0
f 1
nc 3
nop 3
dl 0
loc 8
rs 10
1
<?php
2
3
namespace HnrAzevedo\Router;
4
5
use Exception;
6
7
class Router{
8
    use Helper, CheckTrait, CheckWhere, DefinitionsTrait;
9
10
    private static $instance = null;
11
    private array $routers = [];
12
    private ?string $prefix = null;
13
    private ?string $group = null;
14
    private $lastReturn = null;
15
    private $beforeAll = null;
16
    private $afterAll = null;
17
    private array $afterExcepts = [];
18
    private array $beforeExcepts = [];
19
    private bool $instanced = false;
20
21
    public function __construct()
22
    {
23
        return $this;
24
    }
25
26
    public static function create(): Router
27
    {
28
        if(!self::getInstance()->instanced){
29
            self::getInstance()->checkConfig();
30
            self::getInstance()->import(ROUTER_CONFIG['path']);
31
            self::getInstance()->instanced = true;
32
        }
33
        
34
        return self::getInstance();
35
    }
36
37
    public static function getInstance(): Router
38
    {
39
        self::$instance = (is_null(self::$instance)) ? new self() : self::$instance;
40
        return self::$instance;
41
    }
42
43
    public function set($url ,$walking , string $protocol): Router
44
    {
45
        $this->lastReturn = null;
46
        
47
		$url = (substr($url,0,1) !=='/' and strlen($url) > 0) ? "/{$url}" : $url;
48
49
    	foreach($this->routers as $key => $value){
50
    		if( md5($this->prefix . $value['url'] . $value['protocol'] ) === md5( $url . $protocol ) ){
51
                throw new Exception("There is already a route with the url {$url} and with the {$protocol} protocol configured.");
52
            }
53
        }
54
        
55
        $this->checkTypeRole($walking);
56
57
		$route = [
58
			'url' => $this->prefix.$url,
59
			'role' => $walking,
60
			'protocol' => $protocol,
61
            'filters' => null,
62
            'where' => null,
63
            'before' => null,
64
            'beforeAll' => $this->beforeAll,
65
            'after' => null,
66
            'afterAll' => $this->afterAll,
67
            'group' => self::getInstance()->group
68
		];
69
70
		$this->routers[] = $route;		
71
        
72
        return self::getInstance();
73
    }
74
75
    public static function group(string $prefix,$callback): Router
76
    {
77
        self::getInstance()->prefix = (substr($prefix,0,1) !== '/') ? "/{$prefix}" : $prefix;
78
        self::getInstance()->group = sha1(date('d/m/Y h:m:i'));
79
        $callback();
80
        self::getInstance()->group = null;
81
        self::getInstance()->prefix = null;
82
        self::getInstance()->lastReturn = true;
83
        return self::getInstance();
84
    }
85
86
    public static function where(): Router
87
    {
88
        if(self::getInstance()->lastReturn){
89
            throw new Exception("It is not possible to define parameter tests for groups of routes.");
90
        }
91
92
        self::getInstance()->callWhereAdd(func_get_args());
93
94
        return self::getInstance();
95
    }
96
97
    public static function name(string $name): Router
98
    {
99
        if(self::getInstance()->lastReturn){
100
            throw new Exception("There is no reason to call a {$name} route group.");
101
        }
102
103
        $currentRoute = end(self::getInstance()->routers);
104
105
        self::getInstance()->hasRouteName($name);
106
107
        if(in_array($name,self::getInstance()->beforeExcepts)){
108
            $currentRoute['beforeAll'] = null;
109
        }
110
111
        if(in_array($name,self::getInstance()->afterExcepts)){
112
            $currentRoute['afterAll'] = null;
113
        }
114
115
        unset(self::getInstance()->routers[count(self::getInstance()->routers)-1]);
116
        
117
        self::getInstance()->routers[$name] = $currentRoute;
118
119
        return self::getInstance();
120
    }
121
122
    private function byName(?string $routName)
123
    {
124
        if(!is_null($routName)){
125
            $currentProtocol = $this->getProtocol();
126
127
            $this->checkName($routName);
128
    
129
            $route = $this->routers[$routName];
130
    
131
            if(!$this->checkProtocol($route['protocol'], $currentProtocol)){
132
                throw new Exception('Page not found.',404);
133
            }
134
    
135
            $this->checkFiltering($route);
136
    
137
            $this->toHiking($route['role']);
138
            throw true;
139
        }
140
    }
141
142
    public static function dispatch(?string $routeName = null): bool
143
    {
144
        $instance = self::create();
145
146
        $instance->getInstance()->byName($routeName);
147
148
		$currentProtocol = $instance->getInstance()->getProtocol();
149
150
        foreach(array_reverse($instance->getInstance()->routers) as $r => $route){
151
152
            $instance->getInstance()->currentRoute = $route;
153
154
            if(!$instance->getInstance()->checkProtocol($route['protocol'], $currentProtocol)){
155
                continue;
156
            }
157
158
            $instance->getInstance()->hasProtocol($route, $currentProtocol);
159
160
            $_SERVER['REQUEST_URI'] = (array_key_exists('REQUEST_URI', $_SERVER)) ? $_SERVER['REQUEST_URI'] : '';
161
162
163
            $routs = $instance->getInstance()->explodeRoutes(
164
                (substr($route['url'],strlen($route['url'])-1,1) === '/') , $route['url'],
165
                (substr($_SERVER['REQUEST_URI'],strlen($_SERVER['REQUEST_URI'])-1,1) === '/') , $_SERVER['REQUEST_URI']
166
            );
167
168
            if(!$instance->getInstance()->checkToHiking($route, $routs['routeRequest'], $routs['routeLoop'])){
169
                continue;
170
            }
171
172
            $instance->getInstance()->checkFiltering($route);
173
174
            $instance->getInstance()->toHiking($route);
175
            return true;
176
            
177
        }
178
        
179
        $instance->getInstance()->currentRoute = null;
180
181
	    throw new Exception('Page not found.',404);
182
    }
183
184
    public function filter($filters): Router
185
    {
186
        if($this->lastReturn !== null){
187
            $currentGroup = end($this->routers)['group'];
188
189
            foreach ($this->routers as $key => $value) {
190
191
                if($value['group'] === $currentGroup){
192
                    $currentRoute = $this->addFilter($this->routers[$key],$filters);
193
                    $this->routers[$key] = $currentRoute;
194
                }
195
196
            }
197
            
198
            return $this;
199
        }
200
        
201
        $this->routers[count($this->routers)-1] = $this->addFilter(end($this->routers),$filters);
202
        return $this;
203
    }
204
 
205
    public function before($walking): Router
206
    {
207
        return $this->setOnRoute($walking,'before');
208
    }
209
210
    public static function beforeAll($walking, $except = null): Router
211
    {
212
        $excepts = is_array($except) ? $except : [$except];
213
        self::getInstance()->beforeExcepts = $excepts;
214
        self::getInstance()->beforeAll = $walking;
215
        return self::getInstance()->setOnRoutes($walking,'beforeAll',$excepts);
216
    }
217
218
    public function after($walking): Router
219
    {
220
        return $this->setOnRoute($walking,'after');
221
    }
222
223
    public static function afterAll($walking, $except = null): Router
224
    {
225
        $excepts = is_array($except) ? $except : [$except];
226
        self::getInstance()->afterExcepts = $excepts;
227
        self::getInstance()->afterAll = $walking;
228
        return self::getInstance()->setOnRoutes($walking,'afterAll',$excepts);
229
    }
230
231
    private function setOnRoute($walking, string $state): Router
232
    {
233
        if($this->lastReturn !== null){
234
            $currentGroup = end($this->routers)['group'];
235
236
            foreach ($this->routers as $key => $value) {
237
238
                if($value['group'] === $currentGroup){
239
                    $this->routers[$key][$state] = $walking;
240
                }
241
242
            }
243
            return $this;
244
        }
245
        
246
        $this->routers[count($this->routers)-1][$state] = $walking;
247
        return $this;
248
    }
249
250
    private function setOnRoutes($walking, string $state, array $excepts): Router
251
    {
252
        foreach($this->routers as $r => $route){
253
            if(!in_array($this->routers[$r]['name'],$excepts)){
254
                $this->routers[$r][$state] = $walking;
255
            }
256
        }
257
        return $this;
258
    }
259
260
    public static function addFilter(array $route, $filter): array
261
    {
262
        if(is_null($route['filters'])){
263
            $route['filters'] = $filter;
264
            return $route;
265
        }
266
267
        $filters = (is_array($filter)) ? $filter : [0 => $filter];
268
269
        if(is_array($route['filters'])){
270
            foreach ($route['filters'] as $key => $value) {
271
                $filters[] = $value;
272
            }
273
        }else{
274
            $filters[] = $route['filters'];
275
        }
276
277
        $route['filters'] = $filters;
278
        return $route;
279
    }
280
281
}
282