Problem/Motivation

If a bundle class does not exist, the exception message does not correctly explain the problem:

> Bundle class Drupal\fo\Entity\Bundle\Foo does not extend entity class Drupal\media\Entity\Media.

when in fact the problem is that the class doesn't exist at all.

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Comments

joachim created an issue. See original summary.

andregp’s picture

Assigned: Unassigned » andregp

I'll try to work on that :)

andregp’s picture

Assigned: andregp » Unassigned
Status: Active » Needs review
StatusFileSize
new975 bytes

Here is a patch where I added a conditional for the cases were the bundle class given doesn't exist.

joachim’s picture

Status: Needs review » Needs work

Thanks for the patch!

However, the exception class BundleClassInheritanceException doesn't suit the problem here, because its name says there is an inheritance problem.

The problem we are trying to report here is a missing class.

So we need to add a check for class_exists() before the check for inheritance, and throw a different exception. I think https://api.drupal.org/api/drupal/vendor%21symfony%21error-handler%21Err... would be suitable here?

andregp’s picture

Assigned: Unassigned » andregp

All right, thanks for the orientation. I'll work on that.

dww’s picture

Issue tags: +Bug Smash Initiative

Thanks for opening this issue and working on fixing it! Sorry for the misleading exception text. Something else we all missed in #2570593: Allow entities to be subclassed using "bundle classes" 😉 Agreed this is a bug and tagging to be smashed. Happy to review / RTBC when ready.

Thanks again!
-Derek

andregp’s picture

Assigned: andregp » Unassigned
Status: Needs work » Needs review
StatusFileSize
new1.39 KB

This new patch adds the class_exists() check before the check for inheritance (on the ContentEntityStorageBase class). I haven't sent a diff here because this new patch applies to a different class.

andregp’s picture

Assigned: Unassigned » andregp
Status: Needs review » Needs work

After talking with @joachim he advised that the best approach would be to create a new exception class to use here instead of the "\Symfony\Component\ErrorHandler\Error\ClassNotFoundError" so I'll work on this.

andregp’s picture

StatusFileSize
new2.29 KB
new2.09 KB

So here is a patch with the new MissingBundleClassException which is called when the given bundle class doesn't exist.
Still not marking this issue as "needs review" though, because I believe we'll need to add a new test to cover it. So, I'll try to do it.

joachim’s picture

> Still not marking this issue as "needs review" though, because I believe we'll need to add a new test to cover it. So, I'll try to do it.

I think it's ok to hold off on a test as the location of the check is going to move in #3261540: checks for bundle entity classes should happen in rebuild, not runtime. That will make a test a bit simpler, so writing it here would be work that would be then thrown away.

joachim’s picture

Status: Needs work » Reviewed & tested by the community

Patch looks good to me.
Thanks!

dww’s picture

Status: Reviewed & tested by the community » Needs work

Yeah, even if the test has to move or be updated, we still can’t commit a new exception here without test coverage of it.

dww’s picture

Issue tags: +Needs tests

e.g. Should be pretty trivial to extend core/tests/Drupal/KernelTests/Core/Entity/BundleClassTest.php for this.

andregp’s picture

Okay then, I'll adventure myself on this and try to add the new test. :)

andregp’s picture

Assigned: andregp » Unassigned
Status: Needs work » Needs review
Issue tags: -Needs tests
StatusFileSize
new4.47 KB
new1.84 KB

Here is it!
I hope I have done all right (that's the first time I try to create a Drupal test).
:)

andregp’s picture

StatusFileSize
new1.84 KB

Sorry, wrong diff extension... here is the .txt

joachim’s picture

Status: Needs review » Reviewed & tested by the community

LGTM!

And actually, when we do #3261540: checks for bundle entity classes should happen in rebuild, not runtime, we just have to remove this line from the test:

+++ b/core/tests/Drupal/KernelTests/Core/Entity/BundleClassTest.php
@@ -249,6 +250,17 @@ public function testBundleClassShouldExtendEntityClass() {
+    $this->storage->create(['type' => 'bundle_class']);

The last submitted patch, 15: 3261538-15.patch, failed testing. View results

dww’s picture

StatusFileSize
new4.37 KB
new4.47 KB

#18 is a random fail. However, instead of re-queuing #16 (which I agree is RTBC), here's a test-only and full pair so we can watch the new test fail as expected. Full patch is identical to #16.

Thanks!
-Derek

dww’s picture

StatusFileSize
new4.37 KB
new4.47 KB
new457 bytes

Hah, you'd think after dozens (hundreds?) of times trying to speed up the bot by hacking core/drupalci.yml for a test-only patch, that I could get it right the first time. 🤦‍♂️ Nope! 😆 Let's try that again...

The last submitted patch, 20: 3261538-20.test-only.patch, failed testing. View results

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 20: 3261538-20.patch, failed testing. View results

dww’s picture

Status: Needs work » Needs review

Test only failed as expected. Same random fail for the real patch. Weird. Re-queuing once more.

dww’s picture

Status: Needs review » Reviewed & tested by the community

Not my code, just getting good bot results for commit. Back to RTBC.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/system/tests/modules/entity_test_bundle_class/entity_test_bundle_class.module
@@ -32,6 +32,10 @@ function entity_test_bundle_class_entity_bundle_info_alter(&$bundles) {
+  if (\Drupal::state()->get('entity_test_bundle_class_does_not_exist', FALSE)) {
+    $bundles['entity_test']['bundle_class']['class'] = NonExistentClass::class;
+  }

This fails PHPStan checks on Drupal 10. It would be better if this was not NonExistentClass::class; but something like 'Drupal\Core\NonExistentClass' as using a string rather than ::class has got to be preferrable.

andregp’s picture

But the patch is for Drupal 9, does it need to be changed?
(Also, the other lines on the file follow this same pattern, should we create a separate issue to fix them?)

joachim’s picture

> (Also, the other lines on the file follow this same pattern, should we create a separate issue to fix them?)

The point is that NonExistentClass doesn't exist, so using it in PHP code as if it were a real class causes the static analysis to complain, quite correctly. Maybe that level of static analysis is only done on D10, but IDEs will complain about it in general, so we should fix this.

The other classes in the test, such as EntityTestAmbiguousBundleClass and NonInheritingBundleClass do actually exist, so IDEs are ok with those.

We work around this by giving the class as a quoted string. IDEs see that NonExistentClass::class is a class, but they don't know that 'NonExistentClass' is supposed to be a class.

andregp’s picture

Assigned: Unassigned » andregp

Thanks @joachin for the explanation! :)
I'll fix it!

andregp’s picture

Assigned: andregp » Unassigned
Status: Needs work » Needs review
StatusFileSize
new4.47 KB
new662 bytes

Here is the patch.

joachim’s picture

Status: Needs review » Reviewed & tested by the community

Perfect, thanks!

alexpott’s picture

Version: 9.4.x-dev » 9.3.x-dev
Status: Reviewed & tested by the community » Fixed

Committed and pushed 2b1faaacb1 to 10.0.x and 1d7fd63519 to 9.4.x and cac70bf799 to 9.3.x. Thanks!

diff --git a/core/modules/system/tests/modules/entity_test_bundle_class/entity_test_bundle_class.module b/core/modules/system/tests/modules/entity_test_bundle_class/entity_test_bundle_class.module
index c6c3d2ce5f..47a525634e 100644
--- a/core/modules/system/tests/modules/entity_test_bundle_class/entity_test_bundle_class.module
+++ b/core/modules/system/tests/modules/entity_test_bundle_class/entity_test_bundle_class.module
@@ -34,7 +34,7 @@ function entity_test_bundle_class_entity_bundle_info_alter(&$bundles) {
   }
 
   if (\Drupal::state()->get('entity_test_bundle_class_does_not_exist', FALSE)) {
-    $bundles['entity_test']['bundle_class']['class'] = 'NonExistentClass';
+    $bundles['entity_test']['bundle_class']['class'] = '\Drupal\Core\NonExistentClass';
   }
 }
 

Fixed on commit. I'd rather we were using classes that do not exist from our own namespace and not the global one.

  • alexpott committed 2b1faaa on 10.0.x
    Issue #3261538 by andregp, dww, joachim, alexpott:...

  • alexpott committed 1d7fd63 on 9.4.x
    Issue #3261538 by andregp, dww, joachim, alexpott:...

  • alexpott committed cac70bf on 9.3.x
    Issue #3261538 by andregp, dww, joachim, alexpott:...
dww’s picture

Yay, thanks everyone!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.