Problem/Motivation
Reverting a Display Builder entity view override to its default display has two bugs:
Bug 1 — PHP fatal error:
Error: Call to undefined method
Drupal\display_builder_entity_view\Entity\LayoutBuilderEntityViewDisplay::getSources()
at DisplayBuilderSubscriber::onRevert() line 77.
The subscriber loads a display entity and tries to call getSources() on it, but that method belongs to the DisplayBuildableInterface plugin, not the display entity itself.
What the code does:
$display = $this->entityTypeManager->getStorage('entity_view_display')->load($config['display_id']);
$instance->setNewPresent($display->getSources(), 'Revert 2/2');
// ^^^^^^^^^^ — LayoutBuilderEntityViewDisplay has no getSources()Bug 2 — UI not refreshed (caused by subscriber ordering):
Even after fixing the fatal error (by reading the third-party setting directly instead), the builder UI still shows the old overridden layout after revert. A full page reload reveals the correct state.
The root cause is that ApiPublishingController::revert() dispatches DisplayBuilderEvents::ON_REVERT before mutating the instance. Two event subscribers listen with equal priority (0):
- 1. DisplayBuilderEventsSubscriber::onRevert() — dispatches to islands, which call $instance->getCurrentState() and generate OOB swap responses with stale data
- 2. DisplayBuilderEntityView\DisplayBuilderSubscriber::onRevert() — clears the entity override field and reloads sources from the base display config
Because both have priority 0, execution order depends on container compilation order (module weight). In most cases the islands read the instance before the revert logic runs, producing OOB swaps with stale content. The data is correctly saved to storage, but the UI shows the old state until a full page reload.
Note that publish() and restore() do not have this problem because they both mutate the instance before dispatching their events.
Steps to reproduce
Proposed resolution
Move the revert logic out of the event subscriber and into a revert() method on the Instance entity, called by the controller before dispatching ON_REVERT. This follows the same pattern as publish() and restore().
Remaining tasks
User interface changes
API changes
Data model changes
Issue fork display_builder-3612675
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 #3
pdureau commentedHello ZiQiang,
What you have started, removing
DisplayBuilderSubscriberand triggering the revert fromApiPublishingController::revert()like we already do inotherApiPublishingControllermethods is the way to go 👍Comment #4
pdureau commentedComment #5
ipumpkin@pdureau thanks
Comment #6
mogtofu33 commentedI think it needs rebase + fix phpstan error, and eventually related tests.
Comment #7
mogtofu33 commentedComment #8
ipumpkinComment #9
mogtofu33 commentedI think we are still missing something, as restore after revert is available when it should probably not. And click 'Restore' will delete the override display which is ok, but then the builder is empty.
I check that.
Comment #10
mogtofu33 commentedSeems it needs more for the Restore problem, created #3613399: Entity override Revert -> Restore logic to not block this fix for release.
Thanks for the work.