Skip to content

Commit

Permalink
Merge pull request #1 from netlogix/feature/ADIGITAL-790-init-nlx-mig…
Browse files Browse the repository at this point in the history
…rations

Feature/adigital 790 init nlx migrations
  • Loading branch information
paxuclus authored Oct 2, 2019
2 parents 13452e9 + fe99f13 commit 8355930
Show file tree
Hide file tree
Showing 23 changed files with 1,076 additions and 1 deletion.
105 changes: 105 additions & 0 deletions Classes/Command/MigrationsCommandController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php
declare(strict_types=1);

namespace Netlogix\Migrations\Command;

use Neos\Flow\Cli\CommandController;
use Neos\Flow\Log\ThrowableStorageInterface;
use Neos\Flow\Log\Utility\LogEnvironment;
use Netlogix\Migrations\Domain\Service\MigrationExecutor;
use Netlogix\Migrations\Domain\Service\MigrationService;
use Psr\Log\LoggerInterface;
use Neos\Flow\Annotations as Flow;

/**
* @Flow\Scope("singleton")
*/
class MigrationsCommandController extends CommandController
{
/**
* @var MigrationService
*/
private $migrationService;

/**
* @var MigrationExecutor
*/
private $migrationExecutor;

/**
* @var ThrowableStorageInterface
*/
private $throwableStorage;

/**
* @var LoggerInterface
*/
private $logger;

public function __construct(
MigrationService $migrationService,
MigrationExecutor $migrationExecutor,
ThrowableStorageInterface $throwableStorage,
LoggerInterface $logger
) {
parent::__construct();

$this->migrationService = $migrationService;
$this->migrationExecutor = $migrationExecutor;
$this->throwableStorage = $throwableStorage;
$this->logger = $logger;
}

/**
* Execute all unexecuted migrations
*
* @param bool $quiet If set no output will be send
*/
public function migrateCommand(bool $quiet = false)
{
$unexecutedMigrations = $this->migrationService->findUnexecutedMigrations();

if ($unexecutedMigrations === []) {
$this->outputLine('No new migrations available');
$this->sendAndExit(0);
}

foreach ($unexecutedMigrations as $version => $migration) {
try {
$this->migrationExecutor->execute($migration);
if (false === $quiet) {
$this->outputLine('Executed Migration "' . $version . '".');
}
} catch (\Exception $exception) {
$this->handleException($exception);
}
}
}

/**
* Execute a single migration
*
* @param string $version The version to migrate
* @param string $direction Whether to execute the migration up (default) or down
*/
public function executeCommand(string $version, string $direction = 'up')
{
try {
$migration = $this->migrationService->getMigrationByVersion($version);
$this->migrationExecutor->execute($migration, $direction);
} catch (\Exception $exception) {
$this->handleException($exception);
}
}

protected function handleException(\Exception $exception)
{
$this->outputLine('<error>%s</error>', [$exception->getMessage()]);
$this->outputLine();
$this->outputLine('The exception details have been logged to the Flow system log.');
$message = $this->throwableStorage->logThrowable($exception);
$this->outputLine($message);
$this->logger->error($message, LogEnvironment::fromMethodName(__METHOD__));
$this->quit(1);
}
}
25 changes: 25 additions & 0 deletions Classes/Domain/Handler/DefaultMigrationHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);

namespace Netlogix\Migrations\Domain\Handler;

use Netlogix\Migrations\Domain\Model\DefaultMigration;
use Netlogix\Migrations\Domain\Model\Migration;

class DefaultMigrationHandler implements MigrationHandler
{
public function canExecute(Migration $migration): bool
{
return $migration instanceof DefaultMigration;
}

public function up(Migration $migration): void
{
$migration->up();
}

public function down(Migration $migration): void
{
$migration->down();
}
}
16 changes: 16 additions & 0 deletions Classes/Domain/Handler/MigrationHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php
declare(strict_types=1);

namespace Netlogix\Migrations\Domain\Handler;

use Netlogix\Migrations\Domain\Model\Migration;
use Netlogix\Migrations\Domain\Model\MigrationInterface;

interface MigrationHandler
{
public function canExecute(Migration $migration): bool;

public function up(Migration $migration): void;

public function down(Migration $migration): void;
}
9 changes: 9 additions & 0 deletions Classes/Domain/Model/DefaultMigration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);

namespace Netlogix\Migrations\Domain\Model;

interface DefaultMigration extends Migration
{

}
11 changes: 11 additions & 0 deletions Classes/Domain/Model/Migration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);

namespace Netlogix\Migrations\Domain\Model;

interface Migration
{
public function up(): void;

public function down(): void;
}
31 changes: 31 additions & 0 deletions Classes/Domain/Model/MigrationStatus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
declare(strict_types=1);

namespace Netlogix\Migrations\Domain\Model;

use Doctrine\ORM\Mapping as ORM;
use Neos\Flow\Annotations as Flow;

/**
* @Flow\Entity
* @ORM\Table(name="netlogix_migrationstatus")
*/
class MigrationStatus
{
/**
* @ORM\Id
* @Flow\Identity
* @var string
*/
protected $version;

public function __construct(string $version)
{
$this->version = $version;
}

public function getVersion(): string
{
return $this->version;
}
}
15 changes: 15 additions & 0 deletions Classes/Domain/Repository/MigrationStatusRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);

namespace Netlogix\Migrations\Domain\Repository;

use Neos\Flow\Annotations as Flow;
use Neos\Flow\Persistence\Repository;

/**
* @Flow\Scope("singleton")
*/
class MigrationStatusRepository extends Repository
{

}
60 changes: 60 additions & 0 deletions Classes/Domain/Service/FileSystemMigrationsResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
declare(strict_types=1);

namespace Netlogix\Migrations\Domain\Service;

use Doctrine\DBAL\Migrations\Finder\GlobFinder;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Package\PackageInterface;
use Neos\Flow\Package\PackageManager;
use Neos\Utility\Files;

/**
* @Flow\Scope("singleton")
*/
class FileSystemMigrationsResolver
{
/**
* @var PackageManager
*/
private $packageManager;

/**
* @var GlobFinder
*/
private $globFinder;

public function __construct(PackageManager $packageManager)
{
$this->packageManager = $packageManager;
$this->globFinder = new GlobFinder();
}

/**
* @return string[]
*/
public function findMigrationFiles(): array
{
$classNames = [];
/** @var PackageInterface $package */
foreach ($this->packageManager->getAvailablePackages() as $package) {
$path = Files::concatenatePaths([
$package->getPackagePath(),
'Migrations',
'Netlogix'
]);

if (is_dir($path)) {
$migrations = $this->globFinder->findMigrations(
$path,
'Netlogix\Migrations\Persistence\Migrations'
);

if ($migrations !== []) {
array_push($classNames, ...$migrations);
}
}
}
return $classNames;
}
}
58 changes: 58 additions & 0 deletions Classes/Domain/Service/MigrationExecutor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php
declare(strict_types=1);

namespace Netlogix\Migrations\Domain\Service;

use Neos\Flow\ObjectManagement\ObjectManager;
use Neos\Flow\Reflection\ReflectionService;
use Netlogix\Migrations\Domain\Handler\MigrationHandler;
use Netlogix\Migrations\Domain\Model\Migration;
use Netlogix\Migrations\Error\MissingMigrationHandler;
use Neos\Flow\Annotations as Flow;

/**
* @Flow\Scope("singleton")
*/
class MigrationExecutor
{
/**
* @var ReflectionService
*/
private $reflectionService;

/**
* var ObjectManager
*/
private $objectManager;

/**
* @var VersionLogger
*/
private $versionLogger;

public function __construct(
ReflectionService $reflectionService,
ObjectManager $objectManager,
VersionLogger $versionLogger
) {
$this->reflectionService = $reflectionService;
$this->objectManager = $objectManager;
$this->versionLogger = $versionLogger;
}

public function execute(Migration $migration, $direction = 'up')
{
foreach ($this->reflectionService->getAllImplementationClassNamesForInterface(MigrationHandler::class) as $handlerClassName) {

/** @var MigrationHandler $handler */
$handler = $this->objectManager->get($handlerClassName);

if ($handler->canExecute($migration)) {
$result = $handler->{$direction}($migration);
$this->versionLogger->logMigration($migration, $direction);
return $result;
}
}
throw new MissingMigrationHandler('No Migration Handler found for "'.get_class($migration)."'");
}
}
Loading

0 comments on commit 8355930

Please sign in to comment.