Overview
SdcController::layout() currently works with an array structure to model the tree structure.
In order to unlock other implementations of a tree structure, we need typed value objects.
This will make the tree structure better defined, and would unblock a Just-in-Time approach of loading e.g. Layout Builder into the Experience Builder UI, which in turn enables a smooth, gradual adoption/transition from Layout Builder to Experience Builder.
Proposed resolution
Add objects per https://git.drupalcode.org/project/experience_builder/-/merge_requests/68 (see ComponentLeaf(Interface) and friends)
User interface changes
Issue fork experience_builder-3462235
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
wim leersThis should also allow refactoring #3460856: Create validation constraint for ComponentTreeStructure to make it simpler 👍
Comment #3
larowlanBrought in the value objects and a normalizer. Will continue tomorrow
Comment #4
larowlanComment #6
wim leersComment #8
wim leersReviewed! (Review delayed due to #3446722: Introduce an example set of representative SDC components; transition from "component list" to "component tree", I explained this in my review on the MR.)
Comment #9
wim leersComment #10
larowlanThanks Wim, I'll pick this up again after vacation
Comment #11
wim leers👍 Enjoy! 😊
Comment #12
wim leersHaving introduced the very barebones
ClientSideRepresentationobject last night in #3484678: Simplify ComponentSourceInterface::getClientSideInfo(), introduce ClientSideRepresentation value object, and leverage it, and seeing the existence of both:ClientServerConversionTraitthat was introduced in ~2 months ago at #347856: Gallery module: page not found… makes me realize that you probably just were able to see months into the future with this proposal 😅 🤩
I definitely could not. Not until #3491013: Rework layout API to separate components and slots and #3489899: Add support for global regions had landed, both of which clarified the client-side data model, and it:
docs/adr/0005-Keep-the-front-end-simple.mddocs/data-model.md, sectionNow that all that is in place (i.e. we know the client-side data model), I can totally see the value of what this MR originally envisioned: the ability to "upcast" any data source into the data model expected by the client, which will allow loading it into the client and then saving it into an XB field.
That means I'm now somewhat disagreeing with point 1 of my August 8 comment at https://git.drupalcode.org/project/experience_builder/-/merge_requests/1.... Although I do still think it'd probably be more powerful/interesting to be able to convert to the server-side data model directly, I'm not sure that that is required or even sensible — because I suspect that we'd never auto-convert "Layout Builder data" to "Experience Builder data", but instead make the transition trivial, while still requiring a human to do so.
Conclusion: I think that what I wrote in August might be the ideal scenario from a migration path POV, but I doubt it's realistic to achieve perfection. To overcome that imperfection, we could require human intervention, which is exactly what your proposal achieves. Thoughts?
Comment #13
larowlanThe other thing this enables is the BC layer for Paragraphs and Layout builder for #3462238: Decouple tree storage, introduce tree storage plugins
Because we will need a contract for 'here is an entity, load me a tree for it' and the value object is 'the tree' in that contract.
This will allow us to load legacy layout builder layouts (a subset of what XB supports) and edit them in XB, saving them as XB data - allowing sites to progressively update (one edit at a time).
Comment #14
wim leersYep, very much aware of that! :D
That's what I was referring to in #12. And it's that "require human intervention" question at the end I wanted to double-check you're on the same page for? 🤞
Comment #15
larowlanI'm tagging this as a stable blocker because we need an API for things that aren't
ComponentTreeItemto be able to return a layout/model - e.g. layout builder, paragraphs.We also would make use of it in our config entities and be able to remove
\Drupal\experience_builder\Plugin\Field\FieldType\ComponentTreeItemInstantiatorTrait::createDanglingComponentTreeIt is a blocker for #3462238: Decouple tree storage, introduce tree storage plugins which is a stable blocker (see reasons there)
Comment #16
kristen poltagging for findability
Comment #17
wim leersAFAICT this will essentially have been implemented by #3468272: Store the ComponentTreeStructure field property one row per component instance, see #3468272-34: Store the ComponentTreeStructure field property one row per component instance.
Comment #18
larowlanI think this will likely become 'extract interface from ComponentTreeItemList and ComponentTreeItem' once that issue is in, that will then allow other implementations for EG layout builder and pargraphs update paths.
Comment #19
wim leersHm, that seems pretty different from just-in-time loading mentioned in the issue summary? Because that would be in the client-side data model, whereas everything here is about the server-side data model.
See also the discussion at your other issue, #3462238: Decouple tree storage, introduce tree storage plugins, which this seems to be converging with.
Can we keep only one of the two issues?
Comment #20
wim leersComment #21
larowlanClosing this for now until we actually work on LB support it might not be needed