/** * Migrate a scope in either up or down direction. * steps -> the number of migration steps to perform (optional) * version -> up until what version you want to migrate (ignored if steps are provided) * forceAll -> force to run all migrations (optional) (skips version check) * * @param array $options * @throws InvalidArgumentException * @throws Exception * @return void */ public function migrate($options = array()) { if (!isset($options['direction'])) { throw new InvalidArgumentException(__d('migration', 'Missing "direction" option. Provide it with either "up" or "down".')); } if (isset($options['direction']) && !in_array($options['direction'], array('up', 'down'))) { throw new InvalidArgumentException(__d('migration', 'Invalid migration direction "%s". Use either "up" or "down".', $options['direction'])); } if (isset($options['scope']) && $options['scope'] !== 'app') { $this->_checkScope($options['scope']); } /** * @var string $direction * @var string $scope * @var integer $steps * @var string $version * @var boolean $forceAll */ extract(array_merge($this->_defaults, $options)); $availableMigrations = $this->_getAvailableMigrations($scope, $direction); $offset = 0; if ($forceAll === true) { $steps = false; } else { $currentVersion = $this->SchemaMigration->getCurrentVersion($scope); if ($currentVersion !== false) { $offset = array_search($currentVersion, array_keys($availableMigrations), true) + 1; } } if ($direction === 'down') { $offset--; } if ($version !== false && $version !== 'latest') { if (!array_key_exists($version, $availableMigrations)) { throw new InvalidArgumentException(__d('migration', 'Invalid migration version "%s".', $version)); } $steps = array_search($version, array_keys($availableMigrations)); if ($direction === 'up') { $steps++; } } if ($steps >= 1) { $migrationsToRun = array_slice($availableMigrations, $offset, $steps, true); } else { $migrationsToRun = array_slice($availableMigrations, $offset, null, true); } /** @var DboSource $db */ $db = ConnectionManager::getDataSource($this->connection); $db->begin(); try { foreach ($migrationsToRun as $v => $m) { echo 'Migrating to: ' . $v . "\n\n"; $migration = $this->_getMigrationInstance($m); $migration->{$direction}(); $this->SchemaMigration->{$direction}($scope, $v, $m['className']); } } catch (Exception $e) { $db->rollback(); throw $e; } $db->commit(); }