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
| Comment | File | Size | Author |
|---|---|---|---|
| #29 | interdiff_3261538_20-29.txt | 662 bytes | andregp |
| #29 | 3261538-29.patch | 4.47 KB | andregp |
| #20 | 3261538-20.patch | 4.47 KB | dww |
| #20 | 3261538-20.test-only.patch | 4.37 KB | dww |
| #19 | 3261538-19.patch | 4.47 KB | dww |
Comments
Comment #2
andregp commentedI'll try to work on that :)
Comment #3
andregp commentedHere is a patch where I added a conditional for the cases were the bundle class given doesn't exist.
Comment #4
joachim commentedThanks 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?
Comment #5
andregp commentedAll right, thanks for the orientation. I'll work on that.
Comment #6
dwwThanks 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
Comment #7
andregp commentedThis 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.
Comment #8
andregp commentedAfter 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.
Comment #9
andregp commentedSo 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.
Comment #10
joachim commented> 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.
Comment #11
joachim commentedPatch looks good to me.
Thanks!
Comment #12
dwwYeah, even if the test has to move or be updated, we still can’t commit a new exception here without test coverage of it.
Comment #13
dwwe.g. Should be pretty trivial to extend
core/tests/Drupal/KernelTests/Core/Entity/BundleClassTest.phpfor this.Comment #14
andregp commentedOkay then, I'll adventure myself on this and try to add the new test. :)
Comment #15
andregp commentedHere is it!
I hope I have done all right (that's the first time I try to create a Drupal test).
:)
Comment #16
andregp commentedSorry, wrong diff extension... here is the .txt
Comment #17
joachim commentedLGTM!
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:
Comment #19
dww#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
Comment #20
dwwHah, you'd think after dozens (hundreds?) of times trying to speed up the bot by hacking
core/drupalci.ymlfor a test-only patch, that I could get it right the first time. 🤦♂️ Nope! 😆 Let's try that again...Comment #23
dwwTest only failed as expected. Same random fail for the real patch. Weird. Re-queuing once more.
Comment #24
dwwNot my code, just getting good bot results for commit. Back to RTBC.
Comment #25
alexpottThis 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.Comment #26
andregp commentedBut 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?)
Comment #27
joachim commented> (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.
Comment #28
andregp commentedThanks @joachin for the explanation! :)
I'll fix it!
Comment #29
andregp commentedHere is the patch.
Comment #30
joachim commentedPerfect, thanks!
Comment #31
alexpottCommitted and pushed 2b1faaacb1 to 10.0.x and 1d7fd63519 to 9.4.x and cac70bf799 to 9.3.x. Thanks!
Fixed on commit. I'd rather we were using classes that do not exist from our own namespace and not the global one.
Comment #35
dwwYay, thanks everyone!