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 |
| Comment | File | Size | Author |
|---|---|---|---|
| #38 | token-array-3115486-38.patch | 8.15 KB | den tweed |
| #36 | interdiff.30-36.txt | 1.06 KB | reinfate |
| #36 | token-array-3115486-36.patch | 18.6 KB | reinfate |
| #30 | token-array-3115486-30.patch | 8.34 KB | lisagodare |
| #30 | interdiff.28-30.txt | 1.15 KB | lisagodare |
Issue fork token-3115486
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
Comment #2
berdirHey 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.
Comment #3
anybodyHi @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!
Comment #4
anybodyComment #5
anybodyHere 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!
Comment #6
anybodyComment #7
anybodyComment #8
anybodyPS: 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?
Comment #9
anybodyComment #10
das-peter commented@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.
Comment #11
cgoffin commentedI altered the patch to work with release 8.x-1.8.
Comment #12
cgoffin commentedWrong file naming, new file added.
Comment #13
louis-cuny commentedUpdated patch (just one line of diff context) to work with latest commit.
Comment #14
szantog commentedThis 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?
Comment #15
sorlov commentedYes, it makes sense to have values comma-separated at least.
Comment #16
sorlov commentedUpdated join with comma
Comment #17
andypostPatch makes some CS clean-up
Needs work for tests
Comment #18
dqdFrom 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.
Comment #19
dqdOther 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.
Comment #20
weseze commentedTried 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:
The variable $original is already defined in an outer foreach and overriden here, that could be an issue.
Comment #21
danharper commentedThis 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]
Comment #22
bgilhome commentedI'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.
Comment #23
edison08 commentedThis patch applies to the latest DEV version.
Comment #24
edison08 commentedComment #25
mlncn commentedCode 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"
Comment #26
dimKarp commentedHello. 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 thearray:entity:namewould be useful to add it in the list since some modules (ex. contact_emails) check the existence and the validity of the token.Comment #27
b-prod commentedReroll of #23 against latest version.
Comment #28
penyaskitoThis 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.
Comment #29
penyaskitoAt 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.
Comment #30
lisagodareI also needed the ability to customize the join separator, but #28 didn't work for me. I modified it just a little bit.
Comment #31
penyaskitoMarked 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.
Comment #32
lisagodareSure 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.
Comment #33
penyaskitoThanks 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!
Comment #34
carsoncho commentedThis 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
Comment #36
reinfate commentedFor 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]
Comment #38
den tweed commentedSince 1.17 converted the hooks to OOP hooks I rerolled the patch in #36 for that
Comment #40
liam morlandI created a merge request with the patch in #38.
Comment #42
jastraat commentedFor 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.
Comment #43
das-peter commented@jastraat
[node:field_tags:array:entity:name:join:+]should be fine actually. Everything afterarray: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.