Skip to content

Commit

Permalink
Merge pull request #3 from byjg/2.0.1
Browse files Browse the repository at this point in the history
Fix problem with versions greater than 10.
  • Loading branch information
byjg authored Nov 10, 2017
2 parents a21c419 + 6d3de54 commit 38429be
Show file tree
Hide file tree
Showing 36 changed files with 209 additions and 43 deletions.
79 changes: 67 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,23 +94,70 @@ Migration library creates the 'migrate' script. It has the follow syntax:
Usage:
command [options] [arguments]
Options:
-h, --help Display this help message
-q, --quiet Do not output any message
-V, --version Display this application version
--ansi Force ANSI output
--no-ansi Disable ANSI output
-n, --no-interaction Do not ask any interactive question
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
Available commands:
create Create the directory structure FROM a pre-existing database
down Migrate down the database version.
help Displays help for a command
install Install or upgrade the migrate version in a existing database
down Migrate down the database version.
reset Create a fresh new database
up Migrate Up the database version
list Lists commands
reset Create a fresh new database
up Migrate Up the database version
update Migrate Up or Down the database version based on the current database version and the migration scripts available
version Get the current database version
```

## Commands

### migrate create

Create a empty directory structure with base.sql and migrations/up and migrations/down for migrations. This is
useful for create from scratch a migration scheme.

Ex.

```bash
migrate create /path/to/sql
```

### migrate install

If you already have a database but it is not controlled by the migration system you can use this method for
install the required tables for migration.

```bash
migrate install mysql://server/database
```

### migrate update

Arguments:
connection The connection string. Ex. mysql://root:password@server/database [default: false]
Will apply all necessary migrations to keep your database updated.

Example:
migrate reset mysql://root:password@server/database
migrate up mysql://root:password@server/database
migrate down mysql://root:password@server/database
migrate up --up-to=10 --path=/somepath mysql://root:password@server/database
migrate down --up-to=3 --path=/somepath mysql://root:password@server/database
```bash
migrate update mysql://server/database
```

Update command can choose if up or down your database depending on your current database version.

```bash
migrate update --up-to=34
```

### migrate reset

Creates/replace a database with the "base.sql" and apply ALL migrations

```bash
migrate reset
migrate reset --up-to=5
```

## Supported databases:
Expand All @@ -120,7 +167,15 @@ Example:
* Postgres
* SqlServer

## Installing Globally
## Installing

### At your project level

```
composer require 'byjg/migration=2.0.*'
```

### Globally

```bash
composer global require 'byjg/migration=2.0.*'
Expand Down
1 change: 1 addition & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ and open the template in the editor.
<testsuite name="Test Suite">
<!--<directory>./tests/</directory>-->
<file>./tests/SqliteDatabaseTest.php</file>
<file>./tests/MigrationTest.php</file>
</testsuite>
</testsuites>

Expand Down
3 changes: 1 addition & 2 deletions scripts/migrate
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ if (!file_exists($autoload)) {
}
require_once($autoload);


use Symfony\Component\Console\Application;

$application = new Application('Migrate Script by JG', '2.0.0');
$application = new Application('Migrate Script by JG', '2.0.1');
$application->add(new \ByJG\DbMigration\Console\ResetCommand());
$application->add(new \ByJG\DbMigration\Console\UpCommand());
$application->add(new \ByJG\DbMigration\Console\DownCommand());
Expand Down
8 changes: 8 additions & 0 deletions src/Exception/InvalidMigrationFile.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace ByJG\DbMigration\Exception;

class InvalidMigrationFile extends \Exception
{

}
63 changes: 34 additions & 29 deletions src/Migration.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use ByJG\AnyDataset\Factory;
use ByJG\DbMigration\Database\DatabaseInterface;
use ByJG\DbMigration\Exception\DatabaseIsIncompleteException;
use ByJG\DbMigration\Exception\InvalidMigrationFile;
use ByJG\Util\Uri;

class Migration
Expand All @@ -18,7 +19,7 @@ class Migration
/**
* @var string
*/
protected $_folder;
protected $folder;

/**
* @var DbDriverInterface
Expand All @@ -28,26 +29,27 @@ class Migration
/**
* @var DatabaseInterface
*/
protected $_dbCommand;
protected $dbCommand;

/**
* @var Callable
*/
protected $_callableProgress;
protected $callableProgress;

/**
* Migration constructor.
*
* @param Uri $uri
* @param string $_folder
* @param string $folder
* @throws \ByJG\DbMigration\Exception\InvalidMigrationFile
*/
public function __construct(Uri $uri, $_folder)
public function __construct(Uri $uri, $folder)
{
$this->uri = $uri;
$this->_folder = $_folder;
$this->folder = $folder;

if (!file_exists($this->_folder . '/base.sql')) {
throw new \InvalidArgumentException("Migration script '{$this->_folder}/base.sql' not found");
if (!file_exists($this->folder . '/base.sql')) {
throw new InvalidMigrationFile("Migration script '{$this->folder}/base.sql' not found");
}
}

Expand All @@ -67,11 +69,11 @@ public function getDbDriver()
*/
public function getDbCommand()
{
if (is_null($this->_dbCommand)) {
if (is_null($this->dbCommand)) {
$class = $this->getDatabaseClassName();
$this->_dbCommand = new $class($this->getDbDriver());
$this->dbCommand = new $class($this->getDbDriver());
}
return $this->_dbCommand;
return $this->dbCommand;
}

protected function getDatabaseClassName()
Expand All @@ -86,7 +88,7 @@ protected function getDatabaseClassName()
*/
public function getBaseSql()
{
return $this->_folder . "/base.sql";
return $this->folder . "/base.sql";
}

/**
Expand All @@ -95,6 +97,7 @@ public function getBaseSql()
* @param $version
* @param $increment
* @return string
* @throws \ByJG\DbMigration\Exception\InvalidMigrationFile
*/
public function getMigrationSql($version, $increment)
{
Expand All @@ -106,19 +109,18 @@ public function getMigrationSql($version, $increment)
}
$version = intval($version);

$filePattern = $this->_folder
$filePattern = $this->folder
. "/migrations"
. "/" . ($increment < 0 ? "down" : "up")
. "/*%s.sql";
. "/*.sql";

$result = array_merge(
glob(sprintf($filePattern, "$version")),
glob(sprintf($filePattern, "$version-dev"))
);
$result = array_filter(glob($filePattern), function ($file) use ($version) {
return preg_match("/^0*$version(-dev)?\.sql$/", basename($file));
});

// Valid values are 0 or 1
if (count($result) > 1) {
throw new \InvalidArgumentException("You have two files with the same version $version number");
throw new InvalidMigrationFile("You have two files with the same version number '$version'");
}

foreach ($result as $file) {
Expand All @@ -130,7 +132,7 @@ public function getMigrationSql($version, $increment)
}

/**
* Create the database it it does not exists. Does not use this methos in a production environment;
* Create the database it it does not exists. Does not use this methos in a production environment
*/
public function prepareEnvironment()
{
Expand All @@ -140,14 +142,14 @@ public function prepareEnvironment()

/**
* Restore the database using the "base.sql" script and run all migration scripts
* Note: the database must exists. If dont exist run the method prepareEnvironment.
* Note: the database must exists. If dont exist run the method prepareEnvironment
*
* @param int $upVersion
*/
public function reset($upVersion = null)
{
if ($this->_callableProgress) {
call_user_func_array($this->_callableProgress, ['reset', 0]);
if ($this->callableProgress) {
call_user_func_array($this->callableProgress, ['reset', 0]);
}
$this->getDbCommand()->dropDatabase();
$this->getDbCommand()->createDatabase();
Expand Down Expand Up @@ -218,8 +220,8 @@ protected function migrate($upVersion, $increment, $force)
while ($this->canContinue($currentVersion, $upVersion, $increment)
&& file_exists($file = $this->getMigrationSql($currentVersion, $increment))
) {
if ($this->_callableProgress) {
call_user_func_array($this->_callableProgress, ['migrate', $currentVersion]);
if ($this->callableProgress) {
call_user_func_array($this->callableProgress, ['migrate', $currentVersion]);
}

$this->getDbCommand()->setVersion($currentVersion, 'partial ' . ($increment>0 ? 'up' : 'down'));
Expand Down Expand Up @@ -267,9 +269,12 @@ public function down($upVersion, $force = false)
{
$this->migrate($upVersion, -1, $force);
}

public function addCallbackProgress(Callable $callable)

/**
* @param callable $callable
*/
public function addCallbackProgress(callable $callable)
{
$this->_callableProgress = $callable;
$this->callableProgress = $callable;
}
}
98 changes: 98 additions & 0 deletions tests/MigrationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php
namespace Test;

use ByJG\AnyDataset\Store\PdoMysql;
use ByJG\DbMigration\Migration;
use ByJG\Util\Uri;

// backward compatibility
if (!class_exists('\PHPUnit\Framework\TestCase')) {
class_alias('\PHPUnit_Framework_TestCase', '\PHPUnit\Framework\TestCase');
}

class MigrationTest extends \PHPUnit\Framework\TestCase
{
/**
* @var Migration
*/
protected $object;

public function setUp()
{
$this->object = new Migration(new Uri('mysql://localhost'), __DIR__ . '/dirstructure');
}

public function tearDown()
{
$this->object = null;
}

public function testGetBaseSql()
{
$base = $this->object->getBaseSql();
$this->assertEquals(__DIR__ . '/dirstructure/base.sql', $base);
}

/**
* @expectedException \ByJG\DbMigration\Exception\InvalidMigrationFile
*/
public function testGetBaseSqlNotFound()
{
$this->object = new Migration(new Uri('mysql://localhost'), __DIR__ . '/invalid');
$this->object->getBaseSql();
}

public function testGetMigrationSql1()
{
$version = $this->object->getMigrationSql(1, 1);
$this->assertEquals(__DIR__ . '/dirstructure/migrations/up/00001.sql', $version);
}

public function testGetMigrationSql2()
{
$version = $this->object->getMigrationSql(2, 1);
$this->assertEquals(__DIR__ . '/dirstructure/migrations/up/00002.sql', $version);
}

public function testGetMigrationSql3()
{
$version = $this->object->getMigrationSql(12, 1);
$this->assertEquals(__DIR__ . '/dirstructure/migrations/up/00012-dev.sql', $version);
}

/**
* @expectedException \ByJG\DbMigration\Exception\InvalidMigrationFile
* @expectedExceptionMessage version number '13'
*/
public function testGetMigrationSql4()
{
$this->object->getMigrationSql(13, 1);
}

public function testGetMigrationSqlDown1()
{
$version = $this->object->getMigrationSql(1, -1);
$this->assertEquals(__DIR__ . '/dirstructure/migrations/down/00001.sql', $version);
}

public function testGetMigrationSqlDown2()
{
$version = $this->object->getMigrationSql(2, -1);
$this->assertEquals(__DIR__ . '/dirstructure/migrations/down/00002.sql', $version);
}

public function testGetMigrationSqlDown3()
{
$version = $this->object->getMigrationSql(12, -1);
$this->assertEquals(__DIR__ . '/dirstructure/migrations/down/00012-dev.sql', $version);
}

/**
* @expectedException \ByJG\DbMigration\Exception\InvalidMigrationFile
* @expectedExceptionMessage version number '13'
*/
public function testGetMigrationSqlDown4()
{
$this->object->getMigrationSql(13, -1);
}
}
Empty file added tests/dirstructure/base.sql
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.

0 comments on commit 38429be

Please sign in to comment.