Passed
Branch master (3de301)
by Guillaume
02:14 queued 10s
created

MysqlDatabaseTable::getCollate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
1
<?php
2
3
namespace Starkerxp\DatabaseChecker\Structure;
4
5
6
//@todo Manage data sync by option.
7
use Starkerxp\DatabaseChecker\Exception\TableHasNotColumnException;
8
use Starkerxp\DatabaseChecker\Exception\TablenameHasNotDefinedException;
9
use Starkerxp\DatabaseChecker\LoggerTrait;
10
11
class MysqlDatabaseTable implements DatabaseInterface
12
{
13
14
    use LoggerTrait;
15
16
    /**
17
     * @var string
18
     */
19
    private $database;
20
21
    /**
22
     * @var string
23
     */
24
    private $engine;
25
26
    /**
27
     * @var string
28
     */
29
    private $table;
30
31
    /**
32
     * @var MysqlDatabaseColumn[]
33
     */
34
    private $columns = [];
35
36
    /**
37
     * @var MysqlDatabaseIndex[]
38
     */
39
    private $indexes = [];
40
41
    /**
42
     * @var string
43
     */
44
    private $collate;
45
46
    /**
47
     * DatabaseTableStructure constructor.
48
     *
49
     * @param $table
50
     *
51
     * @throws TablenameHasNotDefinedException
52
     */
53
    public function __construct($table)
54
    {
55
        if (empty($table)) {
56
            $this->critical('You need to define name of your table');
57
            throw new TablenameHasNotDefinedException('');
58
        }
59
        $this->table = $table;
60
    }
61
62
    public function addColumn(MysqlDatabaseColumn $column)
63
    {
64
        $column->setTable($this->getTable());
65
        $this->columns[$column->getName()] = $column;
66
    }
67
68
    /**
69
     * @return mixed
70
     */
71
    public function getTable()
72
    {
73
        return $this->table;
74
    }
75
76
    public function removeColumn($columnName)
77
    {
78
79
        unset($this->columns[$columnName]);
80
    }
81
82
    public function addIndex(array $columns, $indexName = '')
83
    {
84
        $this->addIndexType($indexName, 0, $columns);
85
    }
86
87
    /**
88
     * @param       $indexName
89
     * @param       $unique
90
     * @param array $columns
91
     */
92
    protected function addIndexType($indexName, $unique, array $columns)
93
    {
94
        if (empty($indexName)) {
95
            $indexName = ($unique ? 'UNI_' : 'IDX_') . md5(implode(',', $columns));
96
        }
97
        try {
98
            $index = new MysqlDatabaseIndex($indexName, $columns, $unique);
99
            $index->setTable($this->getTable());
100
            $this->indexes[$indexName] = $index;
101
        } catch (\Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
102
103
        }
104
    }
105
106
    public function addPrimary(array $columnName)
107
    {
108
        $this->addIndexType('PRIMARY', 1, $columnName);
109
    }
110
111
    public function addUnique(array $columnName, $indexName = '')
112
    {
113
        $this->addIndexType($indexName, 1, $columnName);
114
    }
115
116
    public function toArray()
117
    {
118
        $export = [];
119
        $export['columns'] = [];
120
        $columns = $this->getColumns();
121
        foreach ($columns as $column) {
122
            $arrayColumn = $column->toArray();
123
            unset($arrayColumn['table']);
124
            $export['columns'][$column->getName()] = $arrayColumn;
125
        }
126
127
        $export['indexes'] = [];
128
        $export['uniques'] = [];
129
        $indexes = $this->getIndexes();
130
        foreach ($indexes as $index) {
131
            $arrayIndex = $index->toArray();
132
            if ($index->isPrimary()) {
133
                $export['primary'] = $index->getColumns();
134
                continue;
135
            }
136
            if ($index->isUnique()) {
137
                unset($arrayIndex['table'], $arrayIndex['unique']);
138
                $export['uniques'][] = $arrayIndex;
139
                continue;
140
            }
141
            unset($arrayIndex['table'], $arrayIndex['unique']);
142
            $export['indexes'][] = $arrayIndex;
143
        }
144
        $export['collate'] = $this->getCollate();
145
        $export['engine'] = $this->getEngine();
146
        $export = array_filter($export);
147
148
        return [$this->getTable() => $export];
149
    }
150
151
    /**
152
     * @return MysqlDatabaseColumn[]
153
     *
154
     * @throws TableHasNotColumnException
155
     */
156
    public function getColumns()
157
    {
158
        if (!count($this->columns)) {
159
            $this->critical('You need to define columns for this table.', ['table' => $this->getTable()]);
160
            throw new TableHasNotColumnException('');
161
        }
162
163
        return $this->columns;
164
    }
165
166
    public function getIndexes()
167
    {
168
        if (empty($this->indexes)) {
169
            $this->error("You don't have any index. Are you sure ?");
170
        }
171
172
        return $this->indexes;
173
    }
174
175
    /**
176
     * @return string
177
     */
178
    public function getCollate()
179
    {
180
        return $this->collate;
181
    }
182
183
    /**
184
     * @return string
185
     */
186
    public function getEngine()
187
    {
188
        return $this->engine;
189
    }
190
191
    /**
192
     * @param string $collate
193
     */
194
    public function setCollate($collate)
195
    {
196
        $this->collate = $collate;
197
    }
198
199
    /**
200
     * @param string $engine
201
     */
202
    public function setEngine($engine)
203
    {
204
        $this->engine = $engine;
205
    }
206
207
    /**
208
     * @return array
209
     *
210
     * @throws TableHasNotColumnException
211
     * @throws TablenameHasNotDefinedException
212
     */
213
    public function createStatement()
214
    {
215
        $modifications = [];
216
        $modifications[] = [sprintf('CREATE TABLE IF NOT EXISTS `%s`', $this->getTable())];
217
        $columns = $this->getColumns();
218
        foreach ($columns as $column) {
219
220
            if ($this->getCollate() == '') {
221
                $column->setCollate('');
222
            }
223
            $modifications[] = $column->createStatement();
224
        }
225
        $indexes = $this->getIndexes();
226
        foreach ($indexes as $index) {
227
            try {
228
                if (!$this->getIndex($index->getName())) {
229
                    continue;
230
                }
231
                $modifications[] = $index->createStatement();
232
            } catch (\Exception $e) {
233
                $this->critical('Unexpected error are throw.', ['table' => $this->getTable(), 'index' => $index->getName()]);
234
                continue;
235
            }
236
        }
237
238
        if (!$modifications = $this->formatStatements($modifications)) {
239
            return [];
240
        }
241
242
        return $this->formatCreateStatement($modifications);
243
244
    }
245
246
    /**
247
     * @param $indexName
248
     *
249
     * @return MysqlDatabaseIndex
250
     *
251
     * @throws \RuntimeException
252
     */
253
    public function getIndex($indexName)
254
    {
255
256
        if (empty($this->indexes[$indexName])) {
257
            $this->critical('You attempt to get undefined index name.', ['index' => $indexName]);
258
            throw new \RuntimeException('');
259
        }
260
261
        return $this->indexes[$indexName];
262
    }
263
264
    /**
265
     * @param array $modificationsBetweenTable
266
     *
267
     * @return array
268
     */
269
    private function formatStatements(array $modificationsBetweenTable)
270
    {
271
        $statements = [];
272
        foreach ($modificationsBetweenTable as $modifications) {
273
            foreach ((array)$modifications as $modification) {
274
                $statements[] = $modification;
275
            }
276
        }
277
278
        return array_filter(array_unique($statements));
279
    }
280
281
    private function formatCreateStatement(array $modifications)
282
    {
283
        if (!$finalStatement = array_shift($modifications)) {
284
            return [];
285
        }
286
        $tmp = [];
287
        foreach ($modifications as $modification) {
288
            $tmp[] = trim(str_replace(['ALTER TABLE `' . $this->getTable() . '` ADD COLUMN', 'ALTER TABLE `' . $this->getTable() . '` ADD ', ';',], '', $modification));
289
        }
290
        $collate = $this->getCollate() == '' ? '' : sprintf("COLLATE='%s'", $this->getCollate());
291
292
        return [$finalStatement . '(' . implode(',', $tmp) . ')' . $collate . ';'];
293
    }
294
295
    /**
296
     * @return array
297
     *
298
     * @throws \RuntimeException
299
     */
300
    public function alterStatement()
301
    {
302
        $modifications = [];
303
        $modifications = array_merge($modifications, $this->alterStatementCollate());
304
        $modifications = array_merge($modifications, $this->alterStatementEngine());
305
306
        return $modifications;
307
    }
308
309
    /**
310
     * @return array
311
     *
312
     * @throws \RuntimeException
313
     */
314
    private function alterStatementCollate()
315
    {
316
317
        if (empty($this->database)) {
318
            return [];
319
        }
320
        $collateTmp = $this->getCollate();
321
        $collate = $collateTmp == '' ? '' : sprintf('CONVERT TO CHARACTER SET %s COLLATE %s', explode('_', $collateTmp)[0], $collateTmp);
322
        if ($collate == '') {
323
            throw new \RuntimeException('Not implemented');
324
        }
325
326
        $modifications = [
327
            sprintf('ALTER DATABASE %s CHARACTER SET %s COLLATE %s;', $this->database, explode('_', $collateTmp)[0], $collateTmp),
328
            sprintf('ALTER TABLE `%s` %s;', $this->getTable(), $collate),
329
        ];
330
331
        return $modifications;
332
    }
333
334
    private function alterStatementEngine()
335
    {
336
        if (empty($this->engine)) {
337
            return [];
338
        }
339
340
        $modifications = [
341
            sprintf('ALTER TABLE `%s` ENGINE=%s;', $this->getTable(), $this->getEngine()),
342
        ];
343
344
        return $modifications;
345
    }
346
347
    public function setDatabase($database)
348
    {
349
        $this->database = $database;
350
    }
351
352
353
}
0 ignored issues
show
Coding Style introduced by
As per coding style, files should not end with a newline character.

This check marks files that end in a newline character, i.e. an empy line.

Loading history...
354