Completed
Push — master ( cc0e46...765134 )
by Guillaume
02:18
created

MysqlDatabaseTable::createStatement()   C

Complexity

Conditions 8
Paths 70

Size

Total Lines 33
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

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