Passed
Push — master ( 9155e7...72c61b )
by 世昌
02:37
created

MySQLTableCreator   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 221
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 78
dl 0
loc 221
rs 9.68
c 0
b 0
f 0
wmc 34

10 Methods

Rating   Name   Duplication   Size   Complexity  
A parseUniqueKeys() 0 8 3
A parseForeignKeys() 0 13 3
A __construct() 0 5 1
A parseLength() 0 11 5
A parsePrimaryKeys() 0 12 4
A create() 0 5 1
A parseKeys() 0 8 3
A toSQL() 0 18 4
B createField() 0 19 7
A parseIndexKeys() 0 8 3
1
<?php
2
namespace suda\application\database\creator;
3
4
use function implode;
5
use suda\orm\exception\SQLException;
6
use suda\orm\struct\Field;
7
use suda\orm\struct\Fields;
8
use suda\orm\connection\Connection;
9
use suda\orm\statement\QueryStatement;
10
11
/**
12
 * 数据表链接对象
13
 *
14
 */
15
class MySQLTableCreator
16
{
17
    /**
18
     * 连接
19
     *
20
     * @var Connection
21
     */
22
    protected $connection;
23
24
    /**
25
     * 字段
26
     *
27
     * @var Fields
28
     */
29
    protected $fields;
30
31
    /**
32
     *
33
     */
34
    const ENGINE_MYISAM = 'MyISAM';
35
36
    /**
37
     *
38
     */
39
    const ENGINE_INNODB = 'InnoDB';
40
41
    /**
42
     * @var string
43
     */
44
    protected $name;
45
    /**
46
     * @var string
47
     */
48
    protected $engine = self::ENGINE_INNODB;
49
    /**
50
     * @var
51
     */
52
    protected $comment;
53
54
    /**
55
     * @var
56
     */
57
    protected $collate;
58
    /**
59
     * @var string
60
     */
61
    protected $charset = 'utf8mb4';
62
63
    /**
64
     * @var
65
     */
66
    protected $auto;
67
68
    /**
69
     * MySQLTableCreator constructor.
70
     * @param Connection $connection
71
     * @param Fields $fields
72
     */
73
    public function __construct(Connection $connection, Fields $fields)
74
    {
75
        $this->name = $fields->getName();
76
        $this->fields = $fields;
77
        $this->connection = $connection;
78
    }
79
80
    /**
81
     * @return bool
82
     * @throws SQLException
83
     */
84
    public function create()
85
    {
86
        $statement = new QueryStatement($this->toSQL());
87
        $statement->isWrite(true);
88
        return $this->connection->query($statement) > 0;
89
    }
90
91
    /**
92
     * @return string
93
     */
94
    protected function toSQL()
95
    {
96
        $content = [];
97
        foreach ($this->fields->all() as $field) {
98
            $content[] = $this->createField($field);
99
        }
100
        $content[] = $this->parsePrimaryKeys();
101
        $content = $this->parseUniqueKeys($content);
102
        $content = $this->parseIndexKeys($content);
103
        $content = $this->parseKeys($content);
104
        $content = $this->parseForeignKeys($content);
105
        $table = $this->connection->rawTableName($this->name);
106
        $sql = "CREATE TABLE IF NOT EXISTS `{$table}` (\r\n\t";
107
        $sql .= implode(",\r\n\t", array_filter($content, 'strlen'));
108
        $auto = null === $this->auto?'':'AUTO_INCREMENT='.$this->auto;
109
        $collate = null === $this->collate?'':'COLLATE '.$this->collate;
110
        $sql .= "\r\n) ENGINE={$this->engine} {$collate} {$auto} DEFAULT CHARSET={$this->charset};";
111
        return $sql;
112
    }
113
114
115
    /**
116
     * @return string
117
     */
118
    protected function parsePrimaryKeys()
119
    {
120
        $primary = [];
121
        foreach ($this->fields->all() as $field) {
122
            if ($field->getType() === Field::PRIMARY) {
123
                $primary[] = '`'.$field->getName().'`';
124
            }
125
        }
126
        if (count($primary)) {
127
            return 'PRIMARY KEY ('. implode(',', $primary).')';
128
        }
129
        return  '';
130
    }
131
132
133
    /**
134
     * @param array $content
135
     * @return array
136
     */
137
    protected function parseUniqueKeys(array $content)
138
    {
139
        foreach ($this->fields->all() as $field) {
140
            if ($field->getType() === Field::UNIQUE) {
141
                $content[] = 'UNIQUE KEY `'.$field->getName().'` (`'.$field->getName().'`)';
142
            }
143
        }
144
        return $content;
145
    }
146
147
148
    /**
149
     * @param array $content
150
     * @return array
151
     */
152
    protected function parseIndexKeys(array $content)
153
    {
154
        foreach ($this->fields->all() as $field) {
155
            if ($field->getType() === Field::INDEX) {
156
                $content[] = 'INDEX (`'.$field->getName().'`)';
157
            }
158
        }
159
        return $content;
160
    }
161
162
    /**
163
     * @param array $content
164
     * @return array
165
     */
166
    protected function parseKeys(array $content)
167
    {
168
        foreach ($this->fields->all() as $field) {
169
            if ($field->getType() === Field::INDEX) {
170
                $content[] = 'KEY `'.$field->getName().'` (`'.$field->getName().'`)';
171
            }
172
        }
173
        return $content;
174
    }
175
176
177
    /**
178
     * @param array $content
179
     * @return array
180
     */
181
    protected function parseForeignKeys(array $content)
182
    {
183
        foreach ($this->fields->all() as $field) {
184
            if ($field->getForeignKey() !== null) {
185
                $content[] = sprintf(
186
                    "FOREIGN KEY (`%s`) REFERENCES  `_:%s` (`%s`)",
187
                    $field->getName(),
188
                    $field->getTableName(),
189
                    $field->getName()
190
                );
191
            }
192
        }
193
        return $content;
194
    }
195
196
    /**
197
     * @param $length
198
     * @return string
199
     */
200
    protected function parseLength($length)
201
    {
202
        if ($length !== null) {
203
            if (is_string($length) || is_int($length)) {
204
                return '('.$length.')';
205
            }
206
            if (is_array($length)) {
207
                return '('.implode(',', $length).')';
208
            }
209
        }
210
        return  '';
211
    }
212
213
    /**
214
     * @param Field $field
215
     * @return string
216
     */
217
    protected function createField(Field $field)
218
    {
219
        $type = strtoupper($field->getValueType()).$this->parseLength($field->getLength());
220
        $auto = $field->getAuto() ?'AUTO_INCREMENT':'';
221
        $null = $field->isNullable() ?'NULL':'NOT NULL';
222
        $attr = $field->getAttribute() ?strtoupper($field->getAttribute()):'';
223
        $comment = $field->getComment() ?('COMMENT \''.addcslashes($field->getComment(), '\'').'\''):'';
224
        // default设置
225
        if ($field->hasDefault()) {
226
            if (null === $field->getDefault()) {
227
                $default = 'DEFAULT NULL';
228
            } else {
229
                $default = 'DEFAULT \''.addcslashes($field->getDefault(), '\'').'\'';
230
            }
231
        } else {
232
            $default = '';
233
        }
234
        $list = ['`'.$field->getName().'`', $type, $attr, $field->getCharset(), $null, $default, $auto, $comment];
235
        return implode(' ', array_filter(array_map('trim', $list), 'strlen'));
236
    }
237
}
238