Passed
Push — master ( 8a8111...583a39 )
by Jean-Christophe
19:52
created

ControllerParserPathTrait   C

Complexity

Total Complexity 53

Size/Duplication

Total Lines 178
Duplicated Lines 0 %

Test Coverage

Coverage 84.3%

Importance

Changes 3
Bugs 1 Features 1
Metric Value
wmc 53
eloc 123
c 3
b 1
f 1
dl 0
loc 178
ccs 102
cts 121
cp 0.843
rs 6.96

8 Methods

Rating   Name   Duplication   Size   Complexity  
A checkParams() 0 4 4
A getPathFromMethod() 0 20 5
A scanParam() 0 17 5
B parseMainPath() 0 30 8
B addParamsPath() 0 32 8
A parseMethodPath() 0 14 6
B cleanpath() 0 21 10
B checkParamsTypesForRequirement() 0 21 7

How to fix   Complexity   

Complex Class

Complex classes like ControllerParserPathTrait 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.

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 ControllerParserPathTrait, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Ubiquity\cache\parser;
4
5
use Ubiquity\cache\CacheManager;
6
use Ubiquity\utils\base\UString;
7
use Ubiquity\orm\parser\Reflexion;
8
use Ubiquity\exceptions\ParserException;
9
10
/**
11
 * Ubiquity\cache\parser$ControllerParserPathTrait
12
 * This class is part of Ubiquity
13
 *
14
 * @author jcheron <[email protected]>
15
 * @version 1.1.1
16
 *
17
 */
18
trait ControllerParserPathTrait {
19
	protected static $mainParams;
20 17
	protected static function getPathFromMethod(\ReflectionMethod $method) {
21 17
		$methodName = $method->getName ();
22 17
		if ($methodName === "index") {
23 17
			$pathParts = [ "(index/)?" ];
24
		} else {
25 17
			$pathParts = [ $methodName ];
26
		}
27 17
		$parameters = $method->getParameters ();
28 17
		foreach ( $parameters as $parameter ) {
29 17
			if ($parameter->isVariadic ()) {
30
				$pathParts [] = '{...' . $parameter->getName () . '}';
31
				return "/" . \implode ( "/", $pathParts );
32
			}
33 17
			if (! $parameter->isOptional ()) {
34 17
				$pathParts [] = '{' . $parameter->getName () . '}';
35
			} else {
36 17
				$pathParts [\count ( $pathParts ) - 1] .= '{~' . $parameter->getName () . '}';
37
			}
38
		}
39 17
		return "/" . \implode ( "/", $pathParts );
40
	}
41
	
42 59
	private static function checkParams(\ReflectionFunctionAbstract $method,$actualParams){
43 59
		foreach ( $method->getParameters () as $param ) {
44 17
			if(!$param->isOptional() && \array_search($param->name,$actualParams)===false){
45
				throw new ParserException(sprintf('The parameter %s is not present in the route path although it is mandatory.',$param->name));
46
			}
47
		}
48
	}
49
	
50 17
	private static function checkParamsTypesForRequirement(\ReflectionFunctionAbstract $method){
51 17
		$requirements=[];
52 17
		foreach ( $method->getParameters () as $param ) {
53 17
			if($param->hasType()){
54 17
				$type=$param->getType();
55 17
				if($type instanceof \ReflectionNamedType){
56 17
					switch ($type->getName()){
57 17
						case 'int':
58
							$requirements[$param->getName()]='\d+';
59
							break;
60 17
						case 'bool':
61
							$requirements[$param->getName()]='[0-1]{1}';
62
							break;
63 17
						case 'float':
64
							$requirements[$param->getName()]='[+-]?([0-9]*[.])?[0-9]+';
65
							break;
66
					}
67
				}
68
			}
69
		}
70 17
		return $requirements;
71
	}
72
	
73 59
	public static function parseMethodPath(\ReflectionFunctionAbstract $method, $path) {
74 59
		if (! isset ( $path ) || $path === '') {
75
			return;
76
		}
77 59
		$parameters = $method->getParameters ();
78 59
		foreach ( $parameters as $parameter ) {
79 17
			$name = $parameter->getName ();
80 17
			if ($parameter->isVariadic ()) {
81 17
				$path = \str_replace ( '{' . $name . '}', '{...' . $name . '}', $path );
82 17
			} elseif ($parameter->isOptional ()) {
83 17
				$path = \str_replace ( '{' . $name . '}', '{~' . $name . '}', $path );
84
			}
85
		}
86 59
		return $path;
87
	}
88
	
89 59
	public static function cleanpath($prefix, $path = "", &$isRoot=false) {
90 59
		$path = \str_replace ( '//', '/', $path );
91 59
		if ($prefix !== '' && ! UString::startswith ( $prefix, '/' )) {
92 17
			$prefix = '/' . $prefix;
93
		}
94 59
		if (! UString::endswith ( $prefix, '/' )) {
95 59
			$prefix = $prefix . '/';
96
		}
97 59
		if ($path !== '' && UString::startswith ( $path, '/' )) {
98 33
			$path = \substr ( $path, 1 );
99
		}
100 59
		if(UString::startswith($path,'#/')){
101 17
			$path=\substr($path,1);
102 17
			$isRoot=true;
103
		}else {
104 59
			$path = $prefix . $path;
105
		}
106 59
		if (! UString::endswith ( $path, '/' ) && ! UString::endswith ( $path, '(.*?)' ) && ! UString::endswith ( $path, '(index/)?' )) {
107 59
			$path = $path . '/';
108
		}
109 59
		return \str_replace ( '//', '/', $path );
110
	}
111
	
112 59
	public static function addParamsPath($path, \ReflectionFunctionAbstract $method, $requirements) {
113 59
		$parameters = [ ];
114 59
		$hasOptional = false;
115 59
		\preg_match_all ( '@\{(\.\.\.|\~)?(.+?)\}@s', $path, $matches );
116 59
		self::checkParams($method,$matches[2]??[]);
117 59
		if (isset ( $matches [2] ) && \count ( $matches [2] ) > 0) {
118 17
			$path = \preg_quote ( $path );
119 17
			$params = Reflexion::getMethodParameters ( $method );
120 17
			$typeRequirements=self::checkParamsTypesForRequirement($method);
121 17
			$index = 0;
122 17
			foreach ( $matches [2] as $paramMatch ) {
123 17
				$find = \array_search ( $paramMatch, $params );
124 17
				if ($find !== false) {
125 17
					unset($params[$find]);
126 17
					$requirement = '.+?';
127 17
					if (isset ( $requirements [$paramMatch] )) {
128
						$requirement = $requirements [$paramMatch];
129 17
					}elseif (isset($typeRequirements[$paramMatch])){
130
						$requirement = $typeRequirements [$paramMatch];
131
					}
132 17
					self::scanParam ( $parameters, $hasOptional, $matches, $index, $paramMatch, $find, $path, $requirement );
133
				} else {
134
					throw new ParserException ( "{$paramMatch} is not a parameter of the method " . $method->name );
135
				}
136 17
				$index ++;
137
			}
138
		}
139 59
		if ($hasOptional) {
140 17
			$path .= '/(.*?)';
141
		}
142 59
		$path=\str_replace('\\#','#',$path);
143 59
		return [ 'path' => $path,'parameters' => $parameters ];
144
	}
145
	
146 17
	public static function scanParam(&$parameters, &$hasOptional, $matches, $index, $paramMatch, $find, &$path, $requirement) {
147 17
		$toReplace = true;
148 17
		if (isset ( $matches [1] [$index] )) {
149 17
			if ($matches [1] [$index] === '...') {
150 17
				$parameters [] = '*';
151 17
				$path = \str_replace ( '\{\.\.\.' . $paramMatch . '\}', '(.*?)', $path );
152 17
				$toReplace = false;
153 17
			} elseif ($matches [1] [$index] === '~') {
154 17
				$parameters [] = '~' . $find;
155 17
				$path = \str_replace ( '\{~' . $paramMatch . '\}', '', $path );
156 17
				$hasOptional = true;
157 17
				$toReplace = false;
158
			}
159
		}
160 17
		if ($toReplace) {
161 17
			$parameters [] = $find;
162 17
			$path = \str_replace ( '\{' . $paramMatch . '\}', "({$requirement})", $path );
163
		}
164
	}
165
	
166 17
	protected static function parseMainPath(string $path,string $controllerClass): string{
167 17
		\preg_match_all ( '@\{(.+?)\}@s', $path, $matches );
168 17
		self::$mainParams=[];
169 17
		if (isset ( $matches [1] ) && \count ( $matches [1] ) > 0) {
170 17
			foreach ( $matches [1] as $paramMatch ) {
171 17
				if(\substr($paramMatch, -2) === '()'){
172
					$method=\substr($paramMatch,0,\strlen($paramMatch)-2);
173
					if(\method_exists($controllerClass,$method)){
174
						self::$mainParams[]=$method;
175
						$path = \str_replace('{' . $paramMatch . '}', '(.+?)', $path);
176
					}else{
177
						throw new ParserException("Method $method does not exist on $controllerClass");
178
					}
179
				}else{
180 17
					if(\property_exists($controllerClass,$paramMatch)){
181 17
						$rProp=new \ReflectionProperty($controllerClass,$paramMatch);
182 17
						if($rProp->isPublic()){
183 17
							$path = \str_replace('{' . $paramMatch . '}', '(.+?)', $path);
184 17
							self::$mainParams[]=$paramMatch;
185
						}else{
186 17
							throw new ParserException("Property $paramMatch must be public $controllerClass");
187
						}
188
					}else{
189
						throw new ParserException("Property $paramMatch does not exist on $controllerClass");
190
					}
191
				}
192
				
193
			}
194
		}
195 17
		return $path;
196
	}
197
}
198
199