Completed
Push — stable8 ( c45eda...dba072 )
by
unknown
15:55
created

MDB2SchemaReader::loadField()   F

Complexity

Conditions 40
Paths 13329

Size

Total Lines 111
Code Lines 91

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 40
eloc 91
nc 13329
nop 2
dl 0
loc 111
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Copyright (c) 2012 Bart Visscher <[email protected]>
4
 * This file is licensed under the Affero General Public License version 3 or
5
 * later.
6
 * See the COPYING-README file.
7
 */
8
9
namespace OC\DB;
10
11
use Doctrine\DBAL\Platforms\AbstractPlatform;
12
use OCP\IConfig;
13
14
class MDB2SchemaReader {
15
	/**
16
	 * @var string $DBNAME
17
	 */
18
	protected $DBNAME;
19
20
	/**
21
	 * @var string $DBTABLEPREFIX
22
	 */
23
	protected $DBTABLEPREFIX;
24
25
	/**
26
	 * @var \Doctrine\DBAL\Platforms\AbstractPlatform $platform
27
	 */
28
	protected $platform;
29
30
	/**
31
	 * @param \OCP\IConfig $config
32
	 * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
33
	 */
34
	public function __construct(IConfig $config, AbstractPlatform $platform) {
35
		$this->platform = $platform;
36
		$this->DBNAME = $config->getSystemValue('dbname', 'owncloud');
37
		$this->DBTABLEPREFIX = $config->getSystemValue('dbtableprefix', 'oc_');
38
	}
39
40
	/**
41
	 * @param string $file
42
	 * @return \Doctrine\DBAL\Schema\Schema
43
	 * @throws \DomainException
44
	 */
45
	public function loadSchemaFromFile($file) {
46
		$schema = new \Doctrine\DBAL\Schema\Schema();
47
		$loadEntities = libxml_disable_entity_loader(false);
48
		$xml = simplexml_load_file($file);
49
		libxml_disable_entity_loader($loadEntities);
50
		foreach ($xml->children() as $child) {
51
			/**
52
			 * @var \SimpleXMLElement $child
53
			 */
54
			switch ($child->getName()) {
55
				case 'name':
56
				case 'create':
57
				case 'overwrite':
58
				case 'charset':
59
					break;
60
				case 'table':
61
					$this->loadTable($schema, $child);
62
					break;
63
				default:
64
					throw new \DomainException('Unknown element: ' . $child->getName());
65
66
			}
67
		}
68
		return $schema;
69
	}
70
71
	/**
72
	 * @param \Doctrine\DBAL\Schema\Schema $schema
73
	 * @param \SimpleXMLElement $xml
74
	 * @throws \DomainException
75
	 */
76
	private function loadTable($schema, $xml) {
77
		$table = null;
78
		foreach ($xml->children() as $child) {
79
			/**
80
			 * @var \SimpleXMLElement $child
81
			 */
82
			switch ($child->getName()) {
83
				case 'name':
84
					$name = (string)$child;
85
					$name = str_replace('*dbprefix*', $this->DBTABLEPREFIX, $name);
86
					$name = $this->platform->quoteIdentifier($name);
87
					$table = $schema->createTable($name);
88
					$table->addOption('collate', 'utf8_bin');
89
					break;
90
				case 'create':
91
				case 'overwrite':
92
				case 'charset':
93
					break;
94
				case 'declaration':
95
					if (is_null($table)) {
96
						throw new \DomainException('Table declaration before table name');
97
					}
98
					$this->loadDeclaration($table, $child);
99
					break;
100
				default:
101
					throw new \DomainException('Unknown element: ' . $child->getName());
102
103
			}
104
		}
105
	}
106
107
	/**
108
	 * @param \Doctrine\DBAL\Schema\Table $table
109
	 * @param \SimpleXMLElement $xml
110
	 * @throws \DomainException
111
	 */
112
	private function loadDeclaration($table, $xml) {
113
		foreach ($xml->children() as $child) {
114
			/**
115
			 * @var \SimpleXMLElement $child
116
			 */
117
			switch ($child->getName()) {
118
				case 'field':
119
					$this->loadField($table, $child);
120
					break;
121
				case 'index':
122
					$this->loadIndex($table, $child);
123
					break;
124
				default:
125
					throw new \DomainException('Unknown element: ' . $child->getName());
126
127
			}
128
		}
129
	}
130
131
	/**
132
	 * @param \Doctrine\DBAL\Schema\Table $table
133
	 * @param \SimpleXMLElement $xml
134
	 * @throws \DomainException
135
	 */
136
	private function loadField($table, $xml) {
137
		$options = array( 'notnull' => false );
138
		foreach ($xml->children() as $child) {
139
			/**
140
			 * @var \SimpleXMLElement $child
141
			 */
142
			switch ($child->getName()) {
143
				case 'name':
144
					$name = (string)$child;
145
					$name = $this->platform->quoteIdentifier($name);
146
					break;
147
				case 'type':
148
					$type = (string)$child;
149
					switch ($type) {
150
						case 'text':
151
							$type = 'string';
152
							break;
153
						case 'clob':
154
							$type = 'text';
155
							break;
156
						case 'timestamp':
157
							$type = 'datetime';
158
							break;
159
						case 'numeric':
160
							$type = 'decimal';
161
							break;
162
					}
163
					break;
164
				case 'length':
165
					$length = (string)$child;
166
					$options['length'] = $length;
167
					break;
168
				case 'unsigned':
169
					$unsigned = $this->asBool($child);
170
					$options['unsigned'] = $unsigned;
171
					break;
172
				case 'notnull':
173
					$notnull = $this->asBool($child);
174
					$options['notnull'] = $notnull;
175
					break;
176
				case 'autoincrement':
177
					$autoincrement = $this->asBool($child);
178
					$options['autoincrement'] = $autoincrement;
179
					break;
180
				case 'default':
181
					$default = (string)$child;
182
					$options['default'] = $default;
183
					break;
184
				case 'comments':
185
					$comment = (string)$child;
186
					$options['comment'] = $comment;
187
					break;
188
				case 'primary':
189
					$primary = $this->asBool($child);
190
					$options['primary'] = $primary;
191
					break;
192
				case 'precision':
193
					$precision = (string)$child;
194
					$options['precision'] = $precision;
195
					break;
196
				case 'scale':
197
					$scale = (string)$child;
198
					$options['scale'] = $scale;
199
					break;
200
				default:
201
					throw new \DomainException('Unknown element: ' . $child->getName());
202
203
			}
204
		}
205
		if (isset($name) && isset($type)) {
206
			if (isset($options['default']) && empty($options['default'])) {
207
				if (empty($options['notnull']) || !$options['notnull']) {
208
					unset($options['default']);
209
					$options['notnull'] = false;
210
				} else {
211
					$options['default'] = '';
212
				}
213
				if ($type == 'integer' || $type == 'decimal') {
214
					$options['default'] = 0;
215
				} elseif ($type == 'boolean') {
216
					$options['default'] = false;
217
				}
218
				if (!empty($options['autoincrement']) && $options['autoincrement']) {
219
					unset($options['default']);
220
				}
221
			}
222
			if ($type === 'integer' && isset($options['default'])) {
223
				$options['default'] = (int)$options['default'];
224
			}
225
			if ($type === 'integer' && isset($options['length'])) {
226
				$length = $options['length'];
227
				if ($length < 4) {
228
					$type = 'smallint';
229
				} else if ($length > 4) {
230
					$type = 'bigint';
231
				}
232
			}
233
			if ($type === 'boolean' && isset($options['default'])) {
234
				$options['default'] = $this->asBool($options['default']);
235
			}
236
			if (!empty($options['autoincrement'])
237
				&& !empty($options['notnull'])
238
			) {
239
				$options['primary'] = true;
240
			}
241
			$table->addColumn($name, $type, $options);
242
			if (!empty($options['primary']) && $options['primary']) {
243
				$table->setPrimaryKey(array($name));
244
			}
245
		}
246
	}
247
248
	/**
249
	 * @param \Doctrine\DBAL\Schema\Table $table
250
	 * @param \SimpleXMLElement $xml
251
	 * @throws \DomainException
252
	 */
253
	private function loadIndex($table, $xml) {
254
		$name = null;
255
		$fields = array();
256
		foreach ($xml->children() as $child) {
257
			/**
258
			 * @var \SimpleXMLElement $child
259
			 */
260
			switch ($child->getName()) {
261
				case 'name':
262
					$name = (string)$child;
263
					break;
264
				case 'primary':
265
					$primary = $this->asBool($child);
266
					break;
267
				case 'unique':
268
					$unique = $this->asBool($child);
269
					break;
270
				case 'field':
271
					foreach ($child->children() as $field) {
272
						/**
273
						 * @var \SimpleXMLElement $field
274
						 */
275
						switch ($field->getName()) {
276
							case 'name':
277
								$field_name = (string)$field;
278
								$field_name = $this->platform->quoteIdentifier($field_name);
279
								$fields[] = $field_name;
280
								break;
281
							case 'sorting':
282
								break;
283
							default:
284
								throw new \DomainException('Unknown element: ' . $field->getName());
285
286
						}
287
					}
288
					break;
289
				default:
290
					throw new \DomainException('Unknown element: ' . $child->getName());
291
292
			}
293
		}
294
		if (!empty($fields)) {
295
			if (isset($primary) && $primary) {
296
				if ($table->hasPrimaryKey()) {
297
					return;
298
				}
299
				$table->setPrimaryKey($fields, $name);
300
			} else {
301
				if (isset($unique) && $unique) {
302
					$table->addUniqueIndex($fields, $name);
303
				} else {
304
					$table->addIndex($fields, $name);
305
				}
306
			}
307
		} else {
308
			throw new \DomainException('Empty index definition: ' . $name . ' options:' . print_r($fields, true));
309
		}
310
	}
311
312
	/**
313
	 * @param \SimpleXMLElement|string $xml
314
	 * @return bool
315
	 */
316
	private function asBool($xml) {
317
		$result = (string)$xml;
318
		if ($result == 'true') {
319
			$result = true;
320
		} elseif ($result == 'false') {
321
			$result = false;
322
		}
323
		return (bool)$result;
324
	}
325
326
}
327