Skip to content

Commit

Permalink
Merge branch '3.4.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
Paweł Brzozowski committed Aug 1, 2019
2 parents 192d760 + ebb5759 commit 51d59f3
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 29 deletions.
10 changes: 8 additions & 2 deletions src/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
use function count;
use function get_class;
use function in_array;
use function is_array;

/**
* Class Generator
Expand Down Expand Up @@ -73,7 +74,8 @@ class Generator extends Component
public $templateFileUpdate;

/**
* @var string Migration namespace.
* @var string|array Migration namespace.
* Since 3.5.0 this can be array of namespaces.
*/
public $namespace;

Expand Down Expand Up @@ -111,6 +113,10 @@ public function init(): void
if (!($this->db instanceof Connection)) {
throw new InvalidConfigException("Parameter 'db' must be an instance of yii\\db\\Connection!");
}

if ($this->namespace !== null && !is_array($this->namespace)) {
$this->namespace = [$this->namespace];
}
}

protected $_tableSchema;
Expand Down Expand Up @@ -306,7 +312,7 @@ public function getTable(): TableStructure
*/
public function getNormalizedNamespace(): ?string
{
return !empty($this->namespace) ? FileHelper::normalizePath($this->namespace, '\\') : null;
return !empty($this->namespace) ? FileHelper::normalizePath(reset($this->namespace), '\\') : null;
}

/**
Expand Down
24 changes: 20 additions & 4 deletions src/Updater.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ class Updater extends Generator
public $migrationTable = '{{%migration}}';

/**
* @var string Directory storing the migration classes. This can be either a path alias or a directory.
* @var string|array Directory storing the migration classes. This can be either a path alias or a directory.
* Since 3.5.0 this can be array of directories.
*/
public $migrationPath = '@app/migrations';

Expand All @@ -76,6 +77,14 @@ public function init(): void
{
parent::init();

if (empty($this->migrationPath)) {
throw new InvalidConfigException('You must provide "migrationPath" value.');
}

if (!is_array($this->migrationPath)) {
$this->migrationPath = [$this->migrationPath];
}

$this->_currentTable = $this->tableName;

foreach ($this->skipMigrations as $index => $migration) {
Expand Down Expand Up @@ -190,10 +199,17 @@ protected function gatherChanges(array $changes): bool
protected function extract(string $migration): array
{
if (strpos($migration, '\\') === false) {
$file = Yii::getAlias($this->migrationPath . DIRECTORY_SEPARATOR . $migration . '.php');
$fileFound = false;
foreach ($this->migrationPath as $path) {
$file = Yii::getAlias($path . DIRECTORY_SEPARATOR . $migration . '.php');
if (file_exists($file)) {
$fileFound = true;
break;
}
}

if (!file_exists($file)) {
throw new ErrorException("File '{$file}' can not be found! Check migration history table.");
if (!$fileFound) {
throw new ErrorException("File '{$migration}.php' can not be found! Check migration history table.");
}

require_once $file;
Expand Down
63 changes: 44 additions & 19 deletions src/controllers/MigrationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
use function gmdate;
use function implode;
use function in_array;
use function is_array;
use function is_dir;
use function strlen;
use function strpos;
Expand All @@ -39,7 +40,7 @@
* Generates migration file based on the existing database table and previous migrations.
*
* @author Paweł Bizley Brzozowski
* @version 3.4.0
* @version 3.5.0
* @license Apache 2.0
* https://github.com/bizley/yii2-migration
*/
Expand All @@ -48,26 +49,31 @@ class MigrationController extends Controller
/**
* @var string
*/
protected $version = '3.4.0';
protected $version = '3.5.0';

/**
* @var string Default command action.
*/
public $defaultAction = 'list';

/**
* @var string Directory storing the migration classes. This can be either a path alias or a directory.
* @var string|array Directory storing the migration classes. This can be either a path alias or a directory.
* Since 3.5.0 this can be array of directories. In this case the first element will be used for generator and
* only first one will be created if it doesn't exist yet.
* Alias -p
*/
public $migrationPath = '@app/migrations';

/**
* @var string Full migration namespace. If given it's used instead of $migrationPath. Note that backslash (\)
* @var string|array Full migration namespace. If given it's used instead of $migrationPath. Note that backslash (\)
* symbol is usually considered a special character in the shell, so you need to escape it properly to avoid shell
* errors or incorrect behavior.
* Migration namespace should be resolvable as a path alias if prefixed with @, e.g. if you specify the namespace
* 'app\migrations', the code Yii::getAlias('@app/migrations') should be able to return the file path to
* the directory this namespace refers to.
* When this property is given $migrationPath is ignored.
* Since 3.5.0 this can be array of namespaces. In this case the first element will be used for generator and
* only first one will be checked for corresponding directory to exist and be created if needed.
* Alias -n
* @since 1.1
*/
Expand Down Expand Up @@ -290,18 +296,34 @@ public function beforeAction($action): bool // BC declaration
return false;
}

if (!$this->showOnly && in_array($action->id, ['create', 'create-all', 'update', 'update-all'], true)) {
if ($this->migrationPath !== null) {
$this->migrationPath = $this->preparePathDirectory($this->migrationPath);
}

if (in_array($action->id, ['create', 'create-all', 'update', 'update-all'], true)) {
if ($this->migrationNamespace !== null) {
$this->migrationNamespace = FileHelper::normalizePath($this->migrationNamespace, '\\');
$this->workingPath = $this->preparePathDirectory(
FileHelper::normalizePath('@' . $this->migrationNamespace, '/')
);
if (!is_array($this->migrationNamespace)) {
$this->migrationNamespace = [$this->migrationNamespace];
}
foreach ($this->migrationNamespace as &$namespace) {
$namespace = FileHelper::normalizePath($this->migrationNamespace, '\\');

if ($this->workingPath === null && !$this->showOnly) {
$this->workingPath = $this->preparePathDirectory(
'@' . FileHelper::normalizePath($namespace, '/')
);
}
}
} elseif ($this->migrationPath !== null) {
if (!is_array($this->migrationPath)) {
$this->migrationPath = [$this->migrationPath];
}
foreach ($this->migrationPath as $path) {
if ($this->workingPath === null && !$this->showOnly) {
$this->workingPath = $this->preparePathDirectory($path);
break;
}
}
} else {
$this->workingPath = $this->migrationPath;
throw new InvalidConfigException(
'You must provide either "migrationPath" or "migrationNamespace" for this action.'
);
}
}

Expand Down Expand Up @@ -473,7 +495,7 @@ public function actionCreate(string $table): int

$postponedForeignKeys = [];

$counterSize = strlen((string)$countTables) + 1;
$counterSize = strlen((string) $countTables) + 1;
$migrationsGenerated = 0;
foreach ($tables as $name) {
$this->stdout(" > Generating create migration for table '{$name}' ...", Console::FG_YELLOW);
Expand All @@ -488,7 +510,7 @@ public function actionCreate(string $table): int
} else {
$className = sprintf('m%s_create_table_%s', gmdate('ymd_His'), $name);
}
$file = Yii::getAlias($this->workingPath . DIRECTORY_SEPARATOR . $className . '.php');
$file = $this->workingPath . DIRECTORY_SEPARATOR . $className . '.php';

$generator = new Generator([
'db' => $this->db,
Expand Down Expand Up @@ -534,7 +556,10 @@ public function actionCreate(string $table): int

$this->stdout("\n");

$postponedForeignKeys = array_merge($postponedForeignKeys, $generator->getSuppressedForeignKeys());
$supressedKeys = $generator->getSuppressedForeignKeys();
foreach ($supressedKeys as $supressedKey) {
$postponedForeignKeys[] = $supressedKey;
}
}

if ($postponedForeignKeys) {
Expand All @@ -545,7 +570,7 @@ public function actionCreate(string $table): int
gmdate('ymd_His'),
++$migrationsGenerated
);
$file = Yii::getAlias($this->workingPath . DIRECTORY_SEPARATOR . $className . '.php');
$file = $this->workingPath . DIRECTORY_SEPARATOR . $className . '.php';

if ($this->generateFile($file, $this->view->renderFile(Yii::getAlias($this->templateFileForeignKey), [
'fks' => $postponedForeignKeys,
Expand Down Expand Up @@ -625,7 +650,7 @@ public function actionUpdate(string $table): int
$this->stdout(" > Generating update migration for table '{$name}' ...", Console::FG_YELLOW);

$className = 'm' . gmdate('ymd_His') . '_update_table_' . $name;
$file = Yii::getAlias($this->workingPath . DIRECTORY_SEPARATOR . $className . '.php');
$file = $this->workingPath . DIRECTORY_SEPARATOR . $className . '.php';

$updater = new Updater([
'db' => $this->db,
Expand Down
6 changes: 3 additions & 3 deletions tests/cases/DbTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ public static function setUpBeforeClass(): void
'controllerMap' => [
'migration' => [
'class' => MigrationController::class,
'migrationPath' => null,
'migrationNamespace' => null,
],
'migrate' => [
'class' => EchoMigrateController::class,
Expand Down Expand Up @@ -97,7 +95,9 @@ protected static function runSilentMigration(string $route, array $params = []):
*/
public static function tearDownAfterClass(): void
{
static::runSilentMigration('migrate/down', ['all']);
if (static::$runMigrations) {
static::runSilentMigration('migrate/down', ['all']);
}

if (static::$db) {
static::$db->close();
Expand Down
17 changes: 16 additions & 1 deletion tests/cases/MigrationControllerTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ public function testCreateInProperOrder(): void
$output = str_replace(["\r", "\n"], '', $mock->flushStdOutBuffer());

$file = Yii::getAlias(
$mock->migrationPath
reset($mock->migrationPath)
. DIRECTORY_SEPARATOR
. 'm' . gmdate('ymd_His')
. '_01_create_table_test_pk.php'
Expand Down Expand Up @@ -233,4 +233,19 @@ public function testCreatePostponedFK(): void
$this->assertContains('> Generating create migration for foreign keys ...DONE!', $output);
$this->assertContains(' Generated 3 file(s).', $output);
}

/**
* @throws Exception
* @throws InvalidRouteException
*/
public function testInvalidConfig(): void
{
$controller = new MockMigrationController('migration', Yii::$app);
$controller->migrationPath = null;

$this->expectExceptionMessage(
'You must provide either "migrationPath" or "migrationNamespace" for this action.'
);
$controller->runAction('create', ['table']);
}
}

0 comments on commit 51d59f3

Please sign in to comment.