"Defined by token" does not work for derived actions with ":" within plugin ID
>>> [!note] Migrated issue <!-- Drupal.org comment --> <!-- Migrated from issue #3536016. --> Reported by: [starlight-sparkle](https://www.drupal.org/user/3804225) >>> <h3 id="summary-problem-motivation">Problem/Motivation</h3> <p>When I try to use "Defined by token" option for the "Format" configuration in the "Render: Serialize" action, it always defaults to "json" when the action is executed.</p> <p>Debugging reveals that this is because when the token named "eca_render_serialize:serialization_format" is retrieved, it actually retrieves a <code>\Drupal\Core\TypedData\Plugin\DataType\StringData</code> object instead of a scalar string. Hence when the action calls <code>getTokenValue()</code>:</p> <div class="codeblock"> <pre><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br>&nbsp; </span><span style="color: #007700">protected function </span><span style="color: #0000BB">getTokenValue</span><span style="color: #007700">(</span><span style="color: #0000BB">string $fieldKey</span><span style="color: #007700">, </span><span style="color: #0000BB">string $default</span><span style="color: #007700">): </span><span style="color: #0000BB">string </span><span style="color: #007700">{<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000BB">$value </span><span style="color: #007700">= </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">tokenService</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getTokenData</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">buildTokenName</span><span style="color: #007700">(</span><span style="color: #0000BB">$fieldKey</span><span style="color: #007700">));<br>&nbsp;&nbsp;&nbsp; if (</span><span style="color: #0000BB">$value </span><span style="color: #007700">instanceof </span><span style="color: #0000BB">DataTransferObject</span><span style="color: #007700">) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000BB">$value </span><span style="color: #007700">= </span><span style="color: #0000BB">$value</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getValue</span><span style="color: #007700">();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #FF8000">// StringData is not scalar, and it is not instance of DataTransferObject, so $default is returned.<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #007700">return </span><span style="color: #0000BB">is_scalar</span><span style="color: #007700">(</span><span style="color: #0000BB">$value</span><span style="color: #007700">) ? (string) </span><span style="color: #0000BB">$value </span><span style="color: #007700">: </span><span style="color: #0000BB">$default</span><span style="color: #007700">;<br>&nbsp; }<br></span><span style="color: #0000BB">?&gt;</span></span></pre></div> <p>Similar issues are observed for other actions such as "Render: Unserialize".</p> <h4 id="summary-steps-reproduce">Steps to reproduce</h4> <ol> <li>Use Drupal 10.5.1</li> <li>Enable ECA render, ECA base, and core serialization module</li> <li>Create a model</li> <ol> <li>ECA custom event (Event ID: <code>test_token</code>)</li> <li>Token: set value (Name: <code>eca_render_serialize:serialization_format</code> Value: <code>xml</code>)</li> <li>Render: Serialize (Format: <code>Defined by token</code> Token name: <code>serialized</code> Value: <code>test: "yes"</code> Interpret as YAML: <code>Yes</code>)</li> <li>Display a message to the user (Message: <code>[serialized]</code>)</li> </ol> <li>Run terminal command <code>drush eca:trigger:custom_event test_token</code></li> <li>Observe that JSON output is printed instead of XML</li> </ol> <h3 id="summary-proposed-resolution">Proposed resolution</h3> <p>Add an additional check for <code>TypedDataInterface</code> in <code>getTokenValue()</code> and if so, try to call <code>getValue()</code> on the object.</p> <div class="codeblock"> <pre><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br>&nbsp; </span><span style="color: #007700">protected function </span><span style="color: #0000BB">getTokenValue</span><span style="color: #007700">(</span><span style="color: #0000BB">string $fieldKey</span><span style="color: #007700">, </span><span style="color: #0000BB">string $default</span><span style="color: #007700">): </span><span style="color: #0000BB">string </span><span style="color: #007700">{<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000BB">$value </span><span style="color: #007700">= </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">tokenService</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getTokenData</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">buildTokenName</span><span style="color: #007700">(</span><span style="color: #0000BB">$fieldKey</span><span style="color: #007700">));<br>&nbsp;&nbsp;&nbsp; if (</span><span style="color: #0000BB">$value </span><span style="color: #007700">instanceof </span><span style="color: #0000BB">DataTransferObject</span><span style="color: #007700">) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000BB">$value </span><span style="color: #007700">= </span><span style="color: #0000BB">$value</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getValue</span><span style="color: #007700">();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; if (</span><span style="color: #0000BB">$value </span><span style="color: #007700">instanceof </span><span style="color: #0000BB">TypedDataInterface</span><span style="color: #007700">) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000BB">$value </span><span style="color: #007700">= </span><span style="color: #0000BB">$value</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getValue</span><span style="color: #007700">();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; return </span><span style="color: #0000BB">is_scalar</span><span style="color: #007700">(</span><span style="color: #0000BB">$value</span><span style="color: #007700">) ? (string) </span><span style="color: #0000BB">$value </span><span style="color: #007700">: </span><span style="color: #0000BB">$default</span><span style="color: #007700">;<br>&nbsp; }<br></span><span style="color: #0000BB">?&gt;</span></span></pre></div> <h3 id="summary-remaining-tasks">Remaining tasks</h3> <h3 id="summary-ui-changes">User interface changes</h3> <p>No changes</p> <h3 id="summary-api-changes">API changes</h3> <p>No changes</p> <h3 id="summary-data-model-changes">Data model changes</h3>
issue