diff --git a/vendor/doctrine/migrations b/vendor/doctrine/migrations deleted file mode 160000 index 6c527d8ccb..0000000000 --- a/vendor/doctrine/migrations +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6c527d8ccbccec5257bb2c92bca973653b1e3976 diff --git a/vendor/doctrine/migrations/.coveralls.yml b/vendor/doctrine/migrations/.coveralls.yml new file mode 100644 index 0000000000..6b74c21851 --- /dev/null +++ b/vendor/doctrine/migrations/.coveralls.yml @@ -0,0 +1 @@ +src_dir: lib diff --git a/vendor/doctrine/migrations/README.markdown b/vendor/doctrine/migrations/README.markdown new file mode 100644 index 0000000000..1578f426f4 --- /dev/null +++ b/vendor/doctrine/migrations/README.markdown @@ -0,0 +1,108 @@ +# Doctrine Database Migrations + +## Status + +[![Build Status](https://travis-ci.org/doctrine/migrations.svg)](https://travis-ci.org/doctrine/migrations) +[![Dependency Status](https://www.versioneye.com/php/doctrine:migrations/badge.svg)](https://www.versioneye.com/php/doctrine:migrations/) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/doctrine/migrations/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/doctrine/migrations/?branch=master) +[![Code Coverage](https://scrutinizer-ci.com/g/doctrine/migrations/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/doctrine/migrations/?branch=master) + + +## Official Documentation + +All available documentation can be found [here](http://docs.doctrine-project.org/projects/doctrine-migrations/en/latest/). + +The repository containing the documentation is [there](https://github.com/doctrine/migrations-documentation). + +## Working with Doctrine Migrations + +### Using the integration of your framework + + * symfony 2 [doctrine/doctrine-migrations-bundle](https://packagist.org/packages/doctrine/doctrine-migrations-bundle) + * ZF2 [doctrine/doctrine-orm-module](https://packagist.org/packages/doctrine/doctrine-orm-module) + * laravel [mitchellvanw/laravel-doctrine](https://packagist.org/packages/mitchellvanw/laravel-doctrine) + * Silex [kurl/silex-doctrine-migrations-provider](https://packagist.org/packages/kurl/silex-doctrine-migrations-provider) + * nette [zenify/doctrine-migrations](https://packagist.org/packages/zenify/doctrine-migrations) + * others... + +### Using composer + +```composer require doctrine/migrations``` + +### Downloading the latest phar release + +You can download the [doctrine migrations phar](https://github.com/doctrine/migrations/releases) directly on the release page + +### Building Your own Phar + +Make sure Composer and all necessary dependencies are installed: + +```bash +curl -s https://getcomposer.org/installer | php +php composer.phar install --dev +``` + +Make sure that the Box project is installed: + +```bash +curl -s http://box-project.org/installer.php | php +``` + +Build the PHAR archive: + +```bash +php box.phar build +``` + +The `doctrine-migrations.phar` archive is built in the `build` directory. + +#### Creating archive disabled by INI setting + +If you receive an error that looks like: + + creating archive "build/doctrine-migrations.phar" disabled by INI setting + +This can be fixed by setting the following in your php.ini: + +```ini +; http://php.net/phar.readonly +phar.readonly = Off +``` + +## Installing Dependencies + +To install dependencies run a composer update: + +```composer update``` + +## symfony 2.3 users + +Doctrine migration need the doctrine/orm 2.4, you need to [update your composer.json](https://github.com/symfony/symfony-standard/blob/v2.3.28/composer.json#L12) to the last version of it for symfony 2.3. + +That version is compatible with the doctrine/orm 2.4 and there are [very little upgrade needed](https://github.com/doctrine/doctrine2/blob/master/UPGRADE.md#upgrade-to-24). + +## Running the unit tests + +To run the tests, you need the sqlite extension for php. +On Unix-like systems, install: +- php5-sqlite + +On Windows, enable the extension by uncommenting the following lines in php.ini +``` +extension = php_pdo_sqlite.dll +extension = php_sqlite3.dll +extension_dir = ext +``` + +Running the tests from the project root: +``` +./vendor/bin/phpunit +``` + +On Windows run phpunit from the full path +``` +php vendor/phpunit/phpunit/phpunit +``` +This appears to be some bug. + +Happy testing :-) diff --git a/vendor/doctrine/migrations/UPGRADE-1.0.MD b/vendor/doctrine/migrations/UPGRADE-1.0.MD new file mode 100644 index 0000000000..0e91665502 --- /dev/null +++ b/vendor/doctrine/migrations/UPGRADE-1.0.MD @@ -0,0 +1,39 @@ +UPGRADE FROM 1.0-alpha1 to 1.0.0-alpha3 +======================================= + +## AbstractMigration + +### Before: + +The method getName() was defined and it's implementation would change the order in which the migration would be processed. +It would cause discrepencies between the file order in a file browser and the order of execution of the migrations. + +### After: + +The getName method as been removed | set final and new getDescription method has been added. +The goal of this method is to be able to provide context for the migration. +This context is shown for the last migrated migration when the status command is called. + +## --write-sql option from the migrate command + +### Before: + +The --write-sql option would only output sql contained in the migration and would not update the table containing the migrated migrations. + +### After: + +That option now also output the sql queries necessary to update the table containing the state of the migrations. +If you want to go back to the previous behavior just make a request on the bug tracker as for now the need for it is not very clear. + +## MigrationsVersion::VERSION + +### Before: + +MigrationsVersion::VERSION used to be a property. +The returned value was fanciful. + +### After: + +It is now a a function so that a different value can be automatically send back if it's a modified version that's used. +The returned value is now the git tag. +The tag is in lowercase as the other doctrine projects. diff --git a/vendor/doctrine/migrations/bin/doctrine-migrations b/vendor/doctrine/migrations/bin/doctrine-migrations new file mode 100755 index 0000000000..5de7bd09d6 --- /dev/null +++ b/vendor/doctrine/migrations/bin/doctrine-migrations @@ -0,0 +1,3 @@ +#!/usr/bin/env php +. + */ + +$autoloadFiles = array( + __DIR__ . '/../vendor/autoload.php', + __DIR__ . '/../../../autoload.php' +); + +$autoloader = false; +foreach ($autoloadFiles as $autoloadFile) { + if (file_exists($autoloadFile)) { + require_once $autoloadFile; + $autoloader = true; + } +} + +if (!$autoloader) { + if (extension_loaded('phar') && ($uri = Phar::running())) { + echo 'The phar has been builded without the depedencies' . PHP_EOL; + } + die('vendor/autoload.php could not be found. Did you run `php composer.phar install`?'); +} + +// Support for using the Doctrine ORM convention of providing a `cli-config.php` file. +$configFile = getcwd() . DIRECTORY_SEPARATOR . 'cli-config.php'; + +$helperSet = null; +if (file_exists($configFile)) { + if ( ! is_readable($configFile)) { + trigger_error( + 'Configuration file [' . $configFile . '] does not have read permission.', E_ERROR + ); + } + + require $configFile; + + foreach ($GLOBALS as $helperSetCandidate) { + if ($helperSetCandidate instanceof \Symfony\Component\Console\Helper\HelperSet) { + $helperSet = $helperSetCandidate; + break; + } + } +} + +$helperSet = ($helperSet) ?: new \Symfony\Component\Console\Helper\HelperSet(); + +if(class_exists('\Symfony\Component\Console\Helper\QuestionHelper')) { + $helperSet->set(new \Symfony\Component\Console\Helper\QuestionHelper(), 'question'); +} else { + $helperSet->set(new \Symfony\Component\Console\Helper\DialogHelper(), 'dialog'); +} + + +$cli = new \Symfony\Component\Console\Application('Doctrine Migrations', \Doctrine\DBAL\Migrations\MigrationsVersion::VERSION()); +$cli->setCatchExceptions(true); +$cli->setHelperSet($helperSet); +$cli->addCommands(array( + // Migrations Commands + new \Doctrine\DBAL\Migrations\Tools\Console\Command\ExecuteCommand(), + new \Doctrine\DBAL\Migrations\Tools\Console\Command\GenerateCommand(), + new \Doctrine\DBAL\Migrations\Tools\Console\Command\LatestCommand(), + new \Doctrine\DBAL\Migrations\Tools\Console\Command\MigrateCommand(), + new \Doctrine\DBAL\Migrations\Tools\Console\Command\StatusCommand(), + new \Doctrine\DBAL\Migrations\Tools\Console\Command\VersionCommand() +)); +if ($helperSet->has('em')) { + $cli->add(new \Doctrine\DBAL\Migrations\Tools\Console\Command\DiffCommand()); +} + +$input = file_exists('migrations-input.php') + ? include 'migrations-input.php' : null; + +$output = file_exists('migrations-output.php') + ? include 'migrations-output.php' : null; + +$cli->run($input, $output); + diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/AbortMigrationException.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/AbortMigrationException.php new file mode 100644 index 0000000000..b2a0bd3f43 --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/AbortMigrationException.php @@ -0,0 +1,7 @@ +. +*/ + +namespace Doctrine\DBAL\Migrations; + +use Doctrine\DBAL\Schema\Schema; + +/** + * Abstract class for individual migrations to extend from. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan H. Wage + */ +abstract class AbstractMigration +{ + /** + * Reference to the Version instance representing this migration + * + * @var Version + */ + protected $version; + + /** + * The Doctrine\DBAL\Connection instance we are migrating + * + * @var \Doctrine\DBAL\Connection + */ + protected $connection; + + /** + * Reference to the SchemaManager instance referenced by $_connection + * + * @var \Doctrine\DBAL\Schema\AbstractSchemaManager + */ + protected $sm; + + /** + * Reference to the DatabasePlatform instance referenced by $_connection + * + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + protected $platform; + + /** + * The OutputWriter object instance used for outputting information + * + * @var OutputWriter + */ + private $outputWriter; + + public function __construct(Version $version) + { + $config = $version->getConfiguration(); + + $this->version = $version; + $this->connection = $config->getConnection(); + $this->sm = $this->connection->getSchemaManager(); + $this->platform = $this->connection->getDatabasePlatform(); + $this->outputWriter = $config->getOutputWriter(); + } + + /** + * Indicates the transactional mode of this migration. + * If this function returns true (default) the migration will be executed in one transaction, + * otherwise non-transactional state will be used to execute each of the migration SQLs. + * + * Extending class should override this function to alter the return value + * + * @return bool TRUE by default. + */ + public function isTransactional() + { + return true; + } + + /** + * Get migration description + * + * @return string + */ + public function getDescription() + { + return ''; + } + + /** + * Print a warning message if the condition evaluates to TRUE. + * + * @param boolean $condition + * @param string $message + */ + public function warnIf($condition, $message = '') + { + if ($condition) { + $message = $message?: 'Unknown Reason'; + $this->outputWriter->write(sprintf( + ' Warning during %s: %s', + $this->version->getExecutionState(), + $message + )); + } + } + + /** + * Abort the migration if the condition evaluates to TRUE. + * + * @param boolean $condition + * @param string $message + * + * @throws AbortMigrationException + */ + public function abortIf($condition, $message = '') + { + if ($condition) { + throw new AbortMigrationException($message ?: 'Unknown Reason'); + } + } + + /** + * Skip this migration (but not the next ones) if condition evaluates to TRUE. + * + * @param boolean $condition + * @param string $message + * + * @throws SkipMigrationException + */ + public function skipIf($condition, $message = '') + { + if ($condition) { + throw new SkipMigrationException($message ?: 'Unknown Reason'); + } + } + + public function preUp(Schema $schema) + { + } + + public function postUp(Schema $schema) + { + } + + public function preDown(Schema $schema) + { + } + + public function postDown(Schema $schema) + { + } + + abstract public function up(Schema $schema); + abstract public function down(Schema $schema); + + protected function addSql($sql, array $params = array(), array $types = array()) + { + $this->version->addSql($sql, $params, $types); + } + + protected function write($message) + { + $this->outputWriter->write($message); + } + + protected function throwIrreversibleMigrationException($message = null) + { + if (null === $message) { + $message = 'This migration is irreversible and cannot be reverted.'; + } + + throw new IrreversibleMigrationException($message); + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Configuration/AbstractFileConfiguration.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Configuration/AbstractFileConfiguration.php new file mode 100644 index 0000000000..f149ed048f --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Configuration/AbstractFileConfiguration.php @@ -0,0 +1,94 @@ +. +*/ + +namespace Doctrine\DBAL\Migrations\Configuration; + +use Doctrine\DBAL\Migrations\MigrationException; + +/** + * Abstract Migration Configuration class for loading configuration information + * from a configuration file (xml or yml). + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan H. Wage + */ +abstract class AbstractFileConfiguration extends Configuration +{ + /** + * The configuration file used to load configuration information + * + * @var string + */ + private $file; + + /** + * Whether or not the configuration file has been loaded yet or not + * + * @var boolean + */ + private $loaded = false; + + /** + * Load the information from the passed configuration file + * + * @param string $file The path to the configuration file + * + * @throws MigrationException Throws exception if configuration file was already loaded + */ + public function load($file) + { + if ($this->loaded) { + throw MigrationException::configurationFileAlreadyLoaded(); + } + if (file_exists($path = getcwd() . '/' . $file)) { + $file = $path; + } + $this->file = $file; + $this->doLoad($file); + $this->loaded = true; + } + + protected function getDirectoryRelativeToFile($file, $input) + { + $path = realpath(dirname($file) . '/' . $input); + if ($path !== false) { + $directory = $path; + } else { + $directory = $input; + } + + return $directory; + } + + public function getFile() + { + return $this->file; + } + + /** + * Abstract method that each file configuration driver must implement to + * load the given configuration file whether it be xml, yaml, etc. or something + * else. + * + * @param string $file The path to a configuration file. + */ + abstract protected function doLoad($file); +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Configuration/Configuration.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Configuration/Configuration.php new file mode 100644 index 0000000000..6b95d64d7f --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Configuration/Configuration.php @@ -0,0 +1,695 @@ +. +*/ + +namespace Doctrine\DBAL\Migrations\Configuration; + +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Migrations\MigrationException; +use Doctrine\DBAL\Migrations\OutputWriter; +use Doctrine\DBAL\Migrations\Version; +use Doctrine\DBAL\Migrations\Finder\MigrationFinderInterface; +use Doctrine\DBAL\Migrations\Finder\RecursiveRegexFinder; +use Doctrine\DBAL\Schema\Column; +use Doctrine\DBAL\Schema\Table; +use Doctrine\DBAL\Types\Type; + +/** + * Default Migration Configuration object used for configuring an instance of + * the Migration class. Set the connection, version table name, register migration + * classes/versions, etc. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan H. Wage + */ +class Configuration +{ + /** + * Name of this set of migrations + * + * @var string + */ + private $name; + + /** + * Flag for whether or not the migration table has been created + * + * @var boolean + */ + private $migrationTableCreated = false; + + /** + * Connection instance to use for migrations + * + * @var Connection + */ + private $connection; + + /** + * OutputWriter instance for writing output during migrations + * + * @var OutputWriter + */ + private $outputWriter; + + /** + * The migration finder implementation -- used to load migrations from a + * directory. + * + * @var MigrationFinderInterface + */ + private $migrationFinder; + + /** + * The migration table name to track versions in + * + * @var string + */ + private $migrationsTableName = 'doctrine_migration_versions'; + + /** + * The path to a directory where new migration classes will be written + * + * @var string + */ + private $migrationsDirectory; + + /** + * Namespace the migration classes live in + * + * @var string + */ + private $migrationsNamespace; + + /** + * Array of the registered migrations + * + * @var Version[] + */ + private $migrations = array(); + + /** + * Construct a migration configuration object. + * + * @param Connection $connection A Connection instance + * @param OutputWriter $outputWriter A OutputWriter instance + * @param MigrationFinderInterface $finder Migration files finder + */ + public function __construct(Connection $connection, OutputWriter $outputWriter = null, MigrationFinderInterface $finder = null) + { + $this->connection = $connection; + if ($outputWriter === null) { + $outputWriter = new OutputWriter(); + } + $this->outputWriter = $outputWriter; + $this->migrationFinder = $finder; + } + + /** + * Validation that this instance has all the required properties configured + * + * @throws MigrationException + */ + public function validate() + { + if (! $this->migrationsNamespace) { + throw MigrationException::migrationsNamespaceRequired(); + } + if (! $this->migrationsDirectory) { + throw MigrationException::migrationsDirectoryRequired(); + } + } + + /** + * Set the name of this set of migrations + * + * @param string $name The name of this set of migrations + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * Returns the name of this set of migrations + * + * @return string $name The name of this set of migrations + */ + public function getName() + { + return $this->name; + } + + /** + * Returns the OutputWriter instance + * + * @return OutputWriter $outputWriter The OutputWriter instance + */ + public function getOutputWriter() + { + return $this->outputWriter; + } + + /** + * Returns a timestamp version as a formatted date + * + * @param string $version + * + * @return string The formatted version + * @deprecated + */ + public function formatVersion($version) + { + return $this->getDateTime($version); + } + + /** + * Returns the datetime of a migration + * + * @param $version + * @return string + */ + public function getDateTime($version) + { + $datetime = str_replace('Version', '', $version); + $datetime = \DateTime::createFromFormat('YmdHis', $datetime); + + if ($datetime === false){ + return ''; + } + + return $datetime->format('Y-m-d H:i:s'); + } + + /** + * Returns the Connection instance + * + * @return Connection $connection The Connection instance + */ + public function getConnection() + { + return $this->connection; + } + + /** + * Set the migration table name + * + * @param string $tableName The migration table name + */ + public function setMigrationsTableName($tableName) + { + $this->migrationsTableName = $tableName; + } + + /** + * Returns the migration table name + * + * @return string $migrationsTableName The migration table name + */ + public function getMigrationsTableName() + { + return $this->migrationsTableName; + } + + /** + * Set the new migrations directory where new migration classes are generated + * + * @param string $migrationsDirectory The new migrations directory + */ + public function setMigrationsDirectory($migrationsDirectory) + { + $this->migrationsDirectory = $migrationsDirectory; + } + + /** + * Returns the new migrations directory where new migration classes are generated + * + * @return string $migrationsDirectory The new migrations directory + */ + public function getMigrationsDirectory() + { + return $this->migrationsDirectory; + } + + /** + * Set the migrations namespace + * + * @param string $migrationsNamespace The migrations namespace + */ + public function setMigrationsNamespace($migrationsNamespace) + { + $this->migrationsNamespace = $migrationsNamespace; + } + + /** + * Returns the migrations namespace + * + * @return string $migrationsNamespace The migrations namespace + */ + public function getMigrationsNamespace() + { + return $this->migrationsNamespace; + } + + /** + * set the implementation of the migration finder. + * + * @param $finder The new migration finder + * @return void + */ + public function setMigrationFinder(MigrationFinderInterface $finder) + { + $this->migrationFinder = $finder; + } + + /** + * Register migrations from a given directory. Recursively finds all files + * with the pattern VersionYYYYMMDDHHMMSS.php as the filename and registers + * them as migrations. + * + * @param string $path The root directory to where some migration classes live. + * + * @return Version[] The array of migrations registered. + */ + public function registerMigrationsFromDirectory($path) + { + return $this->registerMigrations($this->findMigrations($path)); + } + + /** + * Register a single migration version to be executed by a AbstractMigration + * class. + * + * @param string $version The version of the migration in the format YYYYMMDDHHMMSS. + * @param string $class The migration class to execute for the version. + * + * @return Version + * + * @throws MigrationException + */ + public function registerMigration($version, $class) + { + $version = (string) $version; + $class = (string) $class; + if (isset($this->migrations[$version])) { + throw MigrationException::duplicateMigrationVersion($version, get_class($this->migrations[$version])); + } + $version = new Version($this, $version, $class); + $this->migrations[$version->getVersion()] = $version; + ksort($this->migrations); + + return $version; + } + + /** + * Register an array of migrations. Each key of the array is the version and + * the value is the migration class name. + * + * + * @param array $migrations + * + * @return Version[] + */ + public function registerMigrations(array $migrations) + { + $versions = array(); + foreach ($migrations as $version => $class) { + $versions[] = $this->registerMigration($version, $class); + } + + return $versions; + } + + /** + * Get the array of registered migration versions. + * + * @return Version[] $migrations + */ + public function getMigrations() + { + return $this->migrations; + } + + /** + * Returns the Version instance for a given version in the format YYYYMMDDHHMMSS. + * + * @param string $version The version string in the format YYYYMMDDHHMMSS. + * + * @return Version + * + * @throws MigrationException Throws exception if migration version does not exist. + */ + public function getVersion($version) + { + if ( ! isset($this->migrations[$version])) { + throw MigrationException::unknownMigrationVersion($version); + } + + return $this->migrations[$version]; + } + + /** + * Check if a version exists. + * + * @param string $version + * + * @return boolean + */ + public function hasVersion($version) + { + return isset($this->migrations[$version]); + } + + /** + * Check if a version has been migrated or not yet + * + * @param Version $version + * + * @return boolean + */ + public function hasVersionMigrated(Version $version) + { + $this->createMigrationTable(); + + $version = $this->connection->fetchColumn( + "SELECT version FROM " . $this->migrationsTableName . " WHERE version = ?", + array($version->getVersion()) + ); + + return $version !== false; + } + + /** + * Returns all migrated versions from the versions table, in an array. + * + * @return Version[] + */ + public function getMigratedVersions() + { + $this->createMigrationTable(); + + $ret = $this->connection->fetchAll("SELECT version FROM " . $this->migrationsTableName); + $versions = array(); + foreach ($ret as $version) { + $versions[] = current($version); + } + + return $versions; + } + + /** + * Returns an array of available migration version numbers. + * + * @return array + */ + public function getAvailableVersions() + { + $availableVersions = array(); + foreach ($this->migrations as $migration) { + $availableVersions[] = $migration->getVersion(); + } + + return $availableVersions; + } + + /** + * Returns the current migrated version from the versions table. + * + * @return string + */ + public function getCurrentVersion() + { + $this->createMigrationTable(); + + $where = null; + if (!empty($this->migrations)) { + $migratedVersions = array(); + foreach ($this->migrations as $migration) { + $migratedVersions[] = sprintf("'%s'", $migration->getVersion()); + } + $where = " WHERE version IN (" . implode(', ', $migratedVersions) . ")"; + } + + $sql = sprintf("SELECT version FROM %s%s ORDER BY version DESC", + $this->migrationsTableName, $where + ); + + $sql = $this->connection->getDatabasePlatform()->modifyLimitQuery($sql, 1); + $result = $this->connection->fetchColumn($sql); + + return $result !== false ? (string) $result : '0'; + } + + /** + * Returns the version prior to the current version. + * + * @return string|null A version string, or null if the current version is + * the first. + */ + public function getPrevVersion() + { + return $this->getRelativeVersion($this->getCurrentVersion(), -1); + } + + /** + * Returns the version following the current version. + * + * @return string|null A version string, or null if the current version is + * the latest. + */ + public function getNextVersion() + { + return $this->getRelativeVersion($this->getCurrentVersion(), 1); + } + + /** + * Returns the version with the specified offset to the specified version. + * + * @return string|null A version string, or null if the specified version + * is unknown or the specified delta is not within the + * list of available versions. + */ + public function getRelativeVersion($version, $delta) + { + $versions = array_keys($this->migrations); + array_unshift($versions, 0); + $offset = array_search($version, $versions); + if ($offset === false || !isset($versions[$offset + $delta])) { + // Unknown version or delta out of bounds. + return null; + } + + return (string) $versions[$offset + $delta]; + } + + /** + * Returns the version number from an alias. + * + * Supported aliases are: + * - first: The very first version before any migrations have been run. + * - current: The current version. + * - prev: The version prior to the current version. + * - next: The version following the current version. + * - latest: The latest available version. + * + * If an existing version number is specified, it is returned verbatimly. + * + * @return string|null A version number, or null if the specified alias + * does not map to an existing version, e.g. if "next" + * is passed but the current version is already the + * latest. + */ + public function resolveVersionAlias($alias) + { + if ($this->hasVersion($alias)) { + return $alias; + } + switch ($alias) { + case 'first': + return '0'; + case 'current': + return $this->getCurrentVersion(); + case 'prev': + return $this->getPrevVersion(); + case 'next': + return $this->getNextVersion(); + case 'latest': + return $this->getLatestVersion(); + default: + return null; + } + } + + /** + * Returns the total number of executed migration versions + * + * @return integer + */ + public function getNumberOfExecutedMigrations() + { + $this->createMigrationTable(); + + $result = $this->connection->fetchColumn("SELECT COUNT(version) FROM " . $this->migrationsTableName); + + return $result !== false ? $result : 0; + } + + /** + * Returns the total number of available migration versions + * + * @return integer + */ + public function getNumberOfAvailableMigrations() + { + return count($this->migrations); + } + + /** + * Returns the latest available migration version. + * + * @return string The version string in the format YYYYMMDDHHMMSS. + */ + public function getLatestVersion() + { + $versions = array_keys($this->migrations); + $latest = end($versions); + + return $latest !== false ? (string) $latest : '0'; + } + + /** + * Create the migration table to track migrations with. + * + * @return boolean Whether or not the table was created. + */ + public function createMigrationTable() + { + $this->validate(); + + if ($this->migrationTableCreated) { + return false; + } + + if ( ! $this->connection->getSchemaManager()->tablesExist(array($this->migrationsTableName))) { + $columns = array( + 'version' => new Column('version', Type::getType('string'), array('length' => 255)), + ); + $table = new Table($this->migrationsTableName, $columns); + $table->setPrimaryKey(array('version')); + $this->connection->getSchemaManager()->createTable($table); + + $this->migrationTableCreated = true; + + return true; + } + + $this->migrationTableCreated = true; + + return false; + } + + /** + * Returns the array of migrations to executed based on the given direction + * and target version number. + * + * @param string $direction The direction we are migrating. + * @param string $to The version to migrate to. + * + * @return Version[] $migrations The array of migrations we can execute. + */ + public function getMigrationsToExecute($direction, $to) + { + if ($direction === 'down') { + if (count($this->migrations)) { + $allVersions = array_reverse(array_keys($this->migrations)); + $classes = array_reverse(array_values($this->migrations)); + $allVersions = array_combine($allVersions, $classes); + } else { + $allVersions = array(); + } + } else { + $allVersions = $this->migrations; + } + $versions = array(); + $migrated = $this->getMigratedVersions(); + foreach ($allVersions as $version) { + if ($this->shouldExecuteMigration($direction, $version, $to, $migrated)) { + $versions[$version->getVersion()] = $version; + } + } + + return $versions; + } + + /** + * Find all the migrations in a given directory. + * + * @param string $path the directory to search. + * @return array + */ + protected function findMigrations($path) + { + return $this->getMigrationFinder()->findMigrations($path, $this->getMigrationsNamespace()); + } + + /** + * Get the migration finder, creating one if it's not present. + * + * @return MigrationFinderInterface + */ + protected function getMigrationFinder() + { + if (!$this->migrationFinder) { + $this->migrationFinder = new RecursiveRegexFinder(); + } + + return $this->migrationFinder; + } + + /** + * Check if we should execute a migration for a given direction and target + * migration version. + * + * @param string $direction The direction we are migrating. + * @param Version $version The Version instance to check. + * @param string $to The version we are migrating to. + * @param array $migrated Migrated versions array. + * + * @return boolean + */ + private function shouldExecuteMigration($direction, Version $version, $to, $migrated) + { + if ($direction === 'down') { + if ( ! in_array($version->getVersion(), $migrated)) { + return false; + } + + return $version->getVersion() > $to; + } + + if ($direction === 'up') { + if (in_array($version->getVersion(), $migrated)) { + return false; + } + + return $version->getVersion() <= $to; + } + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Configuration/XmlConfiguration.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Configuration/XmlConfiguration.php new file mode 100644 index 0000000000..84624a3ca8 --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Configuration/XmlConfiguration.php @@ -0,0 +1,58 @@ +. +*/ + +namespace Doctrine\DBAL\Migrations\Configuration; + +/** + * Load migration configuration information from a XML configuration file. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan H. Wage + */ +class XmlConfiguration extends AbstractFileConfiguration +{ + /** + * @inheritdoc + */ + protected function doLoad($file) + { + $xml = simplexml_load_file($file); + if (isset($xml->name)) { + $this->setName((string) $xml->name); + } + if (isset($xml->table['name'])) { + $this->setMigrationsTableName((string) $xml->table['name']); + } + if (isset($xml->{'migrations-namespace'})) { + $this->setMigrationsNamespace((string) $xml->{'migrations-namespace'}); + } + if (isset($xml->{'migrations-directory'})) { + $migrationsDirectory = $this->getDirectoryRelativeToFile($file, (string) $xml->{'migrations-directory'}); + $this->setMigrationsDirectory($migrationsDirectory); + $this->registerMigrationsFromDirectory($migrationsDirectory); + } + if (isset($xml->migrations->migration)) { + foreach ($xml->migrations->migration as $migration) { + $this->registerMigration((string) $migration['version'], (string) $migration['class']); + } + } + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Configuration/YamlConfiguration.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Configuration/YamlConfiguration.php new file mode 100644 index 0000000000..7249fd143d --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Configuration/YamlConfiguration.php @@ -0,0 +1,61 @@ +. +*/ + +namespace Doctrine\DBAL\Migrations\Configuration; + +use Symfony\Component\Yaml\Yaml; + +/** + * Load migration configuration information from a YAML configuration file. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan H. Wage + */ +class YamlConfiguration extends AbstractFileConfiguration +{ + /** + * @inheritdoc + */ + protected function doLoad($file) + { + $array = Yaml::parse(file_get_contents($file)); + + if (isset($array['name'])) { + $this->setName($array['name']); + } + if (isset($array['table_name'])) { + $this->setMigrationsTableName($array['table_name']); + } + if (isset($array['migrations_namespace'])) { + $this->setMigrationsNamespace($array['migrations_namespace']); + } + if (isset($array['migrations_directory'])) { + $migrationsDirectory = $this->getDirectoryRelativeToFile($file, $array['migrations_directory']); + $this->setMigrationsDirectory($migrationsDirectory); + $this->registerMigrationsFromDirectory($migrationsDirectory); + } + if (isset($array['migrations']) && is_array($array['migrations'])) { + foreach ($array['migrations'] as $migration) { + $this->registerMigration($migration['version'], $migration['class']); + } + } + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Finder/AbstractFinder.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Finder/AbstractFinder.php new file mode 100644 index 0000000000..4cf80c1726 --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Finder/AbstractFinder.php @@ -0,0 +1,65 @@ +. + */ + +namespace Doctrine\DBAL\Migrations\Finder; + +/** + * Abstract base class for MigrationFinders + * + * @since 1.0.0-alpha3 + */ +abstract class AbstractFinder implements MigrationFinderInterface +{ + protected static function requireOnce($path) + { + require_once $path; + } + + protected function getRealPath($directory) + { + $dir = realpath($directory); + if (false === $dir || !is_dir($dir)) { + throw new \InvalidArgumentException(sprintf( + 'Cannot load migrations from "%s" because it is not a valid directory', + $directory + )); + } + + return $dir; + } + + /** + * Load the migrations and return an array of thoses loaded migrations + * @param $files array of migration filename found + * @param $namespace namespace of thoses migrations + * @return array constructed with the migration name as key and the value is the fully qualified name of the migration + */ + protected function loadMigrations($files, $namespace) + { + $migrations = []; + foreach ($files as $file) { + static::requireOnce($file); + $className = basename($file, '.php'); + $version = substr($className, 7); + $migrations[$version] = sprintf('%s\\%s', $namespace, $className); + } + + return $migrations; + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Finder/GlobFinder.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Finder/GlobFinder.php new file mode 100644 index 0000000000..a4a49f3b9e --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Finder/GlobFinder.php @@ -0,0 +1,45 @@ +. + */ + +namespace Doctrine\DBAL\Migrations\Finder; + +/** + * A MigrationFinderInterface implementation that uses `glob` and some special file and + * class names to load migrations from a directory. + * + * The migrations are expected to reside in files with the filename + * `VersionYYYYMMDDHHMMSS.php`. Each file should contain one class named + * `VersionYYYYMMDDHHMMSS`. + * + * @since 1.0.0-alpha3 + */ +final class GlobFinder extends AbstractFinder +{ + /** + * {@inheritdoc} + */ + public function findMigrations($directory, $namespace=null) + { + $dir = $this->getRealPath($directory); + + $files = glob(rtrim($dir, '/').'/Version*.php'); + + return $this->loadMigrations($files, $namespace); + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Finder/MigrationFinderInterface.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Finder/MigrationFinderInterface.php new file mode 100644 index 0000000000..ed18423773 --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Finder/MigrationFinderInterface.php @@ -0,0 +1,40 @@ +. + */ + +namespace Doctrine\DBAL\Migrations\Finder; + +/** + * MigrationFinderInterface implementations locate migrations (classes that extend + * `Doctrine\DBAL\Migrations\AbstractMigration`) in a directory. + * + * @since 1.0.0-alpha3 + */ +interface MigrationFinderInterface +{ + /** + * Find all the migrations in a directory for the given path and namespace. + * + * @param string $directory The directory in which to look for migrations + * @param string|null $namespace The namespace of the classes to load + * @throws InvalidArgumentException if the directory does not exist + * @return string[] An array of class names that were found with the version + * as keys. + */ + public function findMigrations($directory, $namespace=null); +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Finder/RecursiveRegexFinder.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Finder/RecursiveRegexFinder.php new file mode 100644 index 0000000000..dacc6d58b2 --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Finder/RecursiveRegexFinder.php @@ -0,0 +1,77 @@ +. + */ + +namespace Doctrine\DBAL\Migrations\Finder; + +/** + * A MigrationFinderInterface implementation that uses a RegexIterator along with a + * RecursiveDirectoryIterator. + * + * @since 1.0.0-alpha3 + */ +final class RecursiveRegexFinder extends AbstractFinder +{ + + /** + * {@inheritdoc} + */ + public function findMigrations($directory, $namespace=null) + { + $dir = $this->getRealPath($directory); + + return $this->loadMigrations($this->getMatches($this->createIterator($dir)), $namespace); + } + + /** + * Create a recursive iterator to find all the migrations in the subdirectories. + * @param $dir + * @return \RegexIterator + */ + private function createIterator($dir) + { + return new \RegexIterator( + new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS), + \RecursiveIteratorIterator::LEAVES_ONLY + ), + $this->getPattern(), + \RegexIterator::GET_MATCH + ); + } + + private function getPattern() + { + return sprintf('#^.+\\%sVersion[^\\%s]{1,255}\\.php$#i', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR); + } + + /** + * Transform the recursiveIterator result array of array into the expected array of migration file + * @param $iteratorFilesMatch + * @return array + */ + private function getMatches($iteratorFilesMatch) + { + $files = []; + foreach($iteratorFilesMatch as $file) { + $files[] = $file[0]; + } + + return $files; + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/IrreversibleMigrationException.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/IrreversibleMigrationException.php new file mode 100644 index 0000000000..14453c275c --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/IrreversibleMigrationException.php @@ -0,0 +1,33 @@ +. +*/ + +namespace Doctrine\DBAL\Migrations; + +/** + * Exception to be thrown in the down() methods of migrations that signifies it + * is an irreversible migration and stops execution. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan H. Wage + */ +class IrreversibleMigrationException extends \Exception +{ +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Migration.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Migration.php new file mode 100644 index 0000000000..d615427960 --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Migration.php @@ -0,0 +1,173 @@ +. +*/ + +namespace Doctrine\DBAL\Migrations; + +use Doctrine\DBAL\Migrations\Configuration\Configuration; + +/** + * Class for running migrations to the current version or a manually specified version. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan H. Wage + */ +class Migration +{ + /** + * The OutputWriter object instance used for outputting information + * + * @var OutputWriter + */ + private $outputWriter; + + /** + * @var Configuration + */ + private $configuration; + + /** + * Construct a Migration instance + * + * @param Configuration $configuration A migration Configuration instance + */ + public function __construct(Configuration $configuration) + { + $this->configuration = $configuration; + $this->outputWriter = $configuration->getOutputWriter(); + } + + /** + * Get the array of versions and SQL queries that would be executed for + * each version but do not execute anything. + * + * @param string $to The version to migrate to. + * + * @return array $sql The array of SQL queries. + */ + public function getSql($to = null) + { + return $this->migrate($to, true); + } + + /** + * Write a migration SQL file to the given path + * + * @param string $path The path to write the migration SQL file. + * @param string $to The version to migrate to. + * + * @return boolean $written + */ + public function writeSqlFile($path, $to = null) + { + $sql = $this->getSql($to); + + $from = $this->configuration->getCurrentVersion(); + if ($to === null) { + $to = $this->configuration->getLatestVersion(); + } + + $direction = $from > $to ? 'down' : 'up'; + + $this->outputWriter->write(sprintf("# Migrating from %s to %s\n", $from, $to)); + + $sqlWriter = new SqlFileWriter( + $this->configuration->getMigrationsTableName(), + $path, + $this->outputWriter + ); + + return $sqlWriter->write($sql, $direction); + } + + /** + * 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 .= ' %s to %s from %s'; + $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 ------------------------\n"); + $this->outputWriter->write(sprintf(" ++ finished in %s", $time)); + $this->outputWriter->write(sprintf(" ++ %s migrations executed", count($migrationsToExecute))); + $this->outputWriter->write(sprintf(" ++ %s sql queries", count($sql, true) - count($sql))); + + return $sql; + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/MigrationException.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/MigrationException.php new file mode 100644 index 0000000000..d7f8afc7fb --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/MigrationException.php @@ -0,0 +1,66 @@ +. +*/ + +namespace Doctrine\DBAL\Migrations; + +/** + * Class for Migrations specific exceptions + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan H. Wage + */ +class MigrationException extends \Exception +{ + public static function migrationsNamespaceRequired() + { + return new self('Migrations namespace must be configured in order to use Doctrine migrations.', 2); + } + + public static function migrationsDirectoryRequired() + { + return new self('Migrations directory must be configured in order to use Doctrine migrations.', 3); + } + + public static function noMigrationsToExecute() + { + return new self('Could not find any migrations to execute.', 4); + } + + public static function unknownMigrationVersion($version) + { + return new self(sprintf('Could not find migration version %s', $version), 5); + } + + public static function alreadyAtVersion($version) + { + return new self(sprintf('Database is already at version %s', $version), 6); + } + + public static function duplicateMigrationVersion($version, $class) + { + return new self(sprintf('Migration version %s already registered with class %s', $version, $class), 7); + } + + public static function configurationFileAlreadyLoaded() + { + return new self(sprintf('Migrations configuration file already loaded'), 8); + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/MigrationsVersion.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/MigrationsVersion.php new file mode 100644 index 0000000000..7e3758588e --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/MigrationsVersion.php @@ -0,0 +1,45 @@ +. + */ + +namespace Doctrine\DBAL\Migrations; + +class MigrationsVersion +{ + private static $version = 'v1.0.0-alpha3'; + + public static function VERSION(){ + $gitversion = '@git-version@'; + + if (self::isACustomPharBuild($gitversion)) { + return $gitversion; + } + return self::$version; + } + + /** + * @param $gitversion + * @return bool + * + * Check if doctrine migration is installed by composer or + * in a modified (not tagged) phar version. + */ + private static function isACustomPharBuild($gitversion) { + return $gitversion !== '@' . 'git-version@'; + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/OutputWriter.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/OutputWriter.php new file mode 100644 index 0000000000..5affa82842 --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/OutputWriter.php @@ -0,0 +1,52 @@ +. +*/ + +namespace Doctrine\DBAL\Migrations; + +/** + * Simple class for outputting information from migrations. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan H. Wage + */ +class OutputWriter +{ + private $closure; + + public function __construct(\Closure $closure = null) + { + if ($closure === null) { + $closure = function ($message) {}; + } + $this->closure = $closure; + } + + /** + * Write output using the configured closure. + * + * @param string $message The message to write. + */ + public function write($message) + { + $closure = $this->closure; + $closure($message); + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Provider/OrmSchemaProvider.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Provider/OrmSchemaProvider.php new file mode 100644 index 0000000000..9ad213e044 --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Provider/OrmSchemaProvider.php @@ -0,0 +1,82 @@ +. +*/ + +namespace Doctrine\DBAL\Migrations\Provider; + +use Doctrine\ORM\EntityManager; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Tools\SchemaTool; + +/** + * A schema provider that uses the doctrine ORM to generate schemas. + * + * @since 1.0.0-alpha3 + */ +final class OrmSchemaProvider implements SchemaProviderInterface +{ + /** + * @var EntityManagerInterface + */ + private $entityManager; + + public function __construct($em) + { + if (!$this->isEntityManager($em)) { + throw new \InvalidArgumentException(sprintf( + '$em is not a valid Doctrine ORM Entity Manager, got "%s"', + is_object($em) ? get_class($em) : gettype($em) + )); + } + + $this->entityManager = $em; + } + + /** + * {@inheritdoc} + */ + public function createSchema() + { + $metadata = $this->entityManager->getMetadataFactory()->getAllMetadata(); + if (empty($metadata)) { + throw new \UnexpectedValueException('No mapping information to process'); + } + + $tool = new SchemaTool($this->entityManager); + + return $tool->getSchemaFromMetadata($metadata); + } + + + /** + * Doctrine's EntityManagerInterface was introduced in version 2.4, since this + * library allows those older version we need to be able to check for those + * old ORM versions. Hence the helper method. + * + * No need to check to see if EntityManagerInterface exists first here, PHP + * doesn't care. + * + * @param mixed $manager Hopefully an entity manager, but it may be anything + * @return boolean + */ + private function isEntityManager($manager) + { + return $manager instanceof EntityManagerInterface || $manager instanceof EntityManager; + } + +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Provider/SchemaProviderInterface.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Provider/SchemaProviderInterface.php new file mode 100644 index 0000000000..3af8735d55 --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Provider/SchemaProviderInterface.php @@ -0,0 +1,36 @@ +. +*/ + +namespace Doctrine\DBAL\Migrations\Provider; + +/** + * Generates `Schema` objects for the diff command. A schema provider should + * return the schema to which the database should be migrated. + * + * @since 1.0.0-alpha3 + */ +interface SchemaProviderInterface +{ + /** + * Create the schema to which the database should be migrated. + * + * @return \Doctrine\DBAL\Schema\Schema + */ + public function createSchema(); +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Provider/StubSchemaProvider.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Provider/StubSchemaProvider.php new file mode 100644 index 0000000000..3d5984ab3e --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Provider/StubSchemaProvider.php @@ -0,0 +1,48 @@ +. +*/ + +namespace Doctrine\DBAL\Migrations\Provider; + +use Doctrine\DBAL\Schema\Schema; + +/** + * A schemea provider implementation that just returns the schema its given. + * + * @since 1.0.0-alpha3 + */ +final class StubSchemaProvider implements SchemaProviderInterface +{ + /** + * @var Schema + */ + private $toSchema; + + public function __construct(Schema $schema) + { + $this->toSchema = $schema; + } + + /** + * {@inheritdoc} + */ + public function createSchema() + { + return $this->toSchema; + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/SkipMigrationException.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/SkipMigrationException.php new file mode 100644 index 0000000000..565e86662b --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/SkipMigrationException.php @@ -0,0 +1,7 @@ +. +*/ + +namespace Doctrine\DBAL\Migrations; + +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Exception\InvalidArgumentException; + +class SqlFileWriter +{ + private $migrationsTableName; + + private $destPath; + + /** @var null|OutputWriter */ + private $outputWriter; + + /** + * @param string $migrationsTableName + * @param string $destPath + * @param \Doctrine\DBAL\Migrations\OutputWriter $outputWriter + */ + public function __construct($migrationsTableName, $destPath, OutputWriter $outputWriter = null) + { + if (empty($migrationsTableName)) { + $this->throwInvalidArgumentException('Migrations table name cannot be empty.'); + } + $this->migrationsTableName = $migrationsTableName; + + if (empty($destPath)) { + $this->throwInvalidArgumentException('Destination file must be specified.'); + } + $this->destPath = $destPath; + + $this->outputWriter = $outputWriter; + } + + /** + * @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 "%s"', $path)); + } + + return file_put_contents($path, $string); + } + + private function buildMigrationFile(array $queriesByVersion, $direction) + { + $string = sprintf("# Doctrine Migration File Generated on %s\n", date('Y-m-d H:i:s')); + + foreach ($queriesByVersion as $version => $queries) { + $string .= "\n# Version " . $version . "\n"; + foreach ($queries as $query) { + $string .= $query . ";\n"; + } + + + $string .= $this->getVersionUpdateQuery($version, $direction); + } + + return $string; + } + + private function getVersionUpdateQuery($version, $direction) + { + if ($direction == 'down') { + $query = "DELETE FROM %s WHERE version = '%s';\n"; + } else { + $query = "INSERT INTO %s (version) VALUES ('%s');\n"; + } + + return sprintf($query, $this->migrationsTableName, $version); + } + + private function buildMigrationFilePath() + { + $path = $this->destPath; + if (is_dir($path)) { + $path = realpath($path); + $path = $path . '/doctrine_migration_' . date('YmdHis') . '.sql'; + } + + return $path; + } + + /** + * This only exists for backwards-compatibiliy with DBAL 2.4 + */ + protected function throwInvalidArgumentException($message) + { + if (class_exists('Doctrine\DBAL\Exception\InvalidArgumentException')) { + throw new InvalidArgumentException($message); + } else { + throw new DBALException($message); + } + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/AbstractCommand.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/AbstractCommand.php new file mode 100644 index 0000000000..89b19eac99 --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/AbstractCommand.php @@ -0,0 +1,181 @@ +. + */ + +namespace Doctrine\DBAL\Migrations\Tools\Console\Command; + +use Doctrine\DBAL\Migrations\Configuration\Configuration; +use Doctrine\DBAL\Migrations\OutputWriter; +use Doctrine\DBAL\Migrations\Tools\Console\Helper\ConfigurationHelper; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Question\ConfirmationQuestion; + +/** + * CLI Command for adding and deleting migration versions from the version table. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan Wage + */ +abstract class AbstractCommand extends Command +{ + /** + * The configuration property only contains the configuration injected by the setter. + * + * @var Configuration + */ + private $configuration; + + /** + * The migrationConfiguration property contains the configuration + * created taking into account the command line options. + * + * @var Configuration + */ + private $migrationConfiguration; + + /** + * @var OutputWriter + */ + private $outputWriter; + + /** + * @var \Doctrine\DBAL\Connection + */ + private $connection; + + protected function configure() + { + $this->addOption('configuration', null, InputOption::VALUE_OPTIONAL, 'The path to a migrations configuration file.'); + $this->addOption('db-configuration', null, InputOption::VALUE_OPTIONAL, 'The path to a database connection configuration file.'); + } + + protected function outputHeader(Configuration $configuration, OutputInterface $output) + { + $name = $configuration->getName(); + $name = $name ? $name : 'Doctrine Database Migrations'; + $name = str_repeat(' ', 20) . $name . str_repeat(' ', 20); + $output->writeln('' . str_repeat(' ', strlen($name)) . ''); + $output->writeln('' . $name . ''); + $output->writeln('' . str_repeat(' ', strlen($name)) . ''); + $output->writeln(''); + } + + public function setMigrationConfiguration(Configuration $config) + { + $this->configuration = $config; + } + + /** + * When any (config) command line option is passed to the migration the migrationConfiguration + * property is set with the new generated configuration. + * If no (config) option is passed the migrationConfiguration property is set to the value + * of the configuration one (if any). + * Else a new configuration is created and assigned to the migrationConfiguration property. + * + * @param InputInterface $input + * @param OutputInterface $output + * + * @return Configuration + */ + protected function getMigrationConfiguration(InputInterface $input, OutputInterface $output) + { + if (!$this->migrationConfiguration) { + $configHelper = new ConfigurationHelper($this->getConnection($input), $this->configuration); + $this->migrationConfiguration = $configHelper->getMigrationConfig($input, $this->getOutputWriter($output)); + } + + return $this->migrationConfiguration; + } + + /** + * This method ensure that we stay compatible with symfony console 2.3 by using the deprecated dialog helper + * but use the ConfirmationQuestion when available. + * + * @param $question + * @param InputInterface $input + * @param OutputInterface $output + * @return mixed + */ + protected function askConfirmation($question, InputInterface $input, OutputInterface $output) + { + if ($this->getHelperSet()->has('question')) { + return $this->getHelper('question')->ask($input, $output, new ConfirmationQuestion($question)); + } else { + return $this->getHelper('dialog')->askConfirmation($output, '' . $question . '', false); + } + } + + /** + * @param \Symfony\Component\Console\Output\OutputInterface $output + * + * @return \Doctrine\DBAL\Migrations\OutputWriter + */ + private function getOutputWriter(OutputInterface $output) + { + if (!$this->outputWriter) { + $this->outputWriter = new OutputWriter(function ($message) use ($output) { + return $output->writeln($message); + }); + } + + return $this->outputWriter; + } + + /** + * @param \Symfony\Component\Console\Input\InputInterface $input + * + * @return \Doctrine\DBAL\Connection + * @throws \Doctrine\DBAL\DBALException + */ + private function getConnection(InputInterface $input) + { + if (!$this->connection) { + if ($input->getOption('db-configuration')) { + if (!file_exists($input->getOption('db-configuration'))) { + throw new \InvalidArgumentException("The specified connection file is not a valid file."); + } + + $params = include $input->getOption('db-configuration'); + if (!is_array($params)) { + throw new \InvalidArgumentException('The connection file has to return an array with database configuration parameters.'); + } + $this->connection = \Doctrine\DBAL\DriverManager::getConnection($params); + } elseif (file_exists('migrations-db.php')) { + $params = include 'migrations-db.php'; + if (!is_array($params)) { + throw new \InvalidArgumentException('The connection file has to return an array with database configuration parameters.'); + } + $this->connection = \Doctrine\DBAL\DriverManager::getConnection($params); + } elseif ($this->getHelperSet()->has('connection')) { + $this->connection = $this->getHelper('connection')->getConnection(); + } elseif ($this->configuration) { + $this->connection = $this->configuration->getConnection(); + } else { + throw new \InvalidArgumentException('You have to specify a --db-configuration file or pass a Database Connection as a dependency to the Migrations.'); + } + } + + return $this->connection; + } + +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/DiffCommand.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/DiffCommand.php new file mode 100644 index 0000000000..27940271ca --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/DiffCommand.php @@ -0,0 +1,167 @@ +. + */ + +namespace Doctrine\DBAL\Migrations\Tools\Console\Command; + +use Doctrine\DBAL\Migrations\Configuration\Configuration; +use Doctrine\DBAL\Version as DbalVersion; +use Doctrine\DBAL\Migrations\Provider\SchemaProviderInterface; +use Doctrine\DBAL\Migrations\Provider\OrmSchemaProvider; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Input\InputOption; + +/** + * Command for generate migration classes by comparing your current database schema + * to your mapping information. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan Wage + */ +class DiffCommand extends GenerateCommand +{ + /** + * @var SchemaProviderInterface + */ + protected $schemaProvider; + + public function __construct(SchemaProviderInterface $schemaProvider=null) + { + $this->schemaProvider = $schemaProvider; + parent::__construct(); + } + + protected function configure() + { + parent::configure(); + + $this + ->setName('migrations:diff') + ->setDescription('Generate a migration by comparing your current database to your mapping information.') + ->setHelp(<<%command.name% command generates a migration by comparing your current database to your mapping information: + + %command.full_name% + +You can optionally specify a --editor-cmd option to open the generated file in your favorite editor: + + %command.full_name% --editor-cmd=mate +EOT + ) + ->addOption('filter-expression', null, InputOption::VALUE_OPTIONAL, 'Tables which are filtered by Regular Expression.'); + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $isDbalOld = (DbalVersion::compare('2.2.0') > 0); + $configuration = $this->getMigrationConfiguration($input, $output); + + $conn = $configuration->getConnection(); + $platform = $conn->getDatabasePlatform(); + + if ($filterExpr = $input->getOption('filter-expression')) { + if ($isDbalOld) { + throw new \InvalidArgumentException('The "--filter-expression" option can only be used as of Doctrine DBAL 2.2'); + } + + $conn->getConfiguration() + ->setFilterSchemaAssetsExpression($filterExpr); + } + + $fromSchema = $conn->getSchemaManager()->createSchema(); + $toSchema = $this->getSchemaProvider()->createSchema(); + + //Not using value from options, because filters can be set from config.yml + if ( ! $isDbalOld && $filterExpr = $conn->getConfiguration()->getFilterSchemaAssetsExpression()) { + foreach ($toSchema->getTables() as $table) { + $tableName = $table->getName(); + if ( ! preg_match($filterExpr, $this->resolveTableName($tableName))) { + $toSchema->dropTable($tableName); + } + } + } + + $up = $this->buildCodeFromSql($configuration, $fromSchema->getMigrateToSql($toSchema, $platform)); + $down = $this->buildCodeFromSql($configuration, $fromSchema->getMigrateFromSql($toSchema, $platform)); + + if (! $up && ! $down) { + $output->writeln('No changes detected in your mapping information.', 'ERROR'); + + return; + } + + $version = date('YmdHis'); + $path = $this->generateMigration($configuration, $input, $version, $up, $down); + + $output->writeln(sprintf('Generated new migration class to "%s" from schema differences.', $path)); + } + + private function buildCodeFromSql(Configuration $configuration, array $sql) + { + $currentPlatform = $configuration->getConnection()->getDatabasePlatform()->getName(); + $code = array(); + foreach ($sql as $query) { + if (stripos($query, $configuration->getMigrationsTableName()) !== false) { + continue; + } + $code[] = sprintf("\$this->addSql(%s);", var_export($query, true)); + } + + if (!empty($code)) { + array_unshift( + $code, + sprintf( + "\$this->abortIf(\$this->connection->getDatabasePlatform()->getName() != %s, %s);", + var_export($currentPlatform, true), + var_export(sprintf("Migration can only be executed safely on '%s'.", $currentPlatform), true) + ), + "" + ); + } + + return implode("\n", $code); + } + + private function getSchemaProvider() + { + if (!$this->schemaProvider) { + $this->schemaProvider = new OrmSchemaProvider($this->getHelper('entityManager')->getEntityManager()); + } + + return $this->schemaProvider; + } + + /** + * Resolve a table name from its fully qualified name. The `$name` argument + * comes from Doctrine\DBAL\Schema\Table#getName which can sometimes return + * a namespaced name with the form `{namespace}.{tableName}`. This extracts + * the table name from that. + * + * @param string $name + * @return string + */ + private function resolveTableName($name) + { + $pos = strpos($name, '.'); + + return false === $pos ? $name : substr($name, $pos + 1); + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/ExecuteCommand.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/ExecuteCommand.php new file mode 100644 index 0000000000..ffd57508ca --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/ExecuteCommand.php @@ -0,0 +1,102 @@ +. + */ + +namespace Doctrine\DBAL\Migrations\Tools\Console\Command; + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; + +/** + * Command for executing single migrations up or down manually. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan Wage + */ +class ExecuteCommand extends AbstractCommand +{ + protected function configure() + { + $this + ->setName('migrations:execute') + ->setDescription('Execute a single migration version up or down manually.') + ->addArgument('version', InputArgument::REQUIRED, 'The version to execute.', null) + ->addOption('write-sql', null, InputOption::VALUE_NONE, 'The path to output the migration SQL file instead of executing it.') + ->addOption('dry-run', null, InputOption::VALUE_NONE, 'Execute the migration as a dry run.') + ->addOption('up', null, InputOption::VALUE_NONE, 'Execute the migration up.') + ->addOption('down', null, InputOption::VALUE_NONE, 'Execute the migration down.') + ->addOption('query-time', null, InputOption::VALUE_NONE, 'Time all the queries individually.') + ->setHelp(<<%command.name% command executes a single migration version up or down manually: + + %command.full_name% YYYYMMDDHHMMSS + +If no --up or --down option is specified it defaults to up: + + %command.full_name% YYYYMMDDHHMMSS --down + +You can also execute the migration as a --dry-run: + + %command.full_name% YYYYMMDDHHMMSS --dry-run + +You can output the would be executed SQL statements to a file with --write-sql: + + %command.full_name% YYYYMMDDHHMMSS --write-sql + +Or you can also execute the migration without a warning message which you need to interact with: + + %command.full_name% --no-interaction +EOT + ); + + parent::configure(); + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $version = $input->getArgument('version'); + $direction = $input->getOption('down') ? 'down' : 'up'; + + $configuration = $this->getMigrationConfiguration($input, $output); + $version = $configuration->getVersion($version); + + $timeAllqueries = $input->getOption('query-time'); + + if ($path = $input->getOption('write-sql')) { + $path = is_bool($path) ? getcwd() : $path; + $version->writeSqlFile($path, $direction); + } else { + if ($input->isInteractive()) { + $question = 'WARNING! You are about to execute a database migration that could result in schema changes and data lost. Are you sure you wish to continue? (y/n)'; + $execute = $this->askConfirmation($question, $input, $output); + } else { + $execute = true; + } + + if ($execute) { + $version->execute($direction, (boolean) $input->getOption('dry-run'), $timeAllqueries); + } else { + $output->writeln('Migration cancelled!'); + } + } + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/GenerateCommand.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/GenerateCommand.php new file mode 100644 index 0000000000..ddb2174bc9 --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/GenerateCommand.php @@ -0,0 +1,135 @@ +. + */ + +namespace Doctrine\DBAL\Migrations\Tools\Console\Command; + +use Doctrine\DBAL\Migrations\Configuration\Configuration; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Input\InputOption; + +/** + * Command for generating new blank migration classes + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan Wage + */ +class GenerateCommand extends AbstractCommand +{ + + private static $_template = + '; + +use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\DBAL\Schema\Schema; + +/** + * Auto-generated Migration: Please modify to your needs! + */ +class Version extends AbstractMigration +{ + /** + * @param Schema $schema + */ + public function up(Schema $schema) + { + // this up() migration is auto-generated, please modify it to your needs + + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + // this down() migration is auto-generated, please modify it to your needs + + } +} +'; + + protected function configure() + { + $this + ->setName('migrations:generate') + ->setDescription('Generate a blank migration class.') + ->addOption('editor-cmd', null, InputOption::VALUE_OPTIONAL, 'Open file with this command upon creation.') + ->setHelp(<<%command.name% command generates a blank migration class: + + %command.full_name% + +You can optionally specify a --editor-cmd option to open the generated file in your favorite editor: + + %command.full_name% --editor-cmd=mate +EOT + ); + + parent::configure(); + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $configuration = $this->getMigrationConfiguration($input, $output); + + $version = date('YmdHis'); + $path = $this->generateMigration($configuration, $input, $version); + + $output->writeln(sprintf('Generated new migration class to "%s"', $path)); + } + + protected function generateMigration(Configuration $configuration, InputInterface $input, $version, $up = null, $down = null) + { + $placeHolders = array( + '', + '', + '', + '' + ); + $replacements = array( + $configuration->getMigrationsNamespace(), + $version, + $up ? " " . implode("\n ", explode("\n", $up)) : null, + $down ? " " . implode("\n ", explode("\n", $down)) : null + ); + $code = str_replace($placeHolders, $replacements, self::$_template); + $code = preg_replace('/^ +$/m', '', $code); + $dir = $configuration->getMigrationsDirectory(); + $dir = $dir ? $dir : getcwd(); + $dir = rtrim($dir, '/'); + $path = $dir . '/Version' . $version . '.php'; + + if ( ! file_exists($dir)) { + throw new \InvalidArgumentException(sprintf('Migrations directory "%s" does not exist.', $dir)); + } + + file_put_contents($path, $code); + + if ($editorCmd = $input->getOption('editor-cmd')) { + proc_open($editorCmd . ' ' . escapeshellarg($path), array(), $pipes); + } + + return $path; + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/LatestCommand.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/LatestCommand.php new file mode 100644 index 0000000000..52d4c6e1bb --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/LatestCommand.php @@ -0,0 +1,48 @@ +. + */ + +namespace Doctrine\DBAL\Migrations\Tools\Console\Command; + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Outputs the latest version number. + * + * @author Kris Wallsmith + */ +class LatestCommand extends AbstractCommand +{ + protected function configure() + { + $this + ->setName('migrations:latest') + ->setDescription('Outputs the latest version number') + ; + + parent::configure(); + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $configuration = $this->getMigrationConfiguration($input, $output); + + $output->writeln($configuration->getLatestVersion()); + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/MigrateCommand.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/MigrateCommand.php new file mode 100644 index 0000000000..056705bc64 --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/MigrateCommand.php @@ -0,0 +1,192 @@ +. + */ + +namespace Doctrine\DBAL\Migrations\Tools\Console\Command; + +use Doctrine\DBAL\Migrations\Configuration\Configuration; +use Doctrine\DBAL\Migrations\Migration; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; + +/** + * Command for executing a migration to a specified version or the latest available version. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan Wage + */ +class MigrateCommand extends AbstractCommand +{ + protected function configure() + { + $this + ->setName('migrations:migrate') + ->setDescription('Execute a migration to a specified version or the latest available version.') + ->addArgument('version', InputArgument::OPTIONAL, 'The version number (YYYYMMDDHHMMSS) or alias (first, prev, next, latest) to migrate to.', 'latest') + ->addOption('write-sql', null, InputOption::VALUE_NONE, 'The path to output the migration SQL file instead of executing it.') + ->addOption('dry-run', null, InputOption::VALUE_NONE, 'Execute the migration as a dry run.') + ->addOption('query-time', null, InputOption::VALUE_NONE, 'Time all the queries individually.') + ->setHelp(<<%command.name% command executes a migration to a specified version or the latest available version: + + %command.full_name% + +You can optionally manually specify the version you wish to migrate to: + + %command.full_name% YYYYMMDDHHMMSS + +You can specify the version you wish to migrate to using an alias: + + %command.full_name% prev + +You can also execute the migration as a --dry-run: + + %command.full_name% YYYYMMDDHHMMSS --dry-run + +You can output the would be executed SQL statements to a file with --write-sql: + + %command.full_name% YYYYMMDDHHMMSS --write-sql + +Or you can also execute the migration without a warning message which you need to interact with: + + %command.full_name% --no-interaction + +You can also time all the different queries if you wanna know which one is taking so long: + + %command.full_name% --query-time +EOT + ); + + parent::configure(); + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $configuration = $this->getMigrationConfiguration($input, $output); + $migration = new Migration($configuration); + + $this->outputHeader($configuration, $output); + + $timeAllqueries = $input->getOption('query-time'); + + $executedMigrations = $configuration->getMigratedVersions(); + $availableMigrations = $configuration->getAvailableVersions(); + $executedUnavailableMigrations = array_diff($executedMigrations, $availableMigrations); + + $version = $this->getVersionNameFromAlias($input->getArgument('version'), $output, $configuration); + if ($version === false) { + return 1; + } + + if (!empty($executedUnavailableMigrations)) { + $output->writeln(sprintf( + 'WARNING! You have %s previously executed migrations' + . ' in the database that are not registered migrations.', + count($executedUnavailableMigrations) + )); + + foreach ($executedUnavailableMigrations as $executedUnavailableMigration) { + $output->writeln(sprintf( + ' >> %s (%s)', + $configuration->getDateTime($executedUnavailableMigration), + $executedUnavailableMigration + )); + } + + $question = 'Are you sure you wish to continue? (y/n)'; + if (! $this->canExecute($question, $input, $output)) { + $output->writeln('Migration cancelled!'); + + return 1; + } + } + + if ($path = $input->getOption('write-sql')) { + $path = is_bool($path) ? getcwd() : $path; + $migration->writeSqlFile($path, $version); + } else { + $dryRun = (boolean) $input->getOption('dry-run'); + + // warn the user if no dry run and interaction is on + if (! $dryRun) { + $question = 'WARNING! You are about to execute a database migration' + . ' that could result in schema changes and data lost.' + . ' Are you sure you wish to continue? (y/n)'; + if (! $this->canExecute($question, $input, $output)) { + $output->writeln('Migration cancelled!'); + + return 1; + } + } + + $sql = $migration->migrate($version, $dryRun, $timeAllqueries); + + if (empty($sql)) { + $output->writeln('No migrations to execute.'); + } + } + } + + /** + * @param string $question + * @param InputInterface $input + * @param OutputInterface $output + * @return bool + */ + private function canExecute($question, InputInterface $input, OutputInterface $output) + { + if ($input->isInteractive() && ! $this->askConfirmation($question, $input, $output)) { + return false; + } + + return true; + } + + /** + * @param string $versionAlias + * @param OutputInterface $output + * @param Configuration $configuration + * @return bool|string + */ + private function getVersionNameFromAlias($versionAlias, OutputInterface $output, Configuration $configuration) + { + $version = $configuration->resolveVersionAlias($versionAlias); + if ($version === null) { + if ($versionAlias == 'prev') { + $output->writeln('Already at first version.'); + return false; + } + if ($versionAlias == 'next') { + $output->writeln('Already at latest version.'); + return false; + } + + $output->writeln(sprintf( + 'Unknown version: %s', + $output->getFormatter()->escape($versionAlias) + )); + return false; + } + + return $version; + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/StatusCommand.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/StatusCommand.php new file mode 100644 index 0000000000..f530b03a0d --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/StatusCommand.php @@ -0,0 +1,140 @@ +. + */ + +namespace Doctrine\DBAL\Migrations\Tools\Console\Command; + +use Doctrine\DBAL\Migrations\Configuration\Configuration; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Input\InputOption; + +/** + * Command to view the status of a set of migrations. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan Wage + */ +class StatusCommand extends AbstractCommand +{ + protected function configure() + { + $this + ->setName('migrations:status') + ->setDescription('View the status of a set of migrations.') + ->addOption('show-versions', null, InputOption::VALUE_NONE, 'This will display a list of all available migrations and their status') + ->setHelp(<<%command.name% command outputs the status of a set of migrations: + + %command.full_name% + +You can output a list of all available migrations and their status with --show-versions: + + %command.full_name% --show-versions +EOT + ); + + parent::configure(); + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $configuration = $this->getMigrationConfiguration($input, $output); + + $formattedVersions = array(); + foreach (array('prev', 'current', 'next', 'latest') as $alias) { + $version = $configuration->resolveVersionAlias($alias); + if ($version === null) { + if ($alias == 'next') { + $formattedVersions[$alias] = 'Already at latest version'; + } elseif ($alias == 'prev') { + $formattedVersions[$alias] = 'Already at first version'; + } + } elseif ($version === '0') { + $formattedVersions[$alias] = '0'; + } else { + $formattedVersions[$alias] = $configuration->getDateTime($version) . ' (' . $version . ')'; + } + } + + $executedMigrations = $configuration->getMigratedVersions(); + $availableMigrations = $configuration->getAvailableVersions(); + $executedUnavailableMigrations = array_diff($executedMigrations, $availableMigrations); + $numExecutedUnavailableMigrations = count($executedUnavailableMigrations); + $newMigrations = count(array_diff($availableMigrations, $executedMigrations)); + + $output->writeln("\n == Configuration\n"); + + $info = array( + 'Name' => $configuration->getName() ? $configuration->getName() : 'Doctrine Database Migrations', + 'Database Driver' => $configuration->getConnection()->getDriver()->getName(), + 'Database Name' => $configuration->getConnection()->getDatabase(), + 'Configuration Source' => $configuration instanceof \Doctrine\DBAL\Migrations\Configuration\AbstractFileConfiguration ? $configuration->getFile() : 'manually configured', + 'Version Table Name' => $configuration->getMigrationsTableName(), + 'Migrations Namespace' => $configuration->getMigrationsNamespace(), + 'Migrations Directory' => $configuration->getMigrationsDirectory(), + 'Previous Version' => $formattedVersions['prev'], + 'Current Version' => $formattedVersions['current'], + 'Next Version' => $formattedVersions['next'], + 'Latest Version' => $formattedVersions['latest'], + 'Executed Migrations' => count($executedMigrations), + 'Executed Unavailable Migrations' => $numExecutedUnavailableMigrations > 0 ? ''.$numExecutedUnavailableMigrations.'' : 0, + 'Available Migrations' => count($availableMigrations), + 'New Migrations' => $newMigrations > 0 ? '' . $newMigrations . '' : 0 + ); + foreach ($info as $name => $value) { + $output->writeln(' >> ' . $name . ': ' . str_repeat(' ', 50 - strlen($name)) . $value); + } + + if ($input->getOption('show-versions')) { + if ($migrations = $configuration->getMigrations()) { + $executedUnavailableMigrations = $migrations; + $output->writeln("\n == Available Migration Versions\n"); + + $this->showVersions($migrations, $configuration, $output); + } + + if (!empty($executedUnavailableMigrations)) { + $output->writeln("\n == Previously Executed Unavailable Migration Versions\n"); + $this->showVersions($executedUnavailableMigrations, $configuration, $output); + } + } + } + + private function showVersions($migrations, Configuration $configuration, $output) + { + $migratedVersions = $configuration->getMigratedVersions(); + + foreach($migrations as $version) { + $isMigrated = in_array($version->getVersion(), $migratedVersions); + $status = $isMigrated ? 'migrated' : 'not migrated'; + $migrationDescription = ''; + if ($version->getMigration()->getDescription()) { + $migrationDescription = str_repeat(' ', 5) . $version->getMigration()->getDescription(); + } + $formattedVersion = $configuration->getDateTime($version->getVersion()); + + $output->writeln(' >> ' . $formattedVersion . + ' (' . $version->getVersion() . ')' . + str_repeat(' ', 49 - strlen($formattedVersion) - strlen($version->getVersion())) . + $status . $migrationDescription); + } + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/VersionCommand.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/VersionCommand.php new file mode 100644 index 0000000000..4a6625c7d5 --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/VersionCommand.php @@ -0,0 +1,177 @@ +. + */ + +namespace Doctrine\DBAL\Migrations\Tools\Console\Command; + +use Doctrine\DBAL\Migrations\MigrationException; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; + +/** + * Command for manually adding and deleting migration versions from the version table. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan Wage + */ +class VersionCommand extends AbstractCommand +{ + /** + * The Migrations Configuration instance + * + * @var \Doctrine\DBAL\Migrations\Configuration\Configuration + */ + private $configuration; + + /** + * Whether or not the versions have to be marked as migrated or not + * + * @var boolean + */ + private $markMigrated; + + protected function configure() + { + $this + ->setName('migrations:version') + ->setDescription('Manually add and delete migration versions from the version table.') + ->addArgument('version', InputArgument::OPTIONAL, 'The version to add or delete.', null) + ->addOption('add', null, InputOption::VALUE_NONE, 'Add the specified version.') + ->addOption('delete', null, InputOption::VALUE_NONE, 'Delete the specified version.') + ->addOption('all', null, InputOption::VALUE_NONE, 'Apply to all the versions.') + ->addOption('range-from', null, InputOption::VALUE_OPTIONAL, 'Apply from specified version.') + ->addOption('range-to', null, InputOption::VALUE_OPTIONAL, 'Apply to specified version.') + ->setHelp(<<%command.name% command allows you to manually add, delete or synchronize migration versions from the version table: + + %command.full_name% YYYYMMDDHHMMSS --add + +If you want to delete a version you can use the --delete option: + + %command.full_name% YYYYMMDDHHMMSS --delete + +If you want to synchronize by adding or deleting all migration versions available in the version table you can use the --all option: + + %command.full_name% --add --all + %command.full_name% --delete --all + +If you want to synchronize by adding or deleting some range of migration versions available in the version table you can use the --range-from/--range-to option: + + %command.full_name% --add --range-from=YYYYMMDDHHMMSS --range-to=YYYYMMDDHHMMSS + %command.full_name% --delete --range-from=YYYYMMDDHHMMSS --range-to=YYYYMMDDHHMMSS + +You can also execute this command without a warning message which you need to interact with: + + %command.full_name% --no-interaction +EOT + ); + + parent::configure(); + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $this->configuration = $this->getMigrationConfiguration($input, $output); + + if ( ! $input->getOption('add') && ! $input->getOption('delete')) { + throw new \InvalidArgumentException('You must specify whether you want to --add or --delete the specified version.'); + } + + $this->markMigrated = (boolean) $input->getOption('add'); + + if ($input->isInteractive()) { + $question = 'WARNING! You are about to add, delete or synchronize migration versions from the version table that could result in data lost. Are you sure you wish to continue? (y/n)'; + + $confirmation = $this->askConfirmation($question, $input, $output); + + if ($confirmation) { + $this->markVersions($input); + } else { + $output->writeln('Migration cancelled!'); + } + } else { + $this->markVersions($input); + } + + } + + private function markVersions(InputInterface $input) + { + $affectedVersion = $input->getArgument('version'); + + $allOption = $input->getOption('all'); + $rangeFromOption = $input->getOption('range-from'); + $rangeToOption = $input->getOption('range-to'); + + if ($allOption && ($rangeFromOption !== null || $rangeToOption !== null)) { + throw new \InvalidArgumentException('Options --all and --range-to/--range-from both used. You should use only one of them.'); + } elseif ($rangeFromOption !== null ^ $rangeToOption !== null) { + throw new \InvalidArgumentException('Options --range-to and --range-from should be used together.'); + } + + if ($allOption === true) { + $availableVersions = $this->configuration->getAvailableVersions(); + foreach ($availableVersions as $version) { + $this->mark($version, true); + } + } elseif ($rangeFromOption !== null && $rangeToOption !== null) { + $availableVersions = $this->configuration->getAvailableVersions(); + foreach ($availableVersions as $version) { + if ($version >= $rangeFromOption && $version <= $rangeToOption) { + $this->mark($version, true); + } + } + } else { + $this->mark($affectedVersion); + } + } + + private function mark($version, $all = false) + { + if ( ! $this->configuration->hasVersion($version)) { + throw MigrationException::unknownMigrationVersion($version); + } + + $version = $this->configuration->getVersion($version); + if ($this->markMigrated && $this->configuration->hasVersionMigrated($version)) { + $marked = true; + if (! $all) { + throw new \InvalidArgumentException(sprintf('The version "%s" already exists in the version table.', $version)); + } + } + + if ( ! $this->markMigrated && ! $this->configuration->hasVersionMigrated($version)) { + $marked = false; + if (! $all) { + throw new \InvalidArgumentException(sprintf('The version "%s" does not exists in the version table.', $version)); + } + } + + if ( ! isset($marked)) { + if ($this->markMigrated) { + $version->markMigrated(); + } else { + $version->markNotMigrated(); + } + } + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Helper/ConfigurationHelper.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Helper/ConfigurationHelper.php new file mode 100644 index 0000000000..1dd8608013 --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Helper/ConfigurationHelper.php @@ -0,0 +1,107 @@ +. + */ + +namespace Doctrine\DBAL\Migrations\Tools\Console\Helper; + +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Migrations\Configuration\Configuration; +use Doctrine\DBAL\Migrations\OutputWriter; +use Symfony\Component\Console\Input\InputInterface; + +/** + * Class ConfigurationHelper + * @package Doctrine\DBAL\Migrations\Tools\Console\Helper + * @internal + */ +final class ConfigurationHelper +{ + + /** + * @var Connection + */ + private $connection; + + /** + * @var Configuration + */ + private $configuration; + + public function __construct(Connection $connection = null, Configuration $configuration = null) + { + $this->connection = $connection; + $this->configuration = $configuration; + } + + 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); + } + + + private function configExists($config) + { + return file_exists($config); + } + + private function loadConfig($config, OutputWriter $outputWriter) + { + $info = pathinfo($config); + $class = 'Doctrine\DBAL\Migrations\Configuration'; + $class .= $info['extension'] === 'xml' ? '\XmlConfiguration' : '\YamlConfiguration'; + $configuration = new $class($this->connection, $outputWriter); + $configuration->load($config); + + return $configuration; + } +} diff --git a/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Version.php b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Version.php new file mode 100644 index 0000000000..41833e158d --- /dev/null +++ b/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Version.php @@ -0,0 +1,392 @@ +. +*/ + +namespace Doctrine\DBAL\Migrations; + +use Doctrine\DBAL\Migrations\Configuration\Configuration; + +/** + * Class which wraps a migration version and allows execution of the + * individual migration version up or down method. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan H. Wage + */ +class Version +{ + const STATE_NONE = 0; + const STATE_PRE = 1; + const STATE_EXEC = 2; + const STATE_POST = 3; + + /** + * The Migrations Configuration instance for this migration + * + * @var Configuration + */ + private $configuration; + + /** + * The OutputWriter object instance used for outputting information + * + * @var OutputWriter + */ + private $outputWriter; + + /** + * The version in timestamp format (YYYYMMDDHHMMSS) + * + * @param int + */ + private $version; + + /** + * @var \Doctrine\DBAL\Schema\AbstractSchemaManager + */ + private $sm; + + /** + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + private $platform; + + /** + * The migration instance for this version + * + * @var AbstractMigration + */ + private $migration; + + /** + * @var \Doctrine\DBAL\Connection + */ + private $connection; + + /** + * @var string + */ + private $class; + + /** The array of collected SQL statements for this version */ + private $sql = array(); + + /** The array of collected parameters for SQL statements for this version */ + private $params = array(); + + /** The array of collected types for SQL statements for this version */ + private $types = array(); + + /** The time in seconds that this migration version took to execute */ + private $time; + + /** + * @var int + */ + private $state = self::STATE_NONE; + + public function __construct(Configuration $configuration, $version, $class) + { + $this->configuration = $configuration; + $this->outputWriter = $configuration->getOutputWriter(); + $this->class = $class; + $this->connection = $configuration->getConnection(); + $this->sm = $this->connection->getSchemaManager(); + $this->platform = $this->connection->getDatabasePlatform(); + $this->migration = new $class($this); + $this->version = $version; + } + + /** + * Returns the string version in the format YYYYMMDDHHMMSS + * + * @return string $version + */ + public function getVersion() + { + return $this->version; + } + + /** + * Returns the Migrations Configuration object instance + * + * @return Configuration $configuration + */ + public function getConfiguration() + { + return $this->configuration; + } + + /** + * Check if this version has been migrated or not. + * + * @return boolean + */ + public function isMigrated() + { + return $this->configuration->hasVersionMigrated($this); + } + + public function markMigrated() + { + $this->configuration->createMigrationTable(); + $this->connection->insert( + $this->configuration->getMigrationsTableName(), + array('version' => $this->version) + ); + } + + public function markNotMigrated() + { + $this->configuration->createMigrationTable(); + $this->connection->delete( + $this->configuration->getMigrationsTableName(), + array('version' => $this->version) + ); + } + + /** + * Add some SQL queries to this versions migration + * + * @param array|string $sql + * @param array $params + * @param array $types + */ + public function addSql($sql, array $params = array(), array $types = array()) + { + if (is_array($sql)) { + foreach ($sql as $key => $query) { + $this->sql[] = $query; + if (isset($params[$key])) { + $this->params[count($this->sql) - 1] = $params[$key]; + $this->types[count($this->sql) - 1] = isset($types[$key]) ? $types[$key] : array(); + } + } + } else { + $this->sql[] = $sql; + if (!empty($params)) { + $index = count($this->sql) - 1; + $this->params[$index] = $params; + $this->types[$index] = $types; + } + } + } + + /** + * Write a migration SQL file to the given path + * + * @param string $path The path to write the migration SQL file. + * @param string $direction The direction to execute. + * + * @return boolean $written + */ + public function writeSqlFile($path, $direction = 'up') + { + $queries = $this->execute($direction, true); + + $this->outputWriter->write("\n# Version " . $this->version . "\n"); + + $sqlQueries = [$this->version => $queries]; + $sqlWriter = new SqlFileWriter( + $this->configuration->getMigrationsTableName(), + $path, + $this->outputWriter + ); + + return $sqlWriter->write($sqlQueries, $direction); + } + + /** + * @return AbstractMigration + */ + public function getMigration() + { + return $this->migration; + } + + /** + * 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. + * @param boolean $timeAllQueries Measuring or not the execution time of each SQL query. + * + * @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(' ++ migrating %s', $this->version) . "\n"); + } else { + $this->outputWriter->write("\n" . sprintf(' -- reverting %s', $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 (!empty($this->sql)) { + foreach ($this->sql as $key => $query) { + $queryStart = microtime(true); + + if ( ! isset($this->params[$key])) { + $this->outputWriter->write(' -> ' . $query); + $this->connection->exec($query); + } else { + $this->outputWriter->write(sprintf(' - %s (with parameters)', $query)); + $this->connection->executeQuery($query, $this->params[$key], $this->types[$key]); + } + + $this->outputQueryTime($queryStart, $timeAllQueries); + } + } else { + $this->outputWriter->write(sprintf( + 'Migration %s was executed but did not result in any SQL statements.', + $this->version + )); + } + + if ($direction === 'up') { + $this->markMigrated(); + } else { + $this->markNotMigrated(); + } + + } else { + foreach ($this->sql as $query) { + $this->outputWriter->write(' -> ' . $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 ++ migrated (%ss)", $this->time)); + } else { + $this->outputWriter->write(sprintf("\n -- 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 SS skipped (Reason: %s)", $e->getMessage())); + + $this->state = self::STATE_NONE; + + return array(); + } catch (\Exception $e) { + + $this->outputWriter->write(sprintf( + 'Migration %s failed during %s. Error %s', + $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; + } + } + + public function getExecutionState() + { + switch ($this->state) { + case self::STATE_PRE: + return 'Pre-Checks'; + case self::STATE_POST: + return 'Post-Checks'; + case self::STATE_EXEC: + return 'Execution'; + default: + return 'No State'; + } + } + + private function outputQueryTime($queryStart, $timeAllQueries = false) + { + if ($timeAllQueries !== false) { + $queryEnd = microtime(true); + $queryTime = round($queryEnd - $queryStart, 4); + + $this->outputWriter->write(sprintf(" %ss", $queryTime)); + } + } + + /** + * Returns the time this migration version took to execute + * + * @return integer $time The time this migration version took to execute + */ + public function getTime() + { + return $this->time; + } + + public function __toString() + { + return $this->version; + } +} diff --git a/vendor/doctrine/migrations/phpunit.xml.dist b/vendor/doctrine/migrations/phpunit.xml.dist new file mode 100644 index 0000000000..e67d2526ce --- /dev/null +++ b/vendor/doctrine/migrations/phpunit.xml.dist @@ -0,0 +1,37 @@ + + + + + + ./tests/Doctrine/ + + + + + + ./lib/ + + + + + + + + + 200 + + + 10 + + + + + + + + + + +