Skip to content

Instantly share code, notes, and snippets.

@crisu83
Created August 20, 2013 21:41
Show Gist options
  • Save crisu83/6287710 to your computer and use it in GitHub Desktop.
Save crisu83/6287710 to your computer and use it in GitHub Desktop.
Migration command for Yii that allows for adding (and removing) of external migrations.
<?php
Yii::import('system.cli.commands.MigrateCommand');
class MigratePathCommand extends MigrateCommand
{
/**
* @var string
*/
public $migrationTable = 'migration';
/**
* @var string
*/
public $migrationFile = 'migrations';
/**
* Adds a migration path from the registry.
* @param $args
* @throws CException
*/
public function actionAddPath($args)
{
echo "Adding migration path ... ";
if (!isset($args[0])) {
$this->usageError("Please provide a migration path to add.");
}
$path = $args[0];
$migrations = $this->readMigrationsFile();
$relativePath = $this->migrationPath . DIRECTORY_SEPARATOR . $path;
if (is_dir($relativePath)) {
$migrations = $this->normalizeMigrations($migrations);
if (!in_array($path, $migrations)) {
$migrations[] = $path;
$this->writeMigrationFile($migrations);
echo "done\n";
} else {
echo "skipped (already registered)\n";
}
} else {
echo "skipped (path not found)\n";
}
}
/**
* Removes a migration path from the registry.
* @param $args
*/
public function actionRemovePath($args)
{
echo "Removing migration path ... ";
if (!isset($args[0])) {
$this->usageError("Please provide a migration path to remove.");
}
$path = $args[0];
$migrations = $this->readMigrationsFile();
$migrations = $this->normalizeMigrations($migrations);
if (($index = array_search($path, $migrations)) !== false) {
unset($migrations[$index]);
$this->writeMigrationFile($migrations);
echo "done\n";
} else {
echo "skipped (not found)\n";
}
}
/**
* @return string
*/
public function getHelp()
{
return parent::getHelp() . <<<EOD
* yiic migrate addPath ../../path/to/migrations
Adds a migration path (relative to the application migrations path).
* yiic migrate removePath ../../path/to/migrations
Remove a migration path (relative to the application migrations path).
EOD;
}
/**
* @param $class
*/
protected function instantiateMigration($class)
{
foreach ($this->getMigrationPaths() as $path) {
$file = $path . DIRECTORY_SEPARATOR . $class . '.php';
if (file_exists($file) && is_file($file)) {
require_once($file);
/* @var CDbMigration $migration */
$migration = new $class;
$migration->setDbConnection($this->getDbConnection());
return $migration;
}
}
return null;
}
/**
* @return array
*/
protected function getNewMigrations()
{
$applied = array();
foreach ($this->getMigrationHistory(-1) as $version => $time) {
$applied[substr($version, 1, 13)] = true;
}
$migrations = array();
foreach ($this->getMigrationPaths() as $migrationPath) {
$handle = opendir($migrationPath);
while (($file = readdir($handle)) !== false) {
if ($file === '.' || $file === '..') {
continue;
}
$path = $migrationPath . DIRECTORY_SEPARATOR . $file;
if (preg_match('/^(m(\d{6}_\d{6})_.*?)\.php$/', $file, $matches) && is_file(
$path
) && !isset($applied[$matches[2]])
) {
$migrations[] = $matches[1];
}
}
closedir($handle);
}
sort($migrations);
return $migrations;
}
/**
* @return array
*/
protected function getMigrationPaths()
{
return array_merge(array($this->migrationPath), $this->readMigrationsFile());
}
/**
* @return mixed
*/
protected function readMigrationsFile()
{
$migrationFile = $this->resolveMigrationFilePath();
if (!file_exists($migrationFile)) {
$this->writeMigrationFile();
}
return require($migrationFile);
}
/**
* @param array $migrations
*/
protected function writeMigrationFile($migrations = array())
{
ob_start();
echo "<?php\n\n";
echo "// {$this->migrationFile}.php generated by MigrationCommand\n\n";
echo "\$migrationDir = __DIR__;\n\n";
echo "return array(\n";
foreach ($migrations as $value) {
echo "\t\$migrationDir . '/" . $value . "',\n";
}
echo ');\n';
$migrationFile = $this->resolveMigrationFilePath();
file_put_contents($migrationFile, ob_get_clean());
}
/**
* @param $migrations
* @return mixed
*/
protected function normalizeMigrations($migrations)
{
foreach ($migrations as &$path) {
$path = ltrim(str_replace($this->migrationPath, '', $path), '/');
}
return $migrations;
}
/**
* @return string
*/
protected function resolveMigrationFilePath()
{
return $this->migrationPath . '/' . $this->migrationFile . '.php';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment