Completed
Push — master ( 30b950...6daa93 )
by
unknown
02:26
created

ClassGenerator::getNamespace()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php declare(strict_types=1);
2
/**
3
 * Created by Vitaly Iegorov <[email protected]>.
4
 * on 03.09.16 at 09:58
5
 */
6
namespace samsonframework\generator;
7
8
use samsonframework\generator\exception\ClassNameNotFoundException;
9
10
/**
11
 * Class generator class.
12
 *
13
 * @author Vitaly Egorov <[email protected]>
14
 */
15
class ClassGenerator extends AbstractGenerator
16
{
17
    use AbstractFinalTrait;
18
19
    /** OOP public visibility */
20
    const VISIBILITY_PUBLIC = 'public';
21
22
    /** OOP protected visibility */
23
    const VISIBILITY_PROTECTED = 'protected';
24
25
    /** OOP private visibility */
26
    const VISIBILITY_PRIVATE = 'private';
27
28
    /** @var string Class name */
29
    protected $className;
30
31
    /** @var string Parent class name */
32
    protected $parentClassName;
33
34
    /** @var string Class namespace */
35
    protected $namespace;
36
37
    /** @var array Collection of class uses */
38
    protected $uses = [];
39
40
    /** @var array Collection of class interfaces */
41
    protected $interfaces = [];
42
43
    /** @var array Collection of class used traits */
44
    protected $traits = [];
45
46
    /** @var string Multi-line file description */
47
    protected $fileDescription;
48
49
    /**
50
     * ClassGenerator constructor.
51
     *
52
     * @param string           $className Class name
53
     * @param AbstractGenerator $parent    Parent generator
54
     */
55 31
    public function __construct(string $className = null, AbstractGenerator $parent = null)
56
    {
57 31
        $this->className = $className;
58
59 31
        parent::__construct($parent);
60 31
    }
61
62
    /**
63
     * Set class file description.
64
     *
65
     * @param array $description Collection of class file description lines
66
     *
67
     * @return ClassGenerator
68
     */
69 1
    public function defDescription(array $description) : ClassGenerator
70
    {
71 1
        $commentsGenerator = new CommentsGenerator($this);
72 1
        foreach ($description as $line) {
73 1
            $commentsGenerator->defLine($line);
74
        }
75
76 1
        $this->fileDescription = $commentsGenerator->code();
77
78 1
        return $this;
79
    }
80
81
    /**
82
     * Set class namespace.
83
     *
84
     * @param string $namespace
85
     *
86
     * @return ClassGenerator
87
     */
88 30
    public function defNamespace(string $namespace) : ClassGenerator
89
    {
90 30
        $this->namespace = $namespace;
91
92 30
        return $this;
93
    }
94
95
    /**
96
     * Set class name.
97
     *
98
     * @param string $className
99
     *
100
     * @return ClassGenerator
101
     */
102 1
    public function defName(string $className) : ClassGenerator
103
    {
104 1
        $this->className = $className;
105
106 1
        return $this;
107
    }
108
109
    /**
110
     * Set class use.
111
     *
112
     * @param string $use Use class name
113
     * @param string $alias Use class name
114
     *
115
     * @return ClassGenerator
116
     */
117 2
    public function defUse(string $use, string $alias = null) : ClassGenerator
118
    {
119
        // Store the alias of class
120 2
        if ($alias) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $alias of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
121 1
            $this->uses[$alias] = $use;
122
        } else {
123 2
            $this->uses[] = $use;
124
        }
125
126 2
        return $this;
127
    }
128
129
    /**
130
     * Set parent class.
131
     *
132
     * @param string $className Parent class name
133
     *
134
     * @return ClassGenerator
135
     */
136 2
    public function defExtends(string $className) : ClassGenerator
137
    {
138 2
        $this->parentClassName = $className;
139
140 2
        return $this;
141
    }
142
143
    /**
144
     * Set implements interfaces.
145
     *
146
     * @param string $interfaceName Interface name
147
     *
148
     * @return ClassGenerator
149
     */
150 3
    public function defImplements(string $interfaceName) : ClassGenerator
151
    {
152 3
        $this->interfaces[] = $interfaceName;
153
154 3
        return $this;
155
    }
156
157
    /**
158
     * Set class trait use.
159
     *
160
     * @param string $trait Trait class name
161
     *
162
     * @return ClassGenerator
163
     */
164 1
    public function defTrait(string $trait) : ClassGenerator
165
    {
166 1
        $this->traits[] = $trait;
167
168 1
        return $this;
169
    }
170
171
    /**
172
     * Set protected class property.
173
     *
174
     * @param string $name        Property name
175
     * @param string $type        Property type
176
     * @param mixed  $value       Property value
177
     * @param string $description Property description
178
     *
179
     * @return PropertyGenerator
180
     */
181 1
    public function defProtectedProperty(string $name, string $type, $value, string $description = null) : PropertyGenerator
182
    {
183 1
        return $this->defProperty($name, $type, $value, $description)->defProtected();
184
    }
185
186
    /**
187
     * Set class property.
188
     *
189
     * @param string $name        Property name
190
     * @param string $type        Property type
191
     * @param mixed  $value       Property value
192
     * @param string $description Property description
193
     *
194
     * @return PropertyGenerator
195
     */
196 6
    public function defProperty(string $name, string $type, $value = null, string $description = null) : PropertyGenerator
197
    {
198 6
        return (new PropertyGenerator($name, $value, $this))
199 6
            ->setIndentation($this->indentation)
200 6
            ->increaseIndentation()
201 6
            ->defComment()
202 6
            ->defVar($type, $description)
203 6
            ->end();
204
    }
205
206
    /**
207
     * Set protected static class property.
208
     *
209
     * @param string $name        Property name
210
     * @param string $type        Property type
211
     * @param mixed  $value       Property value
212
     * @param string $description Property description
213
     *
214
     * @return PropertyGenerator
215
     */
216 1
    public function defProtectedStaticProperty(string $name, string $type, $value, string $description = null) : PropertyGenerator
217
    {
218 1
        return $this->defStaticProperty($name, $type, $value, $description)->defProtected();
219
    }
220
221
    /**
222
     * Set static class property.
223
     *
224
     * @param string $name        Property name
225
     * @param string $type        Property type
226
     * @param mixed  $value       Property value
227
     * @param string $description Property description
228
     *
229
     * @return PropertyGenerator
230
     */
231 2
    public function defStaticProperty(string $name, string $type, $value, string $description = null) : PropertyGenerator
232
    {
233 2
        return $this->defProperty($name, $type, $value, $description)->defStatic();
234
    }
235
236
    /**
237
     * Set protected class method.
238
     *
239
     * @param string $name Method name
240
     *
241
     * @return MethodGenerator
242
     */
243 1
    public function defProtectedMethod(string $name) : MethodGenerator
244
    {
245 1
        return $this->defMethod($name)->defProtected();
246
    }
247
248
    /**
249
     * Set public class method.
250
     *
251
     * @param string $name Method name
252
     *
253
     * @return MethodGenerator
254
     */
255 6
    public function defMethod(string $name) : MethodGenerator
256
    {
257 6
        return (new MethodGenerator($name, $this))->setIndentation($this->indentation)->increaseIndentation();
258
    }
259
260
    /**
261
     * Set protected static class method.
262
     *
263
     * @param string $name Method name
264
     *
265
     * @return MethodGenerator
266
     */
267 1
    public function defProtectedStaticMethod(string $name) : MethodGenerator
268
    {
269 1
        return $this->defStaticMethod($name)->defProtected();
270
    }
271
272
    /**
273
     * Set public static class method.
274
     *
275
     * @param string $name Method name
276
     *
277
     * @return MethodGenerator
278
     */
279 2
    public function defStaticMethod(string $name) : MethodGenerator
280
    {
281 2
        return $this->defMethod($name)->defStatic();
282
    }
283
284
    /**
285
     * Set class constant.
286
     *
287
     * @param string $name
288
     * @param mixed $value
289
     *
290
     * @return $this|ClassConstantGenerator
291
     */
292 1
    public function defConstant(string $name, $value, string $type, string $description) : ClassConstantGenerator
293
    {
294 1
        return (new ClassConstantGenerator($name, $value, $this))
295 1
            ->setIndentation($this->indentation)
296 1
            ->increaseIndentation()
297 1
            ->defComment()
298 1
                ->defLine($type.' '.$description)
299 1
            ->end();
300
    }
301
302 27
    protected function buildUsesCode(array $formattedCode) : array
303
    {
304
        // Add uses
305 27
        foreach ($this->uses as $alias => $use) {
306 2
            $formattedCode[] = 'use ' . $use . (is_string($alias) ? ' as ' . $alias : '') . ';';
307
        }
308
309
        // One empty line after uses if we have them
310 27
        if (count($this->uses)) {
311 2
            $formattedCode[] = '';
312
        }
313
314 27
        return $formattedCode;
315
    }
316
317 27
    protected function buildCommentsCode(array $formattedCode) : array
318
    {
319
        // Add comments
320 27
        if (array_key_exists(CommentsGenerator::class, $this->generatedCode)) {
321 1
            $formattedCode[] = $this->generatedCode[CommentsGenerator::class];
322
        }
323
324 27
        return $formattedCode;
325
    }
326
327 27
    protected function buildTraitsCode(array $formattedCode, string $innerIndentation) : array
328
    {
329
        // Add traits
330 27
        foreach ($this->traits as $trait) {
331 1
            $formattedCode[] = $innerIndentation . 'use ' . $trait . ';';
332
        }
333
334
        // One empty line after traits if we have them
335 27
        if (count($this->traits)) {
336 1
            $formattedCode[] = '';
337
        }
338
339 27
        return $formattedCode;
340
    }
341
342 27
    protected function buildFileDescriptionCode(array $formattedCode) : array
343
    {
344
        // Prepend file description if present
345 27
        if ($this->fileDescription !== null) {
346 1
            array_unshift($formattedCode, $this->fileDescription);
347
        }
348
349 27
        return $formattedCode;
350
    }
351
352 27
    protected function buildConstantsCode(array $formattedCode) : array
353
    {
354
        // Add constants
355 27
        if (array_key_exists(ClassConstantGenerator::class, $this->generatedCode)) {
356 1
            $formattedCode[] = $this->generatedCode[ClassConstantGenerator::class];
357
        }
358
359 27
        return $formattedCode;
360
    }
361
362 27
    protected function buildPropertiesCode(array $formattedCode) : array
363
    {
364 27
        if (array_key_exists(PropertyGenerator::class, $this->generatedCode)) {
365 6
            $formattedCode[] = $this->generatedCode[PropertyGenerator::class];
366
        }
367
368 27
        return $formattedCode;
369
    }
370
371 27
    protected function buildMethodsCode(array $formattedCode) : array
372
    {
373 27
        if (array_key_exists(MethodGenerator::class, $this->generatedCode)) {
374 6
            $formattedCode[] = $this->generatedCode[MethodGenerator::class];
375
        }
376
377 27
        return $formattedCode;
378
    }
379
380 28
    protected function buildNamespaceCode(array $formattedCode = []) : array
381
    {
382 28
        if ($this->namespace === null) {
383 1
            throw new \InvalidArgumentException('Class namespace should be defined');
384
        }
385
386 27
        $formattedCode[] = 'namespace ' . $this->namespace . ';';
387
388
        // One empty line after namespace
389 27
        $formattedCode[] = '';
390
391 27
        return $formattedCode;
392
    }
393
394
    /**
395
     * {@inheritdoc}
396
     * @throws \InvalidArgumentException
397
     * @throws ClassNameNotFoundException
398
     */
399 29
    public function code(int $indentation = 0) : string
400
    {
401 29
        if (!$this->className) {
402 1
            throw new ClassNameNotFoundException('Class name should be defined');
403
        }
404
405 28
        $formattedCode = $this->buildNamespaceCode();
406 27
        $formattedCode = $this->buildFileDescriptionCode($formattedCode);
407 27
        $formattedCode = $this->buildUsesCode($formattedCode);
408 27
        $formattedCode = $this->buildCommentsCode($formattedCode);
409
410
        // Add previously generated code
411 27
        $formattedCode[] = $this->buildDefinition();
412 27
        $formattedCode[] = '{';
413
414 27
        $indentationString = $this->indentation($indentation);
415 27
        $innerIndentation = $this->indentation(1);
416
417 27
        $formattedCode = $this->buildTraitsCode($formattedCode, $innerIndentation);
418 27
        $formattedCode = $this->buildConstantsCode($formattedCode);
419 27
        $formattedCode = $this->buildPropertiesCode($formattedCode);
420 27
        $formattedCode = $this->buildMethodsCode($formattedCode);
421
422 27
        $formattedCode[] = '}';
423
424 27
        return implode("\n" . $indentationString, $formattedCode);
425
    }
426
427
    /**
428
     * Build class definition.
429
     *
430
     * @return string Function definition
431
     */
432 26
    protected function buildDefinition()
433
    {
434 26
        return ($this->isFinal ? 'final ' : '') .
435 26
        ($this->isAbstract ? 'abstract ' : '') .
436 26
        'class ' .
437 26
        $this->className .
438 26
        ($this->parentClassName ? ' extends ' . $this->parentClassName : '') .
439 26
        (count($this->interfaces) ? rtrim(' implements ' . implode(', ', $this->interfaces), ', ') : '');
440
    }
441
442
    /**
443
     * @return string
444
     */
445
    public function getClassName(): string
446
    {
447
        return $this->className;
448
    }
449
450
    /**
451
     * @return string
452
     */
453
    public function getNamespace(): string
454
    {
455
        return $this->namespace;
456
    }
457
}
458