Completed
Push — master ( ce62e6...a2dd34 )
by Song
03:32
created

ResourceGenerator::generateForm()   D

Complexity

Conditions 25
Paths 86

Size

Total Lines 84

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 25
nc 86
nop 0
dl 0
loc 84
rs 4.1666
c 0
b 0
f 0

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
namespace Encore\Admin\Console;
4
5
use Illuminate\Database\Eloquent\Model;
6
7
class ResourceGenerator
8
{
9
    /**
10
     * @var Model
11
     */
12
    protected $model;
13
14
    /**
15
     * @var array
16
     */
17
    protected $formats = [
18
        'form_field'  => "\$form->%s('%s', '%s')",
19
        'show_field'  => "\$show->%s('%s')",
20
        'grid_column' => "\$grid->%s('%s')",
21
    ];
22
23
    /**
24
     * @var array
25
     */
26
    private $doctrineTypeMapping = [
27
        'string' => [
28
            'enum', 'geometry', 'geometrycollection', 'linestring',
29
            'polygon', 'multilinestring', 'multipoint', 'multipolygon',
30
            'point',
31
        ]
32
    ];
33
34
    /**
35
     * @var array
36
     */
37
    protected $fieldTypeMapping = [
38
        'ip'       => 'ip',
39
        'email'    => 'email|mail',
40
        'password' => 'password|pwd',
41
        'url'      => 'url|link|src|href',
42
        'mobile'   => 'mobile|phone',
43
        'color'    => 'color|rgb',
44
        'image'    => 'image|img|avatar|pic|picture|cover',
45
        'file'     => 'file|attachment'
46
    ];
47
48
    /**
49
     * ResourceGenerator constructor.
50
     *
51
     * @param mixed $model
52
     */
53
    public function __construct($model)
54
    {
55
        $this->model = $this->getModel($model);
56
    }
57
58
    /**
59
     * @param mixed $model
60
     * @return mixed
61
     */
62
    protected function getModel($model)
63
    {
64
        if ($model instanceof Model) {
65
            return $model;
66
        }
67
68
        if (!class_exists($model) || !is_string($model) || !is_subclass_of($model, Model::class)) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \Illuminate\Database\Eloquent\Model::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
69
            throw new \InvalidArgumentException("Invalid model [$model] !");
70
        }
71
72
        return new $model;
73
    }
74
75
    /**
76
     * @return string
77
     */
78
    public function generateForm()
79
    {
80
        $reservedColumns = $this->getReservedColumns();
81
82
        $output = '';
83
84
        foreach ($this->getTableColumns() as $column) {
85
            $name = $column->getName();
86
            if (in_array($name, $reservedColumns)) {
87
                continue;
88
            }
89
            $type    = $column->getType()->getName();
90
            $default = $column->getDefault();
91
92
            $defaultValue = '';
93
94
            // set column fieldType and defaultValue
95
            switch ($type) {
96
                case 'boolean':
97
                case 'bool':
98
                    $fieldType = 'switch';
99
                    break;
100
                case 'json':
101
                case 'array':
102
                case 'object':
103
                    $fieldType = 'text';
104
                    break;
105
                case 'string':
106
                    $fieldType = 'text';
107
                    foreach ($this->fieldTypeMapping as $type => $regex) {
108
                        if (preg_match("/^($regex)$/i", $name) !== 0) {
109
                            $fieldType = $type;
110
                            break;
111
                        }
112
                    }
113
                    $defaultValue = "'{$default}'";
114
                    break;
115
                case 'integer':
116
                case 'bigint':
117
                case 'smallint':
118
                case 'timestamp':
119
                    $fieldType = 'number';
120
                    break;
121
                case 'decimal':
122
                case 'float':
123
                case 'real':
124
                    $fieldType = 'decimal';
125
                    break;
126
                case 'datetime':
127
                    $fieldType    = 'datetime';
128
                    $defaultValue = "date('Y-m-d H:i:s')";
129
                    break;
130
                case 'date':
131
                    $fieldType    = 'date';
132
                    $defaultValue = "date('Y-m-d')";
133
                    break;
134
                case 'time':
135
                    $fieldType    = 'time';
136
                    $defaultValue = "date('H:i:s')";
137
                    break;
138
                case 'text':
139
                case 'blob':
140
                    $fieldType = 'textarea';
141
                    break;
142
                default:
143
                    $fieldType    = 'text';
144
                    $defaultValue = "'{$default}'";
145
            }
146
147
            $defaultValue = $defaultValue ?: $default;
148
149
            $label = $this->formatLabel($name);
150
151
            $output .= sprintf($this->formats['form_field'], $fieldType, $name, $label);
152
153
            if (trim($defaultValue, "'\"")) {
154
                $output .= "->default({$defaultValue})";
155
            }
156
157
            $output .= ";\r\n";
158
        }
159
160
        return $output;
161
    }
162
163 View Code Duplication
    public function generateShow()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
164
    {
165
        $output = '';
166
167
        foreach ($this->getTableColumns() as $column) {
168
            $name    = $column->getName();
169
            $comment = $column->getComment();
170
171
            // set column comment
172
            $label = $this->formatLabel($comment ? $comment : $name);
173
174
            $output .= sprintf($this->formats['show_field'], $name, $label);
175
176
            $output .= ";\r\n";
177
        }
178
179
        return $output;
180
    }
181
182 View Code Duplication
    public function generateGrid()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
183
    {
184
        $output = '';
185
186
        foreach ($this->getTableColumns() as $column) {
187
            $name    = $column->getName();
188
            $comment = $column->getComment();
189
190
            $label = $this->formatLabel($comment ? $comment : $name);
191
192
            $output .= sprintf($this->formats['grid_column'], $name, $label);
193
            $output .= ";\r\n";
194
        }
195
196
        return $output;
197
    }
198
199
    protected function getReservedColumns()
200
    {
201
        return [
202
            $this->model->getKeyName(),
203
            $this->model->getCreatedAtColumn(),
204
            $this->model->getUpdatedAtColumn(),
205
            'deleted_at',
206
        ];
207
    }
208
209
    /**
210
     * Get columns of a giving model.
211
     *
212
     * @return \Doctrine\DBAL\Schema\Column[]
213
     * @throws \Exception
214
     */
215
    protected function getTableColumns()
216
    {
217
        if (!$this->model->getConnection()->isDoctrineAvailable()) {
218
            throw new \Exception(
219
                'You need to require doctrine/dbal: ~2.3 in your own composer.json to get database columns. '
220
            );
221
        }
222
223
        $table = $this->model->getConnection()->getTablePrefix() . $this->model->getTable();
224
        /** @var \Doctrine\DBAL\Schema\MySqlSchemaManager $schema */
225
        $schema = $this->model->getConnection()->getDoctrineSchemaManager($table);
0 ignored issues
show
Unused Code introduced by
The call to Connection::getDoctrineSchemaManager() has too many arguments starting with $table.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
226
227
        // custom mapping the types that doctrine/dbal does not support
228
        $databasePlatform = $schema->getDatabasePlatform();
229
230
        foreach ($this->doctrineTypeMapping as $doctrineType => $dbTypes) {
231
            foreach ($dbTypes as $dbType) {
232
                $databasePlatform->registerDoctrineTypeMapping($dbType, $doctrineType);
233
            }
234
        }
235
236
        $database = null;
237
        if (strpos($table, '.')) {
238
            list($database, $table) = explode('.', $table);
239
        }
240
241
        return $schema->listTableColumns($table, $database);
242
    }
243
244
    /**
245
     * Format label.
246
     *
247
     * @param string $value
248
     * @return string
249
     */
250
    protected function formatLabel($value)
251
    {
252
        return ucfirst(str_replace(['-', '_'], ' ', $value));
253
    }
254
}