Passed
Push — master ( f7ade8...7e9287 )
by Jean-Christophe
11:26
created

ControllerParser::createRouteMethod()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 7.9936

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 10
c 2
b 0
f 1
dl 0
loc 14
ccs 8
cts 11
cp 0.7272
rs 8.8333
cc 7
nc 6
nop 12
crap 7.9936

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace Ubiquity\cache\parser;
4
5
use Ubiquity\exceptions\ParserException;
6
use Ubiquity\orm\parser\Reflexion;
7
use Ubiquity\utils\base\UString;
8
use Ubiquity\cache\ClassUtils;
9
use Ubiquity\annotations\AnnotationsEngineInterface;
10
use Ubiquity\exceptions\RouterException;
11
12
/**
13
 * Scans a controller to detect routes defined by annotations or attributes.
14
 * Ubiquity\cache\parser$ControllerParser
15
 * This class is part of Ubiquity
16
 *
17
 * @author jcheron <[email protected]>
18
 * @version 1.1.1
19
 *
20
 */
21
class ControllerParser {
22
	use ControllerParserPathTrait;
23
	
24
	const HTTP_METHODS=['head','get','post','patch','put','delete','options','connect'];
25
	
26
	private string $controllerClass;
27
	private $mainRouteClass;
28
	private array $routesMethods = [ ];
29
	private bool $rest = false;
30
	private bool $silent=false;
31
	private static array $excludeds = [ '__construct','isValid','initialize','finalize','onInvalidControl','loadView','forward','redirectToRoute' ];
32
	
33
	
34
	/**
35
	 *
36
	 * @var AnnotationsEngineInterface
37
	 */
38
	private $annotsEngine;
39
	
40 17
	public function __construct(AnnotationsEngineInterface $annotsEngine) {
41 17
		$this->annotsEngine = $annotsEngine;
42 17
	}
43
	
44 17
	public function parse($controllerClass) {
45 17
		$automated = false;
46 17
		$inherited = false;
47 17
		$this->controllerClass = $controllerClass;
48 17
		$restAnnotsClass = [ ];
49 17
		$reflect = new \ReflectionClass ( $controllerClass );
50 17
		if (! $reflect->isAbstract () && $reflect->isSubclassOf ( \Ubiquity\controllers\Controller::class )) {
51
			try {
52 17
				$annotsClass = Reflexion::getAnnotationClass ( $controllerClass, 'route' );
53 17
				$restAnnotsClass = Reflexion::getAnnotationClass ( $controllerClass, 'rest' );
54
			} catch ( \Exception $e ) {
55
				// When controllerClass generates an exception
56
			}
57 17
			$this->rest = \count ( $restAnnotsClass ) > 0;
58 17
			if (isset ( $annotsClass ) && \count ( $annotsClass ) > 0) {
59 17
				$this->mainRouteClass = $annotsClass [0];
60 17
				$inherited = $this->mainRouteClass->inherited;
61 17
				$automated = $this->mainRouteClass->automated;
62
			}
63 17
			$methods = Reflexion::getMethods ( $controllerClass, \ReflectionMethod::IS_PUBLIC );
64 17
			$this->parseMethods ( $methods, $controllerClass, $inherited, $automated );
65
		}
66 17
	}
67
	
68 17
	private function parseMethods($methods, $controllerClass, $inherited, $automated) {
69 17
		foreach ( $methods as $method ) {
70 17
			if ($method->getDeclaringClass ()->getName () === $controllerClass || $inherited) {
71
				try {
72 17
					$annots = Reflexion::getAnnotationsMethod ( $controllerClass, $method->name, [ 'route','get','post','patch','put','delete','options' ] );
73 17
					if (\count ( $annots ) > 0) {
74 17
						foreach ( $annots as $annot ) {
75 17
							$this->parseAnnot ( $annot, $method );
76
						}
77 17
						$this->routesMethods [$method->name] = [ 'annotations' => $annots,'method' => $method ];
78
					} else {
79 17
						if ($automated) {
80 17
							if ($method->class !== 'Ubiquity\\controllers\\Controller' && \array_search ( $method->name, self::$excludeds ) === false && ! UString::startswith ( $method->name, '_' ))
81 17
								$this->routesMethods [$method->name] = [ 'annotations' => $this->generateRouteAnnotationFromMethod ( $method ),'method' => $method ];
82
						}
83
					}
84
				} catch ( \Exception $e ) {
85
					if (!$this->silent && $e instanceof ParserException){
86
						throw $e;
87
					}
88
					// When controllerClass generates an exception
89
				}
90
			}
91
		}
92 17
	}
93
	
94 17
	private function parseAnnot(&$annot, $method) {
95 17
		if (UString::isNull ( $annot->path )) {
96 17
			$newAnnot = $this->generateRouteAnnotationFromMethod ( $method );
97 17
			$annot->path = $newAnnot [0]->path;
98
		} else {
99 17
			$annot->path = $this->parseMethodPath ( $method, $annot->path );
100
		}
101 17
	}
102
	
103 17
	private function generateRouteAnnotationFromMethod(\ReflectionMethod $method): array {
104 17
		return [ $this->annotsEngine->getAnnotation ( null, 'route', [ 'path' => self::getPathFromMethod ( $method ) ] ) ];
105
	}
106
	
107 17
	private static function generateRouteName(string $controllerName,string $action): string {
108 17
		$ctrl=\str_ireplace('controller','',ClassUtils::getClassSimpleName ( $controllerName ));
109 17
		return \lcfirst($ctrl) . '.' . $action;
110
	}
111
	
112 17
	public function asArray(): array {
113 17
		$result = [ ];
114 17
		$prefix = '';
115 17
		$httpMethods = false;
116 17
		if ($this->mainRouteClass) {
117 17
			if (isset ( $this->mainRouteClass->path )) {
118 17
				$this->mainRouteClass->path=self::parseMainPath($this->mainRouteClass->path,$this->controllerClass);
119 17
				$prefix = $this->mainRouteClass->path;
120
			}
121 17
			if (isset ( $this->mainRouteClass->methods )) {
122
				$httpMethods = $this->mainRouteClass->methods;
123
				if ($httpMethods !== null) {
124
					if (\is_string ( $httpMethods ))
125
						$httpMethods = [ $httpMethods ];
126
				}
127
			}
128
		}
129 17
		foreach ( $this->routesMethods as $method => $arrayAnnotsMethod ) {
130 17
			$routeAnnotations = $arrayAnnotsMethod ['annotations'];
131
			
132 17
			foreach ( $routeAnnotations as $routeAnnotation ) {
133 17
				$params = [ 'path' => $routeAnnotation->path,'methods' => $routeAnnotation->methods,'name' => $routeAnnotation->name,'cache' => $routeAnnotation->cache,'duration' => $routeAnnotation->duration,'requirements' => $routeAnnotation->requirements,'priority' => $routeAnnotation->priority ];
134 17
				self::parseRouteArray ( $result, $this->controllerClass, $params, $arrayAnnotsMethod ['method'], $method, $prefix, $httpMethods );
135
			}
136
		}
137 17
		return $result;
138
	}
139
	
140 41
	public static function parseRouteArray(&$result, $controllerClass, $routeArray, \ReflectionMethod $method, $methodName, $prefix = '', $httpMethods = NULL) {
141 41
		if (! isset ( $routeArray ['path'] )) {
142
			$routeArray ['path'] = self::getPathFromMethod ( $method );
143
		}
144 41
		$pathParameters = self::addParamsPath ( $routeArray ['path'], $method, $routeArray ['requirements'] );
145 41
		$name = $routeArray ['name'];
146 41
		if (! isset ( $name )) {
147 17
			$name = self::generateRouteName($controllerClass,$methodName);
148
		}
149 41
		$cache = $routeArray ['cache'];
150 41
		$duration = $routeArray ['duration'];
151 41
		$path = $pathParameters ['path'];
152 41
		$parameters = $pathParameters ['parameters'];
153 41
		$priority = $routeArray ['priority'];
154 41
		$callback = $routeArray ['callback'] ?? null;
155 41
		$isRoot=false;
156 41
		$path = self::cleanpath ( $prefix, $path ,$isRoot);
157 41
		if (isset ( $routeArray ['methods'] ) && \is_array ( $routeArray ['methods'] )) {
158 17
			self::createRouteMethod ( $result, $controllerClass, $path, $routeArray ['methods'], $methodName, $parameters, $name, $cache, $duration, $priority, $callback , $isRoot);
159 41
		} elseif (\is_array ( $httpMethods )) {
160
			self::createRouteMethod ( $result, $controllerClass, $path, $httpMethods, $methodName, $parameters, $name, $cache, $duration, $priority, $callback , $isRoot);
161
		} else {
162 41
			$v = [ 'controller' => $controllerClass,'action' => $methodName,'parameters' => $parameters,'name' => $name,'cache' => $cache,'duration' => $duration,'priority' => $priority];
163 41
			if (isset ( $callback )) {
164 1
				$v ['callback'] = $callback;
165
			}
166 41
			if(!$isRoot && isset(self::$mainParams) && \count(self::$mainParams)>0){
167 17
				$v['main.params']=self::$mainParams;
168
			}
169 41
			$result [$path] = $v;
170
		}
171 41
	}
172
	
173 17
	private static function createRouteMethod(&$result, $controllerClass, $path, $httpMethods, $method, $parameters, $name, $cache, $duration, $priority, $callback = null,$isRoot=false) {
174 17
		foreach ( $httpMethods as $httpMethod ) {
175 17
			$httpMethod=\strtolower($httpMethod);
176 17
			if(\array_search($httpMethod, self::HTTP_METHODS)===false){
177
				throw new RouterException("$httpMethod is not a valid HTTP method!");
178
			}
179 17
			$v = [ 'controller' => $controllerClass,'action' => $method,'parameters' => $parameters,'name' => $name,'cache' => $cache,'duration' => $duration,'priority' => $priority ];
180 17
			if (isset ( $callback )) {
181
				$v ['callback'] = $callback;
182
			}
183 17
			if(!$isRoot && isset(self::$mainParams) && \count(self::$mainParams)>0){
184
				$v['main.params']=self::$mainParams;
185
			}
186 17
			$result [$path] [$httpMethod] = $v;
187
		}
188 17
	}
189
	
190 17
	public function isRest(): bool {
191 17
		return $this->rest;
192
	}
193
	
194
	/**
195
	 * @param bool $silent
196
	 */
197 17
	public function setSilent(bool $silent): void {
198 17
		$this->silent = $silent;
199 17
	}
200
}
201