Problem/Motivation

I'm currently missing a token that allows me to feed all the target_ids of an entity reference field to a views configuration using EVA.
Having such a token would greatly improve the reach of the token argument handler of EVA.

Proposed resolution

There's already the token handling as well as delta processing for multivalue fields.
I'd suggest to add a new "delta" called array which will use the array handling to provide access to all primitive property types of a field.
A token would look like this: [node:multivalued_field_image:array:target_id:join:+], this would provide 1+2 as value.

Attached patch should provide exactly that.

Remaining tasks

Feedback needed.
Reviews needed.
I suspect the replacement logic could be streamlined, but that makes only sense if the general approach & idea is accepted.

User interface changes

None.

API changes

None. There shouldn't be any sideeffects for existing tokens as it is a separated non numeric keyword that's needed to trigger access the new functionality.

Data model changes

None.

Release notes snippet


Discussion about token structure:

Taxonomy terms and paths for example already implement a join: functionality: [term:parents:join:?].
This part of the issue summary should be the result of our discussion below. The logic should be

No explicit modifier

[node:multivalued_field:*:{Everything like behind delta}]
How to join these value without an explicit modifier like below given?

:join:delimiter

Further modifiers to discuss

:count

Returns the number of elements in the multi value field (max delta?)
Not existing yet on multi value fields.
Suggestions:
a) [node:multivalued_field:count]
b) [node:multivalued_field:*:count]

:first

Returns the first multi value field value.
Equal to delta=0, but should be implemented to be complete because :last exists

Not existing yet on multi value fields.
Suggestions:
a) [node:multivalued_field:first:{Everything like behind delta}]
b) [node:multivalued_field:*:first:{Everything like behind delta}]

:last

Returns the last multi value field value.
Important because we can't know the max delta on a multi-value field.

Not existing yet on multi value fields.
Suggestions:
a) [node:multivalued_field:last:{Everything like behind delta}]
b) [node:multivalued_field:*:last:{Everything like behind delta}]

:reversed

Returns the results in inverse logical order.
Not existing yet on multi value fields.

This might be quite complicated to understand, so perhaps we should better think about an inversed "*" like for example "-*", "*-" or simething similar which inverts the field value order before any values are handled.
a) [node:multivalued_field:-*:{Everything like behind delta}] **suggested**
b) [node:multivalued_field:*:{Everything like behind delta}:reversed]

:join-path

Like :join but with path cleanup and "/" as separator

:keys

Unsure if this makes any sense.
For entity reference fields the result could be similar to [node:multivalued_field:*:target_id] but for other fields like multiple text fields it seems unclear. Better leave out?

Not existing yet on multi value fields.

Suggestions:
a) [node:multivalued_field:keys:{Everything like behind delta}]
b) [node:multivalued_field:*:keys:{Everything like behind delta}]

:values

Unsure if this makes any sense.
For entity reference fields the result could be similar to [node:multivalued_field:*] but for other fields like multiple text fields it seems unclear. Better leave out?

Not existing yet on multi value fields.

Suggestions:
a) [node:multivalued_field:values:{Everything like behind delta}]
b) [node:multivalued_field:*:values:{Everything like behind delta}]

Concrete examples:

Token input Expected result
[node:multivalued_field:*:target_id] TODO
[node:multivalued_field:*:target_id:join:+] TODO
[node:multivalued_field:*:target_id:join:':'] TODO - tricky
[node:multivalued_field:*:entity:title] TODO
[node:multivalued_field:*:entity:title:join:', '] TODO
[node:multivalued_field:*:entity:multivalued_field2:*:target_id:join:', ':join:+] TODO - tricky tricky

Issue fork token-3115486

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

das-peter created an issue. See original summary.

berdir’s picture

Issue tags: +Needs tests

Hey das-peter!

Open to add this, but considering the complexity of the field token code, I think this should have test coverage, would expect it shouldn't be too hard to add that to existing test coverage and would also serve as a usage example.

anybody’s picture

Hi @das-peter and @Berdir,

thank you very much for your work on this. I'd like to discuss the expected results here for some examples because once shipped this will never be easily changed again and it's a HUGE further step forwards for token to allow joining multi-value entity reference values!

So please let's add all examples with a behaviour description to the issue summary so we can then write tests against them. Would you be interested to help?

Writing these examples and comparing / validating them against existing logic for example for menu path etc. is also possible for non developers!

anybody’s picture

Issue summary: View changes
anybody’s picture

Here are my suggestions for multi-value fields:

General

Use * as delta iterator

My basic suggestion is to add "*" as delta iterator for multi value fields. Only multi value items have a delta so that would be safe and short to define * as "0-infinite" delta in ascending order.

[node:multivalued_field:*:{Everything like with delta}]
The difference to an explicit delta number is, that we have to join the result values. Because we iterate over the delta, we hopefully shouldn't have to care much about the concrete results but simply join each delta result.

As a fist step I'll add a discussion results part to the issue summary. Feel free to add examples and improve it. Also the issue summary should be updated according to #2 where @Berdir wrote he's interested.

I'm very excited about this imporant improvement!

anybody’s picture

Issue summary: View changes
anybody’s picture

Issue summary: View changes
anybody’s picture

PS: If the issue author thinks this is too far away from his original issue, I can of course create a new issue.
Otherwise we should align the title to something like "Provide iteration on multi value field deltas". But I guess a native speaker will be able to improve that ;)

PPS: If we form a small group together with @Berdir to push things forward here, I guess we can have fast and well tested results and prevent this from being an issue for years ;) Interested?

anybody’s picture

das-peter’s picture

@Anybody I like the idea and great write-up. I hope I can make some time to help out.
I need to reflect about all the modifiers - I guess main goal should be a consistent approach.

cgoffin’s picture

I altered the patch to work with release 8.x-1.8.

cgoffin’s picture

Wrong file naming, new file added.

louis-cuny’s picture

Updated patch (just one line of diff context) to work with latest commit.

szantog’s picture

+++ b/token.tokens.inc
@@ -1679,6 +1702,29 @@ function field_tokens($type, $tokens, array $data, array $options, BubbleableMet
+                $replacements[$original] = token_render_array($field_data_arr, $options + ['join' => '']);

This part doesn't make too much sense because of the 'join' => '' part. This renders the values without any separator, and there is no chance to explode it. Or did I miss something?

sorlov’s picture

Status: Needs review » Needs work

Yes, it makes sense to have values comma-separated at least.

sorlov’s picture

Status: Needs work » Needs review
StatusFileSize
new5.4 KB

Updated join with comma

andypost’s picture

dqd’s picture

+++ b/token.tokens.inc
@@ -1778,7 +1803,30 @@ function field_tokens($type, $tokens, array $data, array $options, BubbleableMet
+                $replacements[$original] = token_render_array($field_data_arr, $options + ['join' => ',']);
#16 Updated join with comma

From the OT summary TODO list I see the idea to provide options for a choice of common separators, which makes perfectly sense. So, hard coded join with comma should be rather extended by a join with "var of whatever is given behind JOIN:_" in the token.

dqd’s picture

Other question: Is this project https://www.drupal.org/project/aet possibly interesting to look at in any way to check for overlapping functionality? But maybe I am wrong at a glimpse.

weseze’s picture

Tried the patch from #17, but is not giving me the results I expected.
I am testing it out on a webform_submission where I have a webform field that references nodes. Trying to get all email fields from those nodes.

I have tried:
[webform_submission:values:autocaristen:*:entity:field_email]
Results in "webform_stored_value1entitywebform_stored_value1entitywebform_stored_value3"

[webform_submission:values:autocaristen:entity:*:field_email]
Results in nothing, empty string

[webform_submission:values:autocaristen:entity:field_email:*]
Results in nothing, empty string

[webform_submission:values:autocaristen:array:entity:field_email:join:+]
Results in "webform_stored_value1entitywebform_stored_value1entitywebform_stored_value3"

[webform_submission:values:autocaristen:array:entity:field_email:join:,]
Results in error, invalid token

[webform_submission:values:autocaristen:entity:array:field_email:join:+]
Results in nothing, empty string

Is what I am trying to do supposed to work with this patch? If so, how? If not, how can I help get it working?

I also noticed a possible error in the patch code:

  // Handle array tokens if there are any.
  if ($array_token) {
    $property_array_tokens = $token_service->findWithPrefix($field_tokens, 'array');
    foreach ($property_array_tokens as $token => $original) {

The variable $original is already defined in an outer foreach and overriden here, that could be an issue.

danharper’s picture

This patch works for me.

@weseze
This should work but only return the string separated by a comma.
[webform_submission:values:autocaristen:entity:array:field_email]

bgilhome’s picture

StatusFileSize
new7.34 KB

I've attached an updated patch to handle [entity:field_name:array:entity:property_name] type tokens (for accessing properties of referenced entities on an entity reference field).

Interdiff gave me an error so I couldn't generate one - the patch just adds a code block lines 1714-1732 (after application).

NB it doesn't handle the ':join' suffix functionality.

EDIT: it doesn't seem to add the token in hook_token_info.

edison08’s picture

This patch applies to the latest DEV version.

edison08’s picture

Status: Needs work » Needs review
mlncn’s picture

Status: Needs review » Reviewed & tested by the community

Code looks good and it works great. Taxonomy term reference field example (buried all the way in a capability to get information for the current page being viewed, courtesy the Context Stack module):

[current:view:node:field_topics:array:entity:name]

Produces for example: "Politics,Money,Crime"

dimKarp’s picture

Hello. The available token options of the array are not shown in the list of tokens. The only token that is being displayed in the list is array:target_id. At least the array:entity:name would be useful to add it in the list since some modules (ex. contact_emails) check the existence and the validity of the token.

b-prod’s picture

StatusFileSize
new7.39 KB

Reroll of #23 against latest version.

penyaskito’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new2.51 KB
new8.25 KB

This still needs works because of the tests. I needed this too, but I actually needed being able to customize the join ¿separator?

With this patch
[node:multivalued_field_image:array:target_id:join:+] would return 1+2
[node:multivalued_field_image:array:target_id] would return 1,2

This definitely needs a ton of tests though. I'm marking it as needs review just to see if current tests are still passing with this.

penyaskito’s picture

Status: Needs review » Needs work

At least I didn't broke anything. Back to needs work.

@Berdir @Anybody Can we work on defining the minimum acceptable test cases that would need to be for this to be accepted?
I'm willing to work on those.

lisagodare’s picture

StatusFileSize
new1.15 KB
new8.34 KB

I also needed the ability to customize the join separator, but #28 didn't work for me. I modified it just a little bit.

penyaskito’s picture

Status: Needs work » Needs review

Marked as NR to check if tests still pass.
@lisagodare@gmail.com Could you describe your scenario? If last patch wasn't working for you, maybe is something to consider when we write the tests.

lisagodare’s picture

Sure thing!
It's sort of complex, but in the end I'm using tokens + metatag + pivot (multivalue in metatag), and needed to not use the default comma as separator, because that breaks on text that has commas in it.
Using the patch in this issue for a custom delimiter in Metatag, which I have set to `||`:
https://www.drupal.org/node/3067803
And using patch in #28, my field token looks something like:
[node:multivalued_entity_reference_field:array:entity:field_text:join:||]

However, this resulted in always using a comma for the separator, until the changes I made in #30.

penyaskito’s picture

Thanks for the answer! Yeah, my scenario was similar with schema_metatag, i had a similar token pattern that you do and in my case I needed #2976935: Improve support for multi-value schema using Metatag's custom separator option, so I might overlooked yours. Thanks for documenting it!

carsoncho’s picture

This patch does not appear to work with webforms. I'm attempting to get a multivalue term reference field to output the term names in a list with this [webform_submission:values:multivalue_term_reference:array:entity:name] and it's being output as "Term 1 (1)entityTerm 2 (2)".

I am doing token replacement via custom code with a custom WebformHandler that's calling on the webform submission handler's token service.

Any thoughts?

Edit: I wanted to note that I'm using Drupal 10.1 and using Tokens 1.12

AlGab made their first commit to this issue’s fork.

reinfate’s picture

StatusFileSize
new18.6 KB
new1.06 KB

For me, patch #30 doesn't work for image-style tokens like [node:field_image:array:image_style] or [node:field_image:array:entity:image_style]
Patch #36 fixes works for [node:field_image:array:image_style]

bluegeek9 made their first commit to this issue’s fork.

den tweed’s picture

StatusFileSize
new8.15 KB

Since 1.17 converted the hooks to OOP hooks I rerolled the patch in #36 for that

liam morland made their first commit to this issue’s fork.

liam morland’s picture

I created a merge request with the patch in #38.

jastraat’s picture

For our situation, we have a multi-value taxonomy term entity reference field (let's call it field_tags) where some of the term names contain commas. This is incompatible with producing useful data for use in the for example the "about" property with schema_metatag.

I tested the MR and was able to produce a comma-separated list of taxonomy term IDs (versus term names) using:

[node:field_tags:array:target_id]

I was less successful referencing the term name with custom join character and then using that character as the "Separator used with multiple values"

I tried:

[node:field_tags:array:entity:name:join:+]

The issue description doesn't clearly state what syntax the MR is supposed to add/support. If someone knows, it would be good to document that so folks can accurately review.

das-peter’s picture

@jastraat [node:field_tags:array:entity:name:join:+] should be fine actually. Everything after array:entity: should behave like a normal entity token replacement.
However, there was indeed an issue with notations like that: [node:field_tags:array:entity:field_machine_name:value:join:,] while [node:field_tags:array:entity:field_machine_name:join:,] was working.
I've just implemented a fix for that issue and added an unit test to verify the behavior.