Completed
Pull Request — master (#2262)
by
unknown
03:47
created

FormCommand   A

Complexity

Total Complexity 42

Size/Duplication

Total Lines 197
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 0
loc 197
rs 9.0399
c 0
b 0
f 0
wmc 42
lcom 1
cbo 2

3 Methods

Rating   Name   Duplication   Size   Complexity  
F handle() 0 144 38
A checkColumn() 0 9 3
A getOptions() 0 7 1

How to fix   Complexity   

Complex Class

Complex classes like FormCommand often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use FormCommand, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Encore\Admin\Console;
4
5
use Illuminate\Console\Command;
6
use Symfony\Component\Console\Input\InputOption;
7
8
class FormCommand extends Command
9
{
10
    /**
11
     * The console command name.
12
     *
13
     * @var string
14
     */
15
    protected $name = 'admin:form';
16
17
    /**
18
     * The console command description.
19
     *
20
     * @var string
21
     */
22
    protected $description = 'laravel-admin form filed generator';
23
24
    /**
25
     * Execute the console command.
26
     *
27
     * @return bool
28
     */
29
    public function handle()
30
    {
31
        $modelName = $this->option('model');
32
        if (empty($modelName) || !class_exists($modelName)) {
33
            $this->error('Model does not exists !');
34
            return false;
35
        }
36
37
        // use doctrine/dbal
38
        $model = $this->laravel->make($modelName);
0 ignored issues
show
Bug introduced by
It seems like $modelName defined by $this->option('model') on line 31 can also be of type array; however, Illuminate\Contracts\Container\Container::make() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
39
        $table = $model->getConnection()->getTablePrefix() . $model->getTable();
40
        $schema = $model->getConnection()->getDoctrineSchemaManager($table);
41
42
        if (!method_exists($schema, 'getDatabasePlatform')) {
43
            $this->error('You need to require doctrine/dbal: ~2.3 in your own composer.json to get database columns. ');
44
            $this->info('Using install command: composer require doctrine/dbal');
45
            return false;
46
47
        }
48
49
        // custom mapping the types that doctrine/dbal does not support
50
        $databasePlatform = $schema->getDatabasePlatform();
51
        $databasePlatform->registerDoctrineTypeMapping('enum', 'string');
52
        $databasePlatform->registerDoctrineTypeMapping('geometry', 'string');
53
        $databasePlatform->registerDoctrineTypeMapping('geometrycollection', 'string');
54
        $databasePlatform->registerDoctrineTypeMapping('linestring', 'string');
55
        $databasePlatform->registerDoctrineTypeMapping('multilinestring', 'string');
56
        $databasePlatform->registerDoctrineTypeMapping('multipoint', 'string');
57
        $databasePlatform->registerDoctrineTypeMapping('multipolygon', 'string');
58
        $databasePlatform->registerDoctrineTypeMapping('point', 'string');
59
        $databasePlatform->registerDoctrineTypeMapping('polygon', 'string');
60
        $databasePlatform->registerDoctrineTypeMapping('multipolygon', 'string');
61
        $databasePlatform->registerDoctrineTypeMapping('multipolygon', 'string');
62
63
        $database = null;
64
        if (strpos($table, '.')) {
65
            list($database, $table) = explode('.', $table);
66
        }
67
        $columns = $schema->listTableColumns($table, $database);
68
69
        $adminForm = '';
70
        if ($columns) {
71
            foreach ($columns as $column) {
72
                $name = $column->getName();
73
                if (in_array($name, ['id', 'created_at', 'deleted_at'])) {
74
                    continue;
75
                }
76
                $type = $column->getType()->getName();
77
                $comment = $column->getComment();
78
                $default = $column->getDefault();
79
80
                // set column fieldType
81
                switch ($type) {
82
                    case 'boolean':
83
                    case 'bool':
84
                        $fieldType = 'switch';
85
                        break;
86
                    case 'json':
87
                    case 'array':
88
                    case 'object':
89
                        $fieldType = 'text';
90
                        break;
91
                    case 'string':
92
                        switch ($name) {
93
                            case $this->checkColumn($name, ['email']):
94
                                $fieldType = 'email';
95
                                break;
96
                            case $this->checkColumn($name, ['password', 'pwd']):
97
                                $fieldType = 'password';
98
                                break;
99
                            case $this->checkColumn($name, ['url', 'link', 'src', 'href']):
100
                                $fieldType = 'url';
101
                                break;
102
                            case $this->checkColumn($name, ['ip']):
103
                                $fieldType = 'ip';
104
                                break;
105
                            case $this->checkColumn($name, ['mobile', 'phone']):
106
                                $fieldType = 'mobile';
107
                                break;
108
                            case $this->checkColumn($name, ['color', 'rgb']):
109
                                $fieldType = 'color';
110
                                break;
111
                            case $this->checkColumn($name, ['image', 'img', 'avatar']) :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
112
                                $fieldType = 'image';
113
                                break;
114
                            case $this->checkColumn($name, ['file', 'attachment']) :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
115
                                $fieldType = 'file';
116
                                break;
117
                            default:
118
                                $fieldType = 'text';
119
                        }
120
                        break;
121
                    case 'integer':
122
                    case 'bigint':
123
                    case 'smallint':
124
                    case 'timestamp':
125
                        $fieldType = 'number';
126
                        break;
127
                    case 'decimal':
128
                    case 'float':
129
                    case 'real':
130
                        $fieldType = 'decimal';
131
                        break;
132
                    case 'datetime':
133
                        $fieldType = 'datetime';
134
                        $default = "date('Y-m-d H:i:s')";
135
                        break;
136
                    case 'date':
137
                        $fieldType = 'date';
138
                        $default = "date('Y-m-d')";
139
                        break;
140
                    case 'text':
141
                    case 'blob':
142
                        $fieldType = 'textarea';
143
                        $default = '';
144
                        break;
145
                    default:
146
                        $fieldType = 'text';
147
                }
148
149
                // set column comment
150
                $comment = $comment ? $comment : $name;
151
152
                // set column defaultValue
153
                switch ($default) {
154
                    case null:
155
                        $defaultValue = "''";
156
                        break;
157
                    case "date('Y-m-d H:i:s')":
158
                    case "date('Y-m-d')":
159
                    case is_numeric($default):
160
                        $defaultValue = $default;
161
                        break;
162
                    default:
163
                        $defaultValue = "'{$default}'";
164
                }
165
166
                $adminForm .= "\$form->{$fieldType}('{$name}', '{$comment}')->default({$defaultValue});\n";
167
            }
168
            $this->alert("laravel-admin form filed generator for {$modelName}:");
169
            $this->info($adminForm);
170
        }
171
172
    }
173
174
    /**
175
     * Check if the table column contains the specified keywords of the array.
176
     *
177
     * @param string $haystack
178
     * @param array $needle
179
     * @return bool
180
     */
181
    private function checkColumn(string $haystack, array $needle)
182
    {
183
        foreach ($needle as $value) {
184
            if (strstr($haystack, $value) !== false) {
185
                return true;
186
            }
187
        }
188
        return false;
189
    }
190
191
192
    /**
193
     * Get the console command options.
194
     *
195
     * @return array
196
     */
197
    protected function getOptions()
198
    {
199
        return [
200
            ['model', null, InputOption::VALUE_REQUIRED,
201
                'The eloquent model that should be use as controller data source.',],
202
        ];
203
    }
204
}
205