Problem/Motivation
After update to version 3.0.0 I got this error:
'PHP message: Uncaught PHP Exception Drupal\\Core\\Entity\\Exception\\BundleClassInheritanceException: "Bundle class Drupal\\my_node\\Entity\\Bundle\\PersoonNode does not extend entity class Drupal\\book\\Entity\\Node\\Book." at /xxx/web/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php line 216'
My module is allready working for 2 years.
Steps to reproduce
Create a new Drupal 11.3 site
Create a custom module with in the my_module.module file this function:
function my_node_entity_bundle_info_alter(array &$bundles): void {
foreach ($bundles['node'] as $bundle => $data) {
if ($bundle == 'persoon') {
$bundles['node']['persoon']['class'] = PersoonNode::class;
}
}
}
Create in src\Entity\Bundle a file PersoonNode.php and PersoonNodeInterface.php file with some code.
Install the module.
Clear caches.
goto the home page.
Proposed resolution
Remaining tasks
User interface changes
API changes
Data model changes
Issue fork book-3574779
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
smustgrave commentedDid you clear cache ?
Comment #3
promesAfter running update as admin each try to open a page (admin page or regular page) results in an error message. I did try to run rebuild.php but to no avail.
The error occurs also in other sites.
Comment #4
smustgrave commentedneed to run drush cr
Comment #5
promesAfter drush cr still the same error.
Comment #6
smustgrave commentedNot seen that but imagine it's around this code https://git.drupalcode.org/project/book/-/blame/3.0.x/src/Hook/BookHooks...
Comment #7
liam morlandComment #8
aayushpathak commentedworking on it !
Comment #10
aayushpathak commentedComment #11
promesI installed v3.0 and patched it with the code from https://git.drupalcode.org/project/book/-/merge_requests/166/diffs.
After running the update I got this message:
book-module
#103007 update
Failed: Drupal\Core\Entity\Exception\BundleClassInheritanceException: Bundle class Drupal\my_node\Entity\Bundle\PersoonNode does not extend entity class Drupal\book\Entity\Node\Book. in Drupal\Core\Entity\ContentEntityStorageBase->getEntityClass() (line 216 of /xxx/web/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php).
Comment #12
aayushpathak commentedI have updated the merge request to conditionally override the Node entity class only when it still uses the default `Drupal\node\Entity\Node` class. This prevents the Book module from forcing the `Drupal\book\Entity\Node\Book` class when another module defines a custom bundle class . which previously caused the `BundleClassInheritanceException`. Could you please check if the error is still reproducible after applying the updated changes?
Comment #13
smustgrave commentedThis will need test coverage. Also some out of scope styling changes in there
Comment #14
liam morlandI have un-done the coding style changes. All tests and checks are passing now.
Comment #15
aayushpathak commentedAdded kernel test coverage to ensure the Book module does not override custom node entity classes. Please verify.
Comment #16
promesI got the same error again. But this time not in the update.php page (I am using the UX) like yesterday.
I see some differences with my module. I hope this can help you in testing.
The bundle is defined in my module with name my_node.
The actual class is in:
myTest.php
myTestInterface.php
myNode.php:
Comment #17
smustgrave commentedComment #18
philipnorton42 commentedI encountered this issue as well. I attempted to create an entity bundle class and this caused the site to throw the same error as other people have encountered until I just extended the
Bookclass instead of theNodeclass in my bundle class.I'm not sure that replacing the core Node class is the correct approach here. I can see why it's done, but it seems like it will lead to problems as it replaces a core class and any site that uses this entity bundle class replacement technique will trow an error. Unless this is a bug in Drupal I would suggest a different approach.
I've been looking around the Drupal codebase to see how other modules do things. The content moderation module has a
entity_bundle_info_alterthat does a small entity query to figure out which content types are connected to content moderation before injecting a property. See the classDrupal\content_moderation\Hook\ContentModerationHooks.What do you think of using the
entity_type_buildhook to add in the book related items (book_outline etc), and then using theentity_bundle_info_alterhook to change the class? The only issue here is that if a site changed the bundle class they would lose some of the book functionality, rather than crashing the site.Comment #19
philipnorton42 commentedOh, also, if you spot this on your site and need a work around for now then you can extend the Book class in your entity bundle class. Even if your node bundle class doesn't have book functionality.
eg:
Comment #21
smustgrave commentedTrying a different approach using the allowed_types key but causing test failures. Will continue looking at those later if anyone can see if this is fixing hte issue locally.
Comment #22
smustgrave commentedThis change scares the hell out of me. But maybe assigning book to every node was always a bad approach.
Comment #23
liam morlandThere should probably be a
BookInterface.Comment #24
promesI ran composer update to todays 3.0-dev.
Then update.php
Still the same error
Then I did all update s from:
3574779-bundle-class-alternative Comparechanges, plain diff Status: PassedMR !168 mergeable
Hide branch
3574779-bundleclassinheritanceexception Comparechanges, plain diff MR !166
Again update.php. Still the same error.
Should I update only according to:
3574779-bundle-class-alternative Comparechanges, plain diff Status: PassedMR !168 mergeable
Hide branch
3574779-bundleclassinheritanceexception Comparechanges, plain diff MR !166
Comment #25
smustgrave commentedSorry not sure what you're asking but you can apply 168 as a patch. Running updb should trigger a cache rebuild.
Comment #26
joseph.olstadFor those not familiar with gitlab or github, take the mr to the number and add .diff or .patch
https://git.drupalcode.org/project/book/-/merge_requests/168.diff
Comment #28
smustgrave commentedKinda out of scope but added a basic interface
Comment #29
promesI installed the 3.0-dev version and applied !168. After updating I didnt get an error.
Viewing a book goes ok.
I created a new entry for a book. I was not able to add it to the book. First I tried twice in edit mode. Then I tried outline mode and then I got this error:
Drupal\Core\Database\IntegrityConstraintViolationException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '75' for key 'PRIMARY': INSERT INTO "book" ("nid", "bid", "pid", "weight", "depth", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9") VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9, :db_insert_placeholder_10, :db_insert_placeholder_11, :db_insert_placeholder_12, :db_insert_placeholder_13); Array ( [:db_insert_placeholder_0] => 75 [:db_insert_placeholder_1] => 72 [:db_insert_placeholder_2] => 72 [:db_insert_placeholder_3] => 0 [:db_insert_placeholder_4] => 2 [:db_insert_placeholder_5] => 72 [:db_insert_placeholder_6] => 75 [:db_insert_placeholder_7] => 0 [:db_insert_placeholder_8] => 0 [:db_insert_placeholder_9] => 0 [:db_insert_placeholder_10] => 0 [:db_insert_placeholder_11] => 0 [:db_insert_placeholder_12] => 0 [:db_insert_placeholder_13] => 0 ) in Drupal\mysql\Driver\Database\mysql\ExceptionHandler->rethrowNormalizedException() (line 83 of /xxx/web/core/modules/mysql/src/Driver/Database/mysql/ExceptionHandler.php).
The website is created in Drupal 4, upgraded to D5, D6, D7, D9, D10 and now in D11. The book pages are basic_pages assigned to the book.
Comment #30
smustgrave commentedI'm not able to replicate that issue.
Comment #31
promesThe good news is: the book structure in the database is updated and correct. And the new entry can be found in the book.
Comment #32
smustgrave commentedtried again but not getting a duplicate entry error. Could you try on a fresh install? Maybe something got corruptedz/
Comment #33
liam morlandSince
NodeInterfaceis replaced withBookInterfacein several places, that suggests thatBookInterfaceshould extendNodeInterface.Comment #34
promesI did a install on a new site with version 3.0.1.
I am missing the bar at the bottom showing the title of the previous book, Up, and the title of the next book.
When I merge !168 I have these problems:
Go to /admin/structure/book/1 I get an page not found
When I goto /book-1 (the first book page created I get a message something goes wrong:
AssertionError: assert($node instanceof Book) in assert() (line 80 of modules/contrib/book/src/Controller/RouteAccessController.php).
Drupal\book\Controller\RouteAccessController->checkIfBookHasChildren() (Line: 60)
Drupal\book\Controller\RouteAccessController->access()
call_user_func_array() (Line: 66)
Drupal\Core\Access\CustomAccessCheck->access()
call_user_func_array() (Line: 160)
Drupal\Core\Access\AccessManager->performCheck() (Line: 136)
Drupal\Core\Access\AccessManager->check() (Line: 93)
Drupal\Core\Access\AccessManager->checkNamedRoute() (Line: 333)
Drupal\Core\Menu\LocalTaskManager->getTasksBuild() (Line: 375)
Drupal\Core\Menu\LocalTaskManager->getLocalTasks() (Line: 275)
Drupal\navigation\NavigationRenderer->getLocalTasks() (Line: 319)
Drupal\navigation\NavigationRenderer->hasLocalTasks() (Line: 248)
Drupal\navigation\NavigationRenderer->removeLocalTasks() (Line: 111)
Drupal\navigation\Hook\NavigationHooks->blockBuildLocalTasksBlockAlter() (Line: 460)
Drupal\Core\Extension\ModuleHandler->alter() (Line: 91)
Drupal\block\BlockViewBuilder->viewMultiple() (Line: 34)
Drupal\block\BlockViewBuilder->view() (Line: 152)
Drupal\block\Plugin\DisplayVariant\BlockPageVariant->build() (Line: 274)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare() (Line: 131)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse() (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray() (Line: 246)
Symfony\Component\EventDispatcher\EventDispatcher::{closure:Symfony\Component\EventDispatcher\EventDispatcher::optimizeListeners():241}() (Line: 206)
Symfony\Component\EventDispatcher\EventDispatcher->callListeners() (Line: 56)
Symfony\Component\EventDispatcher\EventDispatcher->dispatch() (Line: 188)
Symfony\Component\HttpKernel\HttpKernel->handleRaw() (Line: 76)
Symfony\Component\HttpKernel\HttpKernel->handle() (Line: 53)
Drupal\Core\StackMiddleware\Session->handle() (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle() (Line: 28)
Drupal\Core\StackMiddleware\ContentLength->handle() (Line: 32)
Drupal\big_pipe\StackMiddleware\ContentLength->handle() (Line: 118)
Drupal\page_cache\StackMiddleware\PageCache->pass() (Line: 92)
Drupal\page_cache\StackMiddleware\PageCache->handle() (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle() (Line: 53)
Drupal\Core\StackMiddleware\AjaxPageState->handle() (Line: 54)
Drupal\Core\StackMiddleware\StackedHttpKernel->handle() (Line: 745)
Drupal\Core\DrupalKernel->handle() (Line: 19)
Comment #35
smustgrave commentedIf you do a fresh install this is by design, you have to enable in the display
I'm not able to reproduce this, did you clear cache?
I did find an issue with the preDelete() code.
The previous structure was that all nodes were getting the book key, regardless. So that's stopped now.
Comment #36
promes1. Bar at bottom: thats new for me. Thanks.
Of course I did a clear cache.
Comment #37
promesI reinstalled v3.0.1 and added the current MR !168. Thanks: Great result. It works now.
Comment #38
smustgrave commentedWill merge later this evening thanks!
Comment #39
smustgrave commentedThanks all glad we got there!
Comment #42
promesSorry, I have to reopen the issue. In a second site I updated the module to v3.0.2, updated the site and cleared caches.
I went to a book page and got this error:
Error: Call to undefined method Drupal\mynode\Entity\Bundle\CommonNode::getBook() in Drupal\book\Hook\BookHooks->nodeView() (line 184 of /xxx/web/modules/contrib/book/src/Hook/BookHooks.php).
In mynode\Entity\Bundle\CommonNode I don't use any reference to a book.
I presume in line 184 $node->getBook(); is not specific enough.
Comment #43
smustgrave commentedif ($display->getComponent('book_navigation') || $display->getComponent('book_navigation_without_tree')) {This got triggered first
Comment #44
smustgrave commentedSeems others hit this will do an emergency deploy soon.