From b2c163c97a15c8658c6ac7f145cfa7c449ba3679 Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Tue, 15 Jul 2025 20:36:42 +0200 Subject: [PATCH] BUGFIX: Prevent premature connection to database before `PersistenceManager::persistAllowedObjects` For every simple GET request `persistAllowedObjects` is called via the Package.php in flow. This results in building a db connection, even if there is nothing to do. So if neither the persistentManger nor the entityManager has been created by the object manager instantiating one and thus the other which leads to "work". For the check if the `entityManager` `isOpen` we activate the lazy dependency. Now in this retrieval process - even though doctrines connection is lazy itself - the connection will be made forcefully see `\Neos\Flow\Persistence\Doctrine\EntityManagerFactory::create` line 120 (https://github.com/neos/flow-development-collection/blob/11e2348125dd8286ff9ccc088e5d187dc9143bf5/Neos.Flow/Classes/Persistence/Doctrine/EntityManagerFactory.php#L120) or https://github.com/neos/flow-development-collection/blob/d93b6b09ca2071c87812a9ef4bc120201c44608a/Neos.Flow/Classes/Persistence/Doctrine/EntityManagerConfiguration.php#L229 This is ironic because if there is no connection - or no entity manager and persistence manager in the first place, the current process cannot have made any changes to the transaction. Reason for this is that the Package.php has a wrong check which looks for if the PersistenceManager _exists_ as php class at all rather than if we have an active instance loaded. This is an old regression from: https://github.com/neos/flow-development-collection/commit/163e204df2b724555af2c2a6fd800bd32eb0b95c --- Neos.Flow/Classes/Package.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Neos.Flow/Classes/Package.php b/Neos.Flow/Classes/Package.php index f6ad59cbfb..34561b6e55 100644 --- a/Neos.Flow/Classes/Package.php +++ b/Neos.Flow/Classes/Package.php @@ -71,10 +71,11 @@ public function boot(Core\Bootstrap $bootstrap) $dispatcher = $bootstrap->getSignalSlotDispatcher(); $dispatcher->connect(Mvc\Dispatcher::class, 'afterControllerInvocation', function ($request) use ($bootstrap) { - // No auto-persistence if there is no PersistenceManager registered + // No auto-persistence if there is no PersistenceManager loaded // This signal will not be fired at compile time, as it's only emitted for web requests which happen at runtime. if ( - $bootstrap->getObjectManager()->has(Persistence\PersistenceManagerInterface::class) + /** @phpstan-ignore-next-line the object manager interface doesn't specify this method */ + $bootstrap->getObjectManager()->hasInstance(Persistence\PersistenceManagerInterface::class) ) { if (SecurityHelper::hasSafeMethod($request->getHttpRequest()) !== true) { $bootstrap->getObjectManager()->get(Persistence\PersistenceManagerInterface::class)->persistAll(); @@ -86,9 +87,10 @@ public function boot(Core\Bootstrap $bootstrap) }); $dispatcher->connect(Cli\Dispatcher::class, 'afterControllerInvocation', function () use ($bootstrap) { - // No auto-persistence if there is no PersistenceManager registered or during compile time + // No auto-persistence if there is no PersistenceManager loaded or during compile time if ( - $bootstrap->getObjectManager()->has(Persistence\PersistenceManagerInterface::class) + /** @phpstan-ignore-next-line the object manager interface doesn't specify this method */ + $bootstrap->getObjectManager()->hasInstance(Persistence\PersistenceManagerInterface::class) && !($bootstrap->getObjectManager() instanceof CompileTimeObjectManager) ) { $bootstrap->getObjectManager()->get(Persistence\PersistenceManagerInterface::class)->persistAll();