Organize src/PropExpressions/StructuredData/* classes into an interface structure
>>> [!note] Migrated issue
<!-- Drupal.org comment -->
<!-- Migrated from issue #3567719. -->
Reported by: [wim leers](https://www.drupal.org/user/99777)
Related to !480
>>>
<h3 id="overview">Overview</h3>
<p><code>src/PropExpressions/StructuredData</code> was <a href="https://git.drupalcode.org/project/canvas/-/commit/c00a6f4a">introduced</a> before Canvas was even on d.o. It's <em>ancient</em>. It was a PoC. It was always meant to be refactored.</p>
<p>But here we are: <a href="https://www.drupal.org/project/canvas/releases/1.0.0">https://www.drupal.org/project/canvas/releases/1.0.0</a> shipped with the exact same class names, the exact same concepts, just with more things bolted on.</p>
<p>We always knew this had to be refactored. It just never was important enough. @phenaproxima (rightfully!) called this out as hard to grok while reviewing <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/canvas/-/work_items/3550750" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/canvas/-/work_items/3550750</a></span> (which is the most significant addition to that early infra since … it was introduced!).</p>
<p>So:</p>
<ol>
<li>As requested by @phenaproxima at <a href="https://git.drupalcode.org/project/canvas/-/merge_requests/400#note_640969">https://git.drupalcode.org/project/canvas/-/merge_requests/400#note_640969</a></li>
<li>As proposed by @wimleers at <a href="https://git.drupalcode.org/project/canvas/-/merge_requests/400#note_641186">https://git.drupalcode.org/project/canvas/-/merge_requests/400#note_641186</a></li>
<li>First stab at implementation by @f.mazeikis at <a href="https://git.drupalcode.org/project/canvas/-/merge_requests/467#note_652871">https://git.drupalcode.org/project/canvas/-/merge_requests/467#note_652871</a></li>
<li>Descoped from that MR per @wimleers at <a href="https://git.drupalcode.org/project/canvas/-/merge_requests/467#note_653266">https://git.drupalcode.org/project/canvas/-/merge_requests/467#note_653266</a></li>
</ol>
<p>… let's introduce a proper interface hierarchy.</p>
<h3 id="proposed-resolution">Proposed resolution</h3>
<ul>
<li><strong>starting point</strong>, either:
<ol>
<li>
<code>EntityFieldBasedPropExpressionInterface</code>: for prop expressions that are based in a content entity field (the prop expression starts by declaring the content entity type + bundle it needs to evaluate the prop expression) → for <code>DynamicPropSource</code>s
</li><li><code>FieldTypeBasedPropExpressionInterface</code>: for prop expressions that are "rooted" in a field type (the prop expression starts by declaring the field type it needs to evaluate the prop expression) → for <code>StaticPropSource</code>s
</li></ol>
</li>
<li>is <strong>reference</strong>: <code>ReferencePropExpressionInterface</code> for prop expressions that point to another prop expression (also meaning they cannot evaluate to a scalar or object or array of either — i.e. they evaluate to a complex entity object, not something that can be passed to non-PHP code such as SDCs)
</li><li>is not reference and hence has an <strong>evaluation result shape</strong> that is either:
<ol>
<li><code>ScalarPropExpressionInterface</code> for prop expressions that evaluate to a scalar value (or an array of scalars for multi-value fields)
</li><li><code>ObjectPropExpressionInterface</code> for prop expressions that evaluate to an object value (or an array of objects for multi-value fields)
</li></ol>
</li>
<p>(<code>ReferencePropExpressionInterface</code>, <code>ScalarPropExpressionInterface</code> and <code>ObjectPropExpressionInterface</code> are mutually exclusive.)</p>
<table>
<thead>
<tr>
<th>prop expression class</th>
<th>starting point</th>
<th>reference</th>
<th>evaluation result shape</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>FieldPropExpression</code></td>
<td>entity field</td>
<td>❌</td>
<td>scalar</td>
</tr>
<tr>
<td><code>FieldObjectPropExpression</code></td>
<td>entity field</td>
<td>❌</td>
<td>object</td>
</tr>
<tr>
<td><code>ReferenceFieldPropExpression</code></td>
<td>entity field</td>
<td>✅</td>
<td>❌</td>
</tr>
<tr>
<td><code>FieldTypePropExpression</code></td>
<td>field type</td>
<td>❌</td>
<td>scalar</td>
</tr>
<tr>
<td><code>FieldTypeObjectPropExpression</code></td>
<td>field type</td>
<td>❌</td>
<td>object</td>
</tr>
<tr>
<td><code>ReferenceFieldTypePropExpression</code></td>
<td>field type</td>
<td>✅</td>
<td>❌</td>
</tr>
</tbody>
</table>
<h3 id="ui-changes">User interface changes</h3>
</ul>
issue