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"><?php<br></span><span style="color: #FF8000">// 💻️ 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> </span><span style="color: #007700">? </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">fieldForComponentSuggester</span><span style="color: #007700">-></span><span style="color: #0000BB">suggest</span><span style="color: #007700">(</span><span style="color: #0000BB">$component_plugin</span><span style="color: #007700">-></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">// 👈️👈️👈️👈️ <br> </span><span style="color: #007700">: [];<br></span><span style="color: #0000BB">?></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, 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