Passed
Push — develop ( 7610c9...a34416 )
by nguereza
03:35
created

MakeCommand   A

Complexity

Total Complexity 37

Size/Duplication

Total Lines 417
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 143
c 3
b 0
f 0
dl 0
loc 417
rs 9.44
wmc 37

22 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A interact() 0 10 2
A replaceClassUses() 0 4 1
A getConstructorParamsContent() 0 11 2
A execute() 0 42 4
A getPropertiesContent() 0 13 3
A replaceConstructor() 0 5 1
A replaceClasses() 0 8 1
A getConstructorDocBlockContent() 0 11 2
A getPropertyTemplate() 0 11 1
A getUsesContent() 0 13 3
A getConstructorParamsTemplate() 0 17 3
A getConstructorDocBlockTemplate() 0 7 1
A createClass() 0 12 1
A getConstructorBodyContent() 0 11 2
A replaceNamespace() 0 4 1
A getConstructorBodyTemplate() 0 12 2
A replaceMethodBody() 0 5 1
A getConstructorContent() 0 16 2
A getUsesTemplate() 0 4 1
A getMethodBodyContent() 0 3 1
A replaceProperties() 0 4 1
1
<?php
2
3
/**
4
 * Platine Framework
5
 *
6
 * Platine Framework is a lightweight, high-performance, simple and elegant
7
 * PHP Web framework
8
 *
9
 * This content is released under the MIT License (MIT)
10
 *
11
 * Copyright (c) 2020 Platine Framework
12
 *
13
 * Permission is hereby granted, free of charge, to any person obtaining a copy
14
 * of this software and associated documentation files (the "Software"), to deal
15
 * in the Software without restriction, including without limitation the rights
16
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
 * copies of the Software, and to permit persons to whom the Software is
18
 * furnished to do so, subject to the following conditions:
19
 *
20
 * The above copyright notice and this permission notice shall be included in all
21
 * copies or substantial portions of the Software.
22
 *
23
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
 * SOFTWARE.
30
 */
31
32
/**
33
 *  @file MakeCommand.php
34
 *
35
 *  The Make Command base class
36
 *
37
 *  @package    Platine\Framework\Console
38
 *  @author Platine Developers team
39
 *  @copyright  Copyright (c) 2020
40
 *  @license    http://opensource.org/licenses/MIT  MIT License
41
 *  @link   https://www.platine-php.com
42
 *  @version 1.0.0
43
 *  @filesource
44
 */
45
46
declare(strict_types=1);
47
48
namespace Platine\Framework\Console;
49
50
use Platine\Console\Input\Reader;
51
use Platine\Console\Output\Writer;
52
use Platine\Filesystem\Filesystem;
53
use Platine\Framework\App\Application;
54
55
/**
56
 * @class MakeCommand
57
 * @package Platine\Framework\Console
58
 */
59
abstract class MakeCommand extends BaseCommand
60
{
61
    /**
62
     * The type of class
63
     * @var string
64
     */
65
    protected string $type = '';
66
67
    /**
68
     * The class full name given by user
69
     * @var string
70
     */
71
    protected string $className = '';
72
73
    /**
74
     * The action properties
75
     * @var array<string, array<string, mixed>>
76
     */
77
    protected array $properties = [];
78
79
    /**
80
     * Create new instance
81
     * @param Application $application
82
     * @param Filesystem $filesystem
83
     */
84
    public function __construct(
85
        Application $application,
86
        Filesystem $filesystem
87
    ) {
88
        parent::__construct($application, $filesystem);
89
        $this->addArgument('name', 'The full class name (can include root namespace', null, false);
90
        $this->addOption('-f|--force', 'Overwrite existing files.', false, false);
91
    }
92
93
    /**
94
     * {@inheritdoc}
95
     */
96
    public function execute()
97
    {
98
        $io = $this->io();
99
        $writer = $io->writer();
100
        $name = $this->className;
101
102
        $className = $this->getFullClassName($name);
103
        $path = $this->getPath($name);
104
        $namespace = $this->getNamespace($name);
105
106
        $writer->boldGreen(sprintf(
107
            'Generation of new %s class [%s]',
108
            $this->type,
109
            $className
110
        ), true)->eol();
111
112
113
        if ($this->fileExists($name) && !$this->getOptionValue('force')) {
114
            $writer->red(sprintf(
115
                'File [%s] already exists.',
116
                $path
117
            ), true);
118
119
            return;
120
        }
121
122
        $writer->bold('Class: ');
123
        $writer->boldBlueBgBlack($className, true);
124
125
        $writer->bold('Path: ');
126
        $writer->boldBlueBgBlack($path, true);
127
128
        $writer->bold('Namespace: ');
129
        $writer->boldBlueBgBlack($namespace, true);
130
131
        if ($io->confirm(sprintf('Are you confirm the generation of [%s] ?', $className), 'y')) {
132
            $this->createParentDirectory($path);
133
            $content = $this->createClass();
134
135
            $file = $this->filesystem->file($path);
136
            $file->write($content);
137
            $writer->boldGreen(sprintf('Class [%s] generated successfully.', $className), true);
138
        }
139
    }
140
141
    /**
142
     * {@inheritdoc}
143
     */
144
    public function interact(Reader $reader, Writer $writer): void
145
    {
146
        $writer->boldYellow('GENERATION OF NEW CLASS', true)->eol();
147
        $name = $this->getArgumentValue('name');
148
        if (empty($name)) {
149
            $io = $this->io();
150
            $name = $io->prompt('Enter the full class name (can include root namespace)', null);
151
        }
152
153
        $this->className = $name;
154
    }
155
156
    /**
157
     * Return the the class template
158
     * @return string
159
     */
160
    abstract public function getClassTemplate(): string;
161
162
    /**
163
     * Create the class for the given name
164
     * @return string
165
     */
166
    protected function createClass(): string
167
    {
168
        $template = $this->getClassTemplate();
169
170
        $replaceNamespace = $this->replaceNamespace($template);
171
        $replaceUses = $this->replaceClassUses($replaceNamespace);
172
        $replaceClasses = $this->replaceClasses($replaceUses);
173
        $replaceProperties = $this->replaceProperties($replaceClasses);
174
        $replaceConstructor = $this->replaceConstructor($replaceProperties);
175
        $replaceMethodBody = $this->replaceMethodBody($replaceConstructor);
176
177
        return $replaceMethodBody;
178
    }
179
180
    /**
181
     * Replace the name space
182
     * @param string $content
183
     * @return string
184
     */
185
    protected function replaceNamespace(string $content): string
186
    {
187
        $namespace = $this->getNamespace($this->className);
188
        return str_replace('%namespace%', $namespace, $content);
189
    }
190
191
    /**
192
     * Replace the properties
193
     * @param string $content
194
     * @return string
195
     */
196
    protected function replaceProperties(string $content): string
197
    {
198
        $replaceContent = $this->getPropertiesContent();
199
        return str_replace('%properties%', $replaceContent, $content);
200
    }
201
202
    /**
203
     * Replace the constructor
204
     * @param string $content
205
     * @return string
206
     */
207
    protected function replaceConstructor(string $content): string
208
    {
209
        $replaceContent = $this->getConstructorContent();
210
211
        return str_replace('%constructor%', $replaceContent, $content);
212
    }
213
    
214
    /**
215
     * Replace the method body
216
     * @param string $content
217
     * @return string
218
     */
219
    protected function replaceMethodBody(string $content): string
220
    {
221
        $replaceContent = $this->getMethodBodyContent();
222
223
        return str_replace('%method_body%', $replaceContent, $content);
224
    }
225
226
    /**
227
     * Replace the class uses instructions
228
     * @param string $content
229
     * @return string
230
     */
231
    protected function replaceClassUses(string $content): string
232
    {
233
        $replaceContent = $this->getUsesContent();
234
        return str_replace('%uses%', $replaceContent, $content);
235
    }
236
237
    /**
238
     * Replace the classes
239
     * @param string $content
240
     * @return string
241
     */
242
    protected function replaceClasses(string $content): string
243
    {
244
        $shortClassName = $this->getShortClassName($this->className);
245
        $fullClassName = $this->getFullClassName($this->className);
246
247
        $replaced = str_replace('%classname%', $shortClassName, $content);
248
249
        return str_replace('%fullclassname%', $fullClassName, $replaced);
250
    }
251
252
    /**
253
     * Return the properties content
254
     * @return string
255
     */
256
    protected function getPropertiesContent(): string
257
    {
258
        if (empty($this->properties)) {
259
            return '';
260
        }
261
262
        $content = '';
263
264
        foreach ($this->properties as $className => $info) {
265
            $content .= $this->getPropertyTemplate($className, $info);
266
        }
267
268
        return $content;
269
    }
270
271
    /**
272
     * Return the name space uses content
273
     * @return string
274
     */
275
    protected function getUsesContent(): string
276
    {
277
        if (empty($this->properties)) {
278
            return '';
279
        }
280
281
        $content = '';
282
283
        foreach ($this->properties as $className => $info) {
284
            $content .= $this->getUsesTemplate($className);
285
        }
286
287
        return $content;
288
    }
289
290
291
    /**
292
     * Return the constructor content
293
     * @return string
294
     */
295
    protected function getConstructorContent(): string
296
    {
297
        if (empty($this->properties)) {
298
            return '';
299
        }
300
301
        $docblock = $this->getConstructorDocBlockContent();
302
        $params = $this->getConstructorParamsContent();
303
        $body = $this->getConstructorBodyContent();
304
305
        return <<<EOF
306
        $docblock
307
            public function __construct(
308
               $params
309
            ){
310
                $body
311
            }
312
        EOF;
313
    }
314
    
315
    /**
316
     * Return the constructor content
317
     * @return string
318
     */
319
    protected function getMethodBodyContent(): string
320
    {
321
        return '';
322
    }
323
324
325
    /**
326
     * Return the constructor document block comment content
327
     * @return string
328
     */
329
    protected function getConstructorDocBlockContent(): string
330
    {
331
        $content = '';
332
        foreach ($this->properties as $className => $info) {
333
            $content .= $this->getConstructorDocBlockTemplate($className, $info);
334
        }
335
336
        return <<<EOF
337
        /**
338
            * Create new instance
339
            $content*/
340
        EOF;
341
    }
342
343
    /**
344
     * Return the constructor parameters content
345
     * @return string
346
     */
347
    protected function getConstructorParamsContent(): string
348
    {
349
        $content = '';
350
        $i = 1;
351
        $count = count($this->properties);
352
        foreach ($this->properties as $className => $info) {
353
            $content .= $this->getConstructorParamsTemplate($className, $info, $i === $count);
354
            $i++;
355
        }
356
357
        return $content;
358
    }
359
360
    /**
361
     * Return the constructor body content
362
     * @return string
363
     */
364
    protected function getConstructorBodyContent(): string
365
    {
366
        $content = '';
367
        $i = 1;
368
        $count = count($this->properties);
369
        foreach ($this->properties as $className => $info) {
370
            $content .= $this->getConstructorBodyTemplate($className, $info, $i === $count);
371
            $i++;
372
        }
373
374
        return $content;
375
    }
376
377
    /**
378
     * Return the constructor document block template for the given class
379
     * @param string $className
380
     * @param array<string, string> $info
381
     * @return string
382
     */
383
    protected function getConstructorDocBlockTemplate(string $className, array $info): string
0 ignored issues
show
Unused Code introduced by
The parameter $className is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

383
    protected function getConstructorDocBlockTemplate(/** @scrutinizer ignore-unused */ string $className, array $info): string

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
384
    {
385
        $shortClass = $info['short'];
386
        $name = $info['name'];
387
388
        return <<<EOF
389
        * @param $shortClass \$$name 
390
            
391
        EOF;
392
    }
393
394
    /**
395
     * Return the constructor arguments template for the given class
396
     * @param string $className
397
     * @param array<string, string> $info
398
     * @param bool $isLast
399
     * @return string
400
     */
401
    protected function getConstructorParamsTemplate(
402
        string $className,
0 ignored issues
show
Unused Code introduced by
The parameter $className is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

402
        /** @scrutinizer ignore-unused */ string $className,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
403
        array $info,
404
        bool $isLast = false
405
    ): string {
406
        $shortClass = $info['short'];
407
        $name = $info['name'];
408
        $comma = $isLast ? '' : ',';
409
410
        if ($isLast) {
411
            return <<<EOF
412
            $shortClass \$$name$comma
413
            EOF;
414
        }
415
416
        return <<<EOF
417
        $shortClass \$$name$comma
418
               
419
        EOF;
420
    }
421
422
    /**
423
     * Return the constructor body template for the given class
424
     * @param string $className
425
     * @param array<string, string> $info
426
     * @param bool $isLast
427
     * @return string
428
     */
429
    protected function getConstructorBodyTemplate(string $className, array $info, bool $isLast = false): string
0 ignored issues
show
Unused Code introduced by
The parameter $className is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

429
    protected function getConstructorBodyTemplate(/** @scrutinizer ignore-unused */ string $className, array $info, bool $isLast = false): string

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
430
    {
431
        $name = $info['name'];
432
433
        if ($isLast) {
434
            return <<<EOF
435
            \$this->$name = \$$name;
436
            EOF;
437
        }
438
439
        return <<<EOF
440
        \$this->$name = \$$name;
441
                
442
        EOF;
443
    }
444
445
    /**
446
     * Return the property template for the given class
447
     * @param string $className
448
     * @param array<string, mixed> $info
449
     * @return string
450
     */
451
    protected function getPropertyTemplate(string $className, array $info): string
452
    {
453
        $shortClass = $info['short'];
454
        $name = $info['name'];
455
456
        return <<<EOF
457
        /**
458
            * The $shortClass instance
459
            * @var $shortClass
460
            */
461
            protected $shortClass \$$name;
462
        
463
            
464
        EOF;
465
    }
466
467
    /**
468
     * Return the name space use template for the given class
469
     * @param string $className
470
     * @return string
471
     */
472
    protected function getUsesTemplate(string $className): string
473
    {
474
        return <<<EOF
475
        use $className; 
476
        
477
        EOF;
478
    }
479
}
480