Passed
Push — develop ( afd842...6e46d5 )
by nguereza
03:39
created

MakeFormParamCommand::interact()   C

Complexity

Conditions 14
Paths 144

Size

Total Lines 69
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 14
eloc 43
c 3
b 0
f 0
nc 144
nop 2
dl 0
loc 69
rs 5.9

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 MakeFormParamCommand.php
34
 *
35
 *  The Make form parameter Command class
36
 *
37
 *  @package    Platine\Framework\Console\Command
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\Command;
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
use Platine\Framework\Console\MakeCommand;
55
use Platine\Stdlib\Helper\Str;
56
57
/**
58
 * @class MakeFormParamCommand
59
 * @package Platine\Framework\Console\Command
60
 */
61
class MakeFormParamCommand extends MakeCommand
62
{
63
    /**
64
     * {@inheritdoc}
65
     */
66
    protected string $type = 'form parameter';
67
68
    /**
69
     * Whether to create instance from entity
70
     * @var bool
71
     */
72
    protected bool $createInstanceFormEntity = false;
73
74
    /**
75
     * The list of properties entity field maps
76
     * @var array<string, string>
77
     */
78
    protected array $fromEntityMaps = [];
79
80
    /**
81
     * Create new instance
82
     * @param Application $application
83
     * @param Filesystem $filesystem
84
     */
85
    public function __construct(
86
        Application $application,
87
        Filesystem $filesystem
88
    ) {
89
        parent::__construct($application, $filesystem);
90
        $this->setName('make:param')
91
               ->setDescription('Command to generate new form parameter class');
92
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97
    public function interact(Reader $reader, Writer $writer): void
98
    {
99
        parent::interact($reader, $writer);
100
101
        $properties = [];
102
103
        $io = $this->io();
104
        $writer->boldYellow('Enter the properties list (empty value to finish):', true);
105
        $value = '';
106
        while ($value !== null) {
107
            $value = $io->prompt('Property name', null, null, false);
108
109
            if (!empty($value)) {
110
                $value = trim($value);
111
                $type = 'string';
112
                $required = true;
113
                $default = null;
114
115
                // 0 = field name, 1 = data type, 2 = required (true/false), 3 = default value
116
                $values = (array) explode(':', $value);
117
                if (isset($values[0]) && !empty($values[0])) {
118
                    $value = $values[0];
119
                }
120
121
                if (isset($values[1]) && !empty($values[1])) {
122
                    $type = $values[1];
123
                }
124
125
                if (isset($values[2])) {
126
                    $required = in_array($values[2], ['true', '1', 'yes', 'on', 'y']) ;
127
                }
128
129
                if (isset($values[3])) {
130
                    $default = $values[3];
131
                }
132
133
                $name = Str::camel($value, true);
134
135
                $properties[$name] = [
136
                    'name' => $name,
137
                    'short' => $type, // needed by super class
138
                    'type' => $type,
139
                    'required' => $required,
140
                    'default' => $default,
141
                ];
142
            }
143
        }
144
145
        $this->properties = $properties;
146
147
        if (!empty($this->properties)) {
148
            $this->createInstanceFormEntity = $io->confirm('Create instance from entity ?', 'y');
149
150
            if ($this->createInstanceFormEntity) {
151
                $list = [];
152
                foreach ($this->properties as $name => $info) {
153
                    $value = $io->prompt(
154
                        sprintf('Entity field name for [%s] (just enter to ignore)', $name),
155
                        null,
156
                        null,
157
                        false
158
                    );
159
                    if (!empty($value)) {
160
                        $list[$name] = $value;
161
                    }
162
                }
163
164
                if (!empty($list)) {
165
                    $this->fromEntityMaps = $list;
166
                }
167
            }
168
        }
169
    }
170
171
    /**
172
     * {@inheritdoc}
173
     */
174
    public function getClassTemplate(): string
175
    {
176
        return <<<EOF
177
        <?php
178
        
179
        declare(strict_types=1);
180
        
181
        namespace %namespace%;
182
        
183
        use Platine\Framework\Form\Param\BaseParam;
184
        %uses%
185
186
        /**
187
        * @class %classname%
188
        * @package %namespace%
189
        * %template_entity%
190
        */
191
        class %classname% extends BaseParam
192
        {
193
            %properties%
194
            %from_entity%
195
            %getters%
196
            %setters%
197
        }
198
        
199
        EOF;
200
    }
201
202
    /**
203
     * {@inheritdoc}
204
     */
205
    protected function createClass(): string
206
    {
207
        $content = parent::createClass();
208
209
        $fromEntity = $this->getFromEntityBody($content);
210
        $setters = $this->getSettersBody($fromEntity);
211
212
        return $this->getGettersBody($setters);
213
    }
214
215
    /**
216
     * Return the setters body
217
     * @param string $content
218
     * @return string
219
     */
220
    protected function getSettersBody(string $content): string
221
    {
222
        $result = '';
223
        foreach ($this->properties as $info) {
224
            $result .= $this->getSetterTemplate($info);
225
        }
226
227
        return str_replace('%setters%', $result, $content);
228
    }
229
230
    /**
231
     * Return the getter body
232
     * @param string $content
233
     * @return string
234
     */
235
    protected function getGettersBody(string $content): string
236
    {
237
        $result = '';
238
239
        foreach ($this->properties as $info) {
240
            $result .= $this->getGetterTemplate($info);
241
        }
242
243
        return str_replace('%getters%', $result, $content);
244
    }
245
246
    /**
247
     * Return the setter template
248
     * @param array<string, string> $info
249
     * @return string
250
     */
251
    protected function getSetterTemplate(array $info): string
252
    {
253
        $name = $info['name'];
254
        $type = $info['type'];
255
        $typeDockBlock = $type;
256
        $typeArg = $type;
257
        $required = $info['required'];
258
        if ($required === false) {
0 ignored issues
show
introduced by
The condition $required === false is always false.
Loading history...
259
            $typeDockBlock .= '|null';
260
            $typeArg = '?' . $typeArg;
261
        }
262
        $cleanName = Str::snake($name, ' ');
263
        $setterName = 'set' . Str::ucfirst($name);
264
265
        return <<<EOF
266
        /**
267
            * Set the $cleanName value 
268
            * @param $typeDockBlock \$$name 
269
            * @return \$this
270
            */
271
           public function $setterName($typeArg \$$name): self
272
           {
273
               \$this->$name = \$$name;
274
                
275
               return \$this;
276
           }
277
           
278
           
279
        EOF;
280
    }
281
282
    /**
283
     * Return the getter template
284
     * @param array<string, string> $info
285
     * @return string
286
     */
287
    protected function getGetterTemplate(array $info): string
288
    {
289
        $name = $info['name'];
290
        $type = $info['type'];
291
        $typeDockBlock = $type;
292
        $typeReturn = $type;
293
        $required = $info['required'];
294
        if ($required === false) {
0 ignored issues
show
introduced by
The condition $required === false is always false.
Loading history...
295
            $typeDockBlock .= '|null';
296
            $typeReturn = '?' . $typeReturn;
297
        }
298
        $cleanName = Str::snake($name, ' ');
299
        $getterName = 'get' . Str::ucfirst($name);
300
301
        return <<<EOF
302
        /**
303
            * Return the $cleanName value 
304
            * @return $typeDockBlock
305
            */
306
           public function $getterName(): $typeReturn
307
           {
308
               return \$this->$name;
309
           }
310
           
311
           
312
        EOF;
313
    }
314
315
    /**
316
     * Return the from entity body
317
     * @param string $content
318
     * @return string
319
     */
320
    protected function getFromEntityBody(string $content): string
321
    {
322
        $result = '';
323
        $templateEntity = '';
324
        if ($this->createInstanceFormEntity && !empty($this->fromEntityMaps)) {
325
            $templateEntity = '@template TEntity as Entity';
326
            $result = <<<EOF
327
            /**
328
                * @param TEntity \$entity
329
                * @return \$this
330
                */
331
               public function fromEntity(Entity \$entity): self
332
               {
333
                
334
            EOF;
335
            foreach ($this->fromEntityMaps as $property => $map) {
336
                $result .= <<<EOF
337
                \$this->$property = \$entity->$map;
338
                
339
            EOF;
340
            }
341
342
            $result .= <<<EOF
343
                
344
                   return \$this;
345
               }
346
            
347
            EOF;
348
        }
349
350
        $template = (string) str_replace('%from_entity%', $result, $content);
351
352
        return str_replace('%template_entity%', $templateEntity, $template);
353
    }
354
355
    /**
356
     * {@inheritdoc}
357
     */
358
    protected function getPropertyTemplate(string $className, array $info): string
359
    {
360
        $name = $info['name'];
361
        $cleanName = Str::snake($name, ' ');
362
363
        $default = $info['default'];
364
        $type = $info['type'];
365
        $typeDockBlock = $type;
366
        $typeProp = $type;
367
        $required = $info['required'];
368
        if ($required === false) {
369
            $typeDockBlock .= '|null';
370
            $typeProp = '?' . $typeProp;
371
        }
372
373
        if ($default === null && $required === false) {
374
            $default = 'null';
375
        }
376
377
        if ($default !== null) {
378
            if ($type === 'string' && empty($default)) {
379
                $default = '\'\'';
380
            }
381
382
            $default = ' = ' . $default;
383
        } else {
384
            $default = '';
385
        }
386
387
        return <<<EOF
388
        /**
389
            * The $cleanName field
390
            * @var $typeDockBlock
391
            */
392
            protected $typeProp \$$name$default;
393
        
394
            
395
        EOF;
396
    }
397
398
    /**
399
     * {@inheritdoc}
400
     */
401
    protected function getUsesContent(): string
402
    {
403
        if (!$this->createInstanceFormEntity) {
404
            return '';
405
        }
406
407
        return <<<EOF
408
        use Platine\Orm\Entity; 
409
        
410
        EOF;
411
    }
412
}
413