These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * This file is part of the BEAR.Resource package. |
||
4 | * |
||
5 | * @license http://opensource.org/licenses/MIT MIT |
||
6 | */ |
||
7 | namespace BEAR\Resource; |
||
8 | |||
9 | use BEAR\Resource\Annotation\JsonSchema; |
||
10 | use BEAR\Resource\Annotation\ResourceParam; |
||
11 | use Doctrine\Common\Annotations\Reader; |
||
12 | use phpDocumentor\Reflection\DocBlockFactory; |
||
13 | use Ray\Di\Di\Assisted; |
||
14 | use Ray\Di\Di\Named; |
||
15 | use Ray\WebContextParam\Annotation\AbstractWebContextParam; |
||
16 | use Ray\WebContextParam\Annotation\CookieParam; |
||
17 | use Ray\WebContextParam\Annotation\EnvParam; |
||
18 | use Ray\WebContextParam\Annotation\FormParam; |
||
19 | use Ray\WebContextParam\Annotation\QueryParam; |
||
20 | use Ray\WebContextParam\Annotation\ServerParam; |
||
21 | |||
22 | final class OptionsMethods |
||
23 | { |
||
24 | /** |
||
25 | * Constants for annotation name and "in" name |
||
26 | * |
||
27 | * @var array |
||
28 | */ |
||
29 | private $webContextName = [ |
||
30 | CookieParam::class => 'cookie', |
||
31 | EnvParam::class => 'env', |
||
32 | FormParam::class => 'formData', |
||
33 | QueryParam::class => 'query', |
||
34 | ServerParam::class => 'server' |
||
35 | ]; |
||
36 | private $reader; |
||
37 | |||
38 | /** |
||
39 | * @var string |
||
40 | */ |
||
41 | private $schemaDir; |
||
42 | |||
43 | /** |
||
44 | * @Named("schemaDir=json_schema_dir") |
||
45 | */ |
||
46 | 88 | public function __construct(Reader $reader, $schemaDir = '') |
|
47 | { |
||
48 | 88 | $this->reader = $reader; |
|
49 | 88 | $this->schemaDir = $schemaDir; |
|
50 | 88 | } |
|
51 | |||
52 | 6 | public function __invoke(ResourceObject $ro, string $requestMethod) : array |
|
53 | { |
||
54 | 6 | $method = new \ReflectionMethod($ro, 'on' . $requestMethod); |
|
55 | 6 | $ins = $this->getInMap($method); |
|
56 | 6 | $docComment = $method->getDocComment(); |
|
57 | 6 | $doc = $paramDoc = []; |
|
58 | 6 | if ($docComment) { |
|
59 | 6 | list($doc, $paramDoc) = $this->docBlock($docComment); |
|
60 | } |
||
61 | 6 | $parameters = $method->getParameters(); |
|
62 | 6 | list($paramDoc, $required) = $this->getParameterMetas($parameters, $paramDoc, $ins); |
|
63 | 6 | $paramMetas = []; |
|
64 | 6 | if ((bool) $paramDoc) { |
|
65 | 6 | $paramMetas['parameters'] = $paramDoc; |
|
66 | } |
||
67 | 6 | if ((bool) $required) { |
|
68 | 6 | $paramMetas['required'] = $required; |
|
69 | } |
||
70 | 6 | $paramMetas = $this->ignoreAnnotatedPrameter($method, $paramMetas); |
|
71 | 6 | $schema = $this->getJsonSchema($method); |
|
72 | 6 | $request = $paramMetas ? ['request' => $paramMetas] : []; |
|
73 | 6 | if ($schema) { |
|
0 ignored issues
–
show
|
|||
74 | 1 | return $doc + $request + ['schema' => $schema]; |
|
75 | } |
||
76 | |||
77 | 5 | return $doc + $request; |
|
78 | } |
||
79 | |||
80 | 6 | private function getInMap(\ReflectionMethod $method) : array |
|
81 | { |
||
82 | 6 | $ins = []; |
|
83 | 6 | $annotations = $this->reader->getMethodAnnotations($method); |
|
84 | 6 | foreach ($annotations as $annotation) { |
|
85 | 4 | if ($annotation instanceof AbstractWebContextParam) { |
|
86 | 4 | $ins[$annotation->param] = $this->webContextName[get_class($annotation)]; |
|
87 | } |
||
88 | } |
||
89 | |||
90 | 6 | return $ins; |
|
91 | } |
||
92 | |||
93 | /** |
||
94 | * @return array [$docs, $params] |
||
95 | */ |
||
96 | 6 | private function docBlock(string $docComment) : array |
|
97 | { |
||
98 | 6 | $factory = DocBlockFactory::createInstance(); |
|
99 | 6 | $docblock = $factory->create($docComment); |
|
100 | 6 | $summary = $docblock->getSummary(); |
|
101 | 6 | $docs = $params = []; |
|
102 | 6 | if ($summary) { |
|
103 | 2 | $docs['summary'] = $summary; |
|
104 | } |
||
105 | 6 | $description = (string) $docblock->getDescription(); |
|
106 | 6 | if ($description) { |
|
107 | 2 | $docs['description'] = $description; |
|
108 | } |
||
109 | 6 | $tags = $docblock->getTagsByName('param'); |
|
110 | 6 | $params = $this->docBlogTags($tags, $params); |
|
111 | |||
112 | 6 | return [$docs, $params]; |
|
113 | } |
||
114 | |||
115 | /** |
||
116 | * @param \ReflectionParameter $parameter |
||
117 | * @param array $paramDoc |
||
118 | * @param string $name |
||
119 | * |
||
120 | * @return string|null |
||
121 | */ |
||
122 | 6 | private function getParameterType(\ReflectionParameter $parameter, array $paramDoc, string $name) |
|
123 | { |
||
124 | 6 | $hasType = method_exists($parameter, 'getType') && $parameter->getType(); |
|
125 | 6 | if ($hasType) { |
|
126 | 1 | return $this->getType($parameter); |
|
127 | } |
||
128 | 6 | if (isset($paramDoc[$name]['type'])) { |
|
129 | 3 | return $paramDoc[$name]['type']; |
|
130 | } |
||
131 | 3 | } |
|
132 | |||
133 | /** |
||
134 | * @param \ReflectionParameter[] $parameters |
||
135 | * @param array $paramDoc |
||
136 | * |
||
137 | * @return array [$paramDoc, $required] |
||
138 | */ |
||
139 | 6 | private function getParameterMetas(array $parameters, array $paramDoc, array $ins) : array |
|
140 | { |
||
141 | 6 | $required = []; |
|
142 | 6 | foreach ($parameters as $parameter) { |
|
143 | 6 | if (isset($ins[$parameter->name])) { |
|
144 | 2 | $paramDoc[$parameter->name]['in'] = $ins[$parameter->name]; |
|
145 | } |
||
146 | 6 | if (! isset($paramDoc[$parameter->name])) { |
|
147 | 3 | $paramDoc[$parameter->name] = []; |
|
148 | } |
||
149 | 6 | $paramDoc = $this->paramType($paramDoc, $parameter); |
|
150 | 6 | if (! $parameter->isOptional()) { |
|
151 | 6 | $required[] = $parameter->name; |
|
152 | } |
||
153 | 6 | $paramDoc = $this->paramDefault($paramDoc, $parameter); |
|
154 | } |
||
155 | |||
156 | 6 | return [$paramDoc, $required]; |
|
157 | } |
||
158 | |||
159 | 6 | private function paramDefault(array $paramDoc, \ReflectionParameter $parameter) : array |
|
160 | { |
||
161 | 6 | $hasDefault = $parameter->isDefaultValueAvailable() && $parameter->getDefaultValue() !== null; |
|
162 | 6 | if ($hasDefault) { |
|
163 | 2 | $paramDoc[$parameter->name]['default'] = (string) $parameter->getDefaultValue(); |
|
164 | } |
||
165 | |||
166 | 6 | return $paramDoc; |
|
167 | } |
||
168 | |||
169 | 6 | private function paramType(array $paramDoc, \ReflectionParameter $parameter) : array |
|
170 | { |
||
171 | 6 | $type = $this->getParameterType($parameter, $paramDoc, $parameter->name); |
|
172 | 6 | if (is_string($type)) { |
|
173 | 3 | $paramDoc[$parameter->name]['type'] = $type; |
|
174 | } |
||
175 | |||
176 | 6 | return $paramDoc; |
|
177 | } |
||
178 | |||
179 | /** |
||
180 | * @param \ReflectionParameter $parameter |
||
181 | */ |
||
182 | 1 | private function getType(\ReflectionParameter $parameter) : string |
|
183 | { |
||
184 | 1 | $type = (string) $parameter->getType(); |
|
185 | 1 | if ($type === 'int') { |
|
186 | 1 | $type = 'integer'; |
|
187 | } |
||
188 | |||
189 | 1 | return $type; |
|
190 | } |
||
191 | |||
192 | 6 | private function docBlogTags(array $tags, array $params) : array |
|
193 | { |
||
194 | 6 | foreach ($tags as $tag) { |
|
195 | /* @var $tag \phpDocumentor\Reflection\DocBlock\Tags\Param */ |
||
196 | 3 | $varName = $tag->getVariableName(); |
|
197 | 3 | $tagType = (string) $tag->getType(); |
|
198 | 3 | $type = $tagType === 'int' ? 'integer' : $tagType; |
|
199 | 3 | $params[$varName] = [ |
|
200 | 3 | 'type' => $type |
|
201 | ]; |
||
202 | 3 | $description = (string) $tag->getDescription(); |
|
203 | 3 | if ($description) { |
|
204 | 3 | $params[$varName]['description'] = $description; |
|
205 | } |
||
206 | } |
||
207 | |||
208 | 6 | return $params; |
|
209 | } |
||
210 | |||
211 | /** |
||
212 | * Ignore @ Assisted @ ResourceParam parameter |
||
213 | */ |
||
214 | 6 | private function ignoreAnnotatedPrameter(\ReflectionMethod $method, array $paramMetas) : array |
|
215 | { |
||
216 | 6 | $annotations = $this->reader->getMethodAnnotations($method); |
|
217 | 6 | foreach ($annotations as $annotation) { |
|
218 | 4 | if ($annotation instanceof ResourceParam) { |
|
219 | 1 | unset($paramMetas['parameters'][$annotation->param]); |
|
220 | 1 | $paramMetas['required'] = array_values(array_diff($paramMetas['required'], [$annotation->param])); |
|
221 | } |
||
222 | 4 | if ($annotation instanceof Assisted) { |
|
223 | 4 | $paramMetas = $this->ignorreAssisted($paramMetas, $annotation); |
|
224 | } |
||
225 | } |
||
226 | |||
227 | 6 | return $paramMetas; |
|
228 | } |
||
229 | |||
230 | /** |
||
231 | * Ignore @ Assisted parameter |
||
232 | */ |
||
233 | 1 | private function ignorreAssisted(array $paramMetas, Assisted $annotation) : array |
|
234 | { |
||
235 | 1 | $paramMetas['required'] = array_values(array_diff($paramMetas['required'], $annotation->values)); |
|
236 | 1 | foreach ($annotation->values as $varName) { |
|
237 | 1 | unset($paramMetas['parameters'][$varName]); |
|
238 | } |
||
239 | |||
240 | 1 | return $paramMetas; |
|
241 | } |
||
242 | |||
243 | 6 | private function getJsonSchema(\ReflectionMethod $method) : array |
|
244 | { |
||
245 | 6 | $schema = $this->reader->getMethodAnnotation($method, JsonSchema::class); |
|
246 | 6 | if (! $schema instanceof JsonSchema) { |
|
247 | 5 | return []; |
|
248 | } |
||
249 | 1 | $schemaFile = $this->schemaDir . '/' . $schema->schema; |
|
250 | 1 | if (! file_exists($schemaFile)) { |
|
251 | return []; |
||
252 | } |
||
253 | |||
254 | 1 | return (array) json_decode(file_get_contents($schemaFile)); |
|
255 | } |
||
256 | } |
||
257 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.