Ejemplo n.º 1
0
 public function getMigrationConfig(InputInterface $input, OutputWriter $outputWriter)
 {
     /**
      * If a configuration option is passed to the command line, use that configuration
      * instead of any other one.
      */
     if ($input->getOption('configuration')) {
         $outputWriter->write("Loading configuration from command option: " . $input->getOption('configuration'));
         return $this->loadConfig($input->getOption('configuration'), $outputWriter);
     }
     /**
      * If a configuration has already been set using DI or a Setter use it.
      */
     if ($this->configuration) {
         $outputWriter->write("Loading configuration from the integration code of your framework (setter).");
         return $this->configuration;
     }
     /**
      * If no any other config has been found, look for default config file in the path.
      */
     $defaultConfig = array('migrations.xml', 'migrations.yml', 'migrations.yaml');
     foreach ($defaultConfig as $config) {
         if ($this->configExists($config)) {
             $outputWriter->write("Loading configuration from file: {$config}");
             return $this->loadConfig($config, $outputWriter);
         }
     }
     return new Configuration($this->connection, $outputWriter);
 }
Ejemplo n.º 2
0
 /**
  * @param array $queriesByVersion array Keys are versions and values are arrays of SQL queries (they must be castable to string)
  * @param string $direction
  * @return int|bool
  */
 public function write(array $queriesByVersion, $direction)
 {
     $path = $this->buildMigrationFilePath();
     $string = $this->buildMigrationFile($queriesByVersion, $direction);
     if ($this->outputWriter) {
         $this->outputWriter->write("\n" . sprintf('Writing migration file to "<info>%s</info>"', $path));
     }
     return file_put_contents($path, $string);
 }
Ejemplo n.º 3
0
 private function executeRegisteredSql($dryRun = false, $timeAllQueries = false)
 {
     if (!$dryRun) {
         if (!empty($this->sql)) {
             foreach ($this->sql as $key => $query) {
                 $queryStart = microtime(true);
                 if (!isset($this->params[$key])) {
                     $this->outputWriter->write('     <comment>-></comment> ' . $query);
                     $this->connection->exec($query);
                 } else {
                     $this->outputWriter->write(sprintf('    <comment>-</comment> %s (with parameters)', $query));
                     $this->connection->executeQuery($query, $this->params[$key], $this->types[$key]);
                 }
                 $this->outputQueryTime($queryStart, $timeAllQueries);
             }
         } else {
             $this->outputWriter->write(sprintf('<error>Migration %s was executed but did not result in any SQL statements.</error>', $this->version));
         }
     } else {
         foreach ($this->sql as $query) {
             $this->outputWriter->write('     <comment>-></comment> ' . $query);
         }
     }
     $this->resetRegisteredSql();
 }
Ejemplo n.º 4
0
 /**
  * Print a warning message if the condition evalutes to TRUE.
  *
  * @param bool $condition
  * @param string $message
  */
 public function warnIf($condition, $message = '')
 {
     $message = strlen($message) ? $message : 'Unknown Reason';
     if ($condition === true) {
         $this->outputWriter->write('    <warning>Warning during ' . $this->version->getExecutionState() . ': ' . $message . '</warning>');
     }
 }
Ejemplo n.º 5
0
 private function outputQueryTime($queryStart, $timeAllQueries = false)
 {
     if ($timeAllQueries !== false) {
         $queryEnd = microtime(true);
         $queryTime = round($queryEnd - $queryStart, 4);
         $this->outputWriter->write(sprintf("  <info>%ss</info>", $queryTime));
     }
 }
Ejemplo n.º 6
0
 public function write($message)
 {
     if ($this->outputInterface) {
         $this->outputInterface->writeln($message);
     } else {
         parent::write($message);
     }
 }
Ejemplo n.º 7
0
 /**
  * Run a migration to the current version or the given target version.
  *
  * @param string  $to             The version to migrate to.
  * @param boolean $dryRun         Whether or not to make this a dry run and not execute anything.
  * @param boolean $timeAllQueries Measuring or not the execution time of each SQL query.
  *
  * @return array $sql     The array of migration sql statements
  *
  * @throws MigrationException
  */
 public function migrate($to = null, $dryRun = false, $timeAllQueries = false)
 {
     /**
      * If no version to migrate to is given we default to the last available one.
      */
     if ($to === null) {
         $to = $this->configuration->getLatestVersion();
     }
     $from = (string) $this->configuration->getCurrentVersion();
     $to = (string) $to;
     /**
      * Throw an error if we can't find the migration to migrate to in the registered
      * migrations.
      */
     $migrations = $this->configuration->getMigrations();
     if (!isset($migrations[$to]) && $to > 0) {
         throw MigrationException::unknownMigrationVersion($to);
     }
     $direction = $from > $to ? 'down' : 'up';
     $migrationsToExecute = $this->configuration->getMigrationsToExecute($direction, $to);
     /**
      * If
      *  there are no migrations to execute
      *  and there are migrations,
      *  and the migration from and to are the same
      * means we are already at the destination return an empty array()
      * to signify that there is nothing left to do.
      */
     if ($from === $to && empty($migrationsToExecute) && !empty($migrations)) {
         return array();
     }
     $output = $dryRun ? 'Executing dry run of migration' : 'Migrating';
     $output .= ' <info>%s</info> to <comment>%s</comment> from <comment>%s</comment>';
     $this->outputWriter->write(sprintf($output, $direction, $to, $from));
     /**
      * If there are no migrations to execute throw an exception.
      */
     if (empty($migrationsToExecute)) {
         throw MigrationException::noMigrationsToExecute();
     }
     $sql = array();
     $time = 0;
     foreach ($migrationsToExecute as $version) {
         $versionSql = $version->execute($direction, $dryRun, $timeAllQueries);
         $sql[$version->getVersion()] = $versionSql;
         $time += $version->getTime();
     }
     $this->outputWriter->write("\n  <comment>------------------------</comment>\n");
     $this->outputWriter->write(sprintf("  <info>++</info> finished in %s", $time));
     $this->outputWriter->write(sprintf("  <info>++</info> %s migrations executed", count($migrationsToExecute)));
     $this->outputWriter->write(sprintf("  <info>++</info> %s sql queries", count($sql, true) - count($sql)));
     return $sql;
 }
Ejemplo n.º 8
0
    /**
     * Run a migration to the current version or the given target version.
     *
     * @param string $to      The version to migrate to.
     * @param string $dryRun  Whether or not to make this a dry run and not execute anything.
     * @return array $sql     The array of migration sql statements
     * @throws MigrationException
     */
    public function migrate($to = null, $dryRun = false)
    {
        if ($to === null) {
            $to = $this->configuration->getLatestVersion();
        }

        $from = $this->configuration->getCurrentVersion();
        $from = (string) $from;
        $to = (string) $to;

        $migrations = $this->configuration->getMigrations();
        if ( ! isset($migrations[$to]) && $to > 0) {
            throw MigrationException::unknownMigrationVersion($to);
        }

        if ($from === $to) {
            throw MigrationException::alreadyAtVersion($to);
        }

        $direction = $from > $to ? 'down' : 'up';
        $migrations = $this->configuration->getMigrationsToExecute($direction, $to);

        if ($dryRun === false) {
            $this->outputWriter->write(sprintf('Migrating <info>%s</info> to <comment>%s</comment> from <comment>%s</comment>', $direction, $to, $from));
        } else {
            $this->outputWriter->write(sprintf('Executing dry run of migration <info>%s</info> to <comment>%s</comment> from <comment>%s</comment>', $direction, $to, $from));
        }

        if (empty($migrations)) {
            throw MigrationException::noMigrationsToExecute();
        }

        $sql = array();
        $time = 0;
        foreach ($migrations as $version) {
            $versionSql = $version->execute($direction, $dryRun);
            $sql[$version->getVersion()] = $versionSql;
            $time += $version->getTime();
        }

        $this->outputWriter->write("\n  <comment>------------------------</comment>\n");
        $this->outputWriter->write(sprintf("  <info>++</info> finished in %s", $time));
        $this->outputWriter->write(sprintf("  <info>++</info> %s migrations executed", count($migrations)));
        $this->outputWriter->write(sprintf("  <info>++</info> %s sql queries", count($sql, true) - count($sql)));

        return $sql;
    }
 protected function write($message)
 {
     $this->outputWriter->write($message);
 }
Ejemplo n.º 10
0
 /**
  * Execute this migration version up or down and and return the SQL.
  *
  * @param string  $direction The direction to execute the migration.
  * @param boolean $dryRun    Whether to not actually execute the migration SQL and just do a dry run.
  *
  * @return array $sql
  *
  * @throws \Exception when migration fails
  */
 public function execute($direction, $dryRun = false, $timeAllQueries = false)
 {
     $this->sql = array();
     $transaction = $this->migration->isTransactional();
     if ($transaction) {
         //only start transaction if in transactional mode
         $this->connection->beginTransaction();
     }
     try {
         $migrationStart = microtime(true);
         $this->state = self::STATE_PRE;
         $fromSchema = $this->sm->createSchema();
         $this->migration->{'pre' . ucfirst($direction)}($fromSchema);
         if ($direction === 'up') {
             $this->outputWriter->write("\n" . sprintf('  <info>++</info> migrating <comment>%s</comment>', $this->version) . "\n");
         } else {
             $this->outputWriter->write("\n" . sprintf('  <info>--</info> reverting <comment>%s</comment>', $this->version) . "\n");
         }
         $this->state = self::STATE_EXEC;
         $toSchema = clone $fromSchema;
         $this->migration->{$direction}($toSchema);
         $this->addSql($fromSchema->getMigrateToSql($toSchema, $this->platform));
         if (!$dryRun) {
             if ($this->sql) {
                 foreach ($this->sql as $key => $query) {
                     $queryStart = microtime(true);
                     if (!isset($this->params[$key])) {
                         $this->outputWriter->write('     <comment>-></comment> ' . $query);
                         $this->connection->executeQuery($query);
                     } else {
                         $this->outputWriter->write(sprintf('    <comment>-</comment> %s (with parameters)', $query));
                         $this->connection->executeQuery($query, $this->params[$key], $this->types[$key]);
                     }
                     $queryEnd = microtime(true);
                     $queryTime = round($queryEnd - $queryStart, 4);
                     if ($timeAllQueries !== false) {
                         $this->outputWriter->write(sprintf("  <info>%ss</info>", $queryTime));
                     }
                 }
             } else {
                 $this->outputWriter->write(sprintf('<error>Migration %s was executed but did not result in any SQL statements.</error>', $this->version));
             }
             if ($direction === 'up') {
                 $this->markMigrated();
             } else {
                 $this->markNotMigrated();
             }
         } else {
             foreach ($this->sql as $query) {
                 $this->outputWriter->write('     <comment>-></comment> ' . $query);
             }
         }
         $this->state = self::STATE_POST;
         $this->migration->{'post' . ucfirst($direction)}($toSchema);
         $migrationEnd = microtime(true);
         $this->time = round($migrationEnd - $migrationStart, 2);
         if ($direction === 'up') {
             $this->outputWriter->write(sprintf("\n  <info>++</info> migrated (%ss)", $this->time));
         } else {
             $this->outputWriter->write(sprintf("\n  <info>--</info> reverted (%ss)", $this->time));
         }
         if ($transaction) {
             //commit only if running in transactional mode
             $this->connection->commit();
         }
         $this->state = self::STATE_NONE;
         return $this->sql;
     } catch (SkipMigrationException $e) {
         if ($transaction) {
             //only rollback transaction if in transactional mode
             $this->connection->rollback();
         }
         if ($dryRun == false) {
             // now mark it as migrated
             if ($direction === 'up') {
                 $this->markMigrated();
             } else {
                 $this->markNotMigrated();
             }
         }
         $this->outputWriter->write(sprintf("\n  <info>SS</info> skipped (Reason: %s)", $e->getMessage()));
         $this->state = self::STATE_NONE;
         return array();
     } catch (\Exception $e) {
         $this->outputWriter->write(sprintf('<error>Migration %s failed during %s. Error %s</error>', $this->version, $this->getExecutionState(), $e->getMessage()));
         if ($transaction) {
             //only rollback transaction if in transactional mode
             $this->connection->rollback();
         }
         $this->state = self::STATE_NONE;
         throw $e;
     }
 }
Ejemplo n.º 11
0
 /**
  * Execute this migration version up or down and and return the SQL.
  *
  * @param string $direction   The direction to execute the migration.
  * @param string $dryRun      Whether to not actually execute the migration SQL and just do a dry run.
  * @return array $sql
  * @throws Exception when migration fails
  */
 public function execute($direction, $dryRun = false)
 {
     $this->_sql = array();
     $this->_connection->beginTransaction();
     try {
         $start = microtime(true);
         $this->_state = self::STATE_PRE;
         $fromSchema = $this->_sm->createSchema();
         $this->_migration->{'pre' . ucfirst($direction)}($fromSchema);
         if ($direction === 'up') {
             $this->_outputWriter->write("\n" . sprintf('  <info>++</info> migrating <comment>%s</comment>', $this->_version) . "\n");
         } else {
             $this->_outputWriter->write("\n" . sprintf('  <info>--</info> reverting <comment>%s</comment>', $this->_version) . "\n");
         }
         $this->_state = self::STATE_EXEC;
         $toSchema = clone $fromSchema;
         $this->_migration->{$direction}($toSchema);
         $this->addSql($fromSchema->getMigrateToSql($toSchema, $this->_platform));
         if ($dryRun === false) {
             if ($this->_sql) {
                 $count = count($this->_sql);
                 foreach ($this->_sql as $query) {
                     $this->_outputWriter->write('     <comment>-></comment> ' . $query);
                     $this->_connection->executeQuery($query);
                 }
             } else {
                 $this->_outputWriter->write(sprintf('<error>Migration %s was executed but did not result in any SQL statements.</error>', $this->_version));
             }
             if ($direction === 'up') {
                 $this->markMigrated();
             } else {
                 $this->markNotMigrated();
             }
         } else {
             foreach ($this->_sql as $query) {
                 $this->_outputWriter->write('     <comment>-></comment> ' . $query);
             }
         }
         $this->_state = self::STATE_POST;
         $this->_migration->{'post' . ucfirst($direction)}($toSchema);
         $end = microtime(true);
         $this->_time = round($end - $start, 2);
         if ($direction === 'up') {
             $this->_outputWriter->write(sprintf("\n  <info>++</info> migrated (%ss)", $this->_time));
         } else {
             $this->_outputWriter->write(sprintf("\n  <info>--</info> reverted (%ss)", $this->_time));
         }
         $this->_connection->commit();
         return $this->_sql;
     } catch (SkipMigrationException $e) {
         $this->_connection->rollback();
         // now mark it as migrated
         if ($direction === 'up') {
             $this->markMigrated();
         } else {
             $this->markNotMigrated();
         }
         $this->_outputWriter->write(sprintf("\n  <info>SS</info> skipped (Reason: %s)", $e->getMessage()));
     } catch (\Exception $e) {
         $this->_outputWriter->write(sprintf('<error>Migration %s failed during %s. Error %s</error>', $this->_version, $this->getExecutionState(), $e->getMessage()));
         $this->_connection->rollback();
         $this->_state = self::STATE_NONE;
         throw $e;
     }
     $this->_state = self::STATE_NONE;
 }
Ejemplo n.º 12
0
 /**
  * Outputs a SQL query via the `OutputWriter`.
  *
  * @param int $idx The SQL query index. Used to look up params.
  * @param string $query the query to output
  * @return void
  */
 private function outputSqlQuery($idx, $query)
 {
     $params = $this->formatParamsForOutput(isset($this->params[$idx]) ? $this->params[$idx] : [], isset($this->types[$idx]) ? $this->types[$idx] : []);
     $this->outputWriter->write(rtrim(sprintf('     <comment>-></comment> %s %s', $query, $params)));
 }
 /**
  * Do not accept any parameter
  */
 public function __construct()
 {
     parent::__construct(null);
 }
Ejemplo n.º 14
0
 private function noMigrations()
 {
     $this->outputWriter->write('<comment>No migrations to execute.</comment>');
     return [];
 }