Raw tokens from composite fields are not rendered raw

Created on 28 April 2023, almost 2 years ago
Updated 6 April 2024, about 1 year ago

Problem/Motivation

Field tokens that point to composite subfields are not rendered raw when they should.

In webform.tokens.inc, inside _webform_token_get_submission_value(), there is a check to determine the field's format based on whether the field referenced by the token is a composite or not:

  if ($keys) {
    if ($composite_key) {
      // Must set '#webform_composite_elements' format.
      // @see \Drupal\webform\Plugin\WebformElement\WebformCompositeBase::initialize
      // @see \Drupal\webform\Plugin\WebformElement\WebformCompositeBase::getInitializedCompositeElement
      $element['#webform_composite_elements'][$composite_key]['#format'] = array_shift($keys);
    }
    else {
      $element['#format'] = array_shift($keys);
    }
  }

However, a few lines later, the only check for "raw" is for $element['#format']. Composites will always fall into the last case, returning plain text.

  if (is_array($token_value)) {
    // Note, tokens can't include CSS and JS libraries since they will
    // can be included in an email.
    $token_value = \Drupal::service('renderer')->renderPlain($token_value);
  }
  elseif (isset($element['#format']) && $element['#format'] === 'raw') {
    // Make sure raw tokens are always rendered AS-IS.
    $token_value = Markup::create((string) $token_value);
  }
  elseif (!($token_value instanceof MarkupInterface)) {
    // All strings will be escaped as HtmlEscapedText.
    // @see \Drupal\Core\Utility\Token::replace
    // @see \Drupal\Component\Render\HtmlEscapedText
    $token_value = (string) $token_value;
  }

This causes the Token::doReplace() to treat the value as plain text instead of MarkupInterface and escape it regardless of :raw's presence.

Steps to reproduce

I could not make a simple reproduction, the token I use is semi-custom (a token that retrieves a submission from one form, and uses its fields as the default values for a new submission in another webform). It looks like:

[current-user:WEBFORM_ID:last:values:business_address:address_2:raw]

However, this custom token (the current-user:WEBFORM_ID:last portion) just returns a webform_submission. Everything beyond that (the values:business_address:address_2:raw portion) is the built-in webform_submission token's functionality. In short, it's tokens like this that fail:

[webform_submission:values:business_address:address_2:raw]

Proposed resolution

Add an explicit check for composite fields.

Remaining tasks

- Test
- Review

User interface changes

- None

API changes

- None

Data model changes

- None

πŸ› Bug report
Status

Closed: won't fix

Version

6.1

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States fskreuz

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 9.5.x + Environment: PHP 8.1 & MySQL 5.7
    last update almost 2 years ago
    537 pass
  • Issue created by @fskreuz
  • Status changed to Needs work almost 2 years ago
  • πŸ‡ΊπŸ‡ΈUnited States jrockowitz Brooklyn, NY

    This patch needs test coverage which could be added via \Drupal\Tests\webform\Functional\Composite\WebformCompositeFormatTest

  • Status changed to Closed: won't fix about 1 year ago
  • πŸ‡ΊπŸ‡ΈUnited States jrockowitz Brooklyn, NY

    This feels like a custom code issue because the [webform_submission:values:business_address:address_2:raw] token works as expected. (see attached) I suspect that a token calling another token is the problem in the custom code.

Production build 0.71.5 2024