Completed
Push — master ( 599977...a7d112 )
by Thomas
10:10
created

MDB2SchemaWriter::saveSchemaToFile()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 27
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 19
nc 8
nop 2
dl 0
loc 27
rs 8.439
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Bart Visscher <[email protected]>
4
 * @author Jörn Friedrich Dreyer <[email protected]>
5
 * @author Morris Jobke <[email protected]>
6
 * @author tbelau666 <[email protected]>
7
 * @author Thomas Müller <[email protected]>
8
 *
9
 * @copyright Copyright (c) 2016, ownCloud GmbH.
10
 * @license AGPL-3.0
11
 *
12
 * This code is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License, version 3,
14
 * as published by the Free Software Foundation.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License, version 3,
22
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
23
 *
24
 */
25
26
namespace OC\DB;
27
28
use Doctrine\DBAL\Schema\Column;
29
use Doctrine\DBAL\Schema\Index;
30
31
class MDB2SchemaWriter {
32
33
	/**
34
	 * @param string $file
35
	 * @param \OC\DB\Connection $conn
36
	 * @return bool
37
	 */
38
	static public function saveSchemaToFile($file, \OC\DB\Connection $conn) {
39
		$config = \OC::$server->getConfig();
40
41
		$xml = new \SimpleXMLElement('<database/>');
42
		$xml->addChild('name', $config->getSystemValue('dbname', 'owncloud'));
43
		$xml->addChild('create', 'true');
44
		$xml->addChild('overwrite', 'false');
45
		if($config->getSystemValue('dbtype', 'sqlite') === 'mysql' && $config->getSystemValue('mysql.utf8mb4', false)) {
46
			$xml->addChild('charset', 'utf8mb4');
47
		} else {
48
			$xml->addChild('charset', 'utf8');
49
		}
50
51
		// FIX ME: bloody work around
52
		if ($config->getSystemValue('dbtype', 'sqlite') === 'oci') {
53
			$filterExpression = '/^"' . preg_quote($conn->getPrefix()) . '/';
54
		} else {
55
			$filterExpression = '/^' . preg_quote($conn->getPrefix()) . '/';
56
		}
57
		$conn->getConfiguration()->setFilterSchemaAssetsExpression($filterExpression);
58
59
		foreach ($conn->getSchemaManager()->listTables() as $table) {
60
			self::saveTable($table, $xml->addChild('table'));
61
		}
62
		file_put_contents($file, $xml->asXML());
63
		return true;
64
	}
65
66
	/**
67
	 * @param \Doctrine\DBAL\Schema\Table $table
68
	 * @param \SimpleXMLElement $xml
69
	 */
70
	private static function saveTable($table, $xml) {
71
		$xml->addChild('name', $table->getName());
72
		$declaration = $xml->addChild('declaration');
73
		foreach($table->getColumns() as $column) {
74
			self::saveColumn($column, $declaration->addChild('field'));
75
		}
76
		foreach($table->getIndexes() as $index) {
77
			if ($index->getName() == 'PRIMARY') {
78
				$autoincrement = false;
79
				foreach($index->getColumns() as $column) {
80
					if ($table->getColumn($column)->getAutoincrement()) {
81
						$autoincrement = true;
82
					}
83
				}
84
				if ($autoincrement) {
85
					continue;
86
				}
87
			}
88
			self::saveIndex($index, $declaration->addChild('index'));
89
		}
90
	}
91
92
	/**
93
	 * @param Column $column
94
	 * @param \SimpleXMLElement $xml
95
	 */
96
	private static function saveColumn($column, $xml) {
97
		$xml->addChild('name', $column->getName());
98
		switch($column->getType()) {
99
			case 'SmallInt':
100
			case 'Integer':
101
			case 'BigInt':
102
				$xml->addChild('type', 'integer');
103
				$default = $column->getDefault();
104
				if (is_null($default) && $column->getAutoincrement()) {
105
					$default = '0';
106
				}
107
				$xml->addChild('default', $default);
108
				$xml->addChild('notnull', self::toBool($column->getNotnull()));
109
				if ($column->getAutoincrement()) {
110
					$xml->addChild('autoincrement', '1');
111
				}
112
				if ($column->getUnsigned()) {
113
					$xml->addChild('unsigned', 'true');
114
				}
115
				$length = '4';
116
				if ($column->getType() == 'SmallInt') {
117
					$length = '2';
118
				}
119
				elseif ($column->getType() == 'BigInt') {
120
					$length = '8';
121
				}
122
				$xml->addChild('length', $length);
123
				break;
124
			case 'String':
125
				$xml->addChild('type', 'text');
126
				$default = trim($column->getDefault());
127
				if ($default === '') {
128
					$default = false;
129
				}
130
				$xml->addChild('default', $default);
131
				$xml->addChild('notnull', self::toBool($column->getNotnull()));
132
				$xml->addChild('length', $column->getLength());
133
				break;
134
			case 'Text':
135
				$xml->addChild('type', 'clob');
136
				$xml->addChild('notnull', self::toBool($column->getNotnull()));
137
				break;
138 View Code Duplication
			case 'Decimal':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
139
				$xml->addChild('type', 'decimal');
140
				$xml->addChild('default', $column->getDefault());
141
				$xml->addChild('notnull', self::toBool($column->getNotnull()));
142
				$xml->addChild('length', '15');
143
				break;
144 View Code Duplication
			case 'Boolean':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
145
				$xml->addChild('type', 'integer');
146
				$xml->addChild('default', $column->getDefault());
147
				$xml->addChild('notnull', self::toBool($column->getNotnull()));
148
				$xml->addChild('length', '1');
149
				break;
150
			case 'DateTime':
151
				$xml->addChild('type', 'timestamp');
152
				$xml->addChild('default', $column->getDefault());
153
				$xml->addChild('notnull', self::toBool($column->getNotnull()));
154
				break;
155
156
		}
157
	}
158
159
	/**
160
	 * @param Index $index
161
	 * @param \SimpleXMLElement $xml
162
	 */
163
	private static function saveIndex($index, $xml) {
164
		$xml->addChild('name', $index->getName());
165
		if ($index->isPrimary()) {
166
			$xml->addChild('primary', 'true');
167
		}
168
		elseif ($index->isUnique()) {
169
			$xml->addChild('unique', 'true');
170
		}
171
		foreach($index->getColumns() as $column) {
172
			$field = $xml->addChild('field');
173
			$field->addChild('name', $column);
174
			$field->addChild('sorting', 'ascending');
175
			
176
		}
177
	}
178
179
	private static function toBool($bool) {
180
		return $bool ? 'true' : 'false';
181
	}
182
}
183