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

MysqlDatabaseCheckerService::enableCheckCollate()   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\Checker;
4
5
use Starkerxp\DatabaseChecker\Exception\ColumnNotExistException;
6
use Starkerxp\DatabaseChecker\Exception\TableHasNotColumnException;
7
use Starkerxp\DatabaseChecker\Exception\TableNotExistException;
8
use Starkerxp\DatabaseChecker\LoggerTrait;
9
use Starkerxp\DatabaseChecker\Structure\DatabaseInterface;
10
use Starkerxp\DatabaseChecker\Structure\MysqlDatabaseColumn;
11
use Starkerxp\DatabaseChecker\Structure\MysqlDatabaseTable;
12
13
class MysqlDatabaseCheckerService
14
{
15
    use LoggerTrait;
16
17
    /**
18
     * @var boolean
19
     */
20
    private $checkCollate;
21
22
    /**
23
     * @var boolean
24
     */
25
    private $checkEngine;
26
27
    /**
28
     * @param MysqlDatabaseTable[] $tables
29
     * @param MysqlDatabaseTable[] $newTables
30
     *
31
     * @return array
32
     * @throws TableHasNotColumnException
33
     */
34
    public function diff(array $tables, array $newTables)
35
    {
36
        $modificationsBetweenTable = [];
37
38
        // check Table
39
        foreach ($tables as $table) {
40
            try {
41
                $newTable = $this->getTable($table, $newTables);
42
                $modificationsBetweenTable[] = $this->checkTable($table, $newTable);
43
            } catch (TableNotExistException $e) {
44
                //@todo Drop statement.
45
                //@todo config for generate create or drop.
46
                $modificationsBetweenTable[] = $this->createStatement($table);
47
                continue;
48
            }
49
        }
50
51
        foreach ($newTables as $newTable) {
52
            try {
53
                $this->getTable($newTable, $tables);
54
            } catch (TableNotExistException $e) {
55
                $modificationsBetweenTable[] = $this->createStatement($newTable);
56
                continue;
57
            }
58
        }
59
60
        return $this->formatStatements($modificationsBetweenTable);
61
    }
62
63
    /**
64
     * @param MysqlDatabaseTable $table
65
     * @param MysqlDatabaseTable[] $newTables
66
     *
67
     * @return mixed
68
     * @throws TableNotExistException
69
     */
70
    private function getTable($table, array $newTables)
71
    {
72
        foreach ($newTables as $newTable) {
73
            if (strtolower($table->getTable()) == strtolower($newTable->getTable())) {
74
                return $newTable;
75
            }
76
        }
77
        throw new TableNotExistException('');
78
    }
79
80
    /**
81
     * @param MysqlDatabaseTable $table
82
     * @param MysqlDatabaseTable $newTable
83
     *
84
     * @return array
85
     *
86
     * @throws TableHasNotColumnException
87
     */
88
    private function checkTable(MysqlDatabaseTable $table, MysqlDatabaseTable $newTable)
89
    {
90
        $this->prepareTable($table);
91
        $this->prepareTable($newTable);
92
        // Aucune différence
93
        if ($this->tableIsEquals($table, $newTable)) {
94
            return [];
95
        }
96
97
        $modificationsBetweenTable = $newTable->alterStatement();
98
        $columns = $table->getColumns();
99
        $newColumns = $newTable->getColumns();
100
101
        foreach ($columns as $column) {
102
            try {
103
                $newColumn = $this->getColumn($column, $newColumns);
104
                $modificationsBetweenTable[$newColumn->getName()] = $this->checkColumn($column, $newColumn);
105
            } catch (ColumnNotExistException $e) {
106
                $modificationsBetweenTable[$column->getName()] = $this->createStatement($column);
107
                continue;
108
            } catch (\Exception $e) {
109
                continue;
110
            }
111
        }
112
        $columnNeedAlter = array_unique(array_keys(array_filter($modificationsBetweenTable)));
113
        $indexes = $newTable->getIndexes();
114
        foreach ($indexes as $indexName => $index) {
115
            foreach ($columnNeedAlter as $colonne) {
116
                if (!in_array($colonne, $index->getColumns(), false)) {
117
                    continue;
118
                }
119
                $modificationsBetweenTable[] = $index->alterStatement();
120
            }
121
        }
122
123
124
        return $this->formatStatements($modificationsBetweenTable);
125
    }
126
127
    private function tableIsEquals(MysqlDatabaseTable $table, MysqlDatabaseTable $newTable)
128
    {
129
        // Table is equals no need more check
130
        if ($table == $newTable) {
131
            return true;
132
        }
133
134
        return strtolower(json_encode($table->toArray())) == strtolower(json_encode($newTable->toArray()));
135
    }
136
137
    /**
138
     * @param MysqlDatabaseTable $table
139
     * @throws TableHasNotColumnException
140
     */
141
    private function disabledCollate(MysqlDatabaseTable $table)
142
    {
143
        $table->setCollate('');
144
        $columns = $table->getColumns();
145
        foreach ($columns as $column) {
146
            $column->setCollate('');
147
        }
148
    }
149
150
    /**
151
     * @param MysqlDatabaseColumn $column
152
     * @param MysqlDatabaseColumn[] $newColumns
153
     *
154
     * @return mixed
155
     *
156
     * @throws ColumnNotExistException
157
     */
158
    private function getColumn(MysqlDatabaseColumn $column, array $newColumns)
159
    {
160
        foreach ($newColumns as $newColumn) {
161
            if (strtolower($column->getName()) == strtolower($newColumn->getName())) {
162
                return $newColumn;
163
            }
164
        }
165
        throw new ColumnNotExistException('');
166
    }
167
168
    /**
169
     * @param MysqlDatabaseColumn $column
170
     * @param MysqlDatabaseColumn $newColumn
171
     *
172
     * @return array
173
     *
174
     * @throws \Starkerxp\DatabaseChecker\Exception\TablenameHasNotDefinedException
175
     */
176
    private function checkColumn(MysqlDatabaseColumn $column, MysqlDatabaseColumn $newColumn)
177
    {
178
        if ($this->columnIsEquals($column, $newColumn)) {
179
            return [];
180
        }
181
        try {
182
            $statements = $newColumn->alterStatement();
183
        } catch (\RuntimeException $e) {
184
            return [];
185
        }
186
187
        return $statements;
188
    }
189
190
    private function columnIsEquals(MysqlDatabaseColumn $column, MysqlDatabaseColumn $newColumn)
191
    {
192
        // Column is equals no need more check
193
        if ($column == $newColumn) {
194
            return true;
195
        }
196
197
        return strtolower(json_encode($column->toArray())) == strtolower(json_encode($newColumn->toArray()));
198
    }
199
200
    /**
201
     * @param  $databaseInterface
202
     *
203
     * @return array
204
     */
205
    protected function createStatement(DatabaseInterface $databaseInterface)
206
    {
207
        try {
208
            return $databaseInterface->createStatement();
209
        } catch (TableHasNotColumnException $e) {
210
            return [];
211
        }
212
    }
213
214
    /**
215
     * @param array $modificationsBetweenTable
216
     *
217
     * @return array
218
     */
219
    private function formatStatements(array $modificationsBetweenTable)
220
    {
221
        $statements = [];
222
        foreach ($modificationsBetweenTable as $modifications) {
223
            foreach ((array)$modifications as $modification) {
224
                $statements[] = $modification;
225
            }
226
        }
227
228
        return array_filter(array_unique($statements));
229
    }
230
231
    public function enableCheckCollate()
232
    {
233
        $this->checkCollate = true;
234
    }
235
236
    public function enableCheckEngine()
237
    {
238
        $this->checkEngine = true;
239
    }
240
241
    private function prepareTable(MysqlDatabaseTable $table)
242
    {
243
        if (!$this->checkCollate) {
244
            $this->disabledCollate($table);
245
        }
246
        if (!$this->checkEngine) {
247
            $table->setEngine('');
248
        }
249
    }
250
251
}
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...
252