Completed
Push — master ( ed922a...ce73d9 )
by Nikola
03:26
created

ClassMetadata::__construct()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 25
ccs 0
cts 20
cp 0
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 15
nc 6
nop 8
crap 20

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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;
11
12
use RunOpenCode\AbstractBuilder\Exception\InvalidArgumentException;
13
14
/**
15
 * Class ClassMetadata
16
 *
17
 * @package RunOpenCode\AbstractBuilder\Ast
18
 */
19
class ClassMetadata
20
{
21
    /**
22
     * @var array
23
     */
24
    private $ast;
25
26
    /**
27
     * @var string
28
     */
29
    private $namespace;
30
31
    /**
32
     * @var string
33
     */
34
    private $class;
35
36
    /**
37
     * @var string
38
     */
39
    private $fqcn;
40
41
    /**
42
     * @var string
43
     */
44
    private $filename;
45
46
    /**
47
     * @var bool
48
     */
49
    private $final;
50
51
    /**
52
     * @var bool
53
     */
54
    private $abstract;
55
56
    /**
57
     * @var MethodMetadata[]
58
     */
59
    private $methods;
60
61
    /**
62
     * @var ClassMetadata
63
     */
64
    private $parent;
65
66
    /**
67
     * ClassMetadata constructor.
68
     *
69
     * @param $ast
70
     * @param string $namespace
71
     * @param string $class
72
     * @param null|string $filename
73
     * @param bool $final
74
     * @param bool $abstract
75
     * @param MethodMetadata[] $methods
76
     *
77
     * @throws \RunOpenCode\AbstractBuilder\Exception\InvalidArgumentException
78
     */
79
    public function __construct($ast, $namespace, $class, $filename = null, $final = false, $abstract = false, array $methods = [], ClassMetadata $parent = null)
80
    {
81
        $this->ast = $ast;
82
        $this->namespace = trim($namespace, '\\');
83
        $this->class = trim($class, '\\');
84
        $this->filename = $filename;
85
        $this->final = $final;
86
        $this->abstract = $abstract;
87
        $this->methods = $methods;
88
        $this->parent = $parent;
89
90
        $this->fqcn = '\\'.$this->class;
91
92
        if ($this->namespace) {
93
            $this->fqcn = '\\'.$this->namespace.'\\'.$this->class;
94
        }
95
96
97
        foreach (explode('\\', ltrim($this->fqcn, '\\')) as $part) {
98
99
            if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $part)) {
100
                throw new InvalidArgumentException(sprintf('Provided full qualified class name "%s" is not valid PHP class name.', $this->fqcn));
101
            }
102
        }
103
    }
104
105
    /**
106
     * @return
107
     */
108
    public function getAst()
109
    {
110
        return $this->ast;
111
    }
112
113
    /**
114
     * @return string
115
     */
116
    public function getNamespace()
117
    {
118
        return $this->namespace;
119
    }
120
121
    /**
122
     * @return string
123
     */
124
    public function getClass()
125
    {
126
        return $this->class;
127
    }
128
129
    /**
130
     * @return string
131
     */
132
    public function getFqcn()
133
    {
134
        return $this->fqcn;
135
    }
136
137
    /**
138
     * @return string
139
     */
140
    public function getFilename()
141
    {
142
        return $this->filename;
143
    }
144
145
    /**
146
     * @return bool
147
     */
148
    public function isFinal()
149
    {
150
        return $this->final;
151
    }
152
153
    /**
154
     * @return bool
155
     */
156
    public function isAbstract()
157
    {
158
        return $this->abstract;
159
    }
160
161
    /**
162
     * @return MethodMetadata[]
163
     */
164
    public function getMethods()
165
    {
166
        return $this->methods;
167
    }
168
169
    /**
170
     * @return MethodMetadata|null
171
     */
172
    public function getConstructor()
173
    {
174
        foreach ($this->methods as $method) {
175
176
            if ('__construct' === $method->getName()) {
177
                return $method;
178
            }
179
        }
180
181
        if (null !== $this->parent) {
182
            return $this->parent->getConstructor();
183
        }
184
185
        return null;
186
    }
187
188
    /**
189
     * Check if class inherits some other class.
190
     *
191
     * @return bool
192
     */
193
    public function hasParent()
194
    {
195
        return null !== $this->parent;
196
    }
197
198
    /**
199
     * @return ClassMetadata|null
200
     */
201
    public function getParent()
202
    {
203
        return $this->parent;
204
    }
205
206
    /**
207
     * Check if class has public method, with optional tree traverse.
208
     *
209
     * @param string $name
210
     * @param bool $traverse
211
     *
212
     * @return bool
213
     */
214
    public function hasPublicMethod($name, $traverse = true)
215
    {
216
        foreach ($this->methods as $method) {
217
218
            if ($method->isPublic() && $name === $method->getName()) {
219
                return true;
220
            }
221
        }
222
223
        if ($traverse && $this->hasParent()) {
224
            return $this->getParent()->hasPublicMethod($name, $traverse);
225
        }
226
227
        return false;
228
    }
229
230
    /**
231
     * @return bool
232
     */
233
    public function isAutoloadable()
234
    {
235
        return class_exists($this->getFqcn(), true);
236
    }
237
238
    /**
239
     * {@inheritdoc}
240
     */
241
    public function __toString()
242
    {
243
        return $this->getFqcn();
244
    }
245
246
    /**
247
     * Initialize new, non-existing class.
248
     *
249
     * @param string $fqcn
250
     *
251
     * @return ClassMetadata|static $this
252
     */
253
    public static function create($fqcn)
254
    {
255
        $parts = explode('\\', trim($fqcn, '\\'));
256
        $class = array_pop($parts);
257
        $namespace = implode('\\', $parts);
258
259
        return new static([], $namespace, $class);
260
    }
261
262
    /**
263
     * Clones original metadata object, with possible values overwrite
264
     *
265
     * @param ClassMetadata $original
266
     * @param array $overwrite
267
     *
268
     * @return ClassMetadata|static $this
269
     */
270
    public static function clone(ClassMetadata $original, array $overwrite = [])
271
    {
272
        $data = [
273
            'ast' => $original->getAst(),
274
            'namespace' => $original->getNamespace(),
275
            'class' => $original->getClass(),
276
            'filename' => $original->getFilename(),
277
            'final' => $original->isFinal(),
278
            'abstract ' => $original->isAbstract(),
279
            'methods' => $original->getMethods(),
280
            'parent' => $original->getParent()
281
        ];
282
283
        $data = array_merge($data, $overwrite);
284
285
        return (new \ReflectionClass(static::class))->newInstanceArgs(array_values($data));
286
    }
287
}
288