Problem/Motivation
Nested layout support in lb_plus relies on a nestedStoragePath string (e.g., 0/uuid/1) that encodes the traversal path to a nested section. This path must be threaded through routes, forms, JS, event subscribers, and tempstore operations across 180+ code references. It makes nested layout handling fragile, hard to extend, and tightly coupled to SectionStorageHandler — a god-object that mixes concerns like path encoding/decoding, section traversal, block content loading, and tempstore updates.
Proposed resolution
Replace the path-based system with a NestedAwareSectionStorage decorator that wraps any SectionStorageInterface and provides:
- UUID-based lookups via a
TreeIndex— O(1) access to any block or section by UUID, eliminating path encoding/decoding. - Explicit bubbling —
bubbleChangesToRoot()replaces the oldupdateSectionStorage()pattern of manually threading changes back up. - Scoped storage —
forLayoutBlock($uuid)returns a view scoped to a nested layout block, so core forms using delta-based access work transparently with nested layouts. - Automatic service decoration — all section storages are wrapped via service decoration, so the nested-aware API is available everywhere without manual wrapping.
This eliminates SectionStorageHandler, nestedStoragePath from routes/JS/events, and lb_plus overrides of core's ConfigureSectionForm and RemoveSectionForm. Core and contrib routes with a block {uuid} parameter work automatically with nested layouts via a NestedRouteEnhancer. Section routes use a ?section_uuid= query parameter instead of lb_plus-specific route overrides.
The edit_plus_lb and lb_plus_edit_plus bridge modules are consolidated — their functionality moves into lb_plus (registered conditionally when edit_plus is available) with update hooks to auto-uninstall the deprecated modules.
API changes
SectionStorageHandlerremoved. Callers should useNestedSectionStorageInterface/NestedAwareSectionStorageinstead.nestedStoragePathremoved from routes, events, JS, and contextual link parameters. Use UUID-based methods (getPath(),getSectionsFor(),forLayoutBlock()) instead.SectionToolIndicatorEventandBlockToolIndicatorEventuselayoutBlockUuid/isNested()instead ofnestedStoragePath.- Routes simplified — block operations use
{uuid}only; section operations use core routes with?section_uuid=query parameter. ConfigureSectionFormandRemoveSectionFormremoved — core forms work via route enhancer + response subscriber.
Data model changes
None.
Comments
Comment #3
tim bozeman commented