Symmetrically translatable component trees, STEP 1: introduce `ComponentInstanceInputsConfigSchemaGeneratorInterface`
>>> [!note] Migrated issue
<!-- Drupal.org comment -->
<!-- Migrated from issue #3586342. -->
Reported by: [wim leers](https://www.drupal.org/user/99777)
Related to !962
>>>
<h3 id="approach">Approach</h3>
<p>For high-level overview, see the <a href="https://www.drupal.org/node/3586291">change record</a>.</p>
<ol>
<li>ADR: !901
</li><li>Implementation MR #1: !962 in <span class="drupalorg-gitlab-issue-link project-issue-status-info project-issue-status-7"><a href="https://www.drupal.org/project/canvas/issues/3586342" title="Status: Closed (fixed)">#3586342: Symmetrically translatable component trees, STEP 1: introduce `ComponentInstanceInputsConfigSchemaGeneratorInterface`</a></span>
</li><li>Implementation MR #2: !898 in <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/canvas/-/work_items/3582478" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/canvas/-/work_items/3582478</a></span>
</li><li>Implementation MR #3: !831 in <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/canvas/-/work_items/3582464" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/canvas/-/work_items/3582464</a></span>
</li></ol>
<h3 id="overview">Overview</h3>
<p>#3582478 already landed an ADR, #10. This issue is for implementing <a href="https://git.drupalcode.org/project/canvas/-/blob/1.x/docs/adr/0010-dynamic-config-schema-for-component-tree-translatability.md?ref_type=heads#1-allow-any-componentsource-plugin-to-define-a-componentinstanceinputsconfigschemageneratorinterface">the first decision of that: <q>Allow any <code>ComponentSource</code> plugin to define a <code>ComponentInstanceInputsConfigSchemaGeneratorInterface</code></q></a>. <strong>It also implements decisions 3, 4, 5 and 6.</strong></p>
<p>This is split off from #3582478's implementation MR</p>
<blockquote><ol start="2">
<li>Extract a new blocking issue/MR from this one, specifically focused on the "provide translatability metadata" aspect. So: <code>ComponentInstanceInputsConfigSchemaGeneratorInterface</code> + <code>ComponentInputs::getTranslatableInputKeys()</code> + <code>\Drupal\Tests\canvas\Kernel\Plugin\Canvas\ComponentSource\ComponentSourceTestBase::testGetTranslatableInputKeys</code>.<br>
<strong>This should cut the size of this issue's MR (now sizable, at ~2K LoC!) MR by 30–50%.</strong>
</li></ol>
</blockquote>
<p>— <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/canvas/-/work_items/3582478" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/canvas/-/work_items/3582478</a></span></p>
<p>This blocks both:</p>
<ul>
<li>symmetrical translations of <strong>content</strong>-defined component trees' inputs: <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/canvas/-/work_items/3583684" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/canvas/-/work_items/3583684</a></span></li>
<li>symmetrical translations of <strong>config</strong>-defined component trees' inputs: <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/canvas/-/work_items/3582478" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/canvas/-/work_items/3582478</a></span></li>
</ul>
<h3 id="proposed-resolution">Proposed resolution</h3>
<ol>
<li>✅ Provide an explicit API for this: introduce <code>\Drupal\canvas\Attribute\ComponentSource::__construct(inputs_config_schema_generator)</code> which requires a <code>ComponentInstanceInputsConfigSchemaGeneratorInterface</code>.<br>
(Making the pre-existing <code>ComponentSourceBase::getExplicitInputDefinitions()</code> public is insufficient; we'd need to change its return values, which in turn would result in different component version hashes. That's avoidable disruption. This is still not ideal, but that is true for many of the methods on that interface. The point is to first grow it organically to meet all needs, and then distill a sensible API/interface from it. We have <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/canvas/-/work_items/3520484" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/canvas/-/work_items/3520484</a></span> for that. But this was implemented in a way that follows the pre-existing pattern towards a public API: <code>discovery</code>, <code>updater</code> and now <code>inputs_config_schema_generator</code>.)
</li><li>✅ Make it available in simplified form via <code>ComponentTreeItem</code>'s <code>inputs</code> property. It could be retrieved from <code>$component_tree_item->get('inputs')->getTranslatableInputKeys()</code> but that would be more expensive: config schema construction would ideally not be instantiating field objects like that. Instead, make a <code>public static ComponentInputs::resolveConfigSchemaMapping()</code> available that is used by both classes.
</li>
</ol>
<p><strong>The result: both config translation (#3582478) <em>and</em> content translation (#3583684) can use the same central metadata to determine which of the key-value pairs in <code>inputs</code> for a component instance are actually translatable.<br>
</strong></p>
<h4>Test coverage</h4>
<ol>
<li>✅ Kernel test coverage for all implementations of the new <code>ComponentInstanceInputsConfigSchemaGeneratorInterface</code>: ensured for all component sources thanks to <code>\Drupal\Tests\canvas\Kernel\Plugin\Canvas\ComponentSource\ComponentSourceTestBase::testGetTranslatableInputKeys()</code>'s reliance on an abstract data provider
</li><li>✅ Kernel test coverage for <code>\Drupal\canvas\Plugin\DataType\ComponentInputs::getTranslatableInputKeys()</code>'s edge case handling that does not rely on that new interface:<br>
<pre>ComponentTreeItemListTest::testGetTranslatableInputKeysSourceAgnosticEdgeCases()</pre></li></ol>
<h3 id="ui-changes">User interface changes</h3>
<p>None.</p>
issue