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
|
|
|
|