Passed
Push — master ( 388b38...3472d9 )
by Henri
01:19
created

Router::addFilter()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 11
c 1
b 0
f 0
nc 5
nop 2
dl 0
loc 19
rs 9.6111
1
<?php
2
3
namespace HnrAzevedo\Router;
4
5
use HnrAzevedo\Validator\Validator;
6
7
use Exception;
8
9
class Router{
10
    use Helper;
11
12
    private static $instance = null;
13
    private array $routers = [];
14
    private ?string $prefix = null;
15
    private $protocol = null;
0 ignored issues
show
introduced by
The private property $protocol is not used, and could be removed.
Loading history...
16
    private $filtersSet = null;
0 ignored issues
show
introduced by
The private property $filtersSet is not used, and could be removed.
Loading history...
17
    private $filter = null;
18
    private $group = false;
19
    private $lastReturn = null;
20
21
    public function __construct()
22
    {
23
        return $this;
24
    }
25
26
    public static function create(): Router
27
    {
28
        if(!defined('ROUTER_CONFIG')){
29
            throw new Exception("Information for loading routes has not been defined.");
30
        }
31
        
32
        self::import(ROUTER_CONFIG['path']);
33
        return self::getInstance();
34
    }
35
36
    public static function getInstance(): Router
37
    {
38
        if(is_null(self::$instance)){
39
            self::$instance = new self();
40
        }
41
        return self::$instance;
42
    }
43
44
    private static function import(string $path): Router
45
    {
46
        foreach (scandir($path) as $routeFile) {
47
            if(pathinfo($path.DIRECTORY_SEPARATOR.$routeFile, PATHINFO_EXTENSION) === 'php'){
48
                require_once($path. DIRECTORY_SEPARATOR .$routeFile);
49
            }
50
        }
51
52
        return self::getInstance();
53
    }
54
55
    public static function form(string $uri, string $controll): Router
56
    {
57
        return self::getInstance()->add($uri, $controll, 'form');
58
    }
59
60
    public static function get(string $uri, string $controll): Router
61
    {
62
        return self::getInstance()->add($uri, $controll, 'get');
63
    }
64
65
    public static function post(string $uri, string $controll): Router
66
    {
67
        return self::getInstance()->add($uri, $controll, 'post');
68
    }
69
70
    public static function ajax(string $uri, string $controll): Router
71
    {
72
        return self::getInstance()->add($uri, $controll, 'ajax');
73
    }
74
75
    public static function add(string $uri, string $controll, string $protocol): Router
76
    {
77
        return self::getInstance()->set($uri, $controll, $protocol);
78
    }
79
80
    public function set($url , $role , $protocol = null): Router
81
    {
82
		$url = (substr($url,0,1) !=='/' and strlen($url) > 0) ? "/{$url}" : $url;
83
84
    	foreach($this->routers as $key => $value){
85
    		if( md5($this->prefix . $value['url'] . $value['protocol'] ) === md5( $url . $protocol ) ){
86
                throw new Exception("There is already a route with the url {$url} and with the {$protocol} protocol configured.");
87
            }
88
    	}
89
90
		$route = [
91
			'url' => $this->prefix.$url,
92
			'role' => $role,
93
			'protocol' => $protocol,
94
			'filters' => null,
95
            'group' => self::getInstance()->group
96
		];
97
98
		$this->routers[] = $route;		
99
        
100
        return self::getInstance();
101
    }
102
103
    public static function group(string $prefix,$callback): Router
104
    {
105
        self::getInstance()->prefix = (substr($prefix,0,1) !== '/') ? "/{$prefix}" : $prefix;
106
        self::getInstance()->group = sha1(date('d/m/Y h:m:i'));
107
        $callback();
108
        self::getInstance()->group = null;
109
        self::getInstance()->prefix = null;
110
        self::getInstance()->lastReturn = true;
111
        return self::getInstance();
112
    }
113
114
    public static function name(string $name): Router
115
    {
116
117
        if(self::getInstance()->lastReturn){
118
            throw new Exception("There is no reason to call a {$name} route group.");
119
        }
120
121
        $currentRoute = end(self::getInstance()->routers);
122
123
        foreach(self::getInstance()->routers as $key => $value){
124
            if(array_key_exists($name, self::getInstance()->routers)){
125
                throw new Exception("There is already a route with the name {$name} configured.");
126
            }
127
        }
128
129
        $currentRoute['name'] = $name;
130
131
        self::getInstance()->routers[count(self::getInstance()->routers)-1] = $currentRoute;
132
133
        self::getInstance()->lastReturn = null;
134
135
        return self::getInstance();
136
    }
137
138
    public function byName(string $route_name)
139
    {
140
        $currentProtocol = $this->getProtocol();
141
142
        if(!array_key_exists($route_name,$this->routers)){
143
            throw new Exception('Page not found.'.$route_name,404);
144
        }
145
146
        $route = $this->routers[$route_name];
147
148
        if($route['protocol']!==$currentProtocol){
149
            throw new Exception('Page not found.'.$route_name,404);
150
        }
151
152
        if(!empty($route['filters'])){
153
            if(is_array($route['filters'])){
154
                foreach($route['filters'] as $filter){
155
                    $this->filter->filtering($filter);
156
                }
157
            }else{
158
                $this->filter->filtering($route['filters']);
159
            }
160
        }
161
162
        $this->Controller($route['role']);
163
        return true;
164
    }
165
166
    public function dispatch(?string $route_name = null): bool
167
    {
168
        if(!is_null($route_name)){
169
            return $this->byName($route_name);
170
        }
171
172
		$currentProtocol = $this->getProtocol();
173
174
        foreach(array_reverse($this->routers) as $r => $route){
175
            if(is_array($route['protocol'])){
176
                foreach($route['protocol'] as $protocol){
177
                    if($protocol !== $currentProtocol){
178
                        continue;
179
                    }
180
                }
181
	        }else{
182
				if($route['protocol'] !== $currentProtocol){
183
                    continue;
184
                }
185
			}
186
187
	        $route_loop = explode(
188
                '/',
189
                (substr($route['url'],strlen($route['url'])-1,1) === '/') 
190
                    ? substr($route['url'], 0, -1) 
191
                    : $route['url'] 
192
            );
193
194
            /* ONLY FOR DEBUG CONDITION */
195
            $route_request = $route_loop;
196
	        /*$route_request = explode(
197
                '/',
198
                (substr($_SERVER['REQUEST_URI'],strlen($_SERVER['REQUEST_URI'])-1,1) === '/') 
199
                ? substr($_SERVER['REQUEST_URI'], 0, -1) 
200
                : $_SERVER['REQUEST_URI'] 
201
            );*/
202
203
	        if(count($route_loop) !== count($route_request)){
204
                continue;
205
            }
206
207
	        for($rr = 0; $rr < count($route_loop); $rr++){
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
208
	            $param = (substr($route_loop[$rr],0,1)==='{');
209
210
	            if($param){
211
                    $param_name = substr($route_loop[$rr],1,strlen($route_loop[$rr])-2);
212
	                $data[$param_name] = $route_request[$rr];
213
	            }
214
215
	            if(!$param and $route_loop[$rr] !== $route_request[$rr]){
216
                    continue 2;
217
                }
218
	        }
219
220
	        if(!empty($route['filters'])){
221
	            if(is_array($route['filters'])){
222
	                foreach($route['filters'] as $filter){
223
	                    $this->filter->filtering($filter);
224
	                }
225
	            }else{
226
	                $this->filter->filtering($route['filters']);
227
	            }
228
	        }
229
230
            $this->Controller($route['role']);
231
	        return true;
232
	    }
233
234
	    throw new Exception('Page not found.',404);
235
    }
236
237
    public static function filter($filters): Router
238
    {
239
        if(self::getInstance()->lastReturn !== null){
240
            $currentGroup = end(self::getInstance()->routers)['group'];
241
242
            foreach (self::getInstance()->routers as $key => $value) {
243
                if($value['group'] === $currentGroup){
244
                    $currentRoute = self::getInstance()->addFilter(self::getInstance()->routers[$key],$filters);
245
                    self::getInstance()->routers[$key] = $currentRoute;
246
                }
247
            }
248
            
249
        }else{
250
            $currentRoute = self::getInstance()->addFilter(end(self::getInstance()->routers),$filters);
251
            self::getInstance()->routers[count(self::getInstance()->routers)-1] = $currentRoute;
252
        }
253
254
        return self::getInstance();
255
    }
256
257
    public static function addFilter(array $route, $filter): array
258
    {
259
        if(is_null($route['filters'])){
260
            $route['filters'] = $filter;
261
            return $route;
262
        }
263
264
        $filters = (is_array($filter)) ? $filter : [0 => $filter];
265
266
        if(is_array($route['filters'])){
267
            foreach ($route['filters'] as $key => $value) {
268
                $filters[] = $value;
269
            }
270
        }else{
271
            $filters[] = $route['filters'];
272
        }
273
274
        $route['filters'] = $filters;
275
        return $route;
276
    }
277
278
    
279
280
281
282
283
284
285
286
    public function Controller(string $controll): void
287
    {
288
        $data = $this->getData();
289
290
        foreach ($data['GET'] as $name => $value) {
291
            $controll = str_replace('{'.$name.'}',$value,$controll);
292
        }
293
294
        $d = explode(':',$controll);
295
296
        if(count($d) != 2){
297
            throw new Exception("Controller {$controll} badly set.");
298
        }
299
300
        if(!class_exists('Controllers\\' . ucfirst($d[0]))){
301
            throw new Exception("No controller {$d[0]} found.");
302
        }
303
304
        if(!method_exists('Controllers\\' . ucfirst($d[0]), $d[1])){
305
            throw new Exception("No method {$d[1]} found for {$d[0]}.");
306
        }
307
308
        $controller = 'Controllers\\' . ucfirst($d[0]);
309
        $controller = new $controller();
310
        $method = $d[1];
311
312
        $isForm = ( $this->getProtocol() == 'form');
0 ignored issues
show
Unused Code introduced by
The assignment to $isForm is dead and can be removed.
Loading history...
313
314
        if($isform){
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $isform does not exist. Did you maybe mean $isForm?
Loading history...
315
            $this->ControllerForm($controller, $method, $data['POST']);
316
        }else {
317
            $controller->$method($data);
318
        }
319
    }    
320
321
    public function ControllerForm($controller, string $method, array $values){
322
		if(Validator::execute($values)){
323
            if(!array_key_exists('role',$this->getData()['POST'])){
324
                throw new Exception('O servidor não conseguiu identificar a finalidade deste formulário.');
325
            }
326
327
            $role = ($method !== 'method') ? $method : $this->getData()['POST']['role'];
328
            $data = (!is_null($values)) ? json_decode($values['data']) : null;
0 ignored issues
show
introduced by
The condition is_null($values) is always false.
Loading history...
329
            $controller->$role($data);
330
        }
331
    }
332
333
}
334