Completed
Push — develop ( 4b49c4...89d32a )
by Jaap
09:06 queued 05:30
created

src/phpDocumentor/Descriptor/MethodDescriptor.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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