Completed
Push — master ( c695c6...742385 )
by Jean-Christophe
01:48
created

Router   B

Complexity

Total Complexity 53

Size/Duplication

Total Lines 187
Duplicated Lines 4.81 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 53
lcom 1
cbo 4
dl 9
loc 187
rs 7.4757
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A slashPath() 0 7 3
A start() 0 3 1
A startRest() 0 3 1
B getRoute() 0 14 5
A filterRoutes() 0 10 3
A getRouteInfo() 0 12 4
B getAnnotations() 0 11 5
B getRouteByName() 0 18 7
A path() 0 3 1
A url() 0 3 1
A _getURL() 0 5 1
B checkRouteName() 0 9 6
C getRouteUrlParts() 9 28 8
A cleanParam() 0 5 2
A setExpired() 0 3 1
A addRoute() 0 3 1
A addRouteToRoutes() 0 10 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Router often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Router, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Ubiquity\controllers;
4
5
use Ubiquity\cache\CacheManager;
6
use Ubiquity\utils\RequestUtils;
7
use Ubiquity\cache\parser\ControllerParser;
8
use Ubiquity\utils\StrUtils;
9
10
/**
11
 * Router
12
 * @author jc
13
 * @version 1.0.0.2
14
 */
15
class Router {
16
	private static $routes;
17
18
	public static function slashPath($path){
19
		if(StrUtils::startswith($path,"/")===false)
20
			$path="/" . $path;
21
		if(!StrUtils::endswith($path, "/"))
22
			$path=$path."/";
23
		return $path;
24
	}
25
26
	public static function start() {
27
		self::$routes=CacheManager::getControllerCache();
28
	}
29
30
	public static function startRest() {
31
		self::$routes=CacheManager::getControllerCache(true);
32
	}
33
34
	public static function getRoute($path,$cachedResponse=true) {
35
		$path=self::slashPath($path);
36
		foreach ( self::$routes as $routePath => $routeDetails ) {
37
			if (preg_match("@^" . $routePath . "$@s", $path, $matches)) {
38
				if (!isset($routeDetails["controller"])) {
39
					$method=RequestUtils::getMethod();
40
					if (isset($routeDetails[$method]))
41
						return self::getRouteUrlParts([ "path" => $routePath,"details" => $routeDetails[$method] ], $matches, $routeDetails[$method]["cache"], $routeDetails[$method]["duration"],$cachedResponse);
42
				} else
43
					return self::getRouteUrlParts([ "path" => $routePath,"details" => $routeDetails ], $matches, $routeDetails["cache"], $routeDetails["duration"],$cachedResponse);
44
			}
45
		}
46
		return false;
47
	}
48
49
	public static function filterRoutes($path) {
50
		$path=self::slashPath($path);
51
		$result=[];
52
		foreach ( self::$routes as $routePath => $routeDetails ) {
53
			if (preg_match("@^" . $routePath . ".*?$@s", $path, $matches)) {
54
				$result[$routePath]=$routeDetails;
55
			}
56
		}
57
		return $result;
58
	}
59
60
	public static function getRouteInfo($path){
61
		$path=self::slashPath($path);
62
		foreach ( self::$routes as $routePath => $routeDetails ) {
63
			if (preg_match("@^" . $routePath . "$@s", $path, $matches)) {
64
				if (!isset($routeDetails["controller"])) {
65
						return \reset($routeDetails);
66
				} else
67
					return $routeDetails;
68
			}
69
		}
70
		return false;
71
	}
72
73
	public static function getAnnotations($controllerName,$actionName){
74
		$result=[];
75
		foreach ( self::$routes as $routePath => $routeDetails ) {
76
			if (!isset($routeDetails["controller"])) {
77
				$routeDetails=\reset($routeDetails);
78
			}
79
			if($routeDetails["controller"]===$controllerName && $routeDetails["action"]===$actionName)
80
				$result[$routePath]=$routeDetails;
81
		}
82
		return $result;
83
	}
84
85
	/**
86
	 * Returns the generated path from a route
87
	 * @param string $name name of the route
88
	 * @param array $parameters array of the route parameters. default : []
89
	 * @param boolean $absolute
90
	 */
91
	public static function getRouteByName($name, $parameters=[],$absolute=true) {
92
		foreach ( self::$routes as $routePath => $routeDetails ) {
93
			if(!isset($routeDetails["name"])){
94
				foreach ($routeDetails as $methodRouteDetail){
0 ignored issues
show
Unused Code introduced by
This foreach statement is empty and can be removed.

This check looks for foreach loops that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

Consider removing the loop.

Loading history...
95
96
				}
97
			}
98
			if (self::checkRouteName($routeDetails, $name)) {
99
				if(\sizeof($parameters)>0)
100
					$routePath=self::_getURL($routePath, $parameters);
101
				if ($absolute)
102
					return RequestUtils::getUrl($routePath);
103
				else
104
					return $routePath;
105
			}
106
		}
107
		return false;
108
	}
109
110
	public static function path($name,$parameters=[]){
111
		return self::getRouteByName($name,$parameters,false);
112
	}
113
114
	public static function url($name,$parameters=[]){
115
		return self::getRouteByName($name,$parameters,true);
116
	}
117
	protected static function _getURL($routePath,$params){
118
		return \preg_replace_callback('~\((.*?)\)~', function($matches) use (&$params) {
0 ignored issues
show
Unused Code introduced by
The parameter $matches is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
119
			return array_shift($params);
120
		}, $routePath);
121
	}
122
123
	protected static function checkRouteName($routeDetails,$name){
124
		if(!isset($routeDetails["name"])){
125
			foreach ($routeDetails as $methodRouteDetail){
126
				if(isset($methodRouteDetail["name"]) && $methodRouteDetail==$name)
127
					return true;
128
			}
129
		}
130
		return isset($routeDetails["name"]) && $routeDetails["name"] == $name;
131
	}
132
133
	public static function getRouteUrlParts($routeArray, $params, $cached=false, $duration=NULL,$cachedResponse=true) {
134
		$params=\array_slice($params, 1);
135
		$ctrl=str_replace("\\\\", "\\", $routeArray["details"]["controller"]);
136
		$result=[ $ctrl,$routeArray["details"]["action"] ];
137
		$paramsOrder=$routeArray["details"]["parameters"];
138
		$index=0;
139
		foreach ( $paramsOrder as $order ) {
140 View Code Duplication
			if($order==="*"){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
141
				if(isset($params[$index]))
142
					$result=\array_merge($result,\array_diff(\explode("/", $params[$index]),[""]));
143
				break;
144
			}
145
			if(\substr($order, 0,1)==="~"){
146
				$order=\intval(\substr($order,1,1));
147 View Code Duplication
				if(isset($params[$order])){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
148
					$result=\array_merge($result,\array_diff(\explode("/", $params[$order]),[""]));
149
					break;
150
				}
151
			}
152
			$result[]=self::cleanParam($params[$order]);
153
			unset($params[$order]);
154
			$index++;
155
		}
156
		if ($cached === true && $cachedResponse===true) {
157
			return CacheManager::getRouteCache($result, $duration);
158
		}
159
		return $result;
160
	}
161
162
	private static function cleanParam($param){
163
		if(StrUtils::endswith($param, "/"))
164
			return \substr($param, 0,-1);
165
		return $param;
166
	}
167
168
	/**
169
	 * Déclare une route comme étant expirée ou non
170
	 * @param string $routePath
171
	 * @param boolean $expired
172
	 */
173
	public static function setExpired($routePath, $expired=true) {
174
		CacheManager::setExpired($routePath, $expired);
175
	}
176
177
	/**
178
	 *
179
	 * @param string $path
180
	 * @param string $controller
181
	 * @param string $action
182
	 * @param array|null $methods
183
	 * @param string $name
184
	 * @param boolean $cache
185
	 * @param int $duration
186
	 */
187
	public static function addRoute($path, $controller, $action="index", $methods=null, $name="", $cache=false, $duration=null) {
188
		self::addRouteToRoutes(self::$routes, $path, $controller, $action, $methods, $name, $cache, $duration);
189
	}
190
191
	public static function addRouteToRoutes(&$routesArray, $path, $controller, $action="index", $methods=null, $name="", $cache=false, $duration=null) {
192
		$result=[ ];
193
		if(\class_exists($controller)){
194
			$method=new \ReflectionMethod($controller, $action);
195
			ControllerParser::parseRouteArray($result, $controller, [ "path" => $path,"methods" => $methods,"name" => $name,"cache" => $cache,"duration" => $duration ], $method, $action);
196
			foreach ( $result as $k => $v ) {
197
				$routesArray[$k]=$v;
198
			}
199
		}
200
	}
201
}
202