Completed
Push — master ( 72d2b6...5bac00 )
by Nikola
02:15
created

ClassMetadata::hasPublicMethod()   D

Complexity

Conditions 9
Paths 11

Size

Total Lines 28
Code Lines 11

Duplication

Lines 28
Ratio 100 %

Code Coverage

Tests 7
CRAP Score 12.8936

Importance

Changes 0
Metric Value
dl 28
loc 28
ccs 7
cts 11
cp 0.6364
rs 4.909
c 0
b 0
f 0
cc 9
eloc 11
nc 11
nop 2
crap 12.8936
1
<?php
2
/*
3
 * This file is part of the Abstract builder package, an RunOpenCode project.
4
 *
5
 * (c) 2017 RunOpenCode
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace RunOpenCode\AbstractBuilder\Ast\Metadata;
11
12
use PhpParser\Node\Stmt\Class_;
13
use RunOpenCode\AbstractBuilder\Exception\InvalidArgumentException;
14
use RunOpenCode\AbstractBuilder\Exception\RuntimeException;
15
use RunOpenCode\AbstractBuilder\Utils\ClassUtils;
16
17
/**
18
 * Class ClassMetadata
19
 *
20
 * @package RunOpenCode\AbstractBuilder\Ast\Metadata
21
 */
22
class ClassMetadata
23
{
24
    /**
25
     * @var string
26
     */
27
    private $name;
28
29
    /**
30
     * @var ClassMetadata
31
     */
32
    private $parent;
33
34
    /**
35
     * @var TraitMetadata[]
36
     */
37
    private $traits;
38
39
    /**
40
     * @var bool
41
     */
42
    private $final;
43
44
    /**
45
     * @var bool
46
     */
47
    private $abstract;
48
49
    /**
50
     * @var MethodMetadata[]
51
     */
52
    private $methods;
53
54
    /**
55
     * @var Class_
56
     */
57
    private $ast;
58
59
    /**
60
     * ClassMetadata constructor.
61
     *
62
     * @param string $name
63
     * @param ClassMetadata|null $parent
64
     * @param bool $final
65
     * @param bool $abstract
66
     * @param MethodMetadata[] $methods
67
     * @param Class_ $ast
68
     */
69 4
    public function __construct($name, ClassMetadata $parent = null, array $traits = [], $final = false, $abstract = false, array $methods = [], Class_ $ast = null)
70
    {
71 4
        $this->name = $name;
72
73 4
        if (!ClassUtils::isClassNameValid($this->name)) {
74
            throw new InvalidArgumentException(sprintf('Provided class name "%s" is not valid PHP class name.', $this->name));
75
        }
76
77 4
        $this->parent = $parent;
78 4
        $this->traits = $traits;
79 4
        $this->final = $final;
80 4
        $this->abstract = $abstract;
81 4
        $this->methods = $methods;
82 4
        $this->ast = $ast;
83 4
    }
84
85
    /**
86
     * @return string
87
     */
88 2
    public function getName()
89
    {
90 2
        return $this->name;
91
    }
92
93
    /**
94
     * @return string
95
     */
96
    public function getFqcn()
97
    {
98
        return '\\'.$this->name;
99
    }
100
101
    /**
102
     * @return string
103
     */
104 1
    public function getShortName()
105
    {
106 1
        $parts = explode('\\', $this->name);
107 1
        return end($parts);
108
    }
109
110
    /**
111
     * @return bool
112
     */
113
    public function isAutoloadable()
114
    {
115
        return class_exists($this->getName(), true);
116
    }
117
118
    /**
119
     * Check if class inherits some other class.
120
     *
121
     * @return bool
122
     */
123 1
    public function hasParent()
124
    {
125 1
        return null !== $this->parent;
126
    }
127
128
    /**
129
     * @return ClassMetadata|null
130
     */
131 1
    public function getParent()
132
    {
133 1
        return $this->parent;
134
    }
135
136
    /**
137
     * @return bool
138
     */
139 1
    public function hasTraits()
140
    {
141 1
        return count($this->traits) > 0;
142
    }
143
144
    /**
145
     * @return TraitMetadata[]
146
     */
147
    public function getTraits()
148
    {
149
        return $this->traits;
150
    }
151
152
    /**
153
     * @return bool
154
     */
155
    public function isFinal()
156
    {
157
        return $this->final;
158
    }
159
160
    /**
161
     * @return bool
162
     */
163
    public function isAbstract()
164
    {
165
        return $this->abstract;
166
    }
167
168
    /**
169
     * @return MethodMetadata[]
170
     */
171
    public function getMethods()
172
    {
173
        return $this->methods;
174
    }
175
176
    /**
177
     * Check if class has method, with optional inheritance tree and trait traverse.
178
     *
179
     * @param string $name
180
     * @param bool $traverse
181
     *
182
     * @return bool
183
     */
184 View Code Duplication
    public function hasMethod($name, $traverse = true)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
185
    {
186
        foreach ($this->methods as $method) {
187
188
            if ($name === $method->getName()) {
189
                return true;
190
            }
191
        }
192
193
        if ($traverse && $this->hasTraits()) {
194
195
            /**
196
             * @var TraitMetadata $trait
197
             */
198
            foreach ($this->traits as $trait) {
199
200
                if ($trait->hasMethod($name, $traverse)) {
201
                    return true;
202
                }
203
            }
204
        }
205
206
207
        if ($traverse && $this->hasParent()) {
208
            return $this->getParent()->hasMethod($name, $traverse);
209
        }
210
211
        return false;
212
    }
213
214
    /**
215
     * Check if class has public method, with optional inheritance tree and trait traverse.
216
     *
217
     * @param string $name
218
     * @param bool $traverse
219
     *
220
     * @return bool
221
     */
222 1 View Code Duplication
    public function hasPublicMethod($name, $traverse = true)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
223
    {
224 1
        foreach ($this->methods as $method) {
225
226 1
            if ($name === $method->getName()) {
227 1
                return $method->isPublic();
228
            }
229
        }
230
231 1
        if ($traverse && $this->hasTraits()) {
232
233
            /**
234
             * @var TraitMetadata $trait
235
             */
236
            foreach ($this->traits as $trait) {
237
238
                if ($trait->hasPublicMethod($name, $traverse)) {
239
                    return true;
240
                }
241
            }
242
        }
243
244 1
        if ($traverse && $this->hasParent()) {
245
            return $this->getParent()->hasPublicMethod($name, $traverse);
246
        }
247
248 1
        return false;
249
    }
250
251
    /**
252
     * Get public method for class, with optional inheritance tree and trait traverse.
253
     *
254
     * @param string $name
255
     * @param bool $traverse
256
     *
257
     * @return MethodMetadata
258
     *
259
     * @throws \RunOpenCode\AbstractBuilder\Exception\RuntimeException
260
     */
261 1
    public function getPublicMethod($name, $traverse = true)
262
    {
263 1 View Code Duplication
        foreach ($this->methods as $method) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
264
265 1
            if ($name === $method->getName()) {
266
267 1
                if ($method->isPublic()) {
268 1
                    return $method;
269
                }
270
271
                throw new RuntimeException(sprintf('Method "%s()" for class "%s" exists, but it is not public.', $name, $this->name));
272
            }
273
        }
274
275 View Code Duplication
        if ($traverse && $this->hasTraits()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
276
277
            /**
278
             * @var TraitMetadata $trait
279
             */
280
            foreach ($this->traits as $trait) {
281
282
                if ($trait->hasPublicMethod($name, $traverse)) {
283
                    return $trait->getPublicMethod($name, $traverse);
284
                }
285
            }
286
        }
287
288
        if ($traverse && $this->hasParent() && $this->getParent()->hasPublicMethod($name, $traverse)) {
289
            return $this->getParent()->getPublicMethod($name, $traverse);
290
        }
291
292
        throw new RuntimeException(sprintf('Method "%s()" for class "%s" does not exists.', $name, $this->name));
293
    }
294
295
    /**
296
     * @return Class_
297
     */
298
    public function getAst()
299
    {
300
        return $this->ast;
301
    }
302
303
    /**
304
     * {@inheritdoc}
305
     */
306
    public function __toString()
307
    {
308
        return $this->getName();
309
    }
310
}
311