These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | declare(strict_types=1); |
||
3 | |||
4 | /** |
||
5 | * This file is part of phpDocumentor. |
||
6 | * |
||
7 | * For the full copyright and license information, please view the LICENSE |
||
8 | * file that was distributed with this source code. |
||
9 | * |
||
10 | * @author Mike van Riel <[email protected]> |
||
11 | * @copyright 2010-2018 Mike van Riel / Naenius (http://www.naenius.com) |
||
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT |
||
13 | * @link http://phpdoc.org |
||
14 | */ |
||
15 | |||
16 | namespace phpDocumentor\Descriptor; |
||
17 | |||
18 | use phpDocumentor\Descriptor\Tag\ReturnDescriptor; |
||
19 | use phpDocumentor\Reflection\Type; |
||
20 | |||
21 | /** |
||
22 | * Descriptor representing a Method in a Class, Interface or Trait. |
||
23 | */ |
||
24 | class MethodDescriptor extends DescriptorAbstract implements Interfaces\MethodInterface, Interfaces\VisibilityInterface |
||
25 | { |
||
26 | /** @var ClassDescriptor|InterfaceDescriptor|TraitDescriptor $parent */ |
||
27 | protected $parent; |
||
28 | |||
29 | /** @var bool $abstract */ |
||
30 | protected $abstract = false; |
||
31 | |||
32 | /** @var bool $final */ |
||
33 | protected $final = false; |
||
34 | |||
35 | /** @var bool $static */ |
||
36 | protected $static = false; |
||
37 | |||
38 | /** @var string $visibility */ |
||
39 | protected $visibility = 'public'; |
||
40 | |||
41 | /** @var Collection */ |
||
42 | protected $arguments; |
||
43 | |||
44 | /** @var Type */ |
||
45 | private $returnType; |
||
46 | |||
47 | /** |
||
48 | * Initializes the all properties representing a collection with a new Collection object. |
||
49 | */ |
||
50 | 1 | public function __construct() |
|
51 | { |
||
52 | 1 | parent::__construct(); |
|
53 | |||
54 | 1 | $this->setArguments(new Collection()); |
|
55 | 1 | } |
|
56 | |||
57 | /** |
||
58 | * @param ClassDescriptor|InterfaceDescriptor|TraitDescriptor $parent |
||
59 | */ |
||
60 | public function setParent($parent) |
||
61 | { |
||
62 | $this->setFullyQualifiedStructuralElementName( |
||
63 | $parent->getFullyQualifiedStructuralElementName() . '::' . $this->getName() . '()' |
||
64 | ); |
||
65 | |||
66 | // reset cached inherited element so that it can be re-detected. |
||
67 | $this->inheritedElement = null; |
||
68 | |||
69 | $this->parent = $parent; |
||
70 | } |
||
71 | |||
72 | /** |
||
73 | * @return ClassDescriptor|InterfaceDescriptor|TraitDescriptor |
||
74 | */ |
||
75 | public function getParent() |
||
76 | { |
||
77 | return $this->parent; |
||
78 | } |
||
79 | |||
80 | /** |
||
81 | * {@inheritDoc} |
||
82 | */ |
||
83 | 1 | public function setAbstract($abstract) |
|
84 | { |
||
85 | 1 | $this->abstract = $abstract; |
|
86 | 1 | } |
|
87 | |||
88 | /** |
||
89 | * {@inheritDoc} |
||
90 | */ |
||
91 | 1 | public function isAbstract() |
|
92 | { |
||
93 | 1 | return $this->abstract; |
|
94 | } |
||
95 | |||
96 | /** |
||
97 | * {@inheritDoc} |
||
98 | */ |
||
99 | 1 | public function setFinal($final) |
|
100 | { |
||
101 | 1 | $this->final = $final; |
|
102 | 1 | } |
|
103 | |||
104 | /** |
||
105 | * {@inheritDoc} |
||
106 | */ |
||
107 | 1 | public function isFinal() |
|
108 | { |
||
109 | 1 | return $this->final; |
|
110 | } |
||
111 | |||
112 | /** |
||
113 | * {@inheritDoc} |
||
114 | */ |
||
115 | 1 | public function setStatic($static) |
|
116 | { |
||
117 | 1 | $this->static = $static; |
|
118 | 1 | } |
|
119 | |||
120 | /** |
||
121 | * {@inheritDoc} |
||
122 | */ |
||
123 | 1 | public function isStatic() |
|
124 | { |
||
125 | 1 | return $this->static; |
|
126 | } |
||
127 | |||
128 | /** |
||
129 | * {@inheritDoc} |
||
130 | */ |
||
131 | 1 | public function setVisibility($visibility) |
|
132 | { |
||
133 | 1 | $this->visibility = $visibility; |
|
134 | 1 | } |
|
135 | |||
136 | /** |
||
137 | * {@inheritDoc} |
||
138 | */ |
||
139 | 1 | public function getVisibility() |
|
140 | { |
||
141 | 1 | return $this->visibility; |
|
142 | } |
||
143 | |||
144 | /** |
||
145 | * {@inheritDoc} |
||
146 | */ |
||
147 | 1 | public function setArguments(Collection $arguments) |
|
148 | { |
||
149 | 1 | foreach ($arguments as $argument) { |
|
150 | $argument->setMethod($this); |
||
151 | } |
||
152 | |||
153 | 1 | $this->arguments = $arguments; |
|
154 | 1 | } |
|
155 | |||
156 | /** |
||
157 | * @param string $name |
||
158 | */ |
||
159 | public function addArgument($name, ArgumentDescriptor $argument) |
||
160 | { |
||
161 | $argument->setMethod($this); |
||
162 | $this->arguments->set($name, $argument); |
||
163 | } |
||
164 | |||
165 | /** |
||
166 | * {@inheritDoc} |
||
167 | */ |
||
168 | 1 | public function getArguments() |
|
169 | { |
||
170 | 1 | return $this->arguments; |
|
171 | } |
||
172 | |||
173 | 2 | public function getResponse(): ReturnDescriptor |
|
174 | { |
||
175 | 2 | $definedReturn = new ReturnDescriptor('return'); |
|
176 | 2 | $definedReturn->setType($this->returnType); |
|
177 | |||
178 | /** @var Collection|null $returnTags */ |
||
179 | 2 | $returnTags = $this->getReturn(); |
|
180 | |||
181 | 2 | if ($returnTags instanceof Collection && $returnTags->count() > 0) { |
|
182 | /** @var ReturnDescriptor $returnTag */ |
||
183 | 1 | return current($returnTags->getAll()); |
|
184 | } |
||
185 | |||
186 | 2 | return $definedReturn; |
|
187 | } |
||
188 | |||
189 | /** |
||
190 | * Returns the file associated with the parent class, interface or trait. |
||
191 | * |
||
192 | * @return FileDescriptor |
||
193 | */ |
||
194 | 1 | public function getFile() |
|
195 | { |
||
196 | 1 | return $this->getParent()->getFile(); |
|
197 | } |
||
198 | |||
199 | /** |
||
200 | * @return Collection |
||
201 | */ |
||
202 | 1 | public function getReturn() |
|
203 | { |
||
204 | /** @var Collection $var */ |
||
205 | 1 | $var = $this->getTags()->get('return', new Collection()); |
|
206 | 1 | if ($var->count() !== 0) { |
|
207 | 1 | return $var; |
|
208 | } |
||
209 | |||
210 | 1 | $inheritedElement = $this->getInheritedElement(); |
|
211 | 1 | if ($inheritedElement) { |
|
212 | 1 | return $inheritedElement->getReturn(); |
|
0 ignored issues
–
show
|
|||
213 | } |
||
214 | |||
215 | return new Collection(); |
||
216 | } |
||
217 | |||
218 | /** |
||
219 | * @return Collection |
||
220 | */ |
||
221 | 1 | public function getParam() |
|
222 | { |
||
223 | /** @var Collection $var */ |
||
224 | 1 | $var = $this->getTags()->get('param', new Collection()); |
|
225 | 1 | if ($var instanceof Collection && $var->count() > 0) { |
|
226 | 1 | return $var; |
|
227 | } |
||
228 | |||
229 | 1 | $inheritedElement = $this->getInheritedElement(); |
|
230 | 1 | if ($inheritedElement) { |
|
231 | 1 | return $inheritedElement->getParam(); |
|
0 ignored issues
–
show
The method
getParam does not exist on object<phpDocumentor\Des...tor\DescriptorAbstract> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
Loading history...
|
|||
232 | } |
||
233 | |||
234 | return new Collection(); |
||
235 | } |
||
236 | |||
237 | /** |
||
238 | * Returns the Method from which this method should inherit its information, if any. |
||
239 | * |
||
240 | * The inheritance scheme for a method is more complicated than for most elements; the following business rules |
||
241 | * apply: |
||
242 | * |
||
243 | * 1. if the parent class/interface extends another class or other interfaces (interfaces have multiple |
||
244 | * inheritance!) then: |
||
245 | * 1. Check each parent class/interface's parent if they have a method with the exact same name |
||
246 | * 2. if a method is found with the same name; return the first one encountered. |
||
247 | * 2. if the parent is a class and implements interfaces, check each interface for a method with the exact same |
||
248 | * name. If such a method is found, return the first hit. |
||
249 | * |
||
250 | * @return MethodDescriptor|null |
||
251 | */ |
||
252 | public function getInheritedElement() |
||
253 | { |
||
254 | if ($this->inheritedElement !== null) { |
||
255 | return $this->inheritedElement; |
||
256 | } |
||
257 | |||
258 | /** @var ClassDescriptor|InterfaceDescriptor|null $associatedClass */ |
||
259 | $associatedClass = $this->getParent(); |
||
260 | if (!$associatedClass instanceof ClassDescriptor && !$associatedClass instanceof InterfaceDescriptor) { |
||
261 | return null; |
||
262 | } |
||
263 | |||
264 | /** @var ClassDescriptor|InterfaceDescriptor $parentClass|null */ |
||
265 | $parentClass = $associatedClass->getParent(); |
||
266 | if ($parentClass instanceof ClassDescriptor || $parentClass instanceof Collection) { |
||
267 | // the parent of a class is always a class, but the parent of an interface is a collection of interfaces. |
||
268 | $parents = $parentClass instanceof ClassDescriptor ? [$parentClass] : $parentClass->getAll(); |
||
269 | foreach ($parents as $parent) { |
||
270 | if ($parent instanceof ClassDescriptor || $parent instanceof InterfaceDescriptor) { |
||
271 | /** @var MethodDescriptor $parentMethod */ |
||
272 | $parentMethod = $parent->getMethods()->get($this->getName()); |
||
273 | if ($parentMethod) { |
||
274 | $this->inheritedElement = $parentMethod; |
||
275 | |||
276 | return $this->inheritedElement; |
||
277 | } |
||
278 | } |
||
279 | } |
||
280 | } |
||
281 | |||
282 | // also check all implemented interfaces next if the parent is a class and not an interface |
||
283 | if ($associatedClass instanceof ClassDescriptor) { |
||
284 | /** @var InterfaceDescriptor $interface */ |
||
285 | foreach ($associatedClass->getInterfaces() as $interface) { |
||
286 | if (!$interface instanceof InterfaceDescriptor) { |
||
287 | continue; |
||
288 | } |
||
289 | |||
290 | /** @var MethodDescriptor $parentMethod */ |
||
291 | $parentMethod = $interface->getMethods()->get($this->getName()); |
||
292 | if ($parentMethod) { |
||
293 | $this->inheritedElement = $parentMethod; |
||
294 | |||
295 | return $this->inheritedElement; |
||
296 | } |
||
297 | } |
||
298 | } |
||
299 | |||
300 | return null; |
||
301 | } |
||
302 | |||
303 | /** |
||
304 | 1 | * Sets return type of this method. |
|
305 | */ |
||
306 | 1 | public function setReturnType(Type $returnType) |
|
307 | 1 | { |
|
308 | $this->returnType = $returnType; |
||
309 | } |
||
310 | } |
||
311 |
If you implement
__call
and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.This is often the case, when
__call
is implemented by a parent class and only the child class knows which methods exist: