Passed
Push — master ( 82fa8b...914114 )
by Henri
01:17
created

Router::where()   B

Complexity

Conditions 7
Paths 13

Size

Total Lines 32
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

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