Problem/Motivation
When this module replicates the layout section "components" in a layout builder layout, it does so in such a way that the original order of the blocks may be lost.
A layout builder section stores its components in an array. The order they appear in this array is actually not really relevant to the output order. Instead, each component has a weight property that controls that (since during rendering, the array is converted to a render array, these weights are used). When this module replicates a section, it processes one component at a time, removing it from the section, replicating it, then re-appending to the section using Section::appendComponent. This method resets the weight of the component, losing the original value:
/**
* Appends a component to the end of a region.
*
* @param \Drupal\layout_builder\SectionComponent $component
* The component being appended.
*
* @return $this
*/
public function appendComponent(SectionComponent $component) {
$component->setWeight($this->getNextHighestWeight($component->getRegion()));
$this->setComponent($component);
return $this;
}
Steps to reproduce
- Create a node on a layout-builder enabled (with overrides) content type and edit its layout
- Add block to region of a section
- Add another block to that same region of the section, so it appears below the first
- Drag the 2nd block above the 1st
- Save the layout
- Replicate the node
- Observe that on the replicated node, the order of the blocks is not the same as the original
Proposed resolution
Ideally we could just use the setComponent method of Section, but it's protected.
Instead, I think that we can just order the components by their weight before replicating them.
Remaining tasks
User interface changes
API changes
Data model changes