Opt in to the parallel-successor condition constraint in the modeler
>>> [!note] Migrated issue <!-- Drupal.org comment --> <!-- Migrated from issue #3588497. --> Reported by: [jurgenhaas](https://www.drupal.org/user/168924) Related to !619 >>> <h3>Problem/Motivation</h3> <p>ECA's runtime invokes a component's successors in order. When a component has two-or-more successors that all point to the same target, the only way to distinguish which successor should fire is via a condition. If any of those parallel successors has no condition, the runtime simply invokes the target unconditionally, which makes the conditional siblings redundant or contradictory &mdash; the model is meaningless in practice.</p> <p>The modeler currently allows this configuration to be saved. Once the related <code>modeler_api</code> issue introduces an opt-in <code>requireConditionWhenParallel</code> flag on the per-type successor constraint, ECA can opt in to have the modeler reject such configurations both server-side at save time and client-side before save.</p> <p>This issue is a follow-up to <a href="https://www.drupal.org/project/modeler/issues/3586864">modeler #3586864</a>, which made parallel edges visually distinguishable.</p> <h3>Proposed resolution</h3> <p>In ECA's model owner (<code>modules/ui/src/Plugin/ModelerApiModelOwner/Eca.php</code>), override <code>modelConstraints()</code> to set <code>requireConditionWhenParallel</code> to <code>TRUE</code> for every component type that can be a successor source in an ECA model &mdash; typically <code>COMPONENT_TYPE_START</code>, <code>COMPONENT_TYPE_ELEMENT</code>, and <code>COMPONENT_TYPE_GATEWAY</code>.</p> <p>Example:</p> <pre><pre>public function modelConstraints(): array {<br>&nbsp; return [<br>&nbsp;&nbsp;&nbsp; Api::COMPONENT_TYPE_START =&gt; [<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'successors' =&gt; ['requireConditionWhenParallel' =&gt; TRUE],<br>&nbsp;&nbsp;&nbsp; ],<br>&nbsp;&nbsp;&nbsp; Api::COMPONENT_TYPE_ELEMENT =&gt; [<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'successors' =&gt; ['requireConditionWhenParallel' =&gt; TRUE],<br>&nbsp;&nbsp;&nbsp; ],<br>&nbsp;&nbsp;&nbsp; Api::COMPONENT_TYPE_GATEWAY =&gt; [<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'successors' =&gt; ['requireConditionWhenParallel' =&gt; TRUE],<br>&nbsp;&nbsp;&nbsp; ],<br>&nbsp; ];<br>}</pre></pre><p>Maintainers should review which component types in ECA can legitimately have parallel successors and only opt in for those. If existing per-type cardinality constraints already cover some of the entries, merge the new flag into the existing return value rather than replacing it.</p> <h3>Dependencies</h3> <ul> <li>Requires the new <code>requireConditionWhenParallel</code> flag in <code>modeler_api</code>: <em>(link to modeler_api issue once filed)</em></li> <li>Requires the modeler UI mirror so the user sees errors before save: <em>(link to modeler issue once filed)</em></li> </ul> <h3>Implementation outline</h3> <ol> <li>Wait for the <code>modeler_api</code> change to land (or develop against the corresponding MR).</li> <li>Override <code>modelConstraints()</code> in <code>Eca</code> to enable the flag for the relevant component types.</li> <li>Add a unit test that confirms the constraint is reported by <code>modelConstraints()</code> for the expected types.</li> <li>Add an integration test (or rely on the modeler-side E2E) that constructs a violating ECA model and asserts save is blocked.</li> </ol> <h3>Remaining tasks</h3> <ul> <li>Decide which component types should opt in.</li> <li>Implement the override in <code>Eca::modelConstraints()</code>.</li> <li>Tests.</li> <li>Document in ECA's release notes that previously-saveable degenerate models will now be rejected.</li> </ul> <h3>User interface changes</h3> <p>None directly in ECA. The modeler UI (which ECA uses) will refuse to save ECA models that have two-or-more uncondied successors between the same source and target, displaying a translated error message naming the offending components.</p> <h3>API changes</h3> <p>None.</p> <h3>Data model changes</h3> <p>None. Existing ECA models that already satisfy the rule are unaffected. Existing models that violate the rule will fail validation on the next save attempt &mdash; maintainers should call this out in release notes.</p> <h3>Related issues</h3> <ul> <li>Constraint definition: <em>(link to modeler_api issue once filed)</em></li> <li>Modeler UI mirror: <em>(link to modeler issue once filed)</em></li> <li>Originating context: <a href="https://www.drupal.org/project/modeler/issues/3586864">modeler #3586864</a></li> </ul> > Related issue: [Issue #3588494](https://www.drupal.org/node/3588494)
issue