Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add service migrations (POC) #524

Open
wants to merge 1 commit into
base: 3.4.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 40 additions & 0 deletions config/services.xml
Expand Up @@ -11,6 +11,14 @@
<argument type="service" id="doctrine.migrations.configuration_loader"/>
<argument></argument>
<argument type="service" id="logger" on-invalid="null"></argument>
<call method="setDefinition">
<argument>Doctrine\Migrations\Finder\MigrationFinder</argument>
<argument type="service_closure" id="doctrine.migrations.migration_finder" />
</call>
<call method="setDefinition">
<argument>Doctrine\Migrations\MigrationsRepository</argument>
<argument type="service_closure" id="doctrine.migrations.migrations_repository" />
</call>
</service>

<service id="doctrine.migrations.configuration_loader" class="Doctrine\Migrations\Configuration\Migration\ExistingConfiguration" public="false">
Expand Down Expand Up @@ -146,6 +154,38 @@
<tag name="console.command" command="doctrine:migrations:version" />
</service>

<service id="doctrine.migrations.connection" class="Doctrine\DBAL\Connection">
<factory service="doctrine.migrations.dependency_factory" method="getConnection" />
</service>

<service id="doctrine.migrations.logger" class="Psr\Log\LoggerInterface">
<factory service="doctrine.migrations.dependency_factory" method="getLogger" />
</service>

<service id="doctrine.migrations.migration_finder" class="Doctrine\Migrations\Finder\MigrationFinder">
<factory service="doctrine.migrations.dependency_factory" method="getMigrationsFinder" />
</service>

<service id="doctrine.migrations.filter_service_migration_finder"
class="Doctrine\Bundle\MigrationsBundle\MigrationFinder\FilterServiceMigrationFinder"
decorates="doctrine.migrations.migration_finder"
>
<argument id="doctrine.migrations.filter_service_migration_finder.inner" type="service" />
<argument type="abstract">migrations locator</argument>
</service>

<service id="doctrine.migrations.migrations_repository" class="Doctrine\Migrations\MigrationsRepository">
<factory service="doctrine.migrations.dependency_factory" method="getMigrationRepository" />
</service>

<service id="doctrine.migrations.service_migrations_repository"
class="Doctrine\Bundle\MigrationsBundle\MigrationsRepository\ServiceMigrationsRepository"
decorates="doctrine.migrations.migrations_repository"
>
<argument id="doctrine.migrations.service_migrations_repository.inner" type="service" />
<argument type="abstract">migrations locator</argument>
</service>

</services>

</container>
44 changes: 44 additions & 0 deletions src/DependencyInjection/CompilerPass/RegisterMigrationsPass.php
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

namespace Doctrine\Bundle\MigrationsBundle\DependencyInjection\CompilerPass;

use Doctrine\DBAL\Connection;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\TypedReference;

class RegisterMigrationsPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container): void
{
$migrationRefs = [];

foreach ($container->findTaggedServiceIds('doctrine_migrations.migration', true) as $id => $attributes) {
$definition = $container->getDefinition($id);
$definition->setBindings([
Connection::class => new BoundArgument(new Reference('doctrine.migrations.connection')),
LoggerInterface::class => new BoundArgument(new Reference('doctrine.migrations.logger')),
]);

Check warning on line 27 in src/DependencyInjection/CompilerPass/RegisterMigrationsPass.php

View check run for this annotation

Codecov / codecov/patch

src/DependencyInjection/CompilerPass/RegisterMigrationsPass.php#L23-L27

Added lines #L23 - L27 were not covered by tests

$migrationRefs[$id] = new TypedReference($id, $definition->getClass());

Check warning on line 29 in src/DependencyInjection/CompilerPass/RegisterMigrationsPass.php

View check run for this annotation

Codecov / codecov/patch

src/DependencyInjection/CompilerPass/RegisterMigrationsPass.php#L29

Added line #L29 was not covered by tests
}

if ($migrationRefs !== []) {
$container->getDefinition('doctrine.migrations.filter_service_migration_finder')
->replaceArgument(1, new ServiceLocatorArgument($migrationRefs));
$container->getDefinition('doctrine.migrations.service_migrations_repository')
->replaceArgument(1, new ServiceLocatorArgument($migrationRefs));

Check warning on line 36 in src/DependencyInjection/CompilerPass/RegisterMigrationsPass.php

View check run for this annotation

Codecov / codecov/patch

src/DependencyInjection/CompilerPass/RegisterMigrationsPass.php#L33-L36

Added lines #L33 - L36 were not covered by tests
} else {
$container->removeDefinition('doctrine.migrations.connection');
$container->removeDefinition('doctrine.migrations.logger');
$container->removeDefinition('doctrine.migrations.filter_service_migration_finder');
$container->removeDefinition('doctrine.migrations.service_migrations_repository');
}
}
}
4 changes: 4 additions & 0 deletions src/DependencyInjection/DoctrineMigrationsExtension.php
Expand Up @@ -6,6 +6,7 @@

use Doctrine\Bundle\MigrationsBundle\Collector\MigrationsCollector;
use Doctrine\Bundle\MigrationsBundle\Collector\MigrationsFlattener;
use Doctrine\Migrations\AbstractMigration;
use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
use Doctrine\Migrations\Version\MigrationFactory;
Expand Down Expand Up @@ -48,6 +49,9 @@ public function load(array $configs, ContainerBuilder $container): void

$loader->load('services.xml');

$container->registerForAutoconfiguration(AbstractMigration::class)
->addTag('doctrine_migrations.migration');

$configurationDefinition = $container->getDefinition('doctrine.migrations.configuration');

foreach ($config['migrations_paths'] as $ns => $path) {
Expand Down
5 changes: 3 additions & 2 deletions src/DoctrineMigrationsBundle.php
Expand Up @@ -5,17 +5,18 @@
namespace Doctrine\Bundle\MigrationsBundle;

use Doctrine\Bundle\MigrationsBundle\DependencyInjection\CompilerPass\ConfigureDependencyFactoryPass;
use Doctrine\Bundle\MigrationsBundle\DependencyInjection\CompilerPass\RegisterMigrationsPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;

use function dirname;

class DoctrineMigrationsBundle extends Bundle
{
/** @return void */
public function build(ContainerBuilder $container)
public function build(ContainerBuilder $container): void
{
$container->addCompilerPass(new ConfigureDependencyFactoryPass());
$container->addCompilerPass(new RegisterMigrationsPass());
}

public function getPath(): string
Expand Down
46 changes: 46 additions & 0 deletions src/MigrationFinder/FilterServiceMigrationFinder.php
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace Doctrine\Bundle\MigrationsBundle\MigrationFinder;

use Doctrine\Migrations\Finder\MigrationFinder;
use Psr\Container\ContainerInterface;

use function array_values;

final class FilterServiceMigrationFinder implements MigrationFinder
{
/** @var MigrationFinder */
private $migrationFinder;

/** @var ContainerInterface */
private $container;

public function __construct(MigrationFinder $migrationFinder, ContainerInterface $container)
{
$this->migrationFinder = $migrationFinder;
$this->container = $container;
}

Check warning on line 24 in src/MigrationFinder/FilterServiceMigrationFinder.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationFinder/FilterServiceMigrationFinder.php#L20-L24

Added lines #L20 - L24 were not covered by tests

/**
* {@inheritDoc}
*/
public function findMigrations(string $directory, ?string $namespace = null): array
{
$migrations = $this->migrationFinder->findMigrations(
$directory,
$namespace
);

Check warning on line 34 in src/MigrationFinder/FilterServiceMigrationFinder.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationFinder/FilterServiceMigrationFinder.php#L29-L34

Added lines #L29 - L34 were not covered by tests

foreach ($migrations as $i => $migration) {
if (! $this->container->has($migration)) {
continue;
}

Check warning on line 39 in src/MigrationFinder/FilterServiceMigrationFinder.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationFinder/FilterServiceMigrationFinder.php#L36-L39

Added lines #L36 - L39 were not covered by tests

unset($migrations[$i]);
}

Check warning on line 42 in src/MigrationFinder/FilterServiceMigrationFinder.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationFinder/FilterServiceMigrationFinder.php#L41-L42

Added lines #L41 - L42 were not covered by tests

return array_values($migrations);
}

Check warning on line 45 in src/MigrationFinder/FilterServiceMigrationFinder.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationFinder/FilterServiceMigrationFinder.php#L44-L45

Added lines #L44 - L45 were not covered by tests
}
95 changes: 95 additions & 0 deletions src/MigrationsRepository/ServiceMigrationsRepository.php
@@ -0,0 +1,95 @@
<?php

declare(strict_types=1);

namespace Doctrine\Bundle\MigrationsBundle\MigrationsRepository;

use Doctrine\Migrations\AbstractMigration;
use Doctrine\Migrations\Exception\DuplicateMigrationVersion;
use Doctrine\Migrations\Metadata\AvailableMigration;
use Doctrine\Migrations\Metadata\AvailableMigrationsSet;
use Doctrine\Migrations\MigrationsRepository;
use Doctrine\Migrations\Version\Version;
use Symfony\Contracts\Service\ServiceProviderInterface;

class ServiceMigrationsRepository implements MigrationsRepository
{
/** @var MigrationsRepository */
private $migrationRepository;

/** @var ServiceProviderInterface<AbstractMigration> */
private $container;

/** @var AvailableMigration[] */
private $migrations = [];

/** @param ServiceProviderInterface<AbstractMigration> $container */
public function __construct(
MigrationsRepository $migrationRepository,
ServiceProviderInterface $container
) {
$this->migrationRepository = $migrationRepository;
$this->container = $container;
}

Check warning on line 33 in src/MigrationsRepository/ServiceMigrationsRepository.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L27-L33

Added lines #L27 - L33 were not covered by tests

public function hasMigration(string $version): bool
{
return $this->container->has($version) || $this->migrationRepository->hasMigration($version);
}

Check warning on line 38 in src/MigrationsRepository/ServiceMigrationsRepository.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L35-L38

Added lines #L35 - L38 were not covered by tests

public function getMigration(Version $version): AvailableMigration
{
if (! isset($this->migrations[(string) $version]) && ! $this->loadMigrationFromContainer($version)) {
return $this->migrationRepository->getMigration($version);
}

Check warning on line 44 in src/MigrationsRepository/ServiceMigrationsRepository.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L40-L44

Added lines #L40 - L44 were not covered by tests

return $this->migrations[(string) $version];
}

Check warning on line 47 in src/MigrationsRepository/ServiceMigrationsRepository.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L46-L47

Added lines #L46 - L47 were not covered by tests

/**
* Returns a non-sorted set of migrations.
*/
public function getMigrations(): AvailableMigrationsSet
{
$this->loadMigrationsFromContainer();

Check warning on line 54 in src/MigrationsRepository/ServiceMigrationsRepository.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L52-L54

Added lines #L52 - L54 were not covered by tests

$migrations = $this->migrations;
foreach ($this->migrationRepository->getMigrations()->getItems() as $availableMigration) {
$version = $availableMigration->getVersion();

Check warning on line 58 in src/MigrationsRepository/ServiceMigrationsRepository.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L56-L58

Added lines #L56 - L58 were not covered by tests

if (isset($migrations[(string) $version])) {
throw DuplicateMigrationVersion::new(
(string) $version,
(string) $version
);
}

Check warning on line 65 in src/MigrationsRepository/ServiceMigrationsRepository.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L60-L65

Added lines #L60 - L65 were not covered by tests

$migrations[(string) $version] = $availableMigration;
}

Check warning on line 68 in src/MigrationsRepository/ServiceMigrationsRepository.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L67-L68

Added lines #L67 - L68 were not covered by tests

return new AvailableMigrationsSet($migrations);
}

Check warning on line 71 in src/MigrationsRepository/ServiceMigrationsRepository.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L70-L71

Added lines #L70 - L71 were not covered by tests

private function loadMigrationsFromContainer(): void
{
foreach ($this->container->getProvidedServices() as $id) {
if (isset($this->migrations[$id])) {
continue;
}

Check warning on line 78 in src/MigrationsRepository/ServiceMigrationsRepository.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L73-L78

Added lines #L73 - L78 were not covered by tests

$this->loadMigrationFromContainer(new Version($id));
}
}

Check warning on line 82 in src/MigrationsRepository/ServiceMigrationsRepository.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L80-L82

Added lines #L80 - L82 were not covered by tests

private function loadMigrationFromContainer(Version $version): bool
{
if (! $this->container->has((string) $version)) {
return false;
}

Check warning on line 88 in src/MigrationsRepository/ServiceMigrationsRepository.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L84-L88

Added lines #L84 - L88 were not covered by tests

$migration = $this->container->get((string) $version);
$this->migrations[(string) $version] = new AvailableMigration($version, $migration);

Check warning on line 91 in src/MigrationsRepository/ServiceMigrationsRepository.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L90-L91

Added lines #L90 - L91 were not covered by tests

return true;
}

Check warning on line 94 in src/MigrationsRepository/ServiceMigrationsRepository.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L93-L94

Added lines #L93 - L94 were not covered by tests
}