- Issue created by @LudwigJP
When using tokenized URLs in an iframe field to dynamically pass parameters to an external service to an external service, such as synchronizing languages between the iframe and Drupal, the URLs are unexpectedly saved with the token-replaced values during content editing, even though tokenized string should be preserved.
This behavior conflicts with the expected functionality of "Token Support" for iframe fields.
Examples include using a token like `[current-page:content-language:langcode]` in the URL field to ensure the iframe reflects the current Drupal page's language (`https://example.com?lang=[current-page:content-language:langcode]`). Instead of retaining the tokenized string format after editing, the URL is saved as `https://example.com?lang=en` (with the token replaced), breaking the intended dynamic behavior.
1. Configure an iframe field in a content type and set the "Token Support" option to "Tokens for title and URL field".
2. Create a new content entity and fill the iframe URL field with a tokenized string such as `https://example.com?lang=[current-page:content-language:langcode]`.
3. Save the content and reopen the edit form:
- Issue: You will see that the token has been replaced in the URL field (e.g., `https://example.com?lang=en` is now stored as the value).
4. To verify what goes wrong:
- Set "Token Support" to "No tokens allowed."
- Enter the tokenized URL (`https://example.com?lang=[current-page:content-language:langcode]`) and save your changes. The tokenized string will be stored as entered and displayed correctly when the edit form is reopened (without replacement).
- Switch "Token Support" back to "Tokens for title and URL field," and observe that the token is dynamically replaced at runtime to reflect the current language, as expected (e.g., it shows `https://example.com?lang=en` on the rendered output and changes when switching languages).
5. Attempt to edit the URL value again. You will observe that the token is replaced and saved as its resolved value once more, breaking the tokenized functionality.
Upon investigating the `IframeWidgetBase::validateUrl` function, the issue appears to be in the following section of the code:
public function validateUrl($element, FormStateInterface $form_state, $form) {
// Replace any tokens.
$settings = $this->getFieldSettings();
if (isset($settings['tokensupport']) && $settings['tokensupport'] == 2) {
$element['#value'] = $this->token->replace($element['#value'], ['user' => $this->currentUser]);
}
// Use Drupal core's LinkWidget to validate the URL.
LinkWidget::validateUriElement($element, $form_state, $form);
}
When the `validateUrl` method replaces tokens using `$this->token->replace`, it passes the modified `$element` to `LinkWidget::validateUriElement`. This method seems to manipulate somehow the `$form_state->values`, storing the token-replaced URL (`https://example.com?lang=en`) instead of leaving the original tokenized string intact (`https://example.com?lang=[current-page:content-language:langcode]`).
I don't know how to better handle this situation.
One way could be to simply skip the token replacement in the validation if tokens are allowed.
Active
3.0
Miscellaneous