diff --git a/src/DI/Helpers/BuilderMan.php b/src/DI/Helpers/BuilderMan.php index 2da59c3ac..380849fff 100644 --- a/src/DI/Helpers/BuilderMan.php +++ b/src/DI/Helpers/BuilderMan.php @@ -99,8 +99,10 @@ public function getServiceDefinitionsByTag(string $tag): array $builder = $this->pass->getContainerBuilder(); $definitions = []; + /** @var array{name: string}|string $tagValue */ foreach ($builder->findByTag($tag) as $serviceName => $tagValue) { - $definitions[(string) $tagValue] = $builder->getDefinition($serviceName); + $name = is_array($tagValue) ? $tagValue['name'] : $tagValue; + $definitions[$name] = $builder->getDefinition($serviceName); } return $definitions; @@ -114,8 +116,10 @@ public function getServiceNamesByTag(string $tag): array $builder = $this->pass->getContainerBuilder(); $definitions = []; + /** @var array{name: string}|string $tagValue */ foreach ($builder->findByTag($tag) as $serviceName => $tagValue) { - $definitions[(string) $tagValue] = $serviceName; + $name = is_array($tagValue) ? $tagValue['name'] : $tagValue; + $definitions[$name] = $serviceName; } return $definitions; diff --git a/src/DI/OrmExtension.php b/src/DI/OrmExtension.php index 3d92fb8a3..e83b7f2cd 100644 --- a/src/DI/OrmExtension.php +++ b/src/DI/OrmExtension.php @@ -22,7 +22,7 @@ * @property-read stdClass $config * @phpstan-type TManagerConfig object{ * entityManagerDecoratorClass: string|null, - * configurationClass: string, + * configurationClass: class-string, * lazyNativeObjects: bool|null, * proxyDir: string|null, * autoGenerateProxyClasses: int|bool|Statement, @@ -86,7 +86,7 @@ public function __construct( public function getConfigSchema(): Schema { $parameters = $this->getContainerBuilder()->parameters; - $proxyDir = isset($parameters['tempDir']) ? $parameters['tempDir'] . '/cache/doctrine/orm/proxies' : null; + $proxyDir = isset($parameters['tempDir']) && is_string($parameters['tempDir']) ? $parameters['tempDir'] . '/cache/doctrine/orm/proxies' : null; $autoGenerateProxy = boolval($parameters['debugMode'] ?? true); $expectService = Expect::anyOf( diff --git a/src/ManagerRegistry.php b/src/ManagerRegistry.php index bd612aad6..526238005 100644 --- a/src/ManagerRegistry.php +++ b/src/ManagerRegistry.php @@ -3,6 +3,8 @@ namespace Nettrine\ORM; use Doctrine\ORM\EntityManager; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\UnitOfWork; use Doctrine\Persistence\AbstractManagerRegistry; use Doctrine\Persistence\ObjectManagerDecorator; use Doctrine\Persistence\Proxy; @@ -36,19 +38,30 @@ public function __construct( ); } - /** - * @param ObjectManagerDecorator|EntityManager $manager - */ - public static function reopen(ObjectManagerDecorator|EntityManager $manager): void + public static function reopen(EntityManagerInterface $manager): void { // @phpcs:disable Binder::use($manager, function (): void { if ($this instanceof EntityManager) { // @phpstan-ignore-line $this->closed = false; // @phpstan-ignore-line + + $uow = $this->getUnitOfWork(); + Binder::use($uow, function (): void { + if ($this instanceof UnitOfWork) { // @phpstan-ignore-line + $this->persisters = []; + } + }); } elseif ($this instanceof ObjectManagerDecorator) { Binder::use($this->wrapped, function (): void { // @phpstan-ignore-line if ($this instanceof EntityManager) { // @phpstan-ignore-line $this->closed = false; + + $uow = $this->getUnitOfWork(); + Binder::use($uow, function (): void { + if ($this instanceof UnitOfWork) { // @phpstan-ignore-line + $this->persisters = []; + } + }); } }); } diff --git a/tests/Cases/DI/OrmExtension.schemaIgnoreClasses.phpt b/tests/Cases/DI/OrmExtension.schemaIgnoreClasses.phpt index 9cf00bee2..639f8ac26 100644 --- a/tests/Cases/DI/OrmExtension.schemaIgnoreClasses.phpt +++ b/tests/Cases/DI/OrmExtension.schemaIgnoreClasses.phpt @@ -1,4 +1,4 @@ -addConfig([ 'parameters' => [ 'tempDir' => Tests::TEMP_PATH, + 'fixturesDir' => Tests::FIXTURES_PATH, ], ]); $compiler->addConfig(Neonkit::load( @@ -379,6 +380,11 @@ Toolkit::test(function (): void { password: test user: test path: ":memory:" + second: + driver: pdo_sqlite + password: test + user: test + path: ":memory:" nettrine.orm: managers: default: @@ -386,23 +392,67 @@ Toolkit::test(function (): void { mapping: App: type: attributes - directories: [app/Database] - namespace: App\Database + directories: [%fixturesDir%/Entity] + namespace: Tests\Mocks\Entity + second: + connection: second + entityManagerDecoratorClass: Tests\Mocks\DummyEntityManagerDecorator + mapping: + App: + type: attributes + directories: [%fixturesDir%/Entity] + namespace: Tests\Mocks\Entity NEON )); }) ->build(); - /** @var EntityManager $em */ - $em = $container->getByType(EntityManagerInterface::class); + /** @var ManagerRegistry $registry */ + $registry = $container->getByType(ManagerRegistry::class); + + foreach (['default', 'second'] as $managerName) { + /** @var EntityManagerInterface $em */ + $em = $registry->getManager($managerName); + Assert::true($em->isOpen()); + + /** @var Connection $connection */ + $connection = $registry->getConnection($managerName); + + $connection->executeQuery('CREATE TABLE dummy_entity (id integer primary key autoincrement, username string unique not null)'); + + $persister1 = $em->getUnitOfWork()->getEntityPersister(DummyEntity::class); - Assert::true($em->isOpen()); - $em->close(); - Assert::false($em->isOpen()); + $em->persist(new DummyEntity('test')); + $em->flush(); - NettrineManagerRegistry::reopen($em); + Assert::count(0, $persister1->getInserts(), 'Persister should have no inserts, have ' . count($persister1->getInserts())); - Assert::true($em->isOpen()); + // try to create a new entity with the same username - not unique + $em->persist(new DummyEntity('test')); + try { + $em->flush(); + } catch (UniqueConstraintViolationException) { + Assert::false($em->isOpen()); + } + + // after failing queue there is cached last insert + Assert::count(1, $persister1->getInserts(), 'Persister should have 1 insert, have ' . count($persister1->getInserts())); + + NettrineManagerRegistry::reopen($em); + + Assert::true($em->isOpen()); + + $persister2 = $em->getUnitOfWork()->getEntityPersister(DummyEntity::class); + + // check if the persister is different after reopening + Assert::notSame($persister1, $persister2); + + $dummy2 = new DummyEntity('test2'); + $em->persist($dummy2); + $em->flush(); + + Assert::count(2, $em->getRepository(DummyEntity::class)->findAll()); + } }); // Get repository for manager