Problem/Motivation
Today I worked with a member of my team to add a calculated entity reference base field to the user entity. We expected to see token pick that new field up and offer the tokens for it out of the box, given token's entity, fields, and entity reference support. We had done the same thing in Drupal 7 with success, so we expected at least as much from Drupal 8. Instead we hit up against an inconsistency in Token's entity support, and an inconsistency in token's field support.
(1.) The entity issue: If an entity type is already described to token by another module, token does not add tokens to it.
So in our case, because the User module defines some custom tokens for user entities, token would not expose our new base field and its referenced entity's tokens. We were forced to code this by hand, duplicating code that is already in the token module. It looks like this would be the case for many core entity types. Ughh.
(2.) The field issue: If an entity type defines a calculated base field, token does not provide a token for it.
So we realized that even if we fixed (1.) we were still out of luck because our field wasn't stored in the database. I can't imagine this restriction is by design.
Proposed resolution
Add a configurable setting to control token generation behavior
Similar to how Pathauto has entity type settings for which entity types the path field should be enabled, we propose adding a setting to control whether automatic tokens are generated for each entity type.
Setting behavior:
- NULL (default): Maintains existing behavior - if an entity type already has custom tokens defined, no automatic tokens are generated
- TRUE: Always generate automatic tokens for the entity type, regardless of existing custom tokens
- FALSE: Never generate automatic tokens for the entity type
Implementation approach:
- Extend
\Drupal\token\TokenEntityMapperwith methods to access the setting information - When no explicit setting exists, fall back to the current behavior
- Once someone visits the settings page and saves it, store explicit TRUE/FALSE values for entity types
- This also allows disabling token generation for entity types that will never be used for tokens
Field support improvements:
- Expose calculated/computed base fields along with stored base fields
- Support bundle base fields added via
hook_entity_bundle_field_info_alter()
This approach provides backward compatibility while giving developers and site builders the flexibility to enable comprehensive token support when needed.
Remaining tasks
- Implement configuration settings for entity type token generation
- Extend TokenEntityMapper with setting access methods
- Add support for computed and bundle base fields
- Write tests for new functionality
- Update documentation
- Code review and testing
User interface changes
- New configuration page/settings for controlling token generation per entity type
API changes
- Expanded token generation to include computed and bundle base fields
- New configuration schema for entity type token settings
Data model changes
- New configuration storage for entity type token generation settings
Comments
Comment #2
chrisolof commentedInitial stab at a patch.
Comment #4
chrisolof commentedComment #5
berdirThis is currently not done on purpose to avoid conflicts and duplicate between manually defined and generated tokens. E.g. node token names don't match 1:1 to field names and that will result in confusing duplicates and also even more tokens than there already are, which makes the UI overload problem worse until there is a better one.
Comment #6
chrisolof commented@Berdir If I can't convince you to make this the default behavior... what if we made it an option/setting in the module (keeping today's limited tokens as the default)?
Also - what do you think about the idea of exposing all base fields (including computed)?
Attached patch is updated to include test coverage for computed base fields.
Comment #7
chrisolof commentedComment #8
jonathanshawI see very strong arguments on both sides of this. Some possible ways of reconciling:
1) Hide the extra tokens this patch causes from the UI
2) Allow a setting to toggle the behavior, as suggested by @chrisolof
3) Create a new 'fields' group for each entity type, and put the full set of automatic tokens generated by this patch under that. So it's [node:fields:my_computed_base_field] and you have both [node:fields:title] and [node:title]. Because the extra fields are all collapsed up under 'fields' the clutter is minimised.
I think 3 is cleanest.
Comment #9
claudiu.cristeaI tried #6 but I cannot see my computed field token in the list.
EDIT: Probably because my computed field is a bundle field, added via
hook_entity_bundle_field_info_alter()?Comment #10
mautumn commentedMy usecase was to have the UUID in the path using pathauto. I was slightly surprised that the token module didn't natively support this as this is core entity data. Anyway, I didn't like the idea of using a module specially for this - so I tried @chrisolof 's patch #6. It worked perfectly. Thanks very much indeed.
Comment #11
drcolossos commentedI have the same problem as #9 while using the same hook.
Comment #12
owenbush commentedI too was struggling with bundle base fields and have updated the patch, it probably needs some tests but I am not sure the best way to approach those. Attached is a patch and interdiff for adding bundle base field support too.
Comment #13
berdirHere's a proposal: Add a setting to control this. Similar to how pathauto has an entity type setting for which entity types the path field should be enabled.
To keep the existing behavior, support NULL as an implicit default-behavior value.
We can extend \Drupal\token\TokenEntityMapper with a methods to make it easier to access that information.
If the stored value is an explicit TRUE or FALSE, respect that, if there is no value set, then fall back to the existing check. Once someone visits the settings page, and saves it, we store an explicit TRUE/FALSE for any entity type. That could also be useful if you know that some entity types will never be used for tokens, then you can disable that for you site.
Someone interested in working on that?
Comment #14
mpotter commentedJust FYI, I ran into a case with MetaTags where I needed to reference a Token for a computed field. Used the patch in #12 on my D9.0.10 site and seems to have worked. +1 for getting this in as an option somehow.
Comment #15
it-cruI used patch from #12 with D9.3 to get [node:uuid] working for URL alias patterns. Hope we could get this patch into some of the next releases.
Comment #16
grevil commentedFurthermore, we should let the user decide, if the token module should even create a token for an entity, maybe via annotation.
I am currently working on a module, which needs tokens to display different legal text saved by entities. So additionally to my custom tokens defined in the module file, it automatically creates attribute tokens for my entity, which I want to permit. Doing this is currently quite dirty, since I need to use "hook_token_info_alter" to unset these tokens.
It works, but doing so, will still show the tokens in the Token Help Menu, even if they are not usable.
So perhaps we could add an Entity annotation for automatically creating tokens? What do you guys think? Or did I miss a fundamental way to do this properly?
Comment #17
jacobbell84 commentedLooks like the latest release stopped the patch from applying, so I did a quick reroll
Comment #18
tim-dielsUsed patch from #17 and works.
I use it for [taxonomy_term:uuid].
The issue probably should write out tasks so it is easier to see what is done and still needs to be done?
Comment #19
heddn+1 to #13. But for now, i'm just going to use the latest patch.
Comment #20
mrweiner commentedRe-rolled #17 against latest dev.
Comment #21
unstatu commentedHello @Berdir,
Does your proposal from #13 still valid? Does it worth to put effort on this?
In that case I could invest some time to try to push this issue.
Comment #22
mxr576Opened #3466573: Expose UUID tokens for all content entities in Drupal core that adds UUID support for built-in content entities in Drupal core.
Comment #23
berdirRe #21, yes, I still think that might be a viable way forward.
Comment #24
andriy khomych commented+1 one for this patch.
I have a custom entity type, for which I was provided some custom tokens, but there is no way to have standard tokens work (like id, label, etc.).
This patch solves the issue.
Comment #25
mglaman#20 still requires the
fieldmodule to be installed, even though generic field support has been added:The module exists check can be removed.
Comment #26
ptmkenny commented#3466573: Expose UUID tokens for all content entities in Drupal core has been committed to 11.x.
I was using a patch in this issue to generate UUID tokens for custom entities, but I am now able to remove the patch and I still have UUID tokens as a result of the change referenced above.
Is there still a need for this issue? It seems like it has now been fixed upstream for most? use cases.
Comment #27
berdirMy proposal from #13 is still valid and useful
Comment #28
mxr576Updated the proposed solution based on Berdir's comment at #13, please double check.
Comment #29
a.dmitriiev commentedFor those who were using patch #20 I have re-rolled the patch against version 1.17
Comment #30
a.dmitriiev commentedThere was a typo in previous patch :( sorry
Comment #31
a.dmitriiev commentedThat was really not a good idea to re-roll the patch in a rush, because there is another typo :(