Problem/Motivation
When loading the Layout Builder UI for content that predates lb_plus (or any content whose sections lack the lb_plus.uuid third-party setting), section UUIDs are generated during tree indexing but never persisted to tempstore.
LayoutBuilderPlus::layout() calls prepareLayout() first, which triggers core's PrepareLayout event subscriber to serialize and save the section storage to tempstore. Then getTreeIndex() runs and generates random UUIDs on the in-memory Section objects. These UUIDs appear in the rendered HTML but the tempstore entry still holds the pre-indexing version without them.
On the next AJAX request (moving a block, adding a section, etc.), the section storage is loaded from tempstore without UUIDs, tree indexing generates new random UUIDs, and those don't match the UUIDs in the browser's DOM — breaking the operation.
Steps to reproduce
- Have a content entity with Layout Builder overrides that predate lb_plus (sections have no
lb_plus.uuidthird-party setting) - Open the Layout Builder UI for that entity
- Attempt any AJAX operation (drag a block, add a section, etc.)
- The operation fails because the UUID rendered in the markup no longer matches the UUID generated on the AJAX request
Proposed resolution
Add an isDirty() / markDirty() API to NestedSectionStorageInterface to track when the storage has been modified in a way that needs persisting. When indexSectionsRecursive() generates a new section UUID, it marks the storage as dirty. After building the tree index in LayoutBuilderPlus::layout(), if the storage is dirty, re-save to tempstore so the generated UUIDs are persisted for subsequent requests.
The dirty flag is generic and can be reused by other operations that modify storage state after the initial tempstore save.
API changes
Added two methods to NestedSectionStorageInterface:
isDirty(): bool— checks whether the storage has unsaved changesmarkDirty(): void— marks the storage as having unsaved changes
Data model changes
None.
Issue fork lb_plus-3582911
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
lillian bozeman commentedComment #5
tim bozeman commentedThank you!