Overview

#3498889: ComponentSource plugin for code components introduced GeneratedFieldExplicitInputUxComponentSourceBase. In order to make most of the logic in that class (which powers the input UX for the "SDC" and "JS aka code component" ComponentSource plugins) work, it needs an SDC plugin instance.

Changing it to not need that would've led to even more refactoring in #3498889 than it already did.

Additionally we're hard-coding Article nodes in the same file

// 💻️ app/modules/experience_builder/src/Plugin/ExperienceBuilder/ComponentSource/GeneratedFieldExplicitInputUxComponentSourceBase.php:447
$suggestions = $this instanceof SingleDirectoryComponent
      ? $this->fieldForComponentSuggester->suggest($component_plugin->getPluginId(), EntityDataDefinition::create('node', 'article')) // 👈️👈️👈️👈️ 
      : [];

Proposed resolution

  • Refactor all the XB-owned infrastructure to not expect an SDC plugin instance as an argument, but only a subset of that plugin instance: a ComponentMetadata object.
  • Start with GeneratedFieldExplicitInputUxComponentSourceBase
  • Note: this may require in some places an ephemeral SDC plugin object (not tied to an actually installed SDC on disk) to be generated from that metadata object, for example to be able to call SDC's \Drupal\Core\Theme\Component\ComponentValidator::validateProps().
  • Then move on to \Drupal\experience_builder\ShapeMatcher\FieldForComponentSuggester.
  • Expected end result: SingleDirectoryComponent or JsComponent-specific checks/logic remain.

This will allow docs/components.md to be updated to state something like:

Any `Component Source Plugin` without a native (explicit) input UX can reuse the infrastructure that XB originally
built to provide an input UX for `SDC`-sourced `Component`s. To generate an input UX,  the precise shape of each
input (and it being required or optional) must be expressed in a standardized way. To avoid inventing new infrastructure,
XB opted to rely on the SDC subsystem of Drupal core's abstraction for expressing this: the `ComponentMetadata` class.

While imperfect (because it contains _all_ metadata rather than only that relating to its explicit input shapes), it is
the pragmatic choice to get the job done. See [`XB Shape Matching
into Field Types` doc](shape-matching-into-field-types.md) for details on how that works.

In other words: _any_ `Component Source Plugin` can use the same Drupal Field-powered UX that XB provides for SDCs,
all it requires is generating a `ComponentMetadata` object that expresses its input schema.

@see \Drupal\Core\Theme\Component\ComponentMetadata

User interface changes

None.

Issue fork canvas-3503038

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:

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

wim leers created an issue. See original summary.

longwave’s picture

Title: [PP-1] Refactor GeneratedFieldExplicitInputUxComponentSourceBase and FieldForComponentSuggester to need only SDC's ComponentMetadata, not SDC plugin instances » Refactor GeneratedFieldExplicitInputUxComponentSourceBase and FieldForComponentSuggester to need only SDC's ComponentMetadata, not SDC plugin instances
Status: Postponed » Active
larowlan’s picture

larowlan’s picture

Issue summary: View changes

longwave’s picture

Status: Active » Needs work

Made a start on this.

wim leers’s picture

Issue tags: -stable blocker

I don't think this needs to be a stable blocker; XB at release won't yet allow additional ComponentSourceInterface implementations. Which means this would be an entirely internal refactor?

wim leers’s picture

Component: Shape matching » Component sources
larowlan’s picture

The fact we had to pretend this exists in the fallback plugin makes me feel it is a stable blocker.
I know @mohit_aghera has a pinto component source plugin that is also grappling with this.

larowlan’s picture

Issue tags: +stable blocker

Adding back tag until the conversation above is resolved (we can always remove it again, just want to make sure it's not lost)

wim leers’s picture

Title: Refactor GeneratedFieldExplicitInputUxComponentSourceBase and FieldForComponentSuggester to need only SDC's ComponentMetadata, not SDC plugin instances » [later phase] Refactor GeneratedFieldExplicitInputUxComponentSourceBase and FieldForComponentSuggester to need only SDC's ComponentMetadata, not SDC plugin instances
Status: Needs work » Postponed

I think this is less urgent.

larowlan’s picture

Issue tags: +#pnx-sprint

Tagging for colleagues as this is a bug bear for the Pinto work Mohit has been doing

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

wim leers’s picture

Title: [later phase] Refactor GeneratedFieldExplicitInputUxComponentSourceBase and FieldForComponentSuggester to need only SDC's ComponentMetadata, not SDC plugin instances » Refactor GeneratedFieldExplicitInputUxComponentSourceBase and FieldForComponentSuggester to need only SDC's ComponentMetadata, not SDC plugin instances
Status: Postponed » Active
Issue tags: +Contributed project blocker
Parent issue: » #3520484: [META] Production-ready ComponentSource plugins

Thanks, @mohit_aghera, for pushing this forward! 🥳🙏

effulgentsia’s picture

I read #10, but I don't think this is a stable blocker. We'd be happy to merge this once it's ready though, so by untagging it I have no desire to slow this issue down.

For XB, the definition of stable is different than core's. We'll be adding @internal to almost everything and relaxing that in 1.x minor releases. The main goal of an XB stable release is to unblock a Drupal CMS 2.0 stable release, allowing people/agencies to build and deploy real sites with that. But XB 1.0.0 won't yet have a proper PHP API surface for contrib projects to perform more advanced integrations than what DCMS 2 exercises, except to the extent that issues like this one just happen to get done ahead of a 1.0.0 release.

wim leers’s picture

Title: Refactor GeneratedFieldExplicitInputUxComponentSourceBase and FieldForComponentSuggester to need only SDC's ComponentMetadata, not SDC plugin instances » Enable candidate `DynamicPropSource` suggestions for code components: refactor `GeneratedFieldExplicitInputUxComponentSourceBase` and `FieldForComponentSuggester` to need only SDC's ComponentMetadata, not SDC plugin instances
Version: 0.x-dev » 1.x-dev
Issue tags: +blocker
Related issues: +#3510896: Add a new internal HTTP API for candidate `DynamicPropSource`s to enable a `ContentTemplate` UI, +#3541000: [META] Content templates UI for 1.0: only nodes, no exposed slots, no replacement for the view mode/display UI

This is going to block #3541000: [META] Content templates UI for 1.0: only nodes, no exposed slots, no replacement for the view mode/display UI, and #3510896: Add a new internal HTTP API for candidate `DynamicPropSource`s to enable a `ContentTemplate` UI made it very apparent 😅

Quoting \Drupal\Tests\experience_builder\Functional\ApiUiContentTemplateControllersTest::testSuggestionsClientErrors():

   *           ["node/article/js.xb_test_code_components_with_link_prop", 400, "Code components are not supported yet."]
   *           ["node/article/js.xb_test_code_components_with_no_props", 400, "Code components are not supported yet."]

So, starting point:

diff --git a/src/Controller/ApiUiContentTemplateControllers.php b/src/Controller/ApiUiContentTemplateControllers.php
index 85bcf22f9..3f3909582 100644
--- a/src/Controller/ApiUiContentTemplateControllers.php
+++ b/src/Controller/ApiUiContentTemplateControllers.php
@@ -112,11 +112,6 @@ final class ApiUiContentTemplateControllers extends ApiControllerBase {
       throw new BadRequestHttpException('Only components that define their inputs using JSON Schema and use fields to populate their inputs are currently supported.');
     }
 
-    // @todo Add support for suggestions for code components in https://www.drupal.org/i/3503038
-    if (!$source instanceof SingleDirectoryComponent) {
-      throw new BadRequestHttpException('Code components are not supported yet.');
-    }
-
     if ($this->entityTypeManager->getDefinition($content_entity_type_id, FALSE) === NULL) {
       throw new NotFoundHttpException(sprintf("The `%s` content entity type does not exist.", $content_entity_type_id));
     }
f.mazeikis’s picture

Assigned: Unassigned » f.mazeikis

Project: Experience Builder » Drupal Canvas

Experience Builder has been renamed to Drupal Canvas in preparation for its beta release. You can now track issues on the new project page.

f.mazeikis’s picture

Assigned: f.mazeikis » wim leers
Status: Active » Needs review

wim leers’s picture

Assigned: wim leers » Unassigned
Status: Needs review » Fixed
Issue tags: -Needs documentation updates

Now that this issue is closed, please review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, please credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

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