MakeCommand::getConstructorParamsTemplate()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
eloc 9
c 2
b 0
f 0
nc 2
nop 3
dl 0
loc 16
rs 9.9666
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 (without the root namespace)', null, false);
90
        $this->addOption('-f|--force', 'Overwrite existing files.', false, false);
91
    }
92
93
    /**
94
     * {@inheritdoc}
95
     */
96
    public function execute(): mixed
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 true;
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
        return true;
141
    }
142
143
    /**
144
     * {@inheritdoc}
145
     */
146
    public function interact(Reader $reader, Writer $writer): void
147
    {
148
        $writer->boldYellow('GENERATION OF NEW CLASS', true)->eol();
149
        $name = $this->getArgumentValue('name');
150
        if (empty($name)) {
151
            $io = $this->io();
152
            $name = $io->prompt('Enter the full class name (can include root namespace)', null);
153
        }
154
155
        $this->className = $name;
156
    }
157
158
    /**
159
     * Return the the class template
160
     * @return string
161
     */
162
    abstract public function getClassTemplate(): string;
163
164
    /**
165
     * Create the class for the given name
166
     * @return string
167
     */
168
    protected function createClass(): string
169
    {
170
        $template = $this->getClassTemplate();
171
172
        $replaceNamespace = $this->replaceNamespace($template);
173
        $replaceUses = $this->replaceClassUses($replaceNamespace);
174
        $replaceClasses = $this->replaceClasses($replaceUses);
175
        $replaceProperties = $this->replaceProperties($replaceClasses);
176
        $replaceConstructor = $this->replaceConstructor($replaceProperties);
177
        $replaceMethodBody = $this->replaceMethodBody($replaceConstructor);
178
179
        return $replaceMethodBody;
180
    }
181
182
    /**
183
     * Replace the name space
184
     * @param string $content
185
     * @return string
186
     */
187
    protected function replaceNamespace(string $content): string
188
    {
189
        $namespace = $this->getNamespace($this->className);
190
        return str_replace('%namespace%', $namespace, $content);
191
    }
192
193
    /**
194
     * Replace the properties
195
     * @param string $content
196
     * @return string
197
     */
198
    protected function replaceProperties(string $content): string
199
    {
200
        $replaceContent = $this->getPropertiesContent();
201
        return str_replace('%properties%', $replaceContent, $content);
202
    }
203
204
    /**
205
     * Replace the constructor
206
     * @param string $content
207
     * @return string
208
     */
209
    protected function replaceConstructor(string $content): string
210
    {
211
        $replaceContent = $this->getConstructorContent();
212
213
        return str_replace('%constructor%', $replaceContent, $content);
214
    }
215
216
    /**
217
     * Replace the method body
218
     * @param string $content
219
     * @return string
220
     */
221
    protected function replaceMethodBody(string $content): string
222
    {
223
        $replaceContent = $this->getMethodBodyContent();
224
225
        return str_replace('%method_body%', $replaceContent, $content);
226
    }
227
228
    /**
229
     * Replace the class uses instructions
230
     * @param string $content
231
     * @return string
232
     */
233
    protected function replaceClassUses(string $content): string
234
    {
235
        $replaceContent = $this->getUsesContent();
236
        return str_replace('%uses%', $replaceContent, $content);
237
    }
238
239
    /**
240
     * Replace the classes
241
     * @param string $content
242
     * @return string
243
     */
244
    protected function replaceClasses(string $content): string
245
    {
246
        $shortClassName = $this->getShortClassName($this->className);
247
        $fullClassName = $this->getFullClassName($this->className);
248
249
        $replaced = str_replace('%classname%', $shortClassName, $content);
250
251
        return str_replace('%fullclassname%', $fullClassName, $replaced);
252
    }
253
254
    /**
255
     * Return the properties content
256
     * @return string
257
     */
258
    protected function getPropertiesContent(): string
259
    {
260
        if (count($this->properties) === 0) {
261
            return '';
262
        }
263
264
        $content = '';
265
266
        foreach ($this->properties as $className => $info) {
267
            $content .= $this->getPropertyTemplate($className, $info);
268
        }
269
270
        return $content;
271
    }
272
273
    /**
274
     * Return the name space uses content
275
     * @return string
276
     */
277
    protected function getUsesContent(): string
278
    {
279
        if (count($this->properties) === 0) {
280
            return '';
281
        }
282
283
        $content = '';
284
285
        foreach ($this->properties as $className => $info) {
286
            $content .= $this->getUsesTemplate($className);
287
        }
288
289
        return $content;
290
    }
291
292
293
    /**
294
     * Return the constructor content
295
     * @return string
296
     */
297
    protected function getConstructorContent(): string
298
    {
299
        if (count($this->properties) === 0) {
300
            return '';
301
        }
302
303
        $docblock = $this->getConstructorDocBlockContent();
304
        $params = $this->getConstructorParamsContent();
305
        $body = $this->getConstructorBodyContent();
306
307
        return <<<EOF
308
        $docblock
309
            public function __construct(
310
               $params
311
            ){
312
                $body
313
            }
314
        EOF;
315
    }
316
317
    /**
318
     * Return the constructor content
319
     * @return string
320
     */
321
    protected function getMethodBodyContent(): string
322
    {
323
        return '';
324
    }
325
326
327
    /**
328
     * Return the constructor document block comment content
329
     * @return string
330
     */
331
    protected function getConstructorDocBlockContent(): string
332
    {
333
        $content = '';
334
        foreach ($this->properties as $className => $info) {
335
            $content .= $this->getConstructorDocBlockTemplate($className, $info);
336
        }
337
338
        return <<<EOF
339
        /**
340
            * Create new instance
341
            $content*/
342
        EOF;
343
    }
344
345
    /**
346
     * Return the constructor parameters content
347
     * @return string
348
     */
349
    protected function getConstructorParamsContent(): string
350
    {
351
        $content = '';
352
        $i = 1;
353
        $count = count($this->properties);
354
        foreach ($this->properties as $className => $info) {
355
            $content .= $this->getConstructorParamsTemplate(
356
                $className,
357
                $info,
358
                $i === $count
359
            );
360
            $i++;
361
        }
362
363
        return $content;
364
    }
365
366
    /**
367
     * Return the constructor body content
368
     * @return string
369
     */
370
    protected function getConstructorBodyContent(): string
371
    {
372
        // TODO: since PHP 8 we use the feature
373
        // of constructor property promotion
374
        return '';
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
409
        if ($isLast) {
410
            return <<<EOF
411
            protected $shortClass \$$name,
412
            EOF;
413
        }
414
415
        return <<<EOF
416
        protected $shortClass \$$name,
417
               
418
        EOF;
419
    }
420
421
    /**
422
     * Return the property template for the given class
423
     * @param string $className
424
     * @param array<string, mixed> $info
425
     * @return string
426
     */
427
    protected function getPropertyTemplate(string $className, array $info): string
428
    {
429
        // TODO: since PHP 8 we use the feature
430
        // of constructor property promotion
431
432
        return '';
433
    }
434
435
    /**
436
     * Return the name space use template for the given class
437
     * @param string $className
438
     * @return string
439
     */
440
    protected function getUsesTemplate(string $className): string
441
    {
442
        return <<<EOF
443
        use $className; 
444
        
445
        EOF;
446
    }
447
}
448