There is currently no way to use tokens to extract subelements of webform composite elements. This can make it difficult for example, when using the remote post handler to correctly map webform address fields to the remote's expected post fields.

I was thinking the simplest way to allow this would be to use the [webform_submission:values:?] token. Currently it accepts element_key:format as an argument, and allowing format to contain a sub element key in addition to value and raw, would be fairly simple to implement.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mikeNCM created an issue. See original summary.

mikelutz’s picture

The attached patch overrides WebformCompositeBase::formatTextItem and WebformCompositeBase::formateHtmItem to accept a subelement key as a format for composite elements. This is a stab at a fix that works for my particular use case, but I'm not familiar enough with webform to know if it might have any unintended side effects. It might be better to just create a new token, but that would have significantly more overhead.

On a related note, as I was doing this, I wondered if it might also make sense to override the 3rd argument of that token, the items value, where if the value is numeric, rather than using it as a delimiter between items, it returns the item with that delta. I can't imagine anyone using a number as a delimiter, and it seems like being able to pull a specific delta out might be useful in some cases, for example [webform_submission:values:element_key:value:1]

mikelutz’s picture

Issue summary: View changes
Chris Burge’s picture

I'm running to the same issue. I need to access sub-components for e-mails. (e.g. in the salutation - 'Dear Mr. Smith' instead of 'Dear Mr. Charles A. Smith, Jr.').

What about adding a 'sub-component' format in addition to 'raw' and 'list'? This removes the risk of adversely affect the default behavior.

Simply returning $value[$format] assume the component has a single value, which may not be true. Supporting multiple values would require supporting deltas.

Chris Burge’s picture

Patch attached. It doesn't support multiple values.

mikelutz’s picture

That works too, but I'm not a fan of it just failing if there are multiple items. I'd like to address that use case somehow. I don't think there is any adverse affects from using the format to hold the sub_element key directly. Unless a composite element has a key called 'value', which maybe location does, I don't think there's an issue, and with #2, the current items function remains the same.

jrockowitz’s picture

@Chris Burge and @mikeNCM Thanks for taking a cracking at this issue.

We probably need to add full support for deltas and properties.

[webform_submission:values:NAME:DELTA:PROPERTY:FORMAT]
[webform_submission:values:NAME:PROPERTY:FORMAT]
[webform_submission:values:NAME:FORMAT]

[webform_submission:values:multiple_element:0]
[webform_submission:values:multiple_element:0:value]
[webform_submission:values:single_element]
[webform_submission:values:single_element:value]

[webform_submission:values:multiple_address:0:street]
[webform_submission:values:single_address:street]

This is going to be a pain to implement and require some tests. At least, deltas are always numeric.

mikelutz’s picture

@jrockowitz Alas, I am not good at writing and debugging tests, though I am working on it, and will submit some when I get a chance. In the meantime, here is a patch to support the token format you described above.

mikelutz’s picture

Okay, this is the same patch, but it adds a new test form and test for the values token

Status: Needs review » Needs work
mikelutz’s picture

Whoops, my mistake. Here's a (hopefully) working version.

mikelutz’s picture

Status: Needs work » Needs review
mikelutz’s picture

Same patch, minus 3 extra lines I accidently left in from a previous attempt.

mikelutz’s picture

Chris Burge’s picture

@mikeNCM - Thanks for pushing this issue forward.

In my testing of patch #13, the deltas functionality works. The sub-element functionality does not.

[webform_submission:values:single_address] - returns address (same as before patch)
[webform_submission:values:single_address:street] - returns nothing
[webform_submission:values:multiple_address:0] - returns first address
[webform_submission:values:multiple_address:0:street] - returns nothing

mikelutz’s picture

@Chris

You need to use the same keys that webform uses, for address, that is address, address_2, city, state_province, postal_code, and country.

I believe @jrockowitz was just using street as an example key. It's not that actual key that that element uses for the street address.

When editing a webform composite element, the keys are shown in the ADDRESS SETTINGS block. Perhaps we need to document where to find the keys better.

mikelutz’s picture

My last patch should maintain backwards compatibility with any of the old style tokens, provided there are no formats that are also subelement keys or numeric, which there shouldn't be.

Chris Burge’s picture

My last comment used the examples from #7 provided by @jrockowitz. In my actual testing, I used the following tokens with the name component:

(Single-valued component)
[webform_submission:values:name] - returns name (same as before patch)
[webform_submission:values:name:first] - returns nothing
(Multi-valued component)
[webform_submission:values:name:0] - returns first name
[webform_submission:values:name:0:first] - returns nothing

jrockowitz’s picture

I suspect we might have to tweak the token syntax and write an update hook.

Next week, I can review the patch and make some tweaks. I want to make sure that we can support and future proof the webform submission token syntax.

I can see you started writing some new tests. I think a test_token_submission_value form that has some pre-populated basic, composite, and multiples that just displays the submission value on confirmation page using all the possible token variants could be very helpful. I think this test form could be pretty simple with maybe just 6 elements with a dozen or so tokens on the confirmation page.

mikelutz’s picture

@Chris Can you give me steps to reproduce? Where are you using the tokens? I'm not having trouble accessing subelements in either the kernel tests or in my live site, but I'd love to know if I missed something. I haven't messed with the webform 5 codebase before so I may have missed something.

@jrockowitz I can definitely expand the test form slightly and add tokens to the confirmation page so we can add a functional test, and test more tokens. I didn't see an existing test for tokens, so I made the one just to test for the particular tokens I was adding. I thought it might be useful to add more token tests to it in the future, but I didn't want to put too much in this one patch. I might see if I can revamp a bit this weekend, create a separate issue and patch for generic token testing that we can go off of.

I'm not sure what makes the most sense with the syntax. I built off of your list above, but I'm not a huge fan of having the delta listed first. My feeling is that that last #format_items key, which holds a separator for multiple values should do double duty to hold the delta, since you will need either a separator OR a delta, but never both.

[webform_submission:values:?]
[webform_submission:values:ELEMENT_KEY] (exists)
[webform_submission:values:ELEMENT_KEY:ITEM_FORMAT] (exists)
[webform_submission:values:ELEMENT_KEY:ITEM_FORMAT:ITEMS_FORMAT|DELTA] (changed, if #items_format is numeric, treat it as a delta instead of a seperator)
[webform_submission:values:ELEMENT_KEY:SUBELEMENT_KEY] (new/changed, if the second argument is not a valid format returned by $element_manager->invokeMethod('getItemFormats', $element); assume it is a subelement key, and move the rest of the arguments up)
[webform_submission:values:ELEMENT_KEY:SUBELEMENT_KEY:ITEM_FORMAT] (same as above)
[webform_submission:values:ELEMENT_KEY:SUBELEMENT_KEY:ITEM_FORMAT:ITEMS_FORMAT|DELTA] (same as above)

[webform_submission:values:single_textfield]
[webform_submission:values:single_textfield:value]
[webform_submission:values:multiple_textfield]
[webform_submission:values:multiple_textfield:value:0]
[webform_submission:values:multiple_textfield:value:semicolon]

[webform_submission:values:single_address]
[webform_submission:values:single_address:city]
[webform_submission:values:single_address:value]
[webform_submission:values:single_address:city:value]
[webform_submission:values:multiple_address]
[webform_submission:values:multiple_address:value:0]
[webform_submission:values:multiple_address:value:semicolon]
[webform_submission:values:multiple_address:city]
[webform_submission:values:multiple_address:city:value]
[webform_submission:values:multiple_address:city:value:0]
[webform_submission:values:multiple_address:city:value:0:semicolon]

My other thought to make things less confusing, and continue to preserve compatibility with existing tokens is to make a new subelement_value token. So, you would end up with something like this:

[webform_submission:values:?]
[webform_submission:values:ELEMENT_KEY] (exists)
[webform_submission:values:ELEMENT_KEY:ITEM_FORMAT] (exists)
[webform_submission:values:ELEMENT_KEY:ITEM_FORMAT:ITEMS_FORMAT|DELTA] (changed, if #items_format is numeric, treat it as a delta instead of a seperator)

[webform_submission:subelement_values:?] (new)
[webform_submission:subelement_values:ELEMENT_KEY:SUBELEMENT_KEY] (new)
[webform_submission:subelement_values:ELEMENT_KEY:SUBELEMENT_KEY:ITEM_FORMAT] (new)
[webform_submission:subelement_values:ELEMENT_KEY:SUBELEMENT_KEY:ITEM_FORMAT:ITEMS_FORMAT|DELTA] (new)

[webform_submission:values:single_textfield]
[webform_submission:values:single_textfield:value]
[webform_submission:values:multiple_textfield]
[webform_submission:values:multiple_textfield:value:0]
[webform_submission:values:multiple_textfield:value:semicolon]

[webform_submission:values:single_address]
[webform_submission:subelement_values:single_address:city]
[webform_submission:values:single_address:value]
[webform_submission:subelement_values:single_address:city:value]
[webform_submission:values:multiple_address]
[webform_submission:values:multiple_address:value:0]
[webform_submission:values:multiple_address:value:semicolon]
[webform_submission:subelement_values:multiple_address:city]
[webform_submission:subelement_values:multiple_address:city:value]
[webform_submission:subelement_values:multiple_address:city:value:0]
[webform_submission:subelement_values:multiple_address:city:value:0:semicolon]

At this point, my patch put all the extra delta and subelement logic in the WebformElementBase and WebformCompositeElementBase format functions, so the above (or any other syntax tweaking) is pretty much confined to the token.inc file, and shouldn't be a big deal.

The second one does a better job at separating old/new functionality, but I'm not sure if it's more confusing. It looks more confusing at first glance, but it might be easier to document a second token for subelement values.

jrockowitz’s picture

@mikeNCM @Chris Burge I am going to take a crack at this and see if I can get better test coverage.

  • jrockowitz committed c4d75e8 on 2873307-composite-sub-element
    Issue #2873307 by mikeNCM, Chris Burge: Allow token access to composite...
jrockowitz’s picture

@mikeNCM Your patch definitely pointed me in the right direction. I did have to approach the implementation from a slightly different angle.

  • I created a token test form which can be used to test all token variations. (/form/test-token-submission-value)
  • The token test form is used in the automated test. Having a working form that can be reused for automated tests makes it easier to debug issues.
  • I moved the submission value logic into a dedicated function which makes things a little easier to track.
  • For now, I am only adding the #delta support to WebformElementBase
  • For sub elements, I am only returning the sub element value. There is @todo to add subelement formatting support. This is tricky because the entire composite element needs to be built.,
  • The [webform_submission:values:?] now has a bulleted list of examples.
  • I added support for token values to be returned as HTML.

Chris Burge’s picture

@jrockowitz and @mikeNCM - Thanks for your work on this!

With the latest commit, I'm still finding that sub-elements aren't working. (I don't have time for more thorough testing at the moment.)

I think that that $value needs to be replaced with with $submission_data[$element_key] ($value is undefined).

Also, when checking $delta, I think we want to check that $delta isn't NULL.

@@ -552,11 +552,11 @@ function _webform_token_get_submission_value($value_token, array $submission_opt
   if ($keys && $element_handler->isComposite()) {
     // Return sub-element value without any formatting.
     // @todo: Add support for formatting sub-elements,
-    if ($delta && isset($value[$delta]) && isset($value[$delta][$keys[0]])) {
-      return $value[$delta][$keys[0]];
+    if (!is_null($delta) && isset($submission_data[$element_key][$delta]) && isset($submission_data[$element_key][$delta][$keys[0]])) {
+      return $submission_data[$element_key][$delta][$keys[0]];
     }
-    elseif (isset($value[$keys[0]])) {
-      return $value[$keys[0]];
+    elseif (isset($submission_data[$element_key][$keys[0]])) {
+      return $submission_data[$element_key][$keys[0]];
     }
   }

With these changes, I was able to get the following patterns to work:

(Single-valued component)
[webform_submission:values:name:first] - now works
(Multi-valued component)
[webform_submission:values:name:0:first] - now works

(I'm testing with the e-mail handler, which uses Webform token substitution.)

  • jrockowitz committed 3d4461d on 2873307-composite-sub-element
    Issue #2873307 by mikeNCM, Chris Burge: Allow token access to composite...
jrockowitz’s picture

@Chris Burge Thanks for catching that mistake. I made your suggested tweaks and updated the tests.

  • jrockowitz committed 1fae3c7 on 8.x-5.x
    Issue #2873307 by mikeNCM, jrockowitz, Chris Burge: Allow token access...
jrockowitz’s picture

Status: Needs review » Fixed

I committed the patch, please download and review the latest dev release.

frederickjh’s picture

FileSize
31.74 KB
67.32 KB
27.96 KB

I just tested the latest 8.x-5.x on simplytest.me and it seems to be working fine for tokens in email addresses but only the field part of the token shows after saving. Nothing shows for the subelements after saving while viewing the settings.

Entered tokens in the email fields:

Viewing the settings after saving:

Checking the token rendering in the email resend with debug on:

jrockowitz’s picture

Status: Fixed » Needs work

I missed that issue. The WebformEmailHandler is just trying to truncate the token.

jrockowitz’s picture

Status: Needs work » Needs review
FileSize
1.3 KB

The attached patch fixes the immediate regression.

  • jrockowitz committed 6889eca on 8.x-5.x
    Issue #2873307 by mikeNCM, jrockowitz, Chris Burge, frederickjh: Allow...
jrockowitz’s picture

Status: Needs review » Fixed

I committed the patch, please download and review the latest dev release.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.