Completed
Pull Request — stable8.2 (#24656)
by Joas
12:22
created

MDB2SchemaReader::loadField()   F

Complexity

Conditions 40
Paths 13329

Size

Total Lines 111
Code Lines 91

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 93
CRAP Score 41.8947
Metric Value
dl 0
loc 111
ccs 93
cts 104
cp 0.8942
rs 2
cc 40
eloc 91
nc 13329
nop 2
crap 41.8947

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