Completed
Push — feature/collation ( dfda64...a60b97 )
by Kit Loong
05:53
created

FieldGenerator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 28
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 13
nc 1
nop 13
dl 0
loc 28
rs 9.8333
c 1
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: liow.kitloong
5
 * Date: 2020/03/28
6
 */
7
8
namespace KitLoong\MigrationsGenerator\Generators;
9
10
use Doctrine\DBAL\Schema\Column;
11
use Illuminate\Support\Collection;
12
use KitLoong\MigrationsGenerator\Generators\Modifier\CommentModifier;
13
use KitLoong\MigrationsGenerator\Generators\Modifier\DefaultModifier;
14
use KitLoong\MigrationsGenerator\Generators\Modifier\IndexModifier;
15
use KitLoong\MigrationsGenerator\Generators\Modifier\NullableModifier;
16
use KitLoong\MigrationsGenerator\MigrationMethod\ColumnModifier;
17
use KitLoong\MigrationsGenerator\MigrationMethod\ColumnType;
18
use KitLoong\MigrationsGenerator\Support\CheckLaravelVersion;
19
use KitLoong\MigrationsGenerator\Types\DBALTypes;
20
21
class FieldGenerator
22
{
23
    use CheckLaravelVersion;
24
25
    private $decorator;
26
    private $integerField;
27
    private $datetimeField;
28
    private $decimalField;
29
    private $geometryField;
30
    private $stringField;
31
    private $enumField;
32
    private $setField;
33
    private $otherField;
34
    private $nullableModifier;
35
    private $defaultModifier;
36
    private $indexModifier;
37
    private $commentModifier;
38
39
    public function __construct(
40
        Decorator $decorator,
41
        IntegerField $integerField,
42
        DatetimeField $datetimeField,
43
        DecimalField $decimalField,
44
        GeometryField $geometryField,
45
        StringField $stringField,
46
        EnumField $enumField,
47
        SetField $setField,
48
        OtherField $otherField,
49
        NullableModifier $nullableModifier,
50
        DefaultModifier $defaultModifier,
51
        IndexModifier $indexModifier,
52
        CommentModifier $commentModifier
53
    ) {
54
        $this->decorator = $decorator;
55
        $this->integerField = $integerField;
56
        $this->datetimeField = $datetimeField;
57
        $this->decimalField = $decimalField;
58
        $this->geometryField = $geometryField;
59
        $this->stringField = $stringField;
60
        $this->enumField = $enumField;
61
        $this->setField = $setField;
62
        $this->otherField = $otherField;
63
        $this->nullableModifier = $nullableModifier;
64
        $this->defaultModifier = $defaultModifier;
65
        $this->indexModifier = $indexModifier;
66
        $this->commentModifier = $commentModifier;
67
    }
68
69
    /**
70
     * Convert dbal types to Laravel Migration Types
71
     * @var array
72
     */
73
    public static $fieldTypeMap = [
74
        DBALTypes::SMALLINT => ColumnType::SMALL_INTEGER,
75
        DBALTypes::BIGINT => ColumnType::BIG_INTEGER,
76
        DBALTypes::DATETIME_MUTABLE => ColumnType::DATETIME,
77
        DBALTypes::BLOB => ColumnType::BINARY,
78
    ];
79
80
    /**
81
     * @param  string  $table
82
     * @param  Column[]  $columns
83
     * @param  Collection  $indexes
84
     * @return array
85
     */
86
    public function generate(string $table, $columns, Collection $indexes): array
87
    {
88
        if (count($columns) === 0) {
89
            return [];
90
        }
91
92
        $useTimestamps = $this->datetimeField->isUseTimestamps($columns);
93
94
        $fields = [];
95
96
        foreach ($columns as $column) {
97
            /**
98
             * return [
99
             *  field : Field name,
100
             *  type  : Migration type method, eg: increments, string
101
             *  args  : Migration type arguments,
102
             *      eg: decimal('amount', 8, 2) => decimal('amount', args[0], args[1])
103
             *  decorators
104
             * ]
105
             */
106
            $dbalType = $column->getType()->getName();
107
108
            $field = [
109
                'field' => $this->decorator->addSlash($column->getName()),
110
                'type' => $dbalType,
111
                'args' => [],
112
                'decorators' => []
113
            ];
114
115
            $field = $this->makeLaravelFieldTypeMethod($table, $field, $column, $indexes, $useTimestamps);
116
117
            if (empty($field)) {
118
                continue;
119
            }
120
121
            if (!$column->getNotnull()) {
122
                if ($this->nullableModifier->shouldAddNullableModifier($field['type'])) {
123
                    $field['decorators'][] = ColumnModifier::NULLABLE;
124
                }
125
            }
126
127
            if ($column->getDefault() !== null) {
128
                $field['decorators'][] = $this->defaultModifier->generate($dbalType, $column);
129
            }
130
131
            if ($indexes->has($field['field'])) {
132
                $field['decorators'][] = $this->indexModifier->generate($indexes->get($field['field']));
133
            }
134
135
            if ($column->getComment() !== null) {
136
                $field['decorators'][] = $this->commentModifier->generate($column->getComment());
137
            }
138
139
            if (!$this->atLeastLaravel8()) {
140
                if ($field['type'] === DBALTypes::TIMESTAMP) {
141
                    if (($key1 = array_search(ColumnModifier::USE_CURRENT, $field['decorators'])) !== false &&
142
                        ($key2 = array_search(ColumnModifier::USE_CURRENT_ON_UPDATE, $field['decorators'])) !== false) {
143
                        unset($field['decorators'][$key1]);
144
                        unset($field['decorators'][$key2]);
145
                    }
146
                }
147
            }
148
149
            $fields[] = $field;
150
        }
151
        return $fields;
152
    }
153
154
    /**
155
     * @param  string  $tableName
156
     * @param  array  $field
157
     * @param  Column  $column
158
     * @param  Collection  $indexes
159
     * @param  bool  $useTimestamps
160
     * @return array
161
     */
162
    private function makeLaravelFieldTypeMethod(
163
        string $tableName,
164
        array $field,
165
        Column $column,
166
        Collection $indexes,
167
        bool $useTimestamps
168
    ): array {
169
        switch ($field['type']) {
170
            case DBALTypes::INTEGER:
171
            case DBALTypes::BIGINT:
172
            case DBALTypes::MEDIUMINT:
173
            case DBALTypes::SMALLINT:
174
            case DBALTypes::TINYINT:
175
                return $this->integerField->makeField($tableName, $field, $column, $indexes);
176
            case DBALTypes::DATETIME_MUTABLE:
177
            case DBALTypes::TIMESTAMP:
178
            case DBALTypes::TIME_MUTABLE:
179
                return $this->datetimeField->makeField($tableName, $field, $column, $useTimestamps);
180
            case DBALTypes::DECIMAL:
181
            case DBALTypes::FLOAT:
182
            case DBALTypes::DOUBLE:
183
                return $this->decimalField->makeField($field, $column);
184
            case DBALTypes::ENUM:
185
                return $this->enumField->makeField($tableName, $field, $column);
186
            case DBALTypes::GEOMETRY:
187
                return $this->geometryField->makeField($tableName, $field);
188
            case DBALTypes::SET:
189
                return $this->setField->makeField($tableName, $field, $column);
190
            case DBALTypes::STRING:
191
                return $this->stringField->makeField($tableName, $field, $column);
192
            default:
193
                return $this->otherField->makeField($tableName, $field, $column);
194
        }
195
    }
196
}
197