parent
							
								
									185ca46d42
								
							
						
					
					
						commit
						bfc536942e
					
				@ -1 +0,0 @@ | 
				
			||||
Subproject commit 6c527d8ccbccec5257bb2c92bca973653b1e3976 | 
				
			||||
@ -0,0 +1 @@ | 
				
			||||
src_dir: lib | 
				
			||||
@ -0,0 +1,108 @@ | 
				
			||||
# Doctrine Database Migrations | 
				
			||||
 | 
				
			||||
## Status | 
				
			||||
 | 
				
			||||
[](https://travis-ci.org/doctrine/migrations) | 
				
			||||
[](https://www.versioneye.com/php/doctrine:migrations/) | 
				
			||||
[](https://scrutinizer-ci.com/g/doctrine/migrations/?branch=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 :-) | 
				
			||||
@ -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. | 
				
			||||
@ -0,0 +1,3 @@ | 
				
			||||
#!/usr/bin/env php | 
				
			||||
<?php | 
				
			||||
include('doctrine-migrations.php'); | 
				
			||||
@ -0,0 +1,93 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
$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); | 
				
			||||
 | 
				
			||||
@ -0,0 +1,7 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
namespace Doctrine\DBAL\Migrations; | 
				
			||||
 | 
				
			||||
class AbortMigrationException extends MigrationException | 
				
			||||
{ | 
				
			||||
} | 
				
			||||
@ -0,0 +1,189 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
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 <jonwage@gmail.com> | 
				
			||||
 */ | 
				
			||||
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>Warning during %s: %s</warning>', | 
				
			||||
                $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); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,94 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
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 <jonwage@gmail.com> | 
				
			||||
 */ | 
				
			||||
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); | 
				
			||||
} | 
				
			||||
@ -0,0 +1,695 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
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 <jonwage@gmail.com> | 
				
			||||
 */ | 
				
			||||
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; | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,58 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
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 <jonwage@gmail.com> | 
				
			||||
 */ | 
				
			||||
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']); | 
				
			||||
            } | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,61 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
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 <jonwage@gmail.com> | 
				
			||||
 */ | 
				
			||||
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']); | 
				
			||||
            } | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,65 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
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; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,45 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
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); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,40 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
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); | 
				
			||||
} | 
				
			||||
@ -0,0 +1,77 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
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; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,33 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
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 <jonwage@gmail.com> | 
				
			||||
 */ | 
				
			||||
class IrreversibleMigrationException extends \Exception | 
				
			||||
{ | 
				
			||||
} | 
				
			||||
@ -0,0 +1,173 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
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 <jonwage@gmail.com> | 
				
			||||
 */ | 
				
			||||
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 .= ' <info>%s</info> to <comment>%s</comment> from <comment>%s</comment>'; | 
				
			||||
        $this->outputWriter->write(sprintf($output, $direction, $to, $from)); | 
				
			||||
 | 
				
			||||
        /** | 
				
			||||
         * If there are no migrations to execute throw an exception. | 
				
			||||
         */ | 
				
			||||
        if (empty($migrationsToExecute)) { | 
				
			||||
            throw MigrationException::noMigrationsToExecute(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $sql = array(); | 
				
			||||
        $time = 0; | 
				
			||||
        foreach ($migrationsToExecute as $version) { | 
				
			||||
            $versionSql = $version->execute($direction, $dryRun, $timeAllQueries); | 
				
			||||
            $sql[$version->getVersion()] = $versionSql; | 
				
			||||
            $time += $version->getTime(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $this->outputWriter->write("\n  <comment>------------------------</comment>\n"); | 
				
			||||
        $this->outputWriter->write(sprintf("  <info>++</info> finished in %s", $time)); | 
				
			||||
        $this->outputWriter->write(sprintf("  <info>++</info> %s migrations executed", count($migrationsToExecute))); | 
				
			||||
        $this->outputWriter->write(sprintf("  <info>++</info> %s sql queries", count($sql, true) - count($sql))); | 
				
			||||
 | 
				
			||||
        return $sql; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,66 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
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 <jonwage@gmail.com> | 
				
			||||
 */ | 
				
			||||
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); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,45 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
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@'; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,52 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
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 <jonwage@gmail.com> | 
				
			||||
 */ | 
				
			||||
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); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,82 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
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; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
} | 
				
			||||
@ -0,0 +1,36 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
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(); | 
				
			||||
} | 
				
			||||
@ -0,0 +1,48 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
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; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,7 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
namespace Doctrine\DBAL\Migrations; | 
				
			||||
 | 
				
			||||
class SkipMigrationException extends MigrationException | 
				
			||||
{ | 
				
			||||
} | 
				
			||||
@ -0,0 +1,121 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
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 "<info>%s</info>"', $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); | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,181 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
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 <jonwage@gmail.com> | 
				
			||||
 */ | 
				
			||||
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('<question>' . str_repeat(' ', strlen($name)) . '</question>'); | 
				
			||||
        $output->writeln('<question>' . $name . '</question>'); | 
				
			||||
        $output->writeln('<question>' . str_repeat(' ', strlen($name)) . '</question>'); | 
				
			||||
        $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>' .  $question . '</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; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
} | 
				
			||||
@ -0,0 +1,167 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
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 <jonwage@gmail.com> | 
				
			||||
 */ | 
				
			||||
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(<<<EOT | 
				
			||||
The <info>%command.name%</info> command generates a migration by comparing your current database to your mapping information: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name%</info> | 
				
			||||
 | 
				
			||||
You can optionally specify a <comment>--editor-cmd</comment> option to open the generated file in your favorite editor: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% --editor-cmd=mate</info> | 
				
			||||
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 "<info>%s</info>" 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); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,102 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
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 <jonwage@gmail.com> | 
				
			||||
 */ | 
				
			||||
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(<<<EOT | 
				
			||||
The <info>%command.name%</info> command executes a single migration version up or down manually: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% YYYYMMDDHHMMSS</info> | 
				
			||||
 | 
				
			||||
If no <comment>--up</comment> or <comment>--down</comment> option is specified it defaults to up: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% YYYYMMDDHHMMSS --down</info> | 
				
			||||
 | 
				
			||||
You can also execute the migration as a <comment>--dry-run</comment>: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% YYYYMMDDHHMMSS --dry-run</info> | 
				
			||||
 | 
				
			||||
You can output the would be executed SQL statements to a file with <comment>--write-sql</comment>: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% YYYYMMDDHHMMSS --write-sql</info> | 
				
			||||
 | 
				
			||||
Or you can also execute the migration without a warning message which you need to interact with: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% --no-interaction</info> | 
				
			||||
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('<error>Migration cancelled!</error>'); | 
				
			||||
            } | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,135 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
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 <jonwage@gmail.com> | 
				
			||||
 */ | 
				
			||||
class GenerateCommand extends AbstractCommand | 
				
			||||
{ | 
				
			||||
 | 
				
			||||
    private static $_template = | 
				
			||||
            '<?php | 
				
			||||
 | 
				
			||||
namespace <namespace>; | 
				
			||||
 | 
				
			||||
use Doctrine\DBAL\Migrations\AbstractMigration; | 
				
			||||
use Doctrine\DBAL\Schema\Schema; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * Auto-generated Migration: Please modify to your needs! | 
				
			||||
 */ | 
				
			||||
class Version<version> extends AbstractMigration | 
				
			||||
{ | 
				
			||||
    /** | 
				
			||||
     * @param Schema $schema | 
				
			||||
     */ | 
				
			||||
    public function up(Schema $schema) | 
				
			||||
    { | 
				
			||||
        // this up() migration is auto-generated, please modify it to your needs | 
				
			||||
<up> | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param Schema $schema | 
				
			||||
     */ | 
				
			||||
    public function down(Schema $schema) | 
				
			||||
    { | 
				
			||||
        // this down() migration is auto-generated, please modify it to your needs | 
				
			||||
<down> | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
'; | 
				
			||||
 | 
				
			||||
    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(<<<EOT | 
				
			||||
The <info>%command.name%</info> command generates a blank migration class: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name%</info> | 
				
			||||
 | 
				
			||||
You can optionally specify a <comment>--editor-cmd</comment> option to open the generated file in your favorite editor: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% --editor-cmd=mate</info> | 
				
			||||
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 "<info>%s</info>"', $path)); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    protected function generateMigration(Configuration $configuration, InputInterface $input, $version, $up = null, $down = null) | 
				
			||||
    { | 
				
			||||
        $placeHolders = array( | 
				
			||||
            '<namespace>', | 
				
			||||
            '<version>', | 
				
			||||
            '<up>', | 
				
			||||
            '<down>' | 
				
			||||
        ); | 
				
			||||
        $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; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,48 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
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 <kris.wallsmith@gmail.com> | 
				
			||||
 */ | 
				
			||||
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()); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,192 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
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 <jonwage@gmail.com> | 
				
			||||
 */ | 
				
			||||
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(<<<EOT | 
				
			||||
The <info>%command.name%</info> command executes a migration to a specified version or the latest available version: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name%</info> | 
				
			||||
 | 
				
			||||
You can optionally manually specify the version you wish to migrate to: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% YYYYMMDDHHMMSS</info> | 
				
			||||
 | 
				
			||||
You can specify the version you wish to migrate to using an alias: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% prev</info> | 
				
			||||
 | 
				
			||||
You can also execute the migration as a <comment>--dry-run</comment>: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% YYYYMMDDHHMMSS --dry-run</info> | 
				
			||||
 | 
				
			||||
You can output the would be executed SQL statements to a file with <comment>--write-sql</comment>: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% YYYYMMDDHHMMSS --write-sql</info> | 
				
			||||
 | 
				
			||||
Or you can also execute the migration without a warning message which you need to interact with: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% --no-interaction</info> | 
				
			||||
 | 
				
			||||
You can also time all the different queries if you wanna know which one is taking so long: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% --query-time</info> | 
				
			||||
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( | 
				
			||||
                '<error>WARNING! You have %s previously executed migrations' | 
				
			||||
                . ' in the database that are not registered migrations.</error>', | 
				
			||||
                count($executedUnavailableMigrations) | 
				
			||||
            )); | 
				
			||||
 | 
				
			||||
            foreach ($executedUnavailableMigrations as $executedUnavailableMigration) { | 
				
			||||
                $output->writeln(sprintf( | 
				
			||||
                    '    <comment>>></comment> %s (<comment>%s</comment>)', | 
				
			||||
                    $configuration->getDateTime($executedUnavailableMigration), | 
				
			||||
                    $executedUnavailableMigration | 
				
			||||
                )); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            $question = 'Are you sure you wish to continue? (y/n)'; | 
				
			||||
            if (! $this->canExecute($question, $input, $output)) { | 
				
			||||
                $output->writeln('<error>Migration cancelled!</error>'); | 
				
			||||
 | 
				
			||||
                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('<error>Migration cancelled!</error>'); | 
				
			||||
 | 
				
			||||
                    return 1; | 
				
			||||
                } | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            $sql = $migration->migrate($version, $dryRun, $timeAllqueries); | 
				
			||||
 | 
				
			||||
            if (empty($sql)) { | 
				
			||||
                $output->writeln('<comment>No migrations to execute.</comment>'); | 
				
			||||
            } | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @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('<error>Already at first version.</error>'); | 
				
			||||
                return false; | 
				
			||||
            } | 
				
			||||
            if ($versionAlias == 'next') { | 
				
			||||
                $output->writeln('<error>Already at latest version.</error>'); | 
				
			||||
                return false; | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            $output->writeln(sprintf( | 
				
			||||
                '<error>Unknown version: %s</error>', | 
				
			||||
                $output->getFormatter()->escape($versionAlias) | 
				
			||||
            )); | 
				
			||||
            return false; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return $version; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,140 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
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 <jonwage@gmail.com> | 
				
			||||
 */ | 
				
			||||
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(<<<EOT | 
				
			||||
The <info>%command.name%</info> command outputs the status of a set of migrations: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name%</info> | 
				
			||||
 | 
				
			||||
You can output a list of all available migrations and their status with <comment>--show-versions</comment>: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% --show-versions</info> | 
				
			||||
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] = '<comment>0</comment>'; | 
				
			||||
            } else { | 
				
			||||
                $formattedVersions[$alias] = $configuration->getDateTime($version) . ' (<comment>' . $version . '</comment>)'; | 
				
			||||
            } | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $executedMigrations = $configuration->getMigratedVersions(); | 
				
			||||
        $availableMigrations = $configuration->getAvailableVersions(); | 
				
			||||
        $executedUnavailableMigrations = array_diff($executedMigrations, $availableMigrations); | 
				
			||||
        $numExecutedUnavailableMigrations = count($executedUnavailableMigrations); | 
				
			||||
        $newMigrations = count(array_diff($availableMigrations, $executedMigrations)); | 
				
			||||
 | 
				
			||||
        $output->writeln("\n <info>==</info> 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 ? '<error>'.$numExecutedUnavailableMigrations.'</error>' : 0, | 
				
			||||
            'Available Migrations'              => count($availableMigrations), | 
				
			||||
            'New Migrations'                    => $newMigrations > 0 ? '<question>' . $newMigrations . '</question>' : 0 | 
				
			||||
        ); | 
				
			||||
        foreach ($info as $name => $value) { | 
				
			||||
            $output->writeln('    <comment>>></comment> ' . $name . ': ' . str_repeat(' ', 50 - strlen($name)) . $value); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if ($input->getOption('show-versions')) { | 
				
			||||
            if ($migrations = $configuration->getMigrations()) { | 
				
			||||
                $executedUnavailableMigrations = $migrations; | 
				
			||||
                $output->writeln("\n <info>==</info> Available Migration Versions\n"); | 
				
			||||
 | 
				
			||||
                $this->showVersions($migrations, $configuration, $output); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if (!empty($executedUnavailableMigrations)) { | 
				
			||||
                $output->writeln("\n <info>==</info> 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 ? '<info>migrated</info>' : '<error>not migrated</error>'; | 
				
			||||
            $migrationDescription = ''; | 
				
			||||
            if ($version->getMigration()->getDescription()) { | 
				
			||||
                $migrationDescription = str_repeat(' ', 5) . $version->getMigration()->getDescription(); | 
				
			||||
            } | 
				
			||||
            $formattedVersion = $configuration->getDateTime($version->getVersion()); | 
				
			||||
 | 
				
			||||
            $output->writeln('    <comment>>></comment> ' . $formattedVersion . | 
				
			||||
                ' (<comment>' . $version->getVersion() . '</comment>)' . | 
				
			||||
                str_repeat(' ', 49 - strlen($formattedVersion) - strlen($version->getVersion()))  . | 
				
			||||
                $status  . $migrationDescription); | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,177 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
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 <jonwage@gmail.com> | 
				
			||||
 */ | 
				
			||||
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(<<<EOT | 
				
			||||
The <info>%command.name%</info> command allows you to manually add, delete or synchronize migration versions from the version table: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% YYYYMMDDHHMMSS --add</info> | 
				
			||||
 | 
				
			||||
If you want to delete a version you can use the <comment>--delete</comment> option: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% YYYYMMDDHHMMSS --delete</info> | 
				
			||||
 | 
				
			||||
If you want to synchronize by adding or deleting all migration versions available in the version table you can use the <comment>--all</comment> option: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% --add --all</info> | 
				
			||||
    <info>%command.full_name% --delete --all</info> | 
				
			||||
 | 
				
			||||
If you want to synchronize by adding or deleting some range of migration versions available in the version table you can use the <comment>--range-from/--range-to</comment> option: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% --add --range-from=YYYYMMDDHHMMSS --range-to=YYYYMMDDHHMMSS</info> | 
				
			||||
    <info>%command.full_name% --delete --range-from=YYYYMMDDHHMMSS --range-to=YYYYMMDDHHMMSS</info> | 
				
			||||
 | 
				
			||||
You can also execute this command without a warning message which you need to interact with: | 
				
			||||
 | 
				
			||||
    <info>%command.full_name% --no-interaction</info> | 
				
			||||
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('<error>Migration cancelled!</error>'); | 
				
			||||
            } | 
				
			||||
        } 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(); | 
				
			||||
            } | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,107 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
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; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,392 @@ | 
				
			||||
<?php | 
				
			||||
/* | 
				
			||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
				
			||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
				
			||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
				
			||||
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
				
			||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
				
			||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
				
			||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
				
			||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
				
			||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
				
			||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
				
			||||
 * | 
				
			||||
 * This software consists of voluntary contributions made by many individuals | 
				
			||||
 * and is licensed under the LGPL. For more information, see | 
				
			||||
 * <http://www.doctrine-project.org>. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
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 <jonwage@gmail.com> | 
				
			||||
 */ | 
				
			||||
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('  <info>++</info> migrating <comment>%s</comment>', $this->version) . "\n"); | 
				
			||||
            } else { | 
				
			||||
                $this->outputWriter->write("\n" . sprintf('  <info>--</info> reverting <comment>%s</comment>', $this->version) . "\n"); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            $this->state = self::STATE_EXEC; | 
				
			||||
 | 
				
			||||
            $toSchema = clone $fromSchema; | 
				
			||||
            $this->migration->$direction($toSchema); | 
				
			||||
            $this->addSql($fromSchema->getMigrateToSql($toSchema, $this->platform)); | 
				
			||||
 | 
				
			||||
            if (! $dryRun) { | 
				
			||||
                if (!empty($this->sql)) { | 
				
			||||
                    foreach ($this->sql as $key => $query) { | 
				
			||||
                        $queryStart = microtime(true); | 
				
			||||
 | 
				
			||||
                        if ( ! isset($this->params[$key])) { | 
				
			||||
                            $this->outputWriter->write('     <comment>-></comment> ' . $query); | 
				
			||||
                            $this->connection->exec($query); | 
				
			||||
                        } else { | 
				
			||||
                            $this->outputWriter->write(sprintf('    <comment>-</comment> %s (with parameters)', $query)); | 
				
			||||
                            $this->connection->executeQuery($query, $this->params[$key], $this->types[$key]); | 
				
			||||
                        } | 
				
			||||
 | 
				
			||||
                        $this->outputQueryTime($queryStart, $timeAllQueries); | 
				
			||||
                    } | 
				
			||||
                } else { | 
				
			||||
                    $this->outputWriter->write(sprintf( | 
				
			||||
                        '<error>Migration %s was executed but did not result in any SQL statements.</error>', | 
				
			||||
                        $this->version | 
				
			||||
                    )); | 
				
			||||
                } | 
				
			||||
 | 
				
			||||
                if ($direction === 'up') { | 
				
			||||
                    $this->markMigrated(); | 
				
			||||
                } else { | 
				
			||||
                    $this->markNotMigrated(); | 
				
			||||
                } | 
				
			||||
 | 
				
			||||
            } else { | 
				
			||||
                foreach ($this->sql as $query) { | 
				
			||||
                    $this->outputWriter->write('     <comment>-></comment> ' . $query); | 
				
			||||
                } | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            $this->state = self::STATE_POST; | 
				
			||||
            $this->migration->{'post' . ucfirst($direction)}($toSchema); | 
				
			||||
 | 
				
			||||
            $migrationEnd = microtime(true); | 
				
			||||
            $this->time = round($migrationEnd - $migrationStart, 2); | 
				
			||||
            if ($direction === 'up') { | 
				
			||||
                $this->outputWriter->write(sprintf("\n  <info>++</info> migrated (%ss)", $this->time)); | 
				
			||||
            } else { | 
				
			||||
                $this->outputWriter->write(sprintf("\n  <info>--</info> reverted (%ss)", $this->time)); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if ($transaction) { | 
				
			||||
                //commit only if running in transactional mode | 
				
			||||
                $this->connection->commit(); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            $this->state = self::STATE_NONE; | 
				
			||||
 | 
				
			||||
            return $this->sql; | 
				
			||||
        } catch (SkipMigrationException $e) { | 
				
			||||
            if ($transaction) { | 
				
			||||
                //only rollback transaction if in transactional mode | 
				
			||||
                $this->connection->rollback(); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if ($dryRun === false) { | 
				
			||||
                // now mark it as migrated | 
				
			||||
                if ($direction === 'up') { | 
				
			||||
                    $this->markMigrated(); | 
				
			||||
                } else { | 
				
			||||
                    $this->markNotMigrated(); | 
				
			||||
                } | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            $this->outputWriter->write(sprintf("\n  <info>SS</info> skipped (Reason: %s)",  $e->getMessage())); | 
				
			||||
 | 
				
			||||
            $this->state = self::STATE_NONE; | 
				
			||||
 | 
				
			||||
            return array(); | 
				
			||||
        } catch (\Exception $e) { | 
				
			||||
 | 
				
			||||
            $this->outputWriter->write(sprintf( | 
				
			||||
                '<error>Migration %s failed during %s. Error %s</error>', | 
				
			||||
                $this->version, $this->getExecutionState(), $e->getMessage() | 
				
			||||
            )); | 
				
			||||
 | 
				
			||||
            if ($transaction) { | 
				
			||||
                //only rollback transaction if in transactional mode | 
				
			||||
                $this->connection->rollback(); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            $this->state = self::STATE_NONE; | 
				
			||||
            throw $e; | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    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("  <info>%ss</info>", $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; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,37 @@ | 
				
			||||
<?xml version="1.0" encoding="UTF-8"?> | 
				
			||||
 | 
				
			||||
<phpunit colors="true" bootstrap="tests/bootstrap.php"> | 
				
			||||
    <testsuites> | 
				
			||||
        <testsuite name="Doctrine2 Database Migrations Test Suite"> | 
				
			||||
            <directory>./tests/Doctrine/</directory> | 
				
			||||
        </testsuite> | 
				
			||||
    </testsuites> | 
				
			||||
 | 
				
			||||
    <filter> | 
				
			||||
        <whitelist> | 
				
			||||
            <directory>./lib/</directory> | 
				
			||||
        </whitelist> | 
				
			||||
    </filter> | 
				
			||||
 | 
				
			||||
    <listeners> | 
				
			||||
        <listener class="JohnKary\PHPUnit\Listener\SpeedTrapListener" > | 
				
			||||
            <arguments> | 
				
			||||
                <array> | 
				
			||||
                    <element key="slowThreshold"> | 
				
			||||
                        <integer>200</integer> | 
				
			||||
                    </element> | 
				
			||||
                    <element key="reportLength"> | 
				
			||||
                        <integer>10</integer> | 
				
			||||
                    </element> | 
				
			||||
                </array> | 
				
			||||
            </arguments> | 
				
			||||
        </listener> | 
				
			||||
    </listeners> | 
				
			||||
 | 
				
			||||
    <logging> | 
				
			||||
        <log type="coverage-html" target="build/coverage" title="doctrine migrations" | 
				
			||||
             charset="UTF-8" yui="true" highlight="true" lowUpperBound="5" | 
				
			||||
             highLowerBound="70" /> | 
				
			||||
        <log type="coverage-clover" target="build/logs/clover.xml"/> | 
				
			||||
    </logging> | 
				
			||||
</phpunit> | 
				
			||||
					Loading…
					
					
				
		Reference in new issue