Skip to content

Commit

Permalink
DependencyFactory: refactoring, add more features
Browse files Browse the repository at this point in the history
  • Loading branch information
f3l1x committed Dec 12, 2024
1 parent 4fccb28 commit 6188e21
Show file tree
Hide file tree
Showing 13 changed files with 279 additions and 111 deletions.
22 changes: 21 additions & 1 deletion .docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,27 @@ nettrine.migrations:
directories: array<string, string>
versionsOrganization: <null|year|year_and_month>
customTemplate: <null|path>
allOrNothing: <bool>

migrationFactory: <service>
logger: <service>
connection: <string>
manager: <string>
```
**Multiple databases**
```php
$this->configurator->addDynamicParameters([
'env' => getenv(),
]);
```

```neon
nettrine.migrations:
directories:
App\Migrations: %appDir%/migrations
connection: %env.DATABASE_CONNECTION%
```

## Usage
Expand Down Expand Up @@ -136,4 +157,3 @@ Since this moment when you type `bin/console`, there'll be registered commands f

> [!TIP]
> Take a look at more examples in [contributte/doctrine](https://github.com/contributte/doctrine/tree/master/.docs).

4 changes: 3 additions & 1 deletion ruleset.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="Contributte" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">
<!-- Rulesets -->
<rule ref="./vendor/contributte/qa/ruleset-8.2.xml"/>
<rule ref="./vendor/contributte/qa/ruleset-8.2.xml">
<exclude name="SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming.SuperfluousSuffix"/>
</rule>

<!-- Rules -->
<rule ref="SlevomatCodingStandard.Files.TypeNameMatchesFileName">
Expand Down
22 changes: 22 additions & 0 deletions src/DI/Helpers/SmartStatement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php declare(strict_types = 1);

namespace Nettrine\Migrations\DI\Helpers;

use Nette\DI\Definitions\Statement;
use Nettrine\Migrations\Exceptions\LogicalException;

final class SmartStatement
{

public static function from(mixed $service): Statement
{
if (is_string($service)) {
return new Statement($service);
} elseif ($service instanceof Statement) {
return $service;
} else {
throw new LogicalException('Unsupported type of service');
}
}

}
39 changes: 28 additions & 11 deletions src/DI/MigrationsExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Nettrine\Migrations\DI;

use Doctrine\Migrations\Configuration\Configuration;
use Doctrine\Migrations\DependencyFactory as NativeDependencyFactory;
use Doctrine\Migrations\DependencyFactory;
use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
use Doctrine\Migrations\Tools\Console\Command\CurrentCommand;
use Doctrine\Migrations\Tools\Console\Command\DiffCommand;
Expand All @@ -18,11 +18,13 @@
use Doctrine\Migrations\Tools\Console\Command\SyncMetadataCommand;
use Doctrine\Migrations\Tools\Console\Command\UpToDateCommand;
use Doctrine\Migrations\Tools\Console\Command\VersionCommand;
use Doctrine\Migrations\Version\MigrationFactory;
use Nette\DI\CompilerExtension;
use Nette\DI\Definitions\Statement;
use Nette\Schema\Expect;
use Nette\Schema\Schema;
use Nettrine\Migrations\DependencyFactory;
use Nettrine\Migrations\Version\DbalMigrationFactory;
use Nettrine\Migrations\DependencyFactoryCreator;
use Nettrine\Migrations\DI\Helpers\SmartStatement;
use stdClass;

/**
Expand All @@ -33,6 +35,11 @@ final class MigrationsExtension extends CompilerExtension

public function getConfigSchema(): Schema
{
$expectService = Expect::anyOf(
Expect::string()->required()->assert(fn ($input) => str_starts_with($input, '@') || class_exists($input) || interface_exists($input)),
Expect::type(Statement::class)->required(),
);

return Expect::structure([
'table' => Expect::string('doctrine_migrations'),
'column' => Expect::string('version'),
Expand All @@ -44,6 +51,10 @@ public function getConfigSchema(): Schema
),
'customTemplate' => Expect::string(),
'allOrNothing' => Expect::bool(false),
'logger' => (clone $expectService),
'migrationFactory' => (clone $expectService),
'connection' => Expect::string(),
'manager' => Expect::string(),
]);
}

Expand All @@ -66,6 +77,14 @@ public function loadConfiguration(): void
->addSetup('setMetadataStorageConfiguration', [$storage])
->addSetup('setAllOrNothing', [$config->allOrNothing]);

if ($config->connection !== null) {
$configuration->addSetup('setConnectionName', [$config->connection]);
}

if ($config->manager !== null) {
$configuration->addSetup('setEntityManagerName', [$config->manager]);
}

foreach ($config->directories as $namespace => $directory) {
$configuration->addSetup('addMigrationsDirectory', [$namespace, $directory]);
}
Expand All @@ -76,15 +95,13 @@ public function loadConfiguration(): void
$configuration->addSetup('setMigrationsAreOrganizedByYearAndMonth');
}

$builder->addDefinition($this->prefix('migrationFactory'))
->setFactory(DbalMigrationFactory::class);

$builder->addDefinition($this->prefix('dependencyFactory'))
->setType(NativeDependencyFactory::class)
->setFactory($this->prefix('@internal.dependencyFactory::create'));
$dependencyFactory = $builder->addDefinition($this->prefix('dependencyFactory'))
->setType(DependencyFactory::class)
->setFactory(DependencyFactoryCreator::class . '::create');

$builder->addDefinition($this->prefix('internal.dependencyFactory'))
->setFactory(DependencyFactory::class);
if ($config->migrationFactory !== null) {
$dependencyFactory->addSetup('setService', [MigrationFactory::class, SmartStatement::from($config->migrationFactory)]);
}

// Register commands

Expand Down
51 changes: 0 additions & 51 deletions src/DependencyFactory.php

This file was deleted.

76 changes: 76 additions & 0 deletions src/DependencyFactoryCreator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php declare(strict_types = 1);

namespace Nettrine\Migrations;

use Doctrine\Migrations\AbstractMigration;
use Doctrine\Migrations\Configuration\Configuration;
use Doctrine\Migrations\Configuration\Connection\ConnectionRegistryConnection;
use Doctrine\Migrations\Configuration\EntityManager\ManagerRegistryEntityManager;
use Doctrine\Migrations\Configuration\Migration\ExistingConfiguration;
use Doctrine\Migrations\DependencyFactory;
use Doctrine\Migrations\Version\MigrationFactory;
use Doctrine\Persistence\ConnectionRegistry;
use Doctrine\Persistence\ManagerRegistry;
use Nette\DI\Container;
use Nettrine\Migrations\Exceptions\LogicalException;
use Nettrine\Migrations\Migration\MigrationFactoryDecorator;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;

final class DependencyFactoryCreator
{

public static function create(
Container $container,
Configuration $configuration,
?ConnectionRegistry $connectionRegistry = null,
?ManagerRegistry $managerRegistry = null,
?LoggerInterface $logger = null
): DependencyFactory
{
$logger ??= new NullLogger();

if ($managerRegistry !== null) {
$dependencyFactory = DependencyFactory::fromEntityManager(
new ExistingConfiguration($configuration),
ManagerRegistryEntityManager::withSimpleDefault($managerRegistry),
$logger
);
} elseif ($connectionRegistry !== null) {
$dependencyFactory = DependencyFactory::fromConnection(
new ExistingConfiguration($configuration),
ConnectionRegistryConnection::withSimpleDefault($connectionRegistry),
$logger
);
} else {
throw new LogicalException('You must provide either ManagerRegistry or ConnectionRegistry.');
}

$migrationFactory = new class ($dependencyFactory) implements MigrationFactory {

public function __construct(
private DependencyFactory $dependencyFactory
)
{
}

public function createVersion(string $migrationClassName): AbstractMigration
{
$migration = new $migrationClassName(
$this->dependencyFactory->getConnection(),
$this->dependencyFactory->getLogger()
);

assert($migration instanceof AbstractMigration);

return $migration;
}

};

$dependencyFactory->setService(MigrationFactory::class, new MigrationFactoryDecorator($container, $migrationFactory));

return $dependencyFactory;
}

}
8 changes: 8 additions & 0 deletions src/Exceptions/LogicalException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php declare(strict_types = 1);

namespace Nettrine\Migrations\Exceptions;

final class LogicalException extends \LogicException
{

}
8 changes: 8 additions & 0 deletions src/Exceptions/RuntimeException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php declare(strict_types = 1);

namespace Nettrine\Migrations\Exceptions;

final class RuntimeException extends \RuntimeException
{

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

namespace Nettrine\Migrations\Migration;

use Nette\DI\Container;

interface ContainerAwareInterface
{

public function setContainer(Container $container): void;

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

namespace Nettrine\Migrations\Migration;

use Doctrine\Migrations\AbstractMigration;
use Doctrine\Migrations\Version\MigrationFactory;
use Nette\DI\Container;

class MigrationFactoryDecorator implements MigrationFactory
{

public function __construct(
private Container $container,
private MigrationFactory $migrationFactory,
)
{
}

public function createVersion(string $migrationClassName): AbstractMigration
{
$instance = $this->migrationFactory->createVersion($migrationClassName);

// Call setContainer
if ($instance instanceof ContainerAwareInterface) {
$instance->setContainer($this->container);
}

// Allow to use inject<>
$this->container->callInjects($instance);

return $instance;
}

}
42 changes: 0 additions & 42 deletions src/Version/DbalMigrationFactory.php

This file was deleted.

Loading

0 comments on commit 6188e21

Please sign in to comment.