Issues (150)

src/Blocks/MigrationsAbstract.php (1 issue)

1
<?php
2
3
namespace SoliDry\Blocks;
4
5
use SoliDry\Exceptions\AttributesException;
6
use SoliDry\Helpers\Console;
7
use SoliDry\ApiGenerator;
8
use SoliDry\Types\ModelsInterface;
9
use SoliDry\Types\PhpInterface;
10
use SoliDry\Types\ApiInterface;
11
12
/**
13
 * @property ApiGenerator generator
14
 * @property string sourceCode
15
 */
16
abstract class MigrationsAbstract
17
{
18
    use ContentManager, MigrationsTrait;
0 ignored issues
show
The trait SoliDry\Blocks\ContentManager requires some properties which are not provided by SoliDry\Blocks\MigrationsAbstract: $options, $version, $modulesDir, $className
Loading history...
19
20
    /**
21
     * @var int
22
     */
23
    public static int $counter = 10;
24
25
    public const PATTERN_TIME = 'Y_m_d_Hi';
26
27
    /**
28
     * @var array
29
     */
30
    private array $signedIntegerMap = [
31
        ModelsInterface::INT_DIGITS_TINY => ModelsInterface::MIGRATION_METHOD_TINY_INTEGER,
32
        ModelsInterface::INT_DIGITS_SMALL => ModelsInterface::MIGRATION_METHOD_SMALL_INTEGER,
33
        ModelsInterface::INT_DIGITS_MEDIUM => ModelsInterface::MIGRATION_METHOD_MEDIUM_INTEGER,
34
        ModelsInterface::INT_DIGITS_INT => ModelsInterface::MIGRATION_METHOD_INTEGER,
35
        ModelsInterface::INT_DIGITS_BIGINT => ModelsInterface::MIGRATION_METHOD_BIG_INTEGER,
36
    ];
37
38
    /**
39
     * @var array
40
     */
41
    private array $unsignedIntegerMap = [
42
        ModelsInterface::INT_DIGITS_TINY => ModelsInterface::MIGRATION_METHOD_UTINYINT,
43
        ModelsInterface::INT_DIGITS_SMALL => ModelsInterface::MIGRATION_METHOD_USMALLINT,
44
        ModelsInterface::INT_DIGITS_MEDIUM => ModelsInterface::MIGRATION_METHOD_UMEDIUMINT,
45
        ModelsInterface::INT_DIGITS_INT => ModelsInterface::MIGRATION_METHOD_UINT,
46
        ModelsInterface::INT_DIGITS_BIGINT => ModelsInterface::MIGRATION_METHOD_UBIGINT,
47
    ];
48
49
    /**
50
     *  Sets rows of migration with their description and options
51
     */
52
    protected function setRows(): void
53
    {
54
        $attrs = $this->getEntityAttributes();
55
        foreach ($attrs as $attrKey => $attrVal) {
56
            if (is_array($attrVal)) {
57
                if (empty($attrVal[ApiInterface::RAML_TYPE]) === false) {
58
                    $this->setDescription($attrVal);
59
                    $type = $attrVal[ApiInterface::RAML_TYPE];
60
                    // create migration fields depending on Types
61
                    $this->setRowContent($attrVal, $type, $attrKey);
62
                } else {// non-standard Types aka enum
63
                    if (empty($attrVal[ApiInterface::RAML_ENUM]) === false) {
64
                        $this->setRowContent($attrVal, ApiInterface::RAML_ENUM, $attrKey);
65
                    }
66
                }
67
68
                try {
69
                    $this->setIndex($attrVal, $attrKey);
70
                    $this->setCompositeIndex($attrVal);
71
                } catch (AttributesException $e) {
72
                    echo $e->getTraceAsString();
73
                }
74
            }
75
        }
76
        // created_at/updated_at created for every table
77
        $this->setRow(ModelsInterface::MIGRATION_METHOD_TIMESTAMPS, '', null, null, false);
78
    }
79
80
    /**
81
     *  Sets rows of migration with their description and options
82
     * @param array $attrs
83
     */
84
    protected function setAddRows(array $attrs): void
85
    {
86
        foreach ($attrs as $attrKey => $attrVal) {
87
            if (is_array($attrVal)) {
88
                if (empty($attrVal[ApiInterface::RAML_TYPE]) === false) {
89
                    $this->setDescription($attrVal);
90
                    $type = $attrVal[ApiInterface::RAML_TYPE];
91
                    // create migration fields depending on Types
92
                    $this->setRowContent($attrVal, $type, $attrKey);
93
                } else {// non-standard Types aka enum
94
                    if (empty($attrVal[ApiInterface::RAML_ENUM]) === false) {
95
                        $this->setRowContent($attrVal, ApiInterface::RAML_ENUM, $attrKey);
96
                    }
97
                }
98
                try {
99
                    $this->setIndex($attrVal, $attrKey);
100
                    $this->setCompositeIndex($attrVal);
101
                } catch (AttributesException $e) {
102
                    echo $e->getTraceAsString();
103
                }
104
            }
105
        }
106
    }
107
108
    /**
109
     * Sets row content with opts
110
     * @param array $attrVal
111
     * @param string $type
112
     * @param string $attrKey
113
     */
114
    private function setRowContent(array $attrVal, string $type, string $attrKey): void
115
    {
116
        // create migration fields depending on Types
117
        switch ($type) {
118
            case ApiInterface::RAML_TYPE_STRING:
119
                $this->setStringRow($attrKey, $attrVal);
120
                break;
121
            case ApiInterface::RAML_TYPE_INTEGER:
122
                // create an auto_incremented primary key
123
                $this->setIntegerRow($attrKey, $attrVal, $type);
124
                break;
125
            case ApiInterface::RAML_TYPE_BOOLEAN:
126
                $this->setRow(ModelsInterface::MIGRATION_METHOD_UTINYINT, $attrKey);
127
                break;
128
            case ApiInterface::RAML_TYPE_NUMBER:
129
                $this->setNumberRow($attrVal, $attrKey);
130
                break;
131
            case ApiInterface::RAML_ENUM:
132
                $this->setRow(ModelsInterface::MIGRATION_METHOD_ENUM, $attrKey,
133
                    $this->getArrayParam($attrVal[ModelsInterface::MIGRATION_METHOD_ENUM]));
134
                break;
135
            case ApiInterface::RAML_DATE:
136
                $this->setRow(ModelsInterface::MIGRATION_METHOD_DATE, $attrKey);
137
                break;
138
            case ApiInterface::RAML_TIME:
139
                $this->setRow(ModelsInterface::MIGRATION_METHOD_TIME, $attrKey);
140
                break;
141
            case ApiInterface::RAML_DATETIME:
142
                if ($attrKey === ModelsInterface::COLUMN_DEL_AT) {
143
                    $this->setRow(ModelsInterface::MIGRATION_METHOD_SOFT_DEL, '', null, null, false);
144
                } else {
145
                    $this->setRow(ModelsInterface::MIGRATION_METHOD_DATETIME, $attrKey);
146
                }
147
                break;
148
        }
149
    }
150
151
    /**
152
     * @param array $attrs
153
     */
154
    public function dropRows(array $attrs): void
155
    {
156
        foreach ($attrs as $attrKey => $attrVal) {
157
            $this->setRow(ModelsInterface::MIGRATION_DROP_COLUMN, $attrKey);
158
        }
159
    }
160
161
    /**
162
     *  Sets index for particular column if facets was declared
163
     * @param array $attrVal
164
     * @param string $attrKey
165
     *
166
     * @throws AttributesException
167
     */
168
    public function setIndex(array $attrVal, string $attrKey): void
169
    {
170
        if (empty($attrVal[ApiInterface::RAML_FACETS][ApiInterface::RAML_INDEX]) === false) {
171
            $facets = $attrVal[ApiInterface::RAML_FACETS][ApiInterface::RAML_INDEX];
172
            foreach ($facets as $k => $v) {
173
                switch ($v) {
174
                    case ModelsInterface::INDEX_TYPE_INDEX:
175
                        $this->setRow(ModelsInterface::INDEX_TYPE_INDEX, $attrKey, $this->quoteParam($k));
176
                        break;
177
                    case ModelsInterface::INDEX_TYPE_PRIMARY:
178
                        $this->setRow(ModelsInterface::INDEX_TYPE_PRIMARY, $attrKey, $this->quoteParam($k));
179
                        break;
180
                    case ModelsInterface::INDEX_TYPE_UNIQUE:
181
                        $this->setRow(ModelsInterface::INDEX_TYPE_UNIQUE, $attrKey, $this->quoteParam($k));
182
                        break;
183
                    case ModelsInterface::INDEX_TYPE_FOREIGN:
184
                        $this->setForeignIndex($facets, $attrKey, $k);
185
                        break;
186
                }
187
            }
188
        }
189
    }
190
191
    /**
192
     * @param string $key
193
     * @param int $max
194
     * @param bool $signed
195
     */
196
    private function setIntegerDigit(string $key, int $max = null, bool $signed = false): void
197
    {
198
        if ($signed) {
199
            foreach ($this->signedIntegerMap as $digits => $method) {
200
                $next = next($this->signedIntegerMap);
201
                if ($digits >= $max && ($next === false || ($next !== false && $max < key($this->signedIntegerMap)))) {
202
                    $this->setRow($method, $key);
203
                    break;
204
                }
205
            }
206
        } else {
207
            foreach ($this->unsignedIntegerMap as $digits => $method) {
208
                $next = next($this->unsignedIntegerMap);
209
                if ($digits >= $max && ($next === false || ($next !== false && $max < key($this->unsignedIntegerMap)))) {
210
                    $this->setRow($method, $key);
211
                    break;
212
                }
213
            }
214
        }
215
    }
216
217
    /**
218
     * @param $relationEntity
219
     */
220
    protected function setPivotRows($relationEntity): void
221
    {
222
        $this->setRow(ModelsInterface::MIGRATION_METHOD_INCREMENTS, ApiInterface::RAML_ID);
223
        $attrs = [
224
            strtolower($this->generator->objectName) . PhpInterface::UNDERSCORE . ApiInterface::RAML_ID => $this->generator->types[$this->generator->objectProps[ApiInterface::RAML_ID]],
225
            $relationEntity . PhpInterface::UNDERSCORE . ApiInterface::RAML_ID                          => $this->generator->types[$this->generator->types[ucfirst($relationEntity)][ApiInterface::RAML_PROPS][ApiInterface::RAML_ID]],
226
        ];
227
        foreach ($attrs as $attrKey => $attrVal) {
228
            $this->setRowContent($attrVal, $attrVal[ApiInterface::RAML_TYPE], $attrKey);
229
        }
230
        $this->setRow(ModelsInterface::MIGRATION_METHOD_TIMESTAMPS, '', null, null, false);
231
    }
232
233
    private function getEntityAttributes()
234
    {
235
        $attrsArray = [ApiInterface::RAML_ID => $this->generator->types[$this->generator->objectProps[ApiInterface::RAML_ID]]] +
236
            $this->generator->types[$this->generator->objectProps[ApiInterface::RAML_ATTRS]][ApiInterface::RAML_PROPS];
237
238
        return $attrsArray;
239
    }
240
241
    /**
242
     * @param $attrVal
243
     * @param $attrKey
244
     * @param $type
245
     */
246
    private function setId($attrVal, $attrKey, $type): void
247
    {
248
        // set incremented id int
249
        if ($type === ApiInterface::RAML_TYPE_INTEGER && empty($attrVal[ApiInterface::RAML_INTEGER_MAX]) === false) {
250
            if ($attrVal[ApiInterface::RAML_INTEGER_MAX] > ModelsInterface::ID_MAX_INCREMENTS) {
251
                $this->setRow(ModelsInterface::MIGRATION_METHOD_BIG_INCREMENTS, $attrKey);
252
253
                return;
254
            }
255
        }
256
        $this->setRow(ModelsInterface::MIGRATION_METHOD_INCREMENTS, $attrKey);
257
    }
258
259
    /**
260
     * Creates migration file with time mask
261
     *
262
     * @param string $migrationName
263
     */
264
    protected function createMigrationFile(string $migrationName): void
265
    {
266
        $migrationMask = date(self::PATTERN_TIME) . self::$counter;
267
268
        self::$counter += 2; // 2-step pace for pivots
269
        $file = $this->generator->formatMigrationsPath() . $migrationMask . PhpInterface::UNDERSCORE .
270
            $migrationName . PhpInterface::PHP_EXT;
271
272
        // if migration file with the same name occasionally exists we do not override it
273
        $isCreated = FileManager::createFile($file, $this->sourceCode);
274
        if ($isCreated) {
275
            Console::out($file . PhpInterface::SPACE . Console::CREATED, Console::COLOR_GREEN);
276
        }
277
    }
278
}