Token system does not enforce needs-data flag

Created on 23 September 2021, over 3 years ago
Updated 19 November 2023, over 1 year ago

Problem/Motivation

The token system does not enforce the needs-data flag as defined in implementations of hook_token_info.

For example node.module:


function node_token_info() {
  $type = [
    'name' => t('Nodes'),
    'description' => t('Tokens related to individual content items, or "nodes".'),
    'needs-data' => 'node',
  ]

  $node['nid'] = [
    'name' => t("Content ID"),
    'description' => t('The unique ID of the content item, or "node".'),
  ];

  // ...

  return [
    'types' => ['node' => $type],
    'tokens' => ['node' => $node],
  ];

If some code calls the following, then node_tokens (a hook_tokens implementation) is called with $type === 'node'.

// Empty $data array:
$result = \Drupal::token()->replace('[node:nid'], []);

node.module in this example is adding its own safety in node_tokens:

if ($type == 'node' && !empty($data['node'])) {

I would expect node_tokens (hook_tokens) not to be called in the first place if data is not provided for a 'node' token. The above guard should be made unnecessary.

Steps to reproduce

Call something like this.


$result = \Drupal::token()->replace('[node:nid]', []);

Expect no implementations of hook_tokens to be called with $type === 'node'

Proposed resolution

Dont attempt to resolve tokens when there is no data.

Remaining tasks

Fix

User interface changes

None

API changes

Maybe something...?

Data model changes

None.

🐛 Bug report
Status

Active

Version

11.0 🔥

Component
Token 

Last updated 20 days ago

No maintainer
Created by

🇦🇺Australia dpi Perth, Australia

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

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇬🇧United Kingdom nlisgo

    I'll see if I can progress/smash this one.

  • Issue was unassigned.
  • 🇬🇧United Kingdom nlisgo

    I can't find where needs-data is used at all. It adds zero value currently to add this property. It's not surfaced in any UI unless some contrib is picking it up?

    The case could be made to just strip out. We survived a long time without.

    If we decided that we want to improve the experience for developers and merely setting this property will perform the requisite checks for the presence of a data of the declared type then we need to replace the invokeAll in token > generate() with an invokeAllWith and call the corresponding info for each hook_token and optionally call the hook_token based upon the data being present.

    It would be interesting to know if there is any precedent for this type of check for other hooks in drupal.

  • 🇨🇭Switzerland berdir Switzerland

    > Expect no implementations of hook_tokens to be called with $type === 'node'

    It's just a hook. We have no knowledge of which types a certain hook_tokens() provides, anything can add tokens for everything. We have no metadata about this.

    The needs-data is used by token module, where you tell the UI component which data types you have and as a result, you see only corresponding (and global) tokens.

    So no, we shouldn't remove it, but in it's current form, this is impossible to change. We'd need a completely different API where we know which thing provides tokens for which type. There are some proposals, but I'm not convinced by using a plugin system for this for example.

    I think this should be closed as won't fix, or maybe a documentation issue to clarify it.

  • 🇦🇺Australia acbramley

    Agree with @Berdir, since types aren't tied to any one module (a module can implement multiple types) and they don't have to match the module name, there's no way we can short circuit a hook_tokens call for missing data.

Production build 0.71.5 2024