Completed
Pull Request — master (#24)
by Maarten
01:21
created

RuleParser::toRule()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 33
rs 9.392
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Mtolhuys\LaravelSchematics\Services;
4
5
use Mtolhuys\LaravelSchematics\Models\Migration;
6
7
class RuleParser
8
{
9
    /**
10
     * @param $rule
11
     * @return string|null
12
     */
13
    public static function parseRule($rule = null)
14
    {
15
        if (! $rule) {
16
            return 'string|max:255';
17
        }
18
19
        $valid = array_diff(explode('|', $rule), [
20
            'mediumIncrements',
21
            'smallIncrements',
22
            'tinyIncrements',
23
            'rememberToken',
24
            'softDeletesTz',
25
            'bigIncrements',
26
            'renameColumn',
27
            'softDeletes',
28
            'dropColumn',
29
            'increments',
30
            'macAddress',
31
            'ipAddress',
32
            'unsigned',
33
        ]);
34
35
        if (empty($valid)) {
36
            return null;
37
        }
38
39
        return self::toRule(implode('|', $valid));
40
    }
41
42
    /**
43
     * @param string $rawRules
44
     * @return string
45
     */
46
    public static function toRule(string $rawRules): string
47
    {
48
        $translations = [
49
            'unsignedInteger' => 'numeric',
50
            'mediumInteger' => 'numeric',
51
            'smallInteger' => 'numeric',
52
            'tinyInteger' => 'numeric',
53
            'bigInteger' => 'numeric',
54
            'macAddress'  => 'string',
55
            'integer' => 'numeric',
56
            'decimal' => 'numeric',
57
            'dateTimeTz' => 'date',
58
            'dateTime' => 'date',
59
            'timestampTz' => 'date',
60
            'timestamp' => 'date',
61
            'string' => 'string',
62
            'ipAddress' => 'ip',
63
            'enum' => 'numeric',
64
            'point' => 'numeric',
65
            'polygon' => 'numeric',
66
            'longText' => 'string',
67
            'text' => 'string',
68
            'json' => 'json',
69
            'jsonb' => 'json',
70
            'time' => 'date_format:H:i',
71
        ];
72
73
        return str_replace(
74
            array_keys($translations),
75
            array_values($translations),
76
            $rawRules
77
        );
78
    }
79
    /**
80
     * Parse the rules to column creation methods
81
     *
82
     * @param $fields
83
     * @return string
84
     */
85
    public static function fieldsToMigrationMethods(array $fields): string
86
    {
87
        $columns = '';
88
89
        foreach ($fields as $field) {
90
            $column = key($field);
91
            $rule = $field[$column];
92
            $break = PHP_EOL . str_repeat(' ', 12);
93
94
            if (self::isMethodOnly($rule)) {
95
                $columns .= "\$table->{$rule}();{$break}";
96
97
                continue;
98
            }
99
100
            $max = self::getMax($rule);
101
            $method = self::getMethod($rule);
102
            $oldName = self::getRenameFrom($rule);
103
            $additional = self::getAdditionalUpMethods($rule);
104
105
            $columns .= "\$table->{$method}({$oldName}'$column'{$max}){$additional}{$break}";
106
        }
107
108
        return $columns;
109
    }
110
111
    /**
112
     * @param $rule
113
     * @return string
114
     */
115
    public static function getAdditionalUpMethods($rule): string
116
    {
117
        $methods = '';
118
        $methods .= self::isUnsigned($rule) ? '->unsigned()' : '';
119
        $methods .= !self::isRequired($rule) ? '->nullable()' : '';
120
        $methods .= self::isUnique($rule) ? '->unique()' : '';
121
        $methods .= self::hasChanged($rule) ? '->change()' : '';
122
123
        return "$methods;";
124
    }
125
126
    /**
127
     * Check if $rule should be handled as single method
128
     *
129
     * @param $rule
130
     * @return mixed|string
131
     */
132
    public static function isMethodOnly($rule)
133
    {
134
135
        return self::ruleContains($rule, [
136
            'softDeletes',
137
            'rememberToken',
138
            'softDeletesTz',
139
        ]);
140
    }
141
142
    /**
143
     * Check if $rule contains any of the possible methods
144
     *
145
     * @param $rule
146
     * @return mixed|string
147
     */
148
    public static function getMethod($rule)
149
    {
150
        foreach (Migration::$methods as $method) {
151
            if (stripos($rule, strtolower($method)) !== false) {
152
                return $method;
153
            }
154
        }
155
156
        return 'string';
157
    }
158
159
    /**
160
     * Parses the max:* rule
161
     *
162
     * @param $rule
163
     * @return string
164
     */
165
    public static function getMax($rule): string
166
    {
167
        $max = (int)substr($rule, strpos($rule, 'max:') + 4);
168
169
        if ($max > 0) {
170
            return ", $max";
171
        }
172
173
        return '';
174
    }
175
176
    /**
177
     * Gets old name for renaming column
178
     *
179
     * @param $rule
180
     * @return string
181
     */
182
    public static function getRenameFrom($rule): string
183
    {
184
        foreach (explode('|', $rule) as $token) {
185
            $hasRenameRule = stripos($token, 'from:') !== false;
186
187
            if ($hasRenameRule) {
188
                $from = substr($token, strpos($token, 'from:') + 5);
189
190
                return "'$from', ";
191
            }
192
        }
193
194
        return '';
195
    }
196
197
    /**
198
     * Checks if column can be set to nullable
199
     *
200
     * @param $rule
201
     * @return boolean
202
     */
203
    public static function isRequired($rule): bool
204
    {
205
        return self::ruleContains($rule, ['required'])
206
            || self::isIncrements($rule)
207
            || self::isUnique($rule);
208
    }
209
210
    /**
211
     * Checks if columns needs to be set to unique
212
     *
213
     * @param $rule
214
     * @return boolean
215
     */
216
    public static function isIncrements($rule): bool
217
    {
218
        return self::ruleContains($rule, [
219
            'increments',
220
            'bigIncrements',
221
            'mediumIncrements',
222
            'smallIncrements',
223
            'tinyIncrements',
224
        ]);
225
    }
226
227
    /**
228
     * Checks if columns needs to be set to unique
229
     *
230
     * @param $rule
231
     * @return boolean
232
     */
233
    public static function isUnique($rule): bool
234
    {
235
        return self::ruleContains($rule, ['unique']);
236
    }
237
238
    /**
239
     * Checks if columns is unsigned
240
     *
241
     * @param $rule
242
     * @return boolean
243
     */
244
    public static function isUnsigned($rule): bool
245
    {
246
        return self::ruleContains($rule, ['unsigned'])
247
            && ! self::ruleContains($rule, ['unsignedInteger']);
248
    }
249
250
251
    /**
252
     * Checks if columns has changed
253
     *
254
     * @param $rule
255
     * @return boolean
256
     */
257
    public static function hasChanged($rule): bool
258
    {
259
        return self::ruleContains($rule, ['change']);
260
    }
261
262
    /**
263
     * Checks if columns needs to be constructed as a foreign key
264
     *
265
     * @param $rule
266
     * @return boolean
267
     */
268
    public static function isForeign($rule): bool
269
    {
270
        return self::ruleContains($rule, ['foreign']);
271
    }
272
273
    /**
274
     * For aesthetic reasons
275
     *
276
     * @param $rule
277
     * @param $needles
278
     * @return bool
279
     */
280
    private static function ruleContains($rule, array $needles): bool
281
    {
282
        return !empty(array_filter(
283
            array_map(static function ($rule) use ($needles) {
284
                return in_array($rule, $needles, true);
285
            }, explode('|', $rule))
286
        ));
287
    }
288
}
289
290