diff --git a/lib/Doctrine/Migrations/DependencyFactory.php b/lib/Doctrine/Migrations/DependencyFactory.php index ea8c549534..edc3f5cd20 100644 --- a/lib/Doctrine/Migrations/DependencyFactory.php +++ b/lib/Doctrine/Migrations/DependencyFactory.php @@ -59,6 +59,9 @@ */ class DependencyFactory { + /** @psalm-var array */ + private $inResolution = []; + /** @var Configuration */ private $configuration; @@ -476,8 +479,10 @@ public function getRollup(): Rollup */ private function getDependency(string $id, callable $callback) { - if (array_key_exists($id, $this->factories) && ! array_key_exists($id, $this->dependencies)) { + if (! isset($this->inResolution[$id]) && array_key_exists($id, $this->factories) && ! array_key_exists($id, $this->dependencies)) { + $this->inResolution[$id] = true; $this->dependencies[$id] = call_user_func($this->factories[$id], $this); + unset($this->inResolution); } if (! array_key_exists($id, $this->dependencies)) { diff --git a/tests/Doctrine/Migrations/Tests/DependencyFactoryTest.php b/tests/Doctrine/Migrations/Tests/DependencyFactoryTest.php index a87c26be38..cc77fcc395 100644 --- a/tests/Doctrine/Migrations/Tests/DependencyFactoryTest.php +++ b/tests/Doctrine/Migrations/Tests/DependencyFactoryTest.php @@ -16,6 +16,9 @@ use Doctrine\Migrations\Finder\GlobFinder; use Doctrine\Migrations\Finder\RecursiveRegexFinder; use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration; +use Doctrine\Migrations\Tests\MigrationRepository\Migrations\A\A; +use Doctrine\Migrations\Tests\Stub\CustomClassNameMigrationFactory; +use Doctrine\Migrations\Version\MigrationFactory; use Doctrine\ORM\EntityManager; use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; @@ -156,6 +159,23 @@ public function testServiceDefinition(): void self::assertSame($anotherLogger, $di->getLogger()); } + public function testServiceDecoratesDefaultImplementation(): void + { + $configuration = new Configuration(); + $configuration->addMigrationClass(A::class); + + $di = DependencyFactory::fromConnection(new ExistingConfiguration($configuration), new ExistingConnection($this->connection)); + + $di->setDefinition(MigrationFactory::class, static function (DependencyFactory $innerDi): CustomClassNameMigrationFactory { + $serviceToDecorate = $innerDi->getMigrationFactory(); + + return new CustomClassNameMigrationFactory($serviceToDecorate, A::class); + }); + + $factory = $di->getMigrationFactory(); + self::assertInstanceOf(A::class, $factory->createVersion('SomeVersion')); + } + public function testServiceHasPriorityOverDefinition(): void { $logger = $this->createMock(LoggerInterface::class); diff --git a/tests/Doctrine/Migrations/Tests/Stub/CustomClassNameMigrationFactory.php b/tests/Doctrine/Migrations/Tests/Stub/CustomClassNameMigrationFactory.php new file mode 100644 index 0000000000..bceae29e87 --- /dev/null +++ b/tests/Doctrine/Migrations/Tests/Stub/CustomClassNameMigrationFactory.php @@ -0,0 +1,31 @@ + */ + private $migrationClassName; + + /** + * @param class-string $migrationClassName + */ + public function __construct(MigrationFactory $parentMigrationFactory, string $migrationClassName) + { + $this->parentMigrationFactory = $parentMigrationFactory; + $this->migrationClassName = $migrationClassName; + } + + public function createVersion(string $migrationClassName): AbstractMigration + { + return $this->parentMigrationFactory->createVersion($this->migrationClassName); + } +}