Skip to content

Commit

Permalink
Added the possibility to create migrations with files.
Browse files Browse the repository at this point in the history
  • Loading branch information
Christopher Lorke committed Dec 3, 2018
1 parent 9f14141 commit 0239698
Show file tree
Hide file tree
Showing 10 changed files with 381 additions and 4 deletions.
41 changes: 37 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,54 @@ Elasticsearch migration for laravel.
### Application
The package is registered through the package discovery of laravel and Composer.
>https://laravel.com/docs/5.6/packages
>https://laravel.com/docs/5.7/packages
### Events
Once installed you can now publish your config file and set your correct configuration for using the package.
```php
php artisan vendor:publish --provider="Triadev\EsMigration\Provider\ElasticsearchMigrationServiceProvider" --tag="config"
```

This will create a file ```config/triadev-elasticsearch-migration.php```.

### Configuration
| Key | Env | Value | Description | Example | Default |
|:-------------:|:-------------:|:-------------:|:-----:|:-----:|:-----:|
| filePath | --- | ARRAY | path for file migrations | [KEY => STRING, ...] | null |

## Migration via file
The migration file path must be defined in package config.

### Configuration
| Key | Value | Description | Default |
|:-------------:|:-------------:|:-------------:|:-----:|
| type | STRING | migration type | --- |
| params | ARRAY | configuration | --- |
| priority | INTEGER | order of migration steps | 1 |
| stopOnFailure | BOOL | stop on failure at migration | true |

### CLI-Command
The cli-command imports the migration files to database.
>php artisan triadev:es-migration:import-file-migrations {migration} {filePath}
#### migration
Name of the migration directory.

#### filePath
The already defined file path key in package config.

## Events
[Documentation: Laravel Events](https://laravel.com/docs/5.7/events)

Namespace: Triadev\EsMigration\Business\Events

#### Migration
### Migration
| Event | Status |
|:-------------:|:-----:|
| MigrationRunning | Migration is running |
| MigrationError | Migration is failed |
| MigrationDone | Migration is done |

#### Migration - Step
### Migration - Step
| Event | Status |
|:-------------:|:-----:|
| MigrationStepRunning | Migration step is running |
Expand Down
28 changes: 28 additions & 0 deletions examples/CreateIndex/create_index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

return [
'type' => \Triadev\EsMigration\Business\Mapper\MigrationTypes::MIGRATION_TYPE_CREATE_INDEX,
'params' => [
'index' => 'index',
'body' => [
'mappings' => [
'phpunit' => [
'dynamic' => 'strict',
'properties' => [
'title' => [
'type' => 'text'
],
'count' => [
'type' => 'integer'
]
]
]
],
'settings' => [
'refresh_interval' => "30s"
]
]
],
'priority' => 1,
'stopOnFailure' => true
];
5 changes: 5 additions & 0 deletions src/Config/config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

return [
'filePath' => []
];
145 changes: 145 additions & 0 deletions src/Console/Commands/ImportFileMigrations.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?php
namespace Triadev\EsMigration\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Triadev\EsMigration\Business\Mapper\MigrationTypes;
use Triadev\EsMigration\Contract\ElasticsearchMigrationContract;

class ImportFileMigrations extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'triadev:es-migration:import-file-migrations {migration} {filePath}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Import file migrations.';

/** @var ElasticsearchMigrationContract */
private $elasticsearchMigrationService;

/**
* ImportFileMigrations constructor.
* @param ElasticsearchMigrationContract $elasticsearchMigrationService
*/
public function __construct(ElasticsearchMigrationContract $elasticsearchMigrationService)
{
parent::__construct();

$this->elasticsearchMigrationService = $elasticsearchMigrationService;
}

/**
* Execute the console command.
*
* @throws \Exception
*/
public function handle()
{
$migration = (string)$this->argument('migration');
$filePathSelector = (string)$this->argument('filePath');

$filePath = config('triadev-elasticsearch-migration.filePath');
if (!array_has($filePath, $filePathSelector)) {
throw new \Exception("No migration file path was defined.");
}

$migrationSteps = $this->getMigrationSteps($migration, $filePath[$filePathSelector]);
if (!empty($migrationSteps)) {
$this->elasticsearchMigrationService->createMigration($migration);

$this->importMigrationSteps(
$migration,
$migrationSteps
);
}
}

/**
* @param string $migration
* @param string $filePath
* @return array
* @throws \Exception
*/
private function getMigrationSteps(string $migration, string $filePath) : array
{
$filePath = $filePath . DIRECTORY_SEPARATOR . $migration;
if (!is_dir($filePath)) {
throw new \Exception("The migration directory does not exist.");
}

$files = [];

foreach (scandir($filePath) as $key => $value) {
if (!in_array($value, ['.', '..'])) {
$files[] = $filePath . DIRECTORY_SEPARATOR . $value;
}
}

return $files;
}

/**
* @param string $migration
* @param array $migrationSteps
*/
private function importMigrationSteps(string $migration, array $migrationSteps)
{
try {
foreach ($this->getValidMigrationSteps($migrationSteps) as $validMigrationStep) {
$this->elasticsearchMigrationService->addMigrationStep(
$migration,
array_get($validMigrationStep, 'type'),
array_get($validMigrationStep, 'params'),
array_get($validMigrationStep, 'priority', 1),
array_get($validMigrationStep, 'stopOnFailure', true)
);
}
} catch (\Exception $e) {
Log::error("The migration steps could not be imported.");
}
}

/**
* @param array $migrationSteps
* @return array
* @throws \Exception
*/
private function getValidMigrationSteps(array $migrationSteps) : array
{
$migrationTypes = new MigrationTypes();

$validMigrationSteps = [];

foreach ($migrationSteps as $migrationStep) {
$step = require $migrationStep;

$validator = Validator::make($step, [
'type' => 'required|string',
'params' => 'required|array',
'priority' => 'integer',
'stopOnFailure' => 'boolean'
]);

if ($validator->fails()) {
throw new \Exception("The migration step is invalid.");
}

if (!$migrationTypes->isMigrationTypeValid(array_get($step, 'type'))) {
throw new \Exception("The migration step type is invalid.");
}

$validMigrationSteps[] = $step;
}

return $validMigrationSteps;
}
}
13 changes: 13 additions & 0 deletions src/Provider/ElasticsearchMigrationServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
namespace Triadev\EsMigration\Provider;

use Illuminate\Support\ServiceProvider;
use Triadev\EsMigration\Console\Commands\ImportFileMigrations;
use Triadev\EsMigration\Contract\ElasticsearchMigrationContract;
use Triadev\EsMigration\ElasticsearchMigration;

Expand All @@ -14,7 +15,19 @@ class ElasticsearchMigrationServiceProvider extends ServiceProvider
*/
public function boot()
{
$source = realpath(__DIR__ . '/../Config/config.php');

$this->publishes([
__DIR__ . '/../Config/config.php' => config_path('triadev-elasticsearch-migration.php'),
], 'config');

$this->mergeConfigFrom($source, 'triadev-elasticsearch-migration');

$this->loadMigrationsFrom(__DIR__ . '/../Database/Migrations');

$this->commands([
ImportFileMigrations::class
]);

$this->app->bind(
\Triadev\EsMigration\Contract\Repository\ElasticsearchMigrationContract::class,
Expand Down
81 changes: 81 additions & 0 deletions tests/integration/Console/Commands/ImportFileMigrationsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php
namespace Tests\Integration\Console\Commands;

use Tests\TestCase;
use Triadev\EsMigration\Contract\Repository\ElasticsearchMigrationContract;
use Triadev\EsMigration\Contract\Repository\ElasticsearchMigrationStepContract;

class ImportFileMigrationsTest extends TestCase
{
/** @var ElasticsearchMigrationContract */
private $repositoryMigrations;

/** @var ElasticsearchMigrationStepContract */
private $repositoryMigrationSteps;

/**
* Setup the test environment.
*/
public function setUp()
{
parent::setUp();

$this->repositoryMigrations = app(ElasticsearchMigrationContract::class);
$this->repositoryMigrationSteps = app(ElasticsearchMigrationStepContract::class);
}

/**
* @test
* @expectedException \Exception
* @expectedExceptionMessage No migration file path was defined.
*/
public function it_throws_an_exception_if_no_migration_file_path_was_defined()
{
$this->artisan('triadev:es-migration:import-file-migrations', [
'migration' => 'phpunit',
'filePath' => 'phpunit'
]);
}

/**
* @test
* @expectedException \Exception
* @expectedExceptionMessage The migration directory does not exist.
*/
public function it_throws_an_exception_if_migration_directory_not_exist()
{
config()->set('triadev-elasticsearch-migration.filePath', [
'phpunit' => __DIR__ . '/Migrations'
]);

$this->artisan('triadev:es-migration:import-file-migrations', [
'migration' => 'not_found',
'filePath' => 'phpunit'
]);
}

/**
* @test
*/
public function it_imports_file_migrations()
{
$this->assertNull($this->repositoryMigrations->find('phpunit'));

$this->assertNull($this->repositoryMigrationSteps->find(1));
$this->assertNull($this->repositoryMigrationSteps->find(2));

config()->set('triadev-elasticsearch-migration.filePath', [
'phpunit' => __DIR__ . '/Migrations'
]);

$this->artisan('triadev:es-migration:import-file-migrations', [
'migration' => 'phpunit',
'filePath' => 'phpunit'
]);

$this->assertNotNull($this->repositoryMigrations->find('phpunit'));

$this->assertNotNull($this->repositoryMigrationSteps->find(1));
$this->assertNotNull($this->repositoryMigrationSteps->find(2));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

return [
'type' => \Triadev\EsMigration\Business\Mapper\MigrationTypes::MIGRATION_TYPE_CREATE_INDEX,
'params' => 'DATA_TYPE_IS_INVALID'
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

return [
'type' => 'INVALID',
'params' => [
'index' => 'index',
'body' => [
'mappings' => [
'phpunit' => [
'dynamic' => 'strict',
'properties' => [
'title' => [
'type' => 'text'
],
'count' => [
'type' => 'integer'
]
]
]
],
'settings' => [
'refresh_interval' => "30s"
]
]
],
'priority' => 1,
'stopOnFailure' => true
];
Loading

0 comments on commit 0239698

Please sign in to comment.