Completed
Push — master ( 0db1d4...415713 )
by Guillaume
01:51
created

MysqlDatabaseTable   B

Complexity

Total Complexity 41

Size/Duplication

Total Lines 251
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 41
dl 0
loc 251
rs 8.2769
c 0
b 0
f 0

18 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 2
A formatCreateStatement() 0 12 4
A addIndex() 0 3 1
A addPrimary() 0 3 1
A getIndexes() 0 7 2
A getCollate() 0 3 1
A toArray() 0 16 3
A getTable() 0 3 1
A getIndex() 0 9 2
A formatStatements() 0 10 3
A setCollate() 0 3 1
A addColumn() 0 4 1
A addIndexType() 0 10 4
A addUnique() 0 3 1
A removeColumn() 0 4 1
A getColumns() 0 8 2
A alterStatement() 0 8 3
C createStatement() 0 33 8

How to fix   Complexity   

Complex Class

Complex classes like MysqlDatabaseTable often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use MysqlDatabaseTable, and based on these observations, apply Extract Interface, too.

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
    private $table;
17
    /**
18
     * @var MysqlDatabaseColumn[]
19
     */
20
    private $columns = [];
21
22
    /**
23
     * @var MysqlDatabaseIndex[]
24
     */
25
    private $indexes = [];
26
27
    /**
28
     * @var string
29
     */
30
    private $collate;
31
32
    /**
33
     * DatabaseTableStructure constructor.
34
     *
35
     * @param $table
36
     *
37
     * @throws TablenameHasNotDefinedException
38
     */
39
    public function __construct($table)
40
    {
41
        if (empty($table)) {
42
            $this->critical('You need to define name of your table');
43
            throw new TablenameHasNotDefinedException('');
44
        }
45
        $this->table = $table;
46
    }
47
48
    public function addColumn(MysqlDatabaseColumn $column)
49
    {
50
        $column->setTable($this->getTable());
51
        $this->columns[$column->getName()] = $column;
52
    }
53
54
    /**
55
     * @return mixed
56
     */
57
    public function getTable()
58
    {
59
        return $this->table;
60
    }
61
62
    public function removeColumn($columnName)
63
    {
64
65
        unset($this->columns[$columnName]);
66
    }
67
68
    public function addIndex(array $columns, $indexName = '')
69
    {
70
        $this->addIndexType($indexName, 0, $columns);
71
    }
72
73
    /**
74
     * @param       $indexName
75
     * @param       $unique
76
     * @param array $columns
77
     */
78
    protected function addIndexType($indexName, $unique, array $columns)
79
    {
80
        if (empty($indexName)) {
81
            $indexName = ($unique ? 'UNI_' : 'IDX_') . md5(implode(',', $columns));
82
        }
83
        try {
84
            $index = new MysqlDatabaseIndex($indexName, $columns, $unique);
85
            $index->setTable($this->getTable());
86
            $this->indexes[$indexName] = $index;
87
        } catch (\Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
88
89
        }
90
    }
91
92
    public function addPrimary(array $columnName)
93
    {
94
        $this->addIndexType('PRIMARY', 1, $columnName);
95
    }
96
97
    public function addUnique(array $columnName, $indexName = '')
98
    {
99
        $this->addIndexType($indexName, 1, $columnName);
100
    }
101
102
    public function toArray()
103
    {
104
        $export = [];
105
        $export['columns'] = [];
106
        $columns = $this->getColumns();
107
        foreach ($columns as $column) {
108
            $export['columns'][] = $column->toArray();
109
        }
110
111
        $export['indexes'] = [];
112
        $indexes = $this->getIndexes();
113
        foreach ($indexes as $index) {
114
            $export['indexes'][] = $index->toArray();
115
        }
116
117
        return $export;
118
    }
119
120
    /**
121
     * @return MysqlDatabaseColumn[]
122
     *
123
     * @throws TableHasNotColumnException
124
     */
125
    public function getColumns()
126
    {
127
        if (!count($this->columns)) {
128
            $this->critical('You need to define columns for this table.', ['table' => $this->getTable()]);
129
            throw new TableHasNotColumnException('');
130
        }
131
132
        return $this->columns;
133
    }
134
135
    public function getIndexes()
136
    {
137
        if (empty($this->indexes)) {
138
            $this->error("You don't have any index. Are you sure ?");
139
        }
140
141
        return $this->indexes;
142
    }
143
144
    /**
145
     * @return array
146
     *
147
     * @throws TableHasNotColumnException
148
     */
149
    public function createStatement()
150
    {
151
        $modifications = [];
152
        $modifications[] = [sprintf('CREATE TABLE IF NOT EXISTS `%s`', $this->getTable())];
153
        $columns = $this->getColumns();
154
        foreach ($columns as $column) {
155
            try {
156
                if ($this->getCollate() == '') {
157
                    $column->setCollate('');
158
                }
159
                $modifications[] = $column->createStatement();
160
            } catch (TablenameHasNotDefinedException $e) {
161
                continue;
162
            }
163
        }
164
        $indexes = $this->getIndexes();
165
        foreach ($indexes as $index) {
166
            try {
167
                if (!$this->getIndex($index->getName())) {
168
                    continue;
169
                }
170
                $modifications[] = $index->createStatement();
171
            } catch (\Exception $e) {
172
                $this->critical('Unexpected error are throw.', ['table' => $this->getTable(), 'index' => $index->getName()]);
173
                continue;
174
            }
175
        }
176
177
        if (!$modifications = $this->formatStatements($modifications)) {
178
            return [];
179
        }
180
181
        return $this->formatCreateStatement($modifications);
182
183
    }
184
185
    /**
186
     * @return string
187
     */
188
    public function getCollate()
189
    {
190
        return $this->collate;
191
    }
192
193
    /**
194
     * @param $indexName
195
     *
196
     * @return MysqlDatabaseIndex
197
     *
198
     * @throws \RuntimeException
199
     */
200
    public function getIndex($indexName)
201
    {
202
203
        if (empty($this->indexes[$indexName])) {
204
            $this->critical('You attempt to get undefined index name.', ['index' => $indexName]);
205
            throw new \RuntimeException('');
206
        }
207
208
        return $this->indexes[$indexName];
209
    }
210
211
    /**
212
     * @param array $modificationsBetweenTable
213
     *
214
     * @return array
215
     */
216
    private function formatStatements(array $modificationsBetweenTable)
217
    {
218
        $statements = [];
219
        foreach ($modificationsBetweenTable as $modifications) {
220
            foreach ((array)$modifications as $modification) {
221
                $statements[] = $modification;
222
            }
223
        }
224
225
        return array_filter(array_unique($statements));
226
    }
227
228
    private function formatCreateStatement(array $modifications)
229
    {
230
        if (!$finalStatement = array_shift($modifications)) {
231
            return [];
232
        }
233
        $tmp = [];
234
        foreach ($modifications as $modification) {
235
            $tmp[] = trim(str_replace(['ALTER TABLE `' . $this->getTable() . '` ADD COLUMN', 'ALTER TABLE `' . $this->getTable() . '` ADD ', ';',], '', $modification));
236
        }
237
        $collate = $this->getCollate() == '' ? '' : sprintf("COLLATE='%s'", $this->getCollate());
238
239
        return [$finalStatement . '(' . implode(',', $tmp) . ')' . $collate . ';'];
240
    }
241
242
    /**
243
     * @param string $collate
244
     */
245
    public function setCollate($collate)
246
    {
247
        $this->collate = $collate;
248
    }
249
250
    /**
251
     *
252
     * @throws \RuntimeException
253
     */
254
    public function alterStatement()
255
    {
256
        $collate = $this->getCollate() == '' ? '' : sprintf("COLLATE='%s'", $this->getCollate());
257
        if ($collate == '') {
258
            throw new \RuntimeException('Not implemented');
259
        }
260
261
        return [sprintf('ALTER TABLE `%s` %s;', $this->getTable(), $collate)];
262
    }
263
264
}
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...
265