Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DoctrineBridge] Add support for doctrine/persistence 4 #59575

Merged
merged 1 commit into from
Jan 25, 2025

Conversation

greg0ire
Copy link
Contributor

@greg0ire greg0ire commented Jan 21, 2025

v4 provides a guarantee that ManagerRegistry::getManager() returns an entity manager (as opposed to null).

Q A
Branch? 6.4
Bug fix? no
New feature? no
Deprecations? no
Issues n/a
License MIT

@carsonbot carsonbot added this to the 6.4 milestone Jan 21, 2025
@greg0ire
Copy link
Contributor Author

Let me know if this is the wrong branch, I'm never quite sure for this kind of case with Symfony, but in the past, I think I've been asked to contribute this kind of branch as a patch.

@carsonbot carsonbot changed the title Add support for doctrine/persistence 4 [DoctrineBridge] Add support for doctrine/persistence 4 Jan 21, 2025
Comment on lines 57 to 59
if (method_exists(ObjectManager::class, 'isUninitializedObject')) {
$this->markTestSkipped('This test is not applicable to doctrine/persistence 4');
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does Persistence 4 behave in this situation? Should we have a test for that as well?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@derrabus TypeError in the signature of the AbstractManagerRegistry when passing null as default manager name. And InvalidArgumentException if there is no manager with that name.

@greg0ire we cannot remove support for the case of having no entity manager. As the ManagerRegistry interface extends ConnectionRegistry in doctrine/persistence (which is a mistake to me, but won't be an easy fix) and we don't have any standalone implementation of ConnectionRegistry, DoctrineBundle will still create a manager registry even when your project enables DBAL and not ORM. And so this case exists (it won't be a case of having no manager registry at all)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the proper fix is to fix the mock of the ManagerRegistry. When passing null as argument here, getManagerForClass should indeed return null but getManager should throw an InvalidArgumentException (which is already the behavior of doctrine/persistence 2.x and 3.x btw)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the pointers, I'll try that 👍

Copy link
Member

@stof stof left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is broken in its current state. It should update mocks to match the actual behavior of doctrine/persistence instead of skipping relevant tests.

-1 for merging it in its current state.

@@ -50,6 +50,7 @@ public function resolve(Request $request, ArgumentMetadata $argument): array
if (!$options->class || $options->disabled) {
return [];
}
// doctrine/persistence < 4 compat
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not true. $this->getManager can still return null (see the implementation of the private method). This method call is not a call to the doctrine/persistence method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, didn't spot that!

Comment on lines 57 to 59
if (method_exists(ObjectManager::class, 'isUninitializedObject')) {
$this->markTestSkipped('This test is not applicable to doctrine/persistence 4');
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@derrabus TypeError in the signature of the AbstractManagerRegistry when passing null as default manager name. And InvalidArgumentException if there is no manager with that name.

@greg0ire we cannot remove support for the case of having no entity manager. As the ManagerRegistry interface extends ConnectionRegistry in doctrine/persistence (which is a mistake to me, but won't be an easy fix) and we don't have any standalone implementation of ConnectionRegistry, DoctrineBundle will still create a manager registry even when your project enables DBAL and not ORM. And so this case exists (it won't be a case of having no manager registry at all)

Comment on lines 57 to 59
if (method_exists(ObjectManager::class, 'isUninitializedObject')) {
$this->markTestSkipped('This test is not applicable to doctrine/persistence 4');
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the proper fix is to fix the mock of the ManagerRegistry. When passing null as argument here, getManagerForClass should indeed return null but getManager should throw an InvalidArgumentException (which is already the behavior of doctrine/persistence 2.x and 3.x btw)

@greg0ire
Copy link
Contributor Author

@stof I've addressed your review.

Also, I forgot to mention it, but doctrine/persistence 4 is now indeed installed in at least this job

$registry->expects($this->any())
->method('getManager')
->willReturn($manager);
if (method_exists(ObjectManager::class, 'isUninitializedObject')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should check $manager === null. We don't want to throw when we have an instance.

And I suggest applying this condition even for older versions of doctrine/persistence so that the mock reflects the actual behavior of the class. AbstractManagerRegistry was already throwing an exception in persistence 2.x (I did not check the behavior in 1.x)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not check the behavior in 1.x

It is not allowed by Symfony's composer.json 👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know. That's exactly why I did not check 1.x to see whether our mocks were already wrong back in time or whether they kept emulating the 1.x behavior, because distinguishing those 2 cases does not matter.

@@ -635,6 +639,10 @@ public function testDedicatedEntityManagerNullObject()

public function testEntityManagerNullObject()
{
if (method_exists(ObjectManager::class, 'isUninitializedObject')) {
$this->markTestSkipped('This test is not applicable to doctrine/persistence 4');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those tests are application, for the same reason that the EntityValueResolver test (and with the same issue about a bad definition of the mock)

@@ -71,6 +71,7 @@ public function validate(mixed $entity, Constraint $constraint)
if ($constraint->em) {
$em = $this->registry->getManager($constraint->em);

// doctrine/persistence < 4 compat
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comment is actually wrong. Older versions of doctrine/persistence are also throwing an exception in getManager

@greg0ire greg0ire force-pushed the persistence-4-compat branch 3 times, most recently from d0069f8 to 0b58efa Compare January 23, 2025 14:29
@greg0ire greg0ire requested a review from stof January 23, 2025 14:49
v4 provides a guarantee that ManagerRegistry::getManager() returns an entity
manager (as opposed to null).

The tests need to be adjusted to reflect the behavior of the mocked dependency
more accurately, as it is throwing an exception in case of a null manager for
all three supported versions of the library.
@fabpot fabpot force-pushed the persistence-4-compat branch from 0b58efa to 6c20172 Compare January 25, 2025 08:05
@fabpot
Copy link
Member

fabpot commented Jan 25, 2025

Thank you @greg0ire.

@fabpot fabpot merged commit ef15506 into symfony:6.4 Jan 25, 2025
6 of 7 checks passed
This was referenced Jan 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants