Overview

Requirement list for Experience Builder in row 5 has item defined as “Place blocks as components” (link to spreadsheet). Accompanying this requirement is the following user story:

As a builder, I can place and render blocks and fields rendered via Twig if they are exposed to the page builder as components. Blocks and fields defined in Twig should be able to render both in the preview, and the end-user facing page. This is to enable backwards compatibility with code that already exist in contrib and custom modules.

Currently Component entity is tightly coupled to SDCs, this is being partially resolved in #3469609. However, the Component entity will still be directly tied in 1:1 relationship with single directory components that meet Experience Builder requirements.

Proposed resolution

There seems to be general consensus between @larowlan, @wim-leers, @effulgentsia, @tedbow, @longwave and @fmazeikis that we for we should retain Component entity type, but it needs to be able to function as translation layer between different types of sources, for example - SDCs, Blocks, Layouts and Paragraphs.
@longwave have put it pretty well in 3454519#comment-15778070:

We could try to repurpose SDCs so they can wrap blocks or layouts, but this doesn't conceptually appear to be the right thing to do - SDCs are self contained single directory components by definition, so expanding them with features beyond is scope creep.

We could try to use blocks everywhere and wrap SDCs in blocks, but then we run into the slots issue, and would have to extend blocks so they support slots in some way.

What we are trying to do here is map props/values and slots/components into (at least) three things that are conceptually different (SDCs, blocks, layouts). This is effectively a translation layer and as such should be entirely standalone from the sources and targets of the translation; therefore I think this is the correct direction for this problem.

This issue will adapt some of the code proposed by @larowan in #3454519. Specifically, we will introduce this part of proposal:

Component source plugin

This decouples the component config entity and component tree from SDC components. There's a SingleDirectoryComponent implementation that all the existing logic moves to Adds two additional implementations as follows:

  • Blocks - this will support blocks (e.g. views, menus) as well as a bridge to layout builder

This issue will intentionally not introduce the rest of the proposals of #3454519 in order to limit the scope of the issue to blocks. This issue will only add the initial set of "ComponentSourcePlugins" - "SDC Source Plugin" and "Block Source Plugin".

This doesn't mean this implementation is final and other Source Plugins may be introduced in separate issues or the entire approach could change in the future.

This issue will only allow fully validatable blocks, and blocks that are allowed in Settings Tray, to be placed in the UI.

User interface changes

For now, block plugins appear under the main "Default components" section in the UI, but in a future issue they will be moved to a separate "Dynamic components" section.

Command icon 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

f.mazeikis created an issue. See original summary.

f.mazeikis’s picture

Assigned: Unassigned » f.mazeikis
wim leers’s picture

Title: Add support for Blocks as Components » [PP-1] Add support for Blocks as Components

f.mazeikis’s picture

I wasn't marking it as blocking as it looked as if the issue would be merged anyway and we could have started this issue while the work continued on #3469609. And it is merged now.
I've moved most of the code from MR68 (closed) by @larowlan and reached out to him on slack as I couldn't retain his commit signature.
This is not a working commit and will be used as starting point.

wim leers’s picture

Version: » 0.x-dev
Status: Active » Needs work

Did an initial high-level review. Looks to be on the right track! 😄 👍 I bet @larowlan will be pleased 😁

Thanks for getting this going! 🙏

Marking needs work for the following high-level bugs:

  1. mixed up BlockInterface (which is for Block config entities) versus BlockPluginInterface (which is for block plugins). We need only the latter.
  2. unclear what the purpose of expose_settings is, and AFAICT it cannot result in validatable XB Component config entities
  3. related to the above: the existing defaults should be moved into the SDC source-specific settings
wim leers’s picture

Title: [PP-1] Add support for Blocks as Components » Add support for Blocks as Components
Priority: Normal » Critical
Issue tags: +Needs documentation updates, +Configuration schema, +validation
Related issues: +#3468112: Document the current component discovery + SDC criteria + `Component` config entity, and describe in an ADR

#3469609: Prepare for multiple component types: ComponentTreeStructure should contain Component config entity IDs, not SDC IDs landed ~2 weeks ago. Updating title.


@f.mazeikis just discussed this issue for an ~hour. This comment captures the essence of that meeting.

Docs

Tagging Needs documentation updates because besides an initial implementation, the most crucial part here is that @f.mazeikis documents how he envisions how this will all work. IOW: an equally imporant goal for this issue is to update docs/components.md and docs/config-management.md, which were introduced by #3468112: Document the current component discovery + SDC criteria + `Component` config entity, and describe in an ADR.

Implementation

The initial implementation can be very limited — we shouldn't try to solve everything all at once here. I just discussed this with @f.mazeikis and we agreed on the following high-level points, with more detail/nuance to be defined by @f.mazeikis in the coming days:

  1. XB will auto-generate Component config entities for block plugins just like it does for SDCs
  2. … but only for those block plugins that meet certain requirements (just like for SDCs)
  3. The requirement that immediately comes to mind: fully validatable block settings (possible since #3379725: Make Block config entities fully validatable). Because without that, it's too easy for blocks used in XB to just have arbitrary data blobs associated with them. Validation allows for confidence, reliability, better UX. (And will likely be crucial for upgrade paths for block plugins, too.)
  4. For this MR, a test that verifies a single block plugin gets an auto-generated Component config entity is sufficient. The simplest one: \Drupal\system\Plugin\Block\SystemPoweredByBlock (which has zero settings). Ideally, there would be one more: \Drupal\search\Plugin\Block\SearchBlock (which has a single setting that was made fully validatable in #3379725).

A special case is \Drupal\block_content\Plugin\Block\BlockContentBlock, because it is a (derived) block plugin that depends on content entities. It's crucial in Layout Builder, for which XB eventually must provide an upgrade/migration path. We think we see a way forward for that special case too. Details TBD.

wim leers’s picture

wim leers’s picture

Assigned: f.mazeikis » wim leers
wim leers’s picture

Title: Add support for Blocks as Components » [PP-1] Add support for Blocks as Components
Assigned: wim leers » longwave

Discussed with @longwave, he'll be pushing this forward right after he finishes #3469610: Prepare for multiple component types: prefix Component config entity IDs with `sdc`, which blocks this anyway.

@f.mazeikis did a walkthrough/hand-over with me last Friday, before he went on vacation, so I'll be able to provide reviews 👍

wim leers’s picture

Title: [PP-1] Add support for Blocks as Components » Add support for Blocks as Components

longwave made their first commit to this issue’s fork.

wim leers’s picture

🏓 AFAICT we're on the same page, @longwave :)

wim leers’s picture

#3480217: Add Kernel test coverage of ApiLayoutController is in, which AFAIK should help with getting this MR ready :)

longwave’s picture

Status: Needs work » Needs review

The MR is green. "Search form" is available as a component and the preview works (ish) but after dragging it to the canvas the preview fails with an error; going to continue working on this while looking for reviews of the rest of the changes.

wim leers’s picture

Assigned: longwave » wim leers
Issue tags: -Needs documentation updates

#16 🥳

Reviewing in-depth! Docs definitely have been updated, removing tag 👍

wim leers’s picture

Assigned: wim leers » longwave
Status: Needs review » Needs work
longwave’s picture

Assigned: longwave » Unassigned
Issue tags: +Needs tests

Thanks for the review! I've run out of time now to work on this, so unassigning; I've addressed some of the feedback and added a bunch of @todos but there are still some things to be done - replied to some of the MR comments on those points. Tagging to add test coverage as well as we should add some here to prove that blocks work to some extent.

wim leers’s picture

In DM, @f.mazeikis asked what the point is of keeping the source property around separately, if it's already part of the ID prefix.

Having source separate makes it easy to validate, plus it's relevant information inside the config entity.

The ID's naming structure might still change!

Fortunately, over at #3324140: Convert field_storage_config and field_config's form validation logic to validation constraints, I already worked on a StringParts constraint that simplifies that. Pushing commits to transplant that into XB — because that core issue has not moved forward in a very long time, but that constraint definitely is solid.

longwave’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests

After working on this with Felix for some time, we don't think this is necessarily the final implementation - there are a lot of unknowns and new @todos - but it does decouple SDCs from Components, introduce the capability of placing at least some Blocks, and allows some other issues to be worked on in parallel.

longwave’s picture

Issue summary: View changes
longwave’s picture

Issue summary: View changes
longwave’s picture

Even though we have two source plugins now it's still hard to be 100% confident that we have fully decoupled things in the right way. I feel like it would be helpful to have a third source plugin to really solidify the abstractions here and make sure we have done the right thing. But I don't think that third plugin is known yet so this will have to do for now, we are still in the early phases anyway and landing this means the followups and numerous other issues can be worked on in parallel.

wim leers’s picture

Even though we have two source plugins now it's still hard to be 100% confident that we have fully decoupled things in the right way.

💯

We do not have designs/UX for all XB component types. The designs do not cover the unknown territory of "abstract additional component types", and hence we cannot possibly know what is shared (across component types) vs unique (per component type).

There's no way around this IMHO, but to just build what we do know and acknowledge it will need to evolve.

But I don't think that third plugin is known yet so this will have to do for now, we are still in the early phases anyway and landing this means the followups and numerous other issues can be worked on in parallel.

Well, we do know that we'll need to support layout plugins for sure. See #3454519: [META] Support component types other than SDC, block, and code components.

tedbow’s picture

I think this good enough considering the number of follow-ups we have. There are number of places we assume "props" but I think handling that in #3484666: Show configuration forms for Block components is good enough to get things moving

tedbow’s picture

Status: Needs review » Reviewed & tested by the community

Looks good! Thanks everyone!

wim leers’s picture

Assigned: Unassigned » wim leers

Given this has not been merged yet and sitting at RTBC for 2 hours, I'd like to do one final review pass because it's such a critical leap forward.

Reviewing in the next few hours. If I fail to post my review in the next 3.5 hours, go ahead and merge 🤓

wim leers’s picture

Assigned: wim leers » longwave
Status: Reviewed & tested by the community » Needs work

Finished doing a thorough review. 🥵

This looks great compared to when I last reviewed this >10 days ago! 👍

3 things stand out to me:

  1. The 'settings_tray' => FALSE, criterion is AFAICT at odds with what the PageTemplate functionality (introduced in #3478537: Introduce an XB `PageTemplate` config entity) must able to provide. See https://git.drupalcode.org/project/experience_builder/-/merge_requests/3... for details.
  2. the whole "plugin ID" handling situation, where it is assumed that every Component Source Plugin will have a plugin_id key-value pair in its settings seems wrong. Details: https://git.drupalcode.org/project/experience_builder/-/merge_requests/3.... I think we can do better. I'll push a commit for that tomorrow.
  3. The props term that SDC uses and XB adopted too … kinda gets in the way when abstracting to multiple component types. I proposed "explicit inputs" (as the generalized version of "SDC props" and "block plugin settings") and "implicit inputs" (as the generalized version of "block contexts"; SDCs have no such concept). See #3484666-5: Show configuration forms for Block components for more detail.

… plus a bunch of things lacking clarity, some of which @longwave already addressed.

I think only the first point is commit-blocking, plus the simple requests for clarification on the MR beyond those 3 big points.

longwave’s picture

Assigned: longwave » Unassigned
Status: Needs work » Needs review
wim leers’s picture

Status: Needs review » Reviewed & tested by the community

While reviewing the cacheability test coverage remark I posted in detail, I discovered that there was an actual performance (cacheability) regression. Details at https://git.drupalcode.org/project/experience_builder/-/merge_requests/3.... Fixed.

I'll deal with #31.2 WRT plugin ID handling in a follow-up — because I'm not entirely sure yet my idea will work.

  • wim leers committed f1951a7b on 0.x authored by f.mazeikis
    Issue #3475584 by longwave, f.mazeikis, wim leers, tedbow, larowlan: Add...
wim leers’s picture

Status: Reviewed & tested by the community » Fixed
Related issues: +#3482393: HTTP API: update /xb-components to specify each `Component`'s `source`

See y'all in the follow-ups!

Finally, about this bit of the issue summary:

User interface changes

For now, block plugins appear under the main "Default components" section in the UI, but in a future issue they will be moved to a separate "Dynamic components" section.

→ the infrastructure for that is being added in #3482393: HTTP API: update /xb-components to specify each `Component`'s `source`.

el7cosmos’s picture

Status: Fixed » Needs work

Apologize for coming late, I had some time looking at this.

When I disable a block component via /admin/structure/component, I can't enable it back again with an error message

Drupal\Component\Plugin\Exception\PluginNotFoundException: The "local_tasks_block" plugin does not exist.

.

Is this something to worry about? Or should this be a follow-up issue?

el7cosmos’s picture

Status: Needs work » Fixed

Oops sorry, accidentally changed status

wim leers’s picture

@el7cosmos I think that's in scope for #3484672: Display disabled Block components in /admin/structure/component/status. Will repeat #36 there 👍😊

wim leers’s picture

tedbow’s picture

Status: Fixed » Needs work

looks like 0.x is now failing since this commit https://git.drupalcode.org/project/experience_builder/-/pipelines?page=1...

I can't get it to fail locally

So setting to needs work to alert anyone who is following this issue and might have ideas. We should probably fix in another issue

It could have been a drupal core change but I have pull the latest changes and can't get it to fail

tedbow’s picture

Status: Needs work » Fixed
Related issues: +#3486168: Test failing on 0.x

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.