summaryrefslogtreecommitdiffstats
path: root/core/Command/Db/Migrations/GenerateFromSchemaFileCommand.php
diff options
context:
space:
mode:
Diffstat (limited to 'core/Command/Db/Migrations/GenerateFromSchemaFileCommand.php')
-rw-r--r--core/Command/Db/Migrations/GenerateFromSchemaFileCommand.php201
1 files changed, 201 insertions, 0 deletions
diff --git a/core/Command/Db/Migrations/GenerateFromSchemaFileCommand.php b/core/Command/Db/Migrations/GenerateFromSchemaFileCommand.php
new file mode 100644
index 00000000000..38f8d82b961
--- /dev/null
+++ b/core/Command/Db/Migrations/GenerateFromSchemaFileCommand.php
@@ -0,0 +1,201 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
+ *
+ * @author Joas Schilling <coding@schilljs.com>
+ * @author Julius Haertl <jus@bitgrid.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Core\Command\Db\Migrations;
+
+
+use Doctrine\DBAL\Schema\Schema;
+use OC\DB\MDB2SchemaReader;
+use OC\DB\MigrationService;
+use OC\Migration\ConsoleOutput;
+use OCP\App\IAppManager;
+use OCP\IConfig;
+use OCP\IDBConnection;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class GenerateFromSchemaFileCommand extends GenerateCommand {
+
+ /** @var IConfig */
+ protected $config;
+
+ /** @var IAppManager */
+ protected $appManager;
+
+ public function __construct(IConfig $config, IAppManager $appManager, IDBConnection $connection) {
+ parent::__construct($connection);
+ $this->config = $config;
+ $this->appManager = $appManager;
+ }
+
+
+ protected function configure() {
+ parent::configure();
+
+ $this->setName('migrations:generate-from-schema');
+ }
+
+ public function execute(InputInterface $input, OutputInterface $output) {
+ $appName = $input->getArgument('app');
+ $version = $input->getArgument('version');
+
+ if (!preg_match('/^\d{1,16}$/',$version)) {
+ $output->writeln('<error>The given version is invalid. Only 0-9 are allowed (max. 16 digits)</error>');
+ return 1;
+ }
+
+ $reader = new MDB2SchemaReader($this->config, $this->connection->getDatabasePlatform());
+ $schema = new Schema();
+ if ($appName === 'core') {
+ $reader->loadSchemaFromFile(\OC::$SERVERROOT . '/db_structure.xml', $schema);
+ } else {
+ if (!file_exists($this->appManager->getAppPath($appName) . '/appinfo/database.xml')) {
+ throw new \RuntimeException('App ' . $appName . ' does not have a database.xml file');
+ }
+ $reader->loadSchemaFromFile($this->appManager->getAppPath($appName) . '/appinfo/database.xml', $schema);
+ }
+
+
+ $schemaBody = $this->schemaToMigration($schema);
+
+ $ms = new MigrationService($appName, $this->connection, new ConsoleOutput($output));
+
+ $date = date('YmdHis');
+ $path = $this->generateMigration($ms, 'Version' . $version . 'Date' . $date, $schemaBody);
+
+ $output->writeln("New migration class has been generated to <info>$path</info>");
+ return 0;
+ }
+
+ /**
+ * @param Schema $schema
+ * @return string
+ */
+ protected function schemaToMigration(Schema $schema) {
+ $content = <<<'EOT'
+ /** @var Schema $schema */
+ $schema = $schemaClosure();
+
+EOT;
+
+ foreach ($schema->getTables() as $table) {
+ $content .= str_replace('{{table-name}}', substr($table->getName(), 3), <<<'EOT'
+
+ if (!$schema->hasTable('{{table-name}}')) {
+ $table = $schema->createTable('{{table-name}}');
+
+EOT
+ );
+
+ foreach ($table->getColumns() as $column) {
+ $content .= str_replace(['{{name}}', '{{type}}'], [$column->getName(), $column->getType()->getName()], <<<'EOT'
+ $table->addColumn('{{name}}', '{{type}}', [
+
+EOT
+ );
+ if ($column->getAutoincrement()) {
+ $content .= <<<'EOT'
+ 'autoincrement' => true,
+
+EOT;
+ }
+ $content .= str_replace('{{notnull}}', $column->getNotnull() ? 'true' : 'false', <<<'EOT'
+ 'notnull' => {{notnull}},
+
+EOT
+ );
+ if ($column->getLength() !== null) {
+ $content .= str_replace('{{length}}', $column->getLength(), <<<'EOT'
+ 'length' => {{length}},
+
+EOT
+ );
+ }
+ $default = $column->getDefault();
+ if ($default !== null) {
+ $default = is_numeric($default) ? $default : "'$default'";
+ $content .= str_replace('{{default}}', $default, <<<'EOT'
+ 'default' => {{default}},
+
+EOT
+ );
+ }
+ $content .= <<<'EOT'
+ ]);
+
+EOT;
+ }
+
+ $content .= <<<'EOT'
+
+EOT;
+
+ $primaryKey = $table->getPrimaryKey();
+ if ($primaryKey !== null) {
+ $content .= str_replace('{{columns}}', implode('\', \'', $primaryKey->getUnquotedColumns()), <<<'EOT'
+ $table->setPrimaryKey(['{{columns}}']);
+
+EOT
+ );
+ }
+
+ foreach ($table->getIndexes() as $index) {
+ if ($index->isPrimary()) {
+ continue;
+ }
+
+ if ($index->isUnique()) {
+ $content .= str_replace(
+ ['{{columns}}', '{{name}}'],
+ [implode('\', \'', $index->getUnquotedColumns()), $index->getName()],
+ <<<'EOT'
+ $table->addUniqueIndex(['{{columns}}'], '{{name}}');
+
+EOT
+ );
+ } else {
+ $content .= str_replace(
+ ['{{columns}}', '{{name}}'],
+ [implode('\', \'', $index->getUnquotedColumns()), $index->getName()],
+ <<<'EOT'
+ $table->addIndex(['{{columns}}'], '{{name}}');
+
+EOT
+ );
+ }
+ }
+
+ $content .= <<<'EOT'
+ }
+
+EOT;
+ }
+
+ $content .= <<<'EOT'
+ return $schema;
+EOT;
+
+ return $content;
+ }
+}