Inline Blocks on Layout Builder Fail to Clone Correctly

Created on 22 April 2019, about 5 years ago
Updated 8 May 2024, about 2 months ago

Problem/Motivation

If someone clones any Layout Builder-enabled entity that has inline block content, and then subsequently deletes the original entity, the inline blocks on the cloned entity will be deleted on the next cron run. Content editors will see a "This content is missing or broken" message while in "Layout editing" mode. In "View" mode, the node will omit the content altogether. The missing content cannot be recovered.

Steps to reproduce

1. From a clean site installation, enabled "Layout Builder" and "Entity Clone" and configure a node type to use Layout Builder.
2. Create a page and add a single inline block of any type to the the layout.
3. Clone the page. The content will look fine.
4. Delete the original node. The content on the cloned node will still appear.
5. Run cron.
6. View the cloned page. The content on the cloned node will be missing.

Root cause

The entity_clone module clones Layout Builder-style entities by copying verbatim the data in [entity]__layout_builder__layout from one entity to the next. This data copies the block ID of inline blocks as-is. This works just fine for allowing content changes between the nodes to differ, since changes are stored as new block **revision** IDs.

Example of why things work fine *before* deletion:
- Start with a site empty of content. Create a Layout Builder node with a single inline block.
- Node 1 will now have an inline block with ID 1. That block's revision number is also 1.
- Change the content of that inline block. Node 1 now references block 1, revision 2.
- Clone node 1. A New node, 2, is created. It references block 1, revision 2 (i.e., copied verbatim).
- Change node 1's block. It now references block 1, revision 3, while node 2 still references revision 2.
- Change node 2's block content. It now references block 1, revision 4, while Node 1 still references block 1, revision 3.

The problem arises when the original node is deleted. This marks the inline block with ID 1 as ready for deletion. When layout_builder_cron() executes during the next cron run, it deletes block ID 1, along with all of its revisions, and the content on Node 50 is lost.

Proposed resolution

First, adjust the behavior of the entity_clone module so that when Layout Builder-style entities are cloned, inline blocks are resaved as new blocks with distinct block IDs. This is the correct solution from the standpoint of Layout Builder's architecture: an inline block is expected only to be referenced in one place.

However, this alone will not fix entities cloned prior to the proposed change.

So, second, add an update hook to examine each row in [entity]_revision__layout_builder__layout and count the instances of block references and then re-save ones that have more than one count and update the data in [entity]__layout_builder__layout and [entity]_revision__layout_builder__layout with the new block ids. Special care should be taken to preserve revisions of these newly created blocks (and thus preserve the ability to revert to a previous revision of the node).

Finally, since there are likely some sites with already-missing and unrecoverable blocks, create an audit tool that can identify these for site owners.

User interface changes

None.

API changes

Inline blocks should always be duplicated during clone.

Data model changes

None.

🐛 Bug report
Status

Needs work

Version

2.0

Component

Code

Created by

🇺🇸United States josephdpurcell@gmail.com

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.69.0 2024