Пример #1
0
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $configOptions = [];
     if ($this->hasInputOption('connection', $input)) {
         foreach ($input->getOption('connection') as $conn) {
             $configOptions += $this->connectionToProperties($conn);
         }
     }
     if ($this->hasInputOption('schema-dir', $input)) {
         $configOptions['propel']['paths']['schemaDir'] = $input->getOption('schema-dir');
     }
     if ($this->hasInputOption('output-dir', $input)) {
         $configOptions['propel']['paths']['migrationDir'] = $input->getOption('output-dir');
     }
     $generatorConfig = $this->getGeneratorConfig($configOptions, $input);
     $this->createDirectory($generatorConfig->getSection('paths')['migrationDir']);
     $manager = new MigrationManager();
     $manager->setGeneratorConfig($generatorConfig);
     $manager->setSchemas($this->getSchemas($generatorConfig->getSection('paths')['schemaDir'], $generatorConfig->getSection('generator')['recursive']));
     $migrationsUp = [];
     $migrationsDown = [];
     foreach ($manager->getDatabases() as $appDatabase) {
         $name = $appDatabase->getName();
         $migrationsUp[$name] = '';
         $migrationsDown[$name] = '';
     }
     $timestamp = time();
     $migrationFileName = $manager->getMigrationFileName($timestamp, $input->getOption('suffix'));
     $migrationClassBody = $manager->getMigrationClassBody($migrationsUp, $migrationsDown, $timestamp, $input->getOption('comment'), $input->getOption('suffix'));
     $file = $generatorConfig->getSection('paths')['migrationDir'] . DIRECTORY_SEPARATOR . $migrationFileName;
     file_put_contents($file, $migrationClassBody);
     $output->writeln(sprintf('"%s" file successfully created.', $file));
     if (null !== ($editorCmd = $input->getOption('editor'))) {
         $output->writeln(sprintf('Using "%s" as text editor', $editorCmd));
         shell_exec($editorCmd . ' ' . escapeshellarg($file));
     } else {
         $output->writeln('Now add SQL statements and data migration code as necessary.');
         $output->writeln('Once the migration class is valid, call the "migrate" task to execute it.');
     }
 }
Пример #2
0
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $configOptions = array();
     if ($this->hasInputOption('output-dir', $input)) {
         $configOptions['propel']['paths']['migrationDir'] = $input->getOption('output-dir');
     }
     if ($this->hasInputOption('migration-table', $input)) {
         $configOptions['propel']['migrations']['tableName'] = $input->getOption('migration-table');
     }
     $generatorConfig = $this->getGeneratorConfig($configOptions, $input);
     $this->createDirectory($generatorConfig->getSection('paths')['migrationDir']);
     $manager = new MigrationManager();
     $manager->setGeneratorConfig($generatorConfig);
     $connections = array();
     $optionConnections = $input->getOption('connection');
     if (!$optionConnections) {
         $connections = $generatorConfig->getBuildConnections();
     } else {
         foreach ($optionConnections as $connection) {
             list($name, $dsn, $infos) = $this->parseConnection($connection);
             $connections[$name] = array_merge(array('dsn' => $dsn), $infos);
         }
     }
     $manager->setConnections($connections);
     $manager->setMigrationTable($generatorConfig->getSection('migrations')['tableName']);
     $manager->setWorkingDirectory($generatorConfig->getSection('paths')['migrationDir']);
     $output->writeln('Checking Database Versions...');
     foreach ($manager->getConnections() as $datasource => $params) {
         if ($input->getOption('verbose')) {
             $output->writeln(sprintf('Connecting to database "%s" using DSN "%s"', $datasource, $params['dsn']));
         }
         if (!$manager->migrationTableExists($datasource)) {
             if ($input->getOption('verbose')) {
                 $output->writeln(sprintf('Migration table does not exist in datasource "%s"; creating it.', $datasource));
             }
             $manager->createMigrationTable($datasource);
         }
     }
     $oldestMigrationTimestamp = $manager->getOldestDatabaseVersion();
     if ($input->getOption('verbose')) {
         if ($oldestMigrationTimestamp) {
             $output->writeln(sprintf('Latest migration was executed on %s (timestamp %d)', date('Y-m-d H:i:s', $oldestMigrationTimestamp), $oldestMigrationTimestamp));
         } else {
             $output->writeln('No migration was ever executed on these connection settings.');
         }
     }
     $output->writeln('Listing Migration files...');
     $dir = $generatorConfig->getSection('paths')['migrationDir'];
     $migrationTimestamps = $manager->getMigrationTimestamps();
     $nbExistingMigrations = count($migrationTimestamps);
     if ($migrationTimestamps) {
         $output->writeln(sprintf('%d valid migration classes found in "%s"', $nbExistingMigrations, $dir));
         if ($validTimestamps = $manager->getValidMigrationTimestamps()) {
             $countValidTimestamps = count($validTimestamps);
             if ($countValidTimestamps == 1) {
                 $output->writeln('1 migration needs to be executed:');
             } else {
                 $output->writeln(sprintf('%d migrations need to be executed:', $countValidTimestamps));
             }
         }
         foreach ($migrationTimestamps as $timestamp) {
             if ($timestamp > $oldestMigrationTimestamp || $input->getOption('verbose')) {
                 $output->writeln(sprintf(' %s %s %s', $timestamp == $oldestMigrationTimestamp ? '>' : ' ', $manager->getMigrationClassName($timestamp), !in_array($timestamp, $validTimestamps) ? '(executed)' : ''));
             }
         }
     } else {
         $output->writeln(sprintf('No migration file found in "%s".', $dir));
         return false;
     }
     $migrationTimestamps = $manager->getValidMigrationTimestamps();
     $nbNotYetExecutedMigrations = count($migrationTimestamps);
     if (!$nbNotYetExecutedMigrations) {
         $output->writeln('All migration files were already executed - Nothing to migrate.');
         return false;
     }
     $output->writeln(sprintf('Call the "migrate" task to execute %s', $countValidTimestamps == 1 ? 'it' : 'them'));
 }
Пример #3
0
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $configOptions = array();
     if ($this->hasInputOption('output-dir', $input)) {
         $configOptions['propel']['paths']['migrationDir'] = $input->getOption('output-dir');
     }
     if ($this->hasInputOption('migration-table', $input)) {
         $configOptions['propel']['migrations']['tableName'] = $input->getOption('migration-table');
     }
     $generatorConfig = $this->getGeneratorConfig($configOptions, $input);
     $this->createDirectory($generatorConfig->getSection('paths')['migrationDir']);
     $manager = new MigrationManager();
     $manager->setGeneratorConfig($generatorConfig);
     $connections = array();
     $optionConnections = $input->getOption('connection');
     if (!$optionConnections) {
         $connections = $generatorConfig->getBuildConnections();
     } else {
         foreach ($optionConnections as $connection) {
             list($name, $dsn, $infos) = $this->parseConnection($connection);
             $connections[$name] = array_merge(array('dsn' => $dsn), $infos);
         }
     }
     $manager->setConnections($connections);
     $manager->setMigrationTable($generatorConfig->getSection('migrations')['tableName']);
     $manager->setWorkingDirectory($generatorConfig->getSection('paths')['migrationDir']);
     if (!($nextMigrationTimestamp = $manager->getFirstUpMigrationTimestamp())) {
         $output->writeln('All migrations were already executed - nothing to migrate.');
         return false;
     }
     if ($input->getOption('fake')) {
         $output->writeln(sprintf('Faking migration %s up', $manager->getMigrationClassName($nextMigrationTimestamp)));
     } else {
         $output->writeln(sprintf('Executing migration %s up', $manager->getMigrationClassName($nextMigrationTimestamp)));
     }
     $migration = $manager->getMigrationObject($nextMigrationTimestamp);
     if (!$input->getOption('fake')) {
         if (false === $migration->preUp($manager)) {
             if ($input->getOption('force')) {
                 $output->writeln('<error>preUp() returned false. Continue migration.</error>');
             } else {
                 $output->writeln('<error>preUp() returned false. Aborting migration.</error>');
                 return false;
             }
         }
     }
     foreach ($migration->getUpSQL() as $datasource => $sql) {
         $connection = $manager->getConnection($datasource);
         if ($input->getOption('verbose')) {
             $output->writeln(sprintf('Connecting to database "%s" using DSN "%s"', $datasource, $connection['dsn']));
         }
         $conn = $manager->getAdapterConnection($datasource);
         $res = 0;
         $statements = SqlParser::parseString($sql);
         if (!$input->getOption('fake')) {
             foreach ($statements as $statement) {
                 try {
                     if ($input->getOption('verbose')) {
                         $output->writeln(sprintf('Executing statement "%s"', $statement));
                     }
                     $conn->exec($statement);
                     $res++;
                 } catch (\Exception $e) {
                     if ($input->getOption('force')) {
                         //continue, but print error message
                         $output->writeln(sprintf('<error>Failed to execute SQL "%s". Continue migration.</error>', $statement));
                     } else {
                         throw new RuntimeException(sprintf('<error>Failed to execute SQL "%s". Aborting migration.</error>', $statement), 0, $e);
                     }
                 }
             }
             //make sure foreign_keys are activated again in mysql
             $output->writeln(sprintf('%d of %d SQL statements executed successfully on datasource "%s"', $res, count($statements), $datasource));
         }
         $manager->updateLatestMigrationTimestamp($datasource, $nextMigrationTimestamp);
         if ($input->getOption('verbose')) {
             $output->writeln(sprintf('Updated latest migration date to %d for datasource "%s"', $nextMigrationTimestamp, $datasource));
         }
     }
     if (!$input->getOption('fake')) {
         $migration->postUp($manager);
     }
     if ($timestamps = $manager->getValidMigrationTimestamps()) {
         $output->writeln(sprintf('Migration complete. %d migrations left to execute.', count($timestamps)));
     } else {
         $output->writeln('Migration complete. No further migration to execute.');
     }
 }
Пример #4
0
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $configOptions = array();
     if ($this->hasInputOption('output-dir', $input)) {
         $configOptions['propel']['paths']['migrationDir'] = $input->getOption('output-dir');
     }
     if ($this->hasInputOption('migration-table', $input)) {
         $configOptions['propel']['migrations']['tableName'] = $input->getOption('migration-table');
     }
     $generatorConfig = $this->getGeneratorConfig($configOptions, $input);
     $this->createDirectory($generatorConfig->getSection('paths')['migrationDir']);
     $manager = new MigrationManager();
     $manager->setGeneratorConfig($generatorConfig);
     $connections = array();
     $optionConnections = $input->getOption('connection');
     if (!$optionConnections) {
         $connections = $generatorConfig->getBuildConnections();
     } else {
         foreach ($optionConnections as $connection) {
             list($name, $dsn, $infos) = $this->parseConnection($connection);
             $connections[$name] = array_merge(array('dsn' => $dsn), $infos);
         }
     }
     $manager->setConnections($connections);
     $manager->setMigrationTable($generatorConfig->getSection('migrations')['tableName']);
     $manager->setWorkingDirectory($generatorConfig->getSection('paths')['migrationDir']);
     $previousTimestamps = $manager->getAlreadyExecutedMigrationTimestamps();
     if (!($nextMigrationTimestamp = array_pop($previousTimestamps))) {
         $output->writeln('No migration were ever executed on this database - nothing to reverse.');
         return false;
     }
     $output->writeln(sprintf('Executing migration %s down', $manager->getMigrationClassName($nextMigrationTimestamp)));
     if ($nbPreviousTimestamps = count($previousTimestamps)) {
         $previousTimestamp = array_pop($previousTimestamps);
     } else {
         $previousTimestamp = 0;
     }
     $migration = $manager->getMigrationObject($nextMigrationTimestamp);
     if (!$input->getOption('fake')) {
         if (false === $migration->preDown($manager)) {
             if ($input->getOption('force')) {
                 $output->writeln('<error>preDown() returned false. Continue migration.</error>');
             } else {
                 $output->writeln('<error>preDown() returned false. Aborting migration.</error>');
                 return false;
             }
         }
     }
     foreach ($migration->getDownSQL() as $datasource => $sql) {
         $connection = $manager->getConnection($datasource);
         if ($input->getOption('verbose')) {
             $output->writeln(sprintf('Connecting to database "%s" using DSN "%s"', $datasource, $connection['dsn']));
         }
         $conn = $manager->getAdapterConnection($datasource);
         $res = 0;
         $statements = SqlParser::parseString($sql);
         if (!$input->getOption('fake')) {
             foreach ($statements as $statement) {
                 try {
                     if ($input->getOption('verbose')) {
                         $output->writeln(sprintf('Executing statement "%s"', $statement));
                     }
                     $conn->exec($statement);
                     $res++;
                 } catch (\Exception $e) {
                     if ($input->getOption('force')) {
                         //continue, but print error message
                         $output->writeln(sprintf('<error>Failed to execute SQL "%s". Continue migration.</error>', $statement));
                     } else {
                         throw new RuntimeException(sprintf('<error>Failed to execute SQL "%s". Aborting migration.</error>', $statement), 0, $e);
                     }
                 }
             }
             $output->writeln(sprintf('%d of %d SQL statements executed successfully on datasource "%s"', $res, count($statements), $datasource));
         }
         $manager->removeMigrationTimestamp($datasource, $nextMigrationTimestamp);
         if ($input->getOption('verbose')) {
             $output->writeln(sprintf('Downgraded migration date to %d for datasource "%s"', $previousTimestamp, $datasource));
         }
     }
     if (!$input->getOption('fake')) {
         $migration->postDown($manager);
     }
     if ($nbPreviousTimestamps) {
         $output->writeln(sprintf('Reverse migration complete. %d more migrations available for reverse.', $nbPreviousTimestamps));
     } else {
         $output->writeln('Reverse migration complete. No more migration available for reverse');
     }
 }
Пример #5
0
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $configOptions = [];
     if ($this->hasInputOption('connection', $input)) {
         foreach ($input->getOption('connection') as $conn) {
             $configOptions += $this->connectionToProperties($conn);
         }
     }
     if ($this->hasInputOption('migration-table', $input)) {
         $configOptions['propel']['migrations']['tableName'] = $input->getOption('migration-table');
     }
     if ($this->hasInputOption('schema-dir', $input)) {
         $configOptions['propel']['paths']['schemaDir'] = $input->getOption('schema-dir');
     }
     if ($this->hasInputOption('output-dir', $input)) {
         $configOptions['propel']['paths']['migrationDir'] = $input->getOption('output-dir');
     }
     $generatorConfig = $this->getGeneratorConfig($configOptions, $input);
     $this->createDirectory($generatorConfig->getSection('paths')['migrationDir']);
     $manager = new MigrationManager();
     $manager->setGeneratorConfig($generatorConfig);
     $manager->setSchemas($this->getSchemas($generatorConfig->getSection('paths')['schemaDir'], $input->getOption('recursive')));
     $connections = [];
     $optionConnections = $input->getOption('connection');
     if (!$optionConnections) {
         $connections = $generatorConfig->getBuildConnections();
     } else {
         foreach ($optionConnections as $connection) {
             list($name, $dsn, $infos) = $this->parseConnection($connection);
             $connections[$name] = array_merge(['dsn' => $dsn], $infos);
         }
     }
     $manager->setConnections($connections);
     $manager->setMigrationTable($generatorConfig->getConfigProperty('migrations.tableName'));
     $manager->setWorkingDirectory($generatorConfig->getSection('paths')['migrationDir']);
     if ($manager->hasPendingMigrations()) {
         throw new RuntimeException('Uncommitted migrations have been found ; you should either execute or delete them before rerunning the \'diff\' task');
     }
     $totalNbTables = 0;
     $reversedSchema = new Schema();
     foreach ($manager->getDatabases() as $appDatabase) {
         $name = $appDatabase->getName();
         if (!($params = @$connections[$name])) {
             $output->writeln(sprintf('<info>No connection configured for database "%s"</info>', $name));
         }
         if ($input->getOption('verbose')) {
             $output->writeln(sprintf('Connecting to database "%s" using DSN "%s"', $name, $params['dsn']));
         }
         $conn = $manager->getAdapterConnection($name);
         $platform = $generatorConfig->getConfiguredPlatform($conn, $name);
         if (!$platform->supportsMigrations()) {
             $output->writeln(sprintf('Skipping database "%s" since vendor "%s" does not support migrations', $name, $platform->getDatabaseType()));
             continue;
         }
         $additionalTables = [];
         foreach ($appDatabase->getTables() as $table) {
             if ($table->getSchema() && $table->getSchema() != $appDatabase->getSchema()) {
                 $additionalTables[] = $table;
             }
         }
         if ($input->getOption('disable-identifier-quoting')) {
             $platform->setIdentifierQuoting(false);
         }
         $database = new Database($name);
         $database->setPlatform($platform);
         $database->setSchema($appDatabase->getSchema());
         $database->setDefaultIdMethod(IdMethod::NATIVE);
         $parser = $generatorConfig->getConfiguredSchemaParser($conn, $name);
         $nbTables = $parser->parse($database, $additionalTables);
         $reversedSchema->addDatabase($database);
         $totalNbTables += $nbTables;
         if ($input->getOption('verbose')) {
             $output->writeln(sprintf('%d tables found in database "%s"', $nbTables, $name), Output::VERBOSITY_VERBOSE);
         }
     }
     if ($totalNbTables) {
         $output->writeln(sprintf('%d tables found in all databases.', $totalNbTables));
     } else {
         $output->writeln('No table found in all databases');
     }
     // comparing models
     $output->writeln('Comparing models...');
     $tableRenaming = $input->getOption('table-renaming');
     $migrationsUp = [];
     $migrationsDown = [];
     $removeTable = !$input->getOption('skip-removed-table');
     $excludedTables = $input->getOption('skip-tables');
     foreach ($reversedSchema->getDatabases() as $database) {
         $name = $database->getName();
         if ($input->getOption('verbose')) {
             $output->writeln(sprintf('Comparing database "%s"', $name));
         }
         if (!($appDataDatabase = $manager->getDatabase($name))) {
             $output->writeln(sprintf('<error>Database "%s" does not exist in schema.xml. Skipped.</error>', $name));
             continue;
         }
         $configManager = new ConfigurationManager();
         $excludedTables = array_merge((array) $excludedTables, (array) $configManager->getSection('exclude_tables'));
         $databaseDiff = DatabaseComparator::computeDiff($database, $appDataDatabase, false, $tableRenaming, $removeTable, $excludedTables);
         if (!$databaseDiff) {
             if ($input->getOption('verbose')) {
                 $output->writeln(sprintf('Same XML and database structures for datasource "%s" - no diff to generate', $name));
             }
             continue;
         }
         $output->writeln(sprintf('Structure of database was modified in datasource "%s": %s', $name, $databaseDiff->getDescription()));
         foreach ($databaseDiff->getPossibleRenamedTables() as $fromTableName => $toTableName) {
             $output->writeln(sprintf('<info>Possible table renaming detected: "%s" to "%s". It will be deleted and recreated. Use --table-renaming to only rename it.</info>', $fromTableName, $toTableName));
         }
         $conn = $manager->getAdapterConnection($name);
         $platform = $generatorConfig->getConfiguredPlatform($conn, $name);
         if ($input->getOption('disable-identifier-quoting')) {
             $platform->setIdentifierQuoting(false);
         }
         $migrationsUp[$name] = $platform->getModifyDatabaseDDL($databaseDiff);
         $migrationsDown[$name] = $platform->getModifyDatabaseDDL($databaseDiff->getReverseDiff());
     }
     if (!$migrationsUp) {
         $output->writeln('Same XML and database structures for all datasource - no diff to generate');
         return;
     }
     $timestamp = time();
     $migrationFileName = $manager->getMigrationFileName($timestamp);
     $migrationClassBody = $manager->getMigrationClassBody($migrationsUp, $migrationsDown, $timestamp, $input->getOption('comment'));
     $file = $generatorConfig->getSection('paths')['migrationDir'] . DIRECTORY_SEPARATOR . $migrationFileName;
     file_put_contents($file, $migrationClassBody);
     $output->writeln(sprintf('"%s" file successfully created.', $file));
     if (null !== ($editorCmd = $input->getOption('editor'))) {
         $output->writeln(sprintf('Using "%s" as text editor', $editorCmd));
         shell_exec($editorCmd . ' ' . escapeshellarg($file));
     } else {
         $output->writeln('Please review the generated SQL statements, and add data migration code if necessary.');
         $output->writeln('Once the migration class is valid, call the "migrate" task to execute it.');
     }
 }
Пример #6
0
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $generatorConfig = $this->getGeneratorConfig(array('propel.platform.class' => $input->getOption('platform')), $input);
     $this->createDirectory($input->getOption('output-dir'));
     $manager = new MigrationManager();
     $manager->setGeneratorConfig($generatorConfig);
     $connections = array();
     foreach ($input->getOption('connection') as $connection) {
         list($name, $dsn, $infos) = $this->parseConnection($connection);
         $connections[$name] = array_merge(array('dsn' => $dsn), $infos);
     }
     $manager->setConnections($connections);
     $manager->setMigrationTable($input->getOption('migration-table'));
     $manager->setWorkingDirectory($input->getOption('output-dir'));
     $previousTimestamps = $manager->getAlreadyExecutedMigrationTimestamps();
     if (!($nextMigrationTimestamp = array_pop($previousTimestamps))) {
         $output->writeln('No migration were ever executed on this database - nothing to reverse.');
         return false;
     }
     $output->writeln(sprintf('Executing migration %s down', $manager->getMigrationClassName($nextMigrationTimestamp)));
     if ($nbPreviousTimestamps = count($previousTimestamps)) {
         $previousTimestamp = array_pop($previousTimestamps);
     } else {
         $previousTimestamp = 0;
     }
     $migration = $manager->getMigrationObject($nextMigrationTimestamp);
     if (false === $migration->preDown($manager)) {
         $output->writeln('<error>preDown() returned false. Aborting migration.</error>');
         return false;
     }
     foreach ($migration->getDownSQL() as $datasource => $sql) {
         $connection = $manager->getConnection($datasource);
         if ($input->getOption('verbose')) {
             $output->writeln(sprintf('Connecting to database "%s" using DSN "%s"', $datasource, $connection['dsn']));
         }
         $conn = $manager->getAdapterConnection($datasource);
         $res = 0;
         $statements = SqlParser::parseString($sql);
         foreach ($statements as $statement) {
             try {
                 if ($input->getOption('verbose')) {
                     $output->writeln(sprintf('Executing statement "%s"', $statement));
                 }
                 $stmt = $conn->prepare($statement);
                 $stmt->execute();
                 $res++;
             } catch (PDOException $e) {
                 $output->writeln(sprintf('<error>Failed to execute SQL "%s"</error>', $statement));
             }
         }
         if (!$res) {
             $output->writeln('No statement was executed. The version was not updated.');
             $output->writeln(sprintf('Please review the code in "%s"', $manager->getMigrationDir() . DIRECTORY_SEPARATOR . $manager->getMigrationClassName($nextMigrationTimestamp)));
             $output->writeln('<error>Migration aborted</error>');
             return false;
         }
         $output->writeln(sprintf('%d of %d SQL statements executed successfully on datasource "%s"', $res, count($statements), $datasource));
         $manager->updateLatestMigrationTimestamp($datasource, $previousTimestamp);
         if ($input->getOption('verbose')) {
             $output->writeln(sprintf('Downgraded migration date to %d for datasource "%s"', $previousTimestamp, $datasource));
         }
     }
     $migration->postDown($manager);
     if ($nbPreviousTimestamps) {
         $output->writeln(sprintf('Reverse migration complete. %d more migrations available for reverse.', $nbPreviousTimestamps));
     } else {
         $output->writeln('Reverse migration complete. No more migration available for reverse');
     }
 }
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $configOptions = array();
     if ($this->hasInputOption('output-dir', $input)) {
         $configOptions['propel']['paths']['migrationDir'] = $input->getOption('output-dir');
     }
     $generatorConfig = $this->getGeneratorConfig($configOptions, $input);
     $this->createDirectory($generatorConfig->getSection('paths')['migrationDir']);
     $manager = new MigrationManager();
     $manager->setGeneratorConfig($generatorConfig);
     $connections = array();
     $optionConnections = $input->getOption('connection');
     if (!$optionConnections) {
         $connections = $generatorConfig->getBuildConnections();
     } else {
         foreach ($optionConnections as $connection) {
             list($name, $dsn, $infos) = $this->parseConnection($connection);
             $connections[$name] = array_merge(array('dsn' => $dsn), $infos);
         }
     }
     $manager->setConnections($connections);
     $manager->setMigrationTable($input->getOption('migration-table'));
     $manager->setWorkingDirectory($generatorConfig->getSection('paths')['migrationDir']);
     if (!$manager->getFirstUpMigrationTimestamp()) {
         $output->writeln('All migrations were already executed - nothing to migrate.');
         return false;
     }
     $timestamps = $manager->getValidMigrationTimestamps();
     if (count($timestamps) > 1) {
         $output->writeln(sprintf('%d migrations to execute', count($timestamps)));
     }
     foreach ($timestamps as $timestamp) {
         $output->writeln(sprintf('Executing migration %s up', $manager->getMigrationClassName($timestamp)));
         $migration = $manager->getMigrationObject($timestamp);
         if (property_exists($migration, 'comment') && $migration->comment) {
             $output->writeln(sprintf('<info>%s</info>', $migration->comment));
         }
         if (false === $migration->preUp($manager)) {
             $output->writeln('<error>preUp() returned false. Aborting migration.</error>');
             return false;
         }
         foreach ($migration->getUpSQL() as $datasource => $sql) {
             $connection = $manager->getConnection($datasource);
             if ($input->getOption('verbose')) {
                 $output->writeln(sprintf('Connecting to database "%s" using DSN "%s"', $datasource, $connection['dsn']));
             }
             $conn = $manager->getAdapterConnection($datasource);
             $res = 0;
             $statements = SqlParser::parseString($sql);
             foreach ($statements as $statement) {
                 try {
                     if ($input->getOption('verbose')) {
                         $output->writeln(sprintf('Executing statement "%s"', $statement));
                     }
                     $stmt = $conn->prepare($statement);
                     $stmt->execute();
                     $res++;
                 } catch (\PDOException $e) {
                     $output->writeln(sprintf('<error>Failed to execute SQL "%s": %s</error>', $statement, $e->getMessage()));
                     // continue
                 }
             }
             if (!$res) {
                 $output->writeln('No statement was executed. The version was not updated.');
                 $output->writeln(sprintf('Please review the code in "%s"', $manager->getWorkingDirectory() . DIRECTORY_SEPARATOR . $manager->getMigrationClassName($timestamp)));
                 $output->writeln('<error>Migration aborted</error>');
                 return false;
             }
             $output->writeln(sprintf('%d of %d SQL statements executed successfully on datasource "%s"', $res, count($statements), $datasource));
         }
         // migrations for datasources have passed - update the timestamp
         // for all datasources
         foreach ($manager->getConnections() as $datasource => $connection) {
             $manager->updateLatestMigrationTimestamp($datasource, $timestamp);
             if ($input->getOption('verbose')) {
                 $output->writeln(sprintf('Updated latest migration date to %d for datasource "%s"', $timestamp, $datasource));
             }
         }
         $migration->postUp($manager);
     }
     $output->writeln('Migration complete. No further migration to execute.');
 }
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $generatorConfig = $this->getGeneratorConfig(array('propel.platform.class' => $input->getOption('platform'), 'propel.reverse.parser.class' => $this->getReverseClass($input), 'propel.migration.table' => $input->getOption('migration-table')), $input);
     $this->createDirectory($input->getOption('output-dir'));
     $manager = new MigrationManager();
     $manager->setGeneratorConfig($generatorConfig);
     $manager->setSchemas($this->getSchemas($input->getOption('input-dir')));
     $connections = array();
     $optionConnections = $input->getOption('connection');
     if (!$optionConnections) {
         $connections = $generatorConfig->getBuildConnections($input->getOption('input-dir'));
     } else {
         foreach ($optionConnections as $connection) {
             list($name, $dsn, $infos) = $this->parseConnection($connection);
             $connections[$name] = array_merge(array('dsn' => $dsn), $infos);
         }
     }
     $manager->setConnections($connections);
     $manager->setMigrationTable($input->getOption('migration-table'));
     $manager->setWorkingDirectory($input->getOption('output-dir'));
     if ($manager->hasPendingMigrations()) {
         throw new RuntimeException('Uncommitted migrations have been found ; you should either execute or delete them before rerunning the \'diff\' task');
     }
     $totalNbTables = 0;
     $schema = new Schema();
     foreach ($connections as $name => $params) {
         if ($input->getOption('verbose')) {
             $output->writeln(sprintf('Connecting to database "%s" using DSN "%s"', $name, $params['dsn']));
         }
         $conn = $manager->getAdapterConnection($name);
         $platform = $generatorConfig->getConfiguredPlatform($conn, $name);
         if (!$platform->supportsMigrations()) {
             $output->writeln(sprintf('Skipping database "%s" since vendor "%s" does not support migrations', $name, $platform->getDatabaseType()));
             continue;
         }
         $database = new Database($name);
         $database->setPlatform($platform);
         $database->setDefaultIdMethod(IdMethod::NATIVE);
         $parser = $generatorConfig->getConfiguredSchemaParser($conn);
         $nbTables = $parser->parse($database, $this);
         $schema->addDatabase($database);
         $totalNbTables += $nbTables;
         if ($input->getOption('verbose')) {
             $output->writeln(sprintf('%d tables found in database "%s"', $nbTables, $name), Output::VERBOSITY_VERBOSE);
         }
     }
     if ($totalNbTables) {
         $output->writeln(sprintf('%d tables found in all databases.', $totalNbTables));
     } else {
         $output->writeln('No table found in all databases');
     }
     $appDatasFromXml = $manager->getDataModels();
     $appDataFromXml = array_pop($appDatasFromXml);
     // comparing models
     $output->writeln('Comparing models...');
     $migrationsUp = array();
     $migrationsDown = array();
     foreach ($schema->getDatabases() as $database) {
         $name = $database->getName();
         if ($input->getOption('verbose')) {
             $output->writeln(sprintf('Comparing database "%s"', $name));
         }
         if (!$appDataFromXml->hasDatabase($name)) {
             // FIXME: tables present in database but not in XML
             continue;
         }
         $databaseDiff = DatabaseComparator::computeDiff($database, $appDataFromXml->getDatabase($name));
         if (!$databaseDiff) {
             if ($input->getOption('verbose')) {
                 $output->writeln(sprintf('Same XML and database structures for datasource "%s" - no diff to generate', $name));
             }
             continue;
         }
         $output->writeln(sprintf('Structure of database was modified in datasource "%s": %s', $name, $databaseDiff->getDescription()));
         $platform = $generatorConfig->getConfiguredPlatform(null, $name);
         $migrationsUp[$name] = $platform->getModifyDatabaseDDL($databaseDiff);
         $migrationsDown[$name] = $platform->getModifyDatabaseDDL($databaseDiff->getReverseDiff());
     }
     if (!$migrationsUp) {
         $output->writeln('Same XML and database structures for all datasource - no diff to generate');
         return;
     }
     $timestamp = time();
     $migrationFileName = $manager->getMigrationFileName($timestamp);
     $migrationClassBody = $manager->getMigrationClassBody($migrationsUp, $migrationsDown, $timestamp);
     $file = $input->getOption('output-dir') . DIRECTORY_SEPARATOR . $migrationFileName;
     file_put_contents($file, $migrationClassBody);
     $output->writeln(sprintf('"%s" file successfully created.', $file));
     if (null !== ($editorCmd = $input->getOption('editor'))) {
         $output->writeln(sprintf('Using "%s" as text editor', $editorCmd));
         shell_exec($editorCmd . ' ' . escapeshellarg($file));
     } else {
         $output->writeln('Please review the generated SQL statements, and add data migration code if necessary.');
         $output->writeln('Once the migration class is valid, call the "migrate" task to execute it.');
     }
 }