Skip to content

Commit

Permalink
Add service migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
HypeMC committed Apr 3, 2024
1 parent bc599a5 commit cf481fc
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 2 deletions.
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
}

0 comments on commit cf481fc

Please sign in to comment.