Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ludofleury/881081 to your computer and use it in GitHub Desktop.
Save ludofleury/881081 to your computer and use it in GitHub Desktop.
Custom migrations using schema.yml revision.
<?php
class sdzDoctrineGenerateMigrationsDiffTask extends sfDoctrineBaseTask
{
/**
* @see sfTask
*/
protected function configure()
{
$this->addOptions(array(
new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
));
$this->namespace = 'sdz';
$this->name = 'generate-migrations-diff';
$this->briefDescription = 'Generate migration classes by producing a diff between your old and new schema.';
$this->detailedDescription = <<<EOF
The [doctrine:generate-migrations-diff|INFO] task generates migration classes by
producing a diff between your old and new schema.
[./symfony doctrine:generate-migrations-diff|INFO]
EOF;
}
/**
* @see sfTask
*/
protected function execute($arguments = array(), $options = array())
{
$databaseManager = new sfDatabaseManager($this->configuration);
$config = $this->getCliConfig();
$this->logSection('doctrine', 'generating migration diff');
if (!is_dir($config['migrations_path']))
{
$this->getFilesystem()->mkdirs($config['migrations_path']);
}
spl_autoload_register(array('Doctrine_Core', 'modelsAutoload'));
$schemaFileHistory = sfFinder::type('file')->name('*.yml')->sort_by_name()->follow_link()->in($config['migrations_path'].'/schema');
if(empty($schemaFileHistory))
{
$this->logSection('sdz','Empty migration schema repository');
$initFile = $this->prepareSchemaFile($config['yaml_schema_path']);
$this->commitSchemaFile($initFile, 0);
$this->logSection('sdz','Initialized migration schema repository');
}
else
{
$lastestVersion = end($schemaFileHistory);
$actualVersion = $this->prepareSchemaFile($config['yaml_schema_path']);
try
{
$from = $lastestVersion;
$to = $actualVersion;
$migration = new Doctrine_Migration($config['migrations_path']);
$diff = new Doctrine_Migration_Diff($from, $to, $migration);
$changes = $diff->generateMigrationClasses();
$numChanges = count($changes, true) - count($changes);
if ( ! $numChanges)
{
throw new Doctrine_Task_Exception('Could not generate migration classes from difference (seems to be up-to-date)');
}
else
{
$this->logSection('sdz', 'Generated migration classes successfully from difference '.'('.$numChanges.')');
}
$versions = sfFinder::type('file')->name('*.php')->sort_by_name()->follow_link()->in($config['migrations_path']);
$this->commitSchemaFile($actualVersion,count($versions));
$this->logSection('sdz', 'Processed migration generation successfully');
}
catch(Exception $e)
{
throw $e;
}
}
}
/**
*
* @param string $file
* @param int $id
*/
protected function commitSchemaFile($file, $id)
{
$config = $this->getCliConfig();
$this->logSection('file+', $file);
$commitPath = $config['migrations_path'].'/schema/';
$commitFileName = ($id > 0 ? 'version'.$id.'.yml' : 'version0.yml');
if(file_exists($commitPath.$commitFileName))
{
throw new Exception ('Unbable to commit : invalid id');
}
$this->getFilesystem()->copy($file,$commitPath.$commitFileName);
if(!file_exists($commitPath.$commitFileName))
{
throw new Exception ('Unable to commit schema');
}
$this->logSection('sdz', 'Schema '.$commitFileName.' versionned');
}
}
?>
<?php
class sdzDoctrineMigrateTask extends sfDoctrineBaseTask
{
/**
* @see sfTask
*/
protected function configure()
{
$this->addArguments(array(
new sfCommandArgument('version', sfCommandArgument::OPTIONAL, 'The version to migrate to'),
));
$this->addOptions(array(
new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
new sfCommandOption('up', null, sfCommandOption::PARAMETER_NONE, 'Migrate up one version'),
new sfCommandOption('down', null, sfCommandOption::PARAMETER_NONE, 'Migrate down one version'),
new sfCommandOption('dry-run', null, sfCommandOption::PARAMETER_NONE, 'Do not persist migrations'),
));
$this->namespace = 'sdz';
$this->name = 'migrate';
$this->briefDescription = 'Migrates database to current/specified version';
$this->detailedDescription = <<<EOF
The [doctrine:migrate|INFO] task migrates the database:
[./symfony doctrine:migrate|INFO]
Provide a version argument to migrate to a specific version:
[./symfony doctrine:migrate 10|INFO]
To migration up or down one migration, use the [--up|COMMENT] or [--down|COMMENT] options:
[./symfony doctrine:migrate --down|INFO]
If your database supports rolling back DDL statements, you can run migrations
in dry-run mode using the [--dry-run|COMMENT] option:
[./symfony doctrine:migrate --dry-run|INFO]
EOF;
}
/**
* @see sfTask
*/
protected function execute($arguments = array(), $options = array())
{
$config = $this->getCliConfig();
$reposiroty = sfFinder::type('file')->name('*.yml')->sort_by_name()->follow_link()->in($config['migrations_path'].'/schema');
if(empty($reposiroty))
{
$this->logSection('sdz','Empty migration repository : initializing migrations');
$task = new sdzDoctrineGenerateMigrationsDiffTask($this->dispatcher, $this->formatter);
$task->setCommandApplication($this->commandApplication);
$task->setConfiguration($this->configuration);
$ret = $task->run();
}
else
{
$databaseManager = new sfDatabaseManager($this->configuration);
$migration = new Doctrine_Migration($config['migrations_path']);
$from = $version = $migration->getCurrentVersion();
foreach($reposiroty as $stableVersion)
{
$stableVersions[] = str_replace(array($config['migrations_path'].'/schema/version','.yml'),'',$stableVersion);
}
$currentVersionIndex = array_search($from,$stableVersions);
# is_numeric still not safe for handy/debug reasons
if (is_numeric($arguments['version']))
{
$version = $arguments['version'];
}
else if ($options['up'])
{
if($currentVersionIndex < count($stableVersions))
{
$version = $stableVersions[$currentVersionIndex+1];
}
}
else if ($options['down'])
{
if(0 < $currentVersionIndex)
{
$version = $stableVersions[$currentVersionIndex-1];
}
}
else
{
$version = $migration->getLatestVersion();
}
if ($from == $version)
{
$this->logSection('doctrine', sprintf('Already at migration version %s', $version));
return;
}
$this->logSection('doctrine', sprintf('Migrating from version %s to %s%s', $from, $version, $options['dry-run'] ? ' (dry run)' : ''));
try
{
$migration->migrate($version, $options['dry-run']);
}
catch (Exception $e)
{
}
// render errors
if ($migration->hasErrors())
{
if ($this->commandApplication && $this->commandApplication->withTrace())
{
$this->logSection('doctrine', 'The following errors occurred:');
foreach ($migration->getErrors() as $error)
{
$this->commandApplication->renderException($error);
}
}
else
{
$this->logBlock(array_merge(
array('The following errors occurred:', ''),
array_map(create_function('$e', 'return \' - \'.$e->getMessage();'), $migration->getErrors())
), 'ERROR_LARGE');
}
return 1;
}
$this->logSection('doctrine', 'Migration complete');
}
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment