Completed
Push — master ( 63676d...3faef6 )
by Lukas
28:10 queued 12:28
created

GenerateFromSchemaFileCommand   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 162
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
dl 0
loc 162
rs 10
c 0
b 0
f 0
wmc 17
lcom 1
cbo 6

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A configure() 0 5 1
B execute() 0 29 3
D schemaToMigration() 0 106 12
1
<?php
2
/**
3
 * @copyright Copyright (c) 2017 Joas Schilling <[email protected]>
4
 *
5
 * @author Joas Schilling <[email protected]>
6
 * @author Julius Haertl <[email protected]>
7
 *
8
 * @license GNU AGPL version 3 or any later version
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU Affero General Public License as
12
 * published by the Free Software Foundation, either version 3 of the
13
 * License, or (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU Affero General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Affero General Public License
21
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 *
23
 */
24
25
namespace OC\Core\Command\Db\Migrations;
26
27
28
use Doctrine\DBAL\Schema\Schema;
29
use OC\DB\MDB2SchemaReader;
30
use OC\DB\MigrationService;
31
use OC\Migration\ConsoleOutput;
32
use OCP\App\IAppManager;
33
use OCP\IConfig;
34
use OCP\IDBConnection;
35
use Symfony\Component\Console\Input\InputInterface;
36
use Symfony\Component\Console\Output\OutputInterface;
37
38
class GenerateFromSchemaFileCommand extends GenerateCommand {
39
40
	/** @var IConfig */
41
	protected $config;
42
43
	/** @var IAppManager */
44
	protected $appManager;
45
46
	public function __construct(IConfig $config, IAppManager $appManager, IDBConnection $connection) {
47
		parent::__construct($connection);
48
		$this->config = $config;
49
		$this->appManager = $appManager;
50
	}
51
52
53
	protected function configure() {
54
		parent::configure();
55
56
		$this->setName('migrations:generate-from-schema');
57
	}
58
59
	public function execute(InputInterface $input, OutputInterface $output) {
60
		$appName = $input->getArgument('app');
61
		$version = $input->getArgument('version');
62
63
		if (!preg_match('/^\d{1,16}$/',$version)) {
64
			$output->writeln('<error>The given version is invalid. Only 0-9 are allowed (max. 16 digits)</error>');
65
			return 1;
66
		}
67
68
		$schemaFile = $this->appManager->getAppPath($appName) . '/appinfo/database.xml';
69
		if (!file_exists($schemaFile)) {
70
			$output->writeln('<error>App ' . $appName . ' does not have a database.xml file</error>');
71
			return 2;
72
		}
73
74
		$reader = new MDB2SchemaReader($this->config, $this->connection->getDatabasePlatform());
75
		$schema = new Schema();
76
		$reader->loadSchemaFromFile($schemaFile, $schema);
77
78
		$schemaBody = $this->schemaToMigration($schema);
79
80
		$ms = new MigrationService($appName, $this->connection, new ConsoleOutput($output));
81
82
		$date = date('YmdHis');
83
		$path = $this->generateMigration($ms, 'Version' . $version . 'Date' . $date, $schemaBody);
84
85
		$output->writeln("New migration class has been generated to <info>$path</info>");
86
		return 0;
87
	}
88
89
	/**
90
	 * @param Schema $schema
91
	 * @return string
92
	 */
93
	protected function schemaToMigration(Schema $schema) {
94
		$content = <<<'EOT'
95
		/** @var Schema $schema */
96
		$schema = $schemaClosure();
97
98
EOT;
99
100
		foreach ($schema->getTables() as $table) {
101
			$content .= str_replace('{{table-name}}', substr($table->getName(), 3), <<<'EOT'
102
103
		if (!$schema->hasTable('{{table-name}}')) {
104
			$table = $schema->createTable('{{table-name}}');
105
106
EOT
107
			);
108
109
			foreach ($table->getColumns() as $column) {
110
				$content .= str_replace(['{{name}}', '{{type}}'], [$column->getName(), $column->getType()->getName()], <<<'EOT'
111
			$table->addColumn('{{name}}', '{{type}}', [
112
113
EOT
114
				);
115
				if ($column->getAutoincrement()) {
116
					$content .= <<<'EOT'
117
				'autoincrement' => true,
118
119
EOT;
120
				}
121
				$content .= str_replace('{{notnull}}', $column->getNotnull() ? 'true' : 'false', <<<'EOT'
122
				'notnull' => {{notnull}},
123
124
EOT
125
				);
126
				if ($column->getLength() !== null) {
127
					$content .= str_replace('{{length}}', $column->getLength(), <<<'EOT'
128
				'length' => {{length}},
129
130
EOT
131
					);
132
				}
133
				$default = $column->getDefault();
134
				if ($default !== null) {
135
					$default = is_numeric($default) ? $default : "'$default'";
136
					$content .= str_replace('{{default}}', $default, <<<'EOT'
137
				'default' => {{default}},
138
139
EOT
140
					);
141
				}
142
				$content .= <<<'EOT'
143
			]);
144
145
EOT;
146
			}
147
148
			$content .= <<<'EOT'
149
150
EOT;
151
152
			$primaryKey = $table->getPrimaryKey();
153
			if ($primaryKey !== null) {
154
				$content .= str_replace('{{columns}}', implode('\', \'', $primaryKey->getUnquotedColumns()), <<<'EOT'
155
			$table->setPrimaryKey(['{{columns}}']);
156
157
EOT
158
				);
159
			}
160
161
			foreach ($table->getIndexes() as $index) {
162
				if ($index->isPrimary()) {
163
					continue;
164
				}
165
166
				if ($index->isUnique()) {
167
					$content .= str_replace(
168
						['{{columns}}', '{{name}}'],
169
						[implode('\', \'', $index->getUnquotedColumns()), $index->getName()],
170
						<<<'EOT'
171
			$table->addUniqueIndex(['{{columns}}'], '{{name}}');
172
173
EOT
174
					);
175
				} else {
176
					$content .= str_replace(
177
						['{{columns}}', '{{name}}'],
178
						[implode('\', \'', $index->getUnquotedColumns()), $index->getName()],
179
						<<<'EOT'
180
			$table->addIndex(['{{columns}}'], '{{name}}');
181
182
EOT
183
					);
184
				}
185
			}
186
187
			$content .= <<<'EOT'
188
		}
189
190
EOT;
191
		}
192
193
		$content .= <<<'EOT'
194
		return $schema;
195
EOT;
196
197
		return $content;
198
	}
199
}
200