Enable candidate `DynamicPropSource` suggestions for code components: refactor `GeneratedFieldExplicitInputUxComponentSourceBase` and `FieldForComponentSuggester` to need only SDC's ComponentMetadata, not SDC plugin instances
>>> [!note] Migrated issue <!-- Drupal.org comment --> <!-- Migrated from issue #3503038. --> Reported by: [wim leers](https://www.drupal.org/user/99777) Related to !78 !819 >>> <h3 id="overview">Overview</h3> <p><span class="drupalorg-gitlab-issue-link project-issue-status-info project-issue-status-7"><a href="https://www.drupal.org/project/experience_builder/issues/3498889" title="Status: Closed (fixed)">#3498889: ComponentSource plugin for code components</a></span> introduced <code>GeneratedFieldExplicitInputUxComponentSourceBase</code>. In order to make most of the logic in that class (which powers the input UX for the "SDC" and "JS aka code component" <code>ComponentSource</code> plugins) work, it needs an SDC plugin instance.</p> <p>Changing it to <em>not</em> need that would've led to even more refactoring in #3498889 than it already did.</p> <p>Additionally we're hard-coding Article nodes in the same file</p> <div class="codeblock"> <pre><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br></span><span style="color: #FF8000">// &#128187;&#65039; app/modules/experience_builder/src/Plugin/ExperienceBuilder/ComponentSource/GeneratedFieldExplicitInputUxComponentSourceBase.php:447<br></span><span style="color: #0000BB">$suggestions </span><span style="color: #007700">= </span><span style="color: #0000BB">$this </span><span style="color: #007700">instanceof </span><span style="color: #0000BB">SingleDirectoryComponent<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #007700">? </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">fieldForComponentSuggester</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">suggest</span><span style="color: #007700">(</span><span style="color: #0000BB">$component_plugin</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getPluginId</span><span style="color: #007700">(), </span><span style="color: #0000BB">EntityDataDefinition</span><span style="color: #007700">::</span><span style="color: #0000BB">create</span><span style="color: #007700">(</span><span style="color: #DD0000">'node'</span><span style="color: #007700">, </span><span style="color: #DD0000">'article'</span><span style="color: #007700">)) </span><span style="color: #FF8000">// &#128072;&#65039;&#128072;&#65039;&#128072;&#65039;&#128072;&#65039; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #007700">: [];<br></span><span style="color: #0000BB">?&gt;</span></span></pre></div> <h3 id="proposed-resolution">Proposed resolution</h3> <ul> <li>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 <code>ComponentMetadata</code> object.</li> <li>Start with <code>GeneratedFieldExplicitInputUxComponentSourceBase</code></li> <li>Note: this may require in some places an <em>ephemeral</em> 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 <code>\Drupal\Core\Theme\Component\ComponentValidator::validateProps()</code>.</li> <li>Then move on to <code>\Drupal\experience_builder\ShapeMatcher\FieldForComponentSuggester</code>.</li> <li>Expected end result: <code>SingleDirectoryComponent</code> or <code>JsComponent</code>-specific checks/logic remain.</li> </ul> <p>This will allow <code>docs/components.md</code> to be updated to state something like:</p> <pre>Any `Component Source Plugin` without a native (explicit) input UX can reuse the infrastructure that XB originally<br>built to provide an input UX for `SDC`-sourced `Component`s. To generate an input UX,&nbsp; the precise shape of each<br>input (and it being required or optional) must be expressed in a standardized way. To avoid inventing new infrastructure,<br>XB opted to rely on the SDC subsystem of Drupal core's abstraction for expressing this: the `ComponentMetadata` class.<br><br>While imperfect (because it contains _all_ metadata rather than only that relating to its explicit input shapes), it is<br>the pragmatic choice to get the job done. See [`XB Shape Matching<br>into Field Types` doc](shape-matching-into-field-types.md) for details on how that works.<br><br>In other words: _any_ `Component Source Plugin` can use the same Drupal Field-powered UX that XB provides for SDCs,<br>all it requires is generating a `ComponentMetadata` object that expresses its input schema.<br><br>@see \Drupal\Core\Theme\Component\ComponentMetadata</pre><h3 id="ui-changes">User interface changes</h3> <p>None.</p> > Related issue: [Issue #3498889](https://www.drupal.org/node/3498889) > Related issue: [Issue #3513589](https://www.drupal.org/node/3513589) > Related issue: [Issue #3510896](https://www.drupal.org/node/3510896) > Related issue: [Issue #3541000](https://www.drupal.org/node/3541000) > Related issue: [Issue #3520484](https://www.drupal.org/node/3520484)
issue