Completed
Pull Request — master (#2799)
by
unknown
02:23
created

ResourceGenerator::getReservedColumns()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
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
     *
61
     * @return mixed
62
     */
63
    protected function getModel($model)
64
    {
65
        if ($model instanceof Model) {
66
            return $model;
67
        }
68
69
        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...
70
            throw new \InvalidArgumentException("Invalid model [$model] !");
71
        }
72
73
        return new $model();
74
    }
75
76
    /**
77
     * @return string
78
     */
79
    public function generateForm()
80
    {
81
        $reservedColumns = $this->getReservedColumns();
82
83
        $output = '';
84
85
        foreach ($this->getTableColumns() as $column) {
86
            $name = $column->getName();
87
            if (in_array($name, $reservedColumns)) {
88
                continue;
89
            }
90
            $type = $column->getType()->getName();
91
            $default = $column->getDefault();
92
93
            $defaultValue = '';
94
95
            // set column fieldType and defaultValue
96
            switch ($type) {
97
                case 'boolean':
98
                case 'bool':
99
                    $fieldType = 'switch';
100
                    break;
101
                case 'json':
102
                case 'array':
103
                case 'object':
104
                    $fieldType = 'text';
105
                    break;
106
                case 'string':
107
                    $fieldType = 'text';
108
                    foreach ($this->fieldTypeMapping as $type => $regex) {
109
                        if (preg_match("/^($regex)$/i", $name) !== 0) {
110
                            $fieldType = $type;
111
                            break;
112
                        }
113
                    }
114
                    $defaultValue = "'{$default}'";
115
                    break;
116
                case 'integer':
117
                case 'bigint':
118
                case 'smallint':
119
                case 'timestamp':
120
                    $fieldType = 'number';
121
                    break;
122
                case 'decimal':
123
                case 'float':
124
                case 'real':
125
                    $fieldType = 'decimal';
126
                    break;
127
                case 'datetime':
128
                    $fieldType = 'datetime';
129
                    $defaultValue = "date('Y-m-d H:i:s')";
130
                    break;
131
                case 'date':
132
                    $fieldType = 'date';
133
                    $defaultValue = "date('Y-m-d')";
134
                    break;
135
                case 'time':
136
                    $fieldType = 'time';
137
                    $defaultValue = "date('H:i:s')";
138
                    break;
139
                case 'text':
140
                case 'blob':
141
                    $fieldType = 'textarea';
142
                    break;
143
                default:
144
                    $fieldType = 'text';
145
                    $defaultValue = "'{$default}'";
146
            }
147
148
            $defaultValue = $defaultValue ?: $default;
149
150
            $label = $this->formatLabel($name);
151
152
            $output .= sprintf($this->formats['form_field'], $fieldType, $name, $label);
153
154
            if (trim($defaultValue, "'\"")) {
155
                $output .= "->default({$defaultValue})";
156
            }
157
158
            $output .= ";\r\n";
159
        }
160
161
        return $output;
162
    }
163
164 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...
165
    {
166
        $output = '';
167
168
        foreach ($this->getTableColumns() as $column) {
169
            $name = $column->getName();
170
            switch ($name) {
171
                case 'id':
172
                case 'created_at':
173
                case 'updated_at':
174
                    $label = trans('admin.'.$this->formatLabel($name));
175
                    break;
176
                
177
                default:
178
                    // set column label
179
                    $label = $this->formatLabel($name);
180
                    break;
181
            }
182
            
183
184
            $output .= sprintf($this->formats['show_field'], $name, $label);
185
186
            $output .= ";\r\n";
187
        }
188
189
        return $output;
190
    }
191
192 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...
193
    {
194
        $output = '';
195
196
        foreach ($this->getTableColumns() as $column) {
197
            $name = $column->getName();
198
            switch ($name) {
199
                case 'id':
200
                case 'created_at':
201
                case 'updated_at':
202
                    $label = trans('admin.'.$this->formatLabel($name));
203
                    break;
204
                
205
                default:
206
                    // set column label
207
                    $label = $this->formatLabel($name);
208
                    break;
209
            }
210
211
            $output .= sprintf($this->formats['grid_column'], $name, $label);
212
            $output .= ";\r\n";
213
        }
214
215
        return $output;
216
    }
217
218
    protected function getReservedColumns()
219
    {
220
        return [
221
            $this->model->getKeyName(),
222
            $this->model->getCreatedAtColumn(),
223
            $this->model->getUpdatedAtColumn(),
224
            'deleted_at',
225
        ];
226
    }
227
228
    /**
229
     * Get columns of a giving model.
230
     *
231
     * @throws \Exception
232
     *
233
     * @return \Doctrine\DBAL\Schema\Column[]
234
     */
235
    protected function getTableColumns()
236
    {
237
        if (!$this->model->getConnection()->isDoctrineAvailable()) {
238
            throw new \Exception(
239
                'You need to require doctrine/dbal: ~2.3 in your own composer.json to get database columns. '
240
            );
241
        }
242
243
        $table = $this->model->getConnection()->getTablePrefix().$this->model->getTable();
244
        /** @var \Doctrine\DBAL\Schema\MySqlSchemaManager $schema */
245
        $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...
246
247
        // custom mapping the types that doctrine/dbal does not support
248
        $databasePlatform = $schema->getDatabasePlatform();
249
250
        foreach ($this->doctrineTypeMapping as $doctrineType => $dbTypes) {
251
            foreach ($dbTypes as $dbType) {
252
                $databasePlatform->registerDoctrineTypeMapping($dbType, $doctrineType);
253
            }
254
        }
255
256
        $database = null;
257
        if (strpos($table, '.')) {
258
            list($database, $table) = explode('.', $table);
259
        }
260
261
        return $schema->listTableColumns($table, $database);
262
    }
263
264
    /**
265
     * Format label.
266
     *
267
     * @param string $value
268
     *
269
     * @return string
270
     */
271
    protected function formatLabel($value)
272
    {
273
        return ucfirst(str_replace(['-', '_'], ' ', $value));
274
    }
275
}
276