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