diff options
author | Joas Schilling <coding@schilljs.com> | 2017-07-18 13:37:01 +0200 |
---|---|---|
committer | Joas Schilling <coding@schilljs.com> | 2017-07-25 12:45:38 +0200 |
commit | f6c48b1548763e0eda66af7c2720d363e1671090 (patch) | |
tree | d3ae4f2a405d08c4e052e7beabb06e3609b7423e /core/Command/Db/Migrations | |
parent | 8d751ff2b429380af7e5c870844a6a32f82f0741 (diff) | |
download | nextcloud-server-f6c48b1548763e0eda66af7c2720d363e1671090.tar.gz nextcloud-server-f6c48b1548763e0eda66af7c2720d363e1671090.zip |
Add a script to generate a migration from database.xml
Signed-off-by: Joas Schilling <coding@schilljs.com>
Diffstat (limited to 'core/Command/Db/Migrations')
-rw-r--r-- | core/Command/Db/Migrations/GenerateCommand.php | 18 | ||||
-rw-r--r-- | core/Command/Db/Migrations/GenerateFromSchemaFileCommand.php | 201 |
2 files changed, 214 insertions, 5 deletions
diff --git a/core/Command/Db/Migrations/GenerateCommand.php b/core/Command/Db/Migrations/GenerateCommand.php index e6c38d06e5d..f8a992940f9 100644 --- a/core/Command/Db/Migrations/GenerateCommand.php +++ b/core/Command/Db/Migrations/GenerateCommand.php @@ -36,7 +36,7 @@ use Symfony\Component\Console\Output\OutputInterface; class GenerateCommand extends Command { - private static $_templateSimple = + protected static $_templateSimple = '<?php namespace <namespace>; @@ -66,7 +66,7 @@ class <classname> extends SimpleMigrationStep { * @since 13.0.0 */ public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) { - return null; +<schemabody> } /** @@ -81,7 +81,7 @@ class <classname> extends SimpleMigrationStep { '; /** @var IDBConnection */ - private $connection; + protected $connection; /** * @param IDBConnection $connection @@ -123,16 +123,24 @@ class <classname> extends SimpleMigrationStep { /** * @param MigrationService $ms * @param string $className + * @param string $schemaBody * @return string */ - private function generateMigration(MigrationService $ms, $className) { + protected function generateMigration(MigrationService $ms, $className, $schemaBody = '') { + if ($schemaBody === '') { + $schemaBody = "\t\t" . 'return null;'; + } + + $placeHolders = [ '<namespace>', '<classname>', + '<schemabody>', ]; $replacements = [ $ms->getMigrationsNamespace(), $className, + $schemaBody, ]; $code = str_replace($placeHolders, $replacements, self::$_templateSimple); $dir = $ms->getMigrationsDirectory(); @@ -147,7 +155,7 @@ class <classname> extends SimpleMigrationStep { return $path; } - private function ensureMigrationDirExists($directory) { + protected function ensureMigrationDirExists($directory) { if (file_exists($directory) && is_dir($directory)) { return; } 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; + } +} |