Passed
Branch master (8fd4e9)
by Henri
02:11 queued 58s
created

Router   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 217
Duplicated Lines 0 %

Importance

Changes 28
Bugs 0 Features 5
Metric Value
eloc 109
c 28
b 0
f 5
dl 0
loc 217
rs 9.6
wmc 35

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A getInstance() 0 4 2
A create() 0 9 2
A filter() 0 19 4
A set() 0 30 5
A name() 0 23 4
A byName() 0 17 3
A group() 0 9 2
A where() 0 9 2
A dispatch() 0 40 5
A addFilter() 0 19 5
1
<?php
2
3
namespace HnrAzevedo\Router;
4
5
use Exception;
6
7
class Router{
8
    use Helper, CheckTrait, CheckWhere, DefinitionsTrait, ExtraJobsTrait;
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 static function addFilter(array $route, $filter): array
206
    {
207
        if(is_null($route['filters'])){
208
            $route['filters'] = $filter;
209
            return $route;
210
        }
211
212
        $filters = (is_array($filter)) ? $filter : [0 => $filter];
213
214
        if(is_array($route['filters'])){
215
            foreach ($route['filters'] as $key => $value) {
216
                $filters[] = $value;
217
            }
218
        }else{
219
            $filters[] = $route['filters'];
220
        }
221
222
        $route['filters'] = $filters;
223
        return $route;
224
    }
225
226
}
227