Completed
Push — master ( 52f191...d51707 )
by Nicolas
04:02
created

SchemaParser::parse()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 16
ccs 8
cts 8
cp 1
crap 2
rs 9.7333
c 0
b 0
f 0
1
<?php
2
3
namespace Nwidart\Modules\Support\Migrations;
4
5
use Illuminate\Contracts\Support\Arrayable;
6
use Illuminate\Support\Arr;
7
use Illuminate\Support\Str;
8
9
class SchemaParser implements Arrayable
10
{
11
    /**
12
     * The array of custom attributes.
13
     *
14
     * @var array
15
     */
16
    protected $customAttributes = [
17
        'remember_token' => 'rememberToken()',
18
        'soft_delete' => 'softDeletes()',
19
    ];
20
21
    /**
22
     * The migration schema.
23
     *
24
     * @var string
25
     */
26
    protected $schema;
27
28
    /**
29
     * The relationship keys.
30
     *
31
     * @var array
32
     */
33
    protected $relationshipKeys = [
34
        'belongsTo',
35
    ];
36
37
    /**
38
     * Create new instance.
39
     *
40
     * @param string|null $schema
41
     */
42 12
    public function __construct($schema = null)
43
    {
44 12
        $this->schema = $schema;
45 12
    }
46
47
    /**
48
     * Parse a string to array of formatted schema.
49
     *
50
     * @param string $schema
51
     *
52
     * @return array
53
     */
54 12
    public function parse($schema)
55
    {
56 12
        $this->schema = $schema;
57
58 12
        $parsed = [];
59
60 12
        foreach ($this->getSchemas() as $schemaArray) {
61 3
            $column = $this->getColumn($schemaArray);
62
63 3
            $attributes = $this->getAttributes($column, $schemaArray);
64
65 3
            $parsed[$column] = $attributes;
66
        }
67
68 12
        return $parsed;
69
    }
70
71
    /**
72
     * Get array of schema.
73
     *
74
     * @return array
75
     */
76 12
    public function getSchemas()
77
    {
78 12
        if (is_null($this->schema)) {
79 9
            return [];
80
        }
81
82 3
        return explode(',', str_replace(' ', '', $this->schema));
83
    }
84
85
    /**
86
     * Convert string migration to array.
87
     *
88
     * @return array
89
     */
90 12
    public function toArray()
91
    {
92 12
        return $this->parse($this->schema);
93
    }
94
95
    /**
96
     * Render the migration to formatted script.
97
     *
98
     * @return string
99
     */
100 11
    public function render()
101
    {
102 11
        $results = '';
103
104 11
        foreach ($this->toArray() as $column => $attributes) {
105 2
            $results .= $this->createField($column, $attributes);
106
        }
107
108 11
        return $results;
109
    }
110
111
    /**
112
     * Render up migration fields.
113
     *
114
     * @return string
115
     */
116 3
    public function up()
117
    {
118 3
        return $this->render();
119
    }
120
121
    /**
122
     * Render down migration fields.
123
     *
124
     * @return string
125
     */
126 3
    public function down()
127
    {
128 3
        $results = '';
129
130 3
        foreach ($this->toArray() as $column => $attributes) {
131 1
            $attributes = [head($attributes)];
132 1
            $results .= $this->createField($column, $attributes, 'remove');
133
        }
134
135 3
        return $results;
136
    }
137
138
    /**
139
     * Create field.
140
     *
141
     * @param string $column
142
     * @param array  $attributes
143
     * @param string $type
144
     *
145
     * @return string
146
     */
147 3
    public function createField($column, $attributes, $type = 'add')
148
    {
149 3
        $results = "\t\t\t" . '$table';
150
151 3
        foreach ($attributes as $key => $field) {
152 3
            if (in_array($column, $this->relationshipKeys)) {
153
                $results .= $this->addRelationColumn($key, $field, $column);
154
            } else {
155 3
                $results .= $this->{"{$type}Column"}($key, $field, $column);
156
            }
157
        }
158
159 3
        return $results . ';' . PHP_EOL;
160
    }
161
162
    /**
163
     * Add relation column.
164
     *
165
     * @param int    $key
166
     * @param string $field
167
     * @param string $column
168
     *
169
     * @return string
170
     */
171
    protected function addRelationColumn($key, $field, $column)
172
    {
173
        if($key == 0) {
174
            $relatedColumn = snake_case(class_basename($field)) . '_id';
175
            return "->integer('{$relatedColumn}')->unsigned();".PHP_EOL."\t\t\t" . "\$table->foreign('{$relatedColumn}')";
176
        } elseif ($key == 1) {
177
            return "->references('{$field}')";
178
        } elseif ($key == 2) {
179
            return "->on('{$field}')";
180
        } else {
181
            if (str_contains($field, '(')) {
182
                return '->' . $field;
183
            }
184
            return '->' . $field . '()';
185
        }
186
    }
187
188
    /**
189
     * Format field to script.
190
     *
191
     * @param int    $key
192
     * @param string $field
193
     * @param string $column
194
     *
195
     * @return string
196
     */
197 2
    protected function addColumn($key, $field, $column)
198
    {
199 2
        if ($this->hasCustomAttribute($column)) {
200
            return '->' . $field;
201
        }
202
203 2
        if ($key == 0) {
204 2
            return '->' . $field . "('" . $column . "')";
205
        }
206
207
        if (Str::contains($field, '(')) {
208
            return '->' . $field;
209
        }
210
211
        return '->' . $field . '()';
212
    }
213
214
    /**
215
     * Format field to script.
216
     *
217
     * @param int    $key
218
     * @param string $field
219
     * @param string $column
220
     *
221
     * @return string
222
     */
223 1
    protected function removeColumn($key, $field, $column)
224
    {
225 1
        if ($this->hasCustomAttribute($column)) {
226
            return '->' . $field;
227
        }
228
229 1
        return '->dropColumn(' . "'" . $column . "')";
230
    }
231
232
    /**
233
     * Get column name from schema.
234
     *
235
     * @param string $schema
236
     *
237
     * @return string
238
     */
239 3
    public function getColumn($schema)
240
    {
241 3
        return Arr::get(explode(':', $schema), 0);
242
    }
243
244
    /**
245
     * Get column attributes.
246
     *
247
     * @param string $column
248
     * @param string $schema
249
     *
250
     * @return array
251
     */
252 3
    public function getAttributes($column, $schema)
253
    {
254 3
        $fields = str_replace($column . ':', '', $schema);
255
256 3
        return $this->hasCustomAttribute($column) ? $this->getCustomAttribute($column) : explode(':', $fields);
257
    }
258
259
    /**
260
     * Determine whether the given column is exist in customAttributes array.
261
     *
262
     * @param string $column
263
     *
264
     * @return bool
265
     */
266 3
    public function hasCustomAttribute($column)
267
    {
268 3
        return array_key_exists($column, $this->customAttributes);
269
    }
270
271
    /**
272
     * Get custom attributes value.
273
     *
274
     * @param string $column
275
     *
276
     * @return array
277
     */
278
    public function getCustomAttribute($column)
279
    {
280
        return (array) $this->customAttributes[$column];
281
    }
282
}
283