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 28d9f01
Show file tree
Hide file tree
Showing 6 changed files with 235 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
}
98 changes: 98 additions & 0 deletions src/MigrationsRepository/ServiceMigrationsRepository.php
@@ -0,0 +1,98 @@
<?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;

use function assert;

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

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

Check failure on line 23 in src/MigrationsRepository/ServiceMigrationsRepository.php

View workflow job for this annotation

GitHub Actions / Static Analysis / PHPStan (8.2)

Property Doctrine\Bundle\MigrationsBundle\MigrationsRepository\ServiceMigrationsRepository::$container with generic interface Symfony\Contracts\Service\ServiceProviderInterface does not specify its types: T

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

public function __construct(

Check failure on line 28 in src/MigrationsRepository/ServiceMigrationsRepository.php

View workflow job for this annotation

GitHub Actions / Static Analysis / PHPStan (8.2)

Method Doctrine\Bundle\MigrationsBundle\MigrationsRepository\ServiceMigrationsRepository::__construct() has parameter $container with generic interface Symfony\Contracts\Service\ServiceProviderInterface but does not specify its types: T
MigrationsRepository $migrationRepository,
ServiceProviderInterface $container
) {
$this->migrationRepository = $migrationRepository;
$this->container = $container;
}

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

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L28-L34

Added lines #L28 - L34 were not covered by tests

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

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

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L36-L39

Added lines #L36 - L39 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 45 in src/MigrationsRepository/ServiceMigrationsRepository.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L41-L45

Added lines #L41 - L45 were not covered by tests

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

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

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L47-L48

Added lines #L47 - L48 were not covered by tests

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

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

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L53-L55

Added lines #L53 - L55 were not covered by tests

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

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

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L57-L59

Added lines #L57 - L59 were not covered by tests

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

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

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L61-L66

Added lines #L61 - L66 were not covered by tests

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

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

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L68-L69

Added lines #L68 - L69 were not covered by tests

return new AvailableMigrationsSet($migrations);
}

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

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L71-L72

Added lines #L71 - L72 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 79 in src/MigrationsRepository/ServiceMigrationsRepository.php

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L74-L79

Added lines #L74 - L79 were not covered by tests

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

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

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L81-L83

Added lines #L81 - L83 were not covered by tests

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

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

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L85-L89

Added lines #L85 - L89 were not covered by tests

$migration = $this->container->get((string) $version);
assert($migration instanceof AbstractMigration);

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

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L91-L92

Added lines #L91 - L92 were not covered by tests

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

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

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L94

Added line #L94 was not covered by tests

return true;
}

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

View check run for this annotation

Codecov / codecov/patch

src/MigrationsRepository/ServiceMigrationsRepository.php#L96-L97

Added lines #L96 - L97 were not covered by tests
}

0 comments on commit 28d9f01

Please sign in to comment.