hook_token_info() is used to expose data objects and their properties. The odd thing about this hook is that the data objects are declared separately from their tokens, which causes some confusion.

I attached a patch that updates system.api.php with a reworked hook_token_info() and hook_token_info_alter(). It groups data types and their tokens together, and moved the function of needs-data 'properties' to array keys, so the whole array structure is simper, and so is the documentation. Note that the patch indeed only updates the documentation. Once a consensus has been reached, the 7 hook_token_info() implementations in core can be changed, as well as the code that calls these hooks.

Comments

xano’s picture

StatusFileSize
new6.48 KB
dave reid’s picture

Status: Needs review » Needs work
+++ b/core/modules/system/system.api.phpundefined
@@ -3326,81 +3326,64 @@ function hook_tokens_alter(array &$replacements, array $context) {
-    'needs-data' => 'node',

This is critical information that tells us if the token is global, or requires input.

xano’s picture

Status: Needs work » Needs review

This is critical information that tells us if the token is global, or requires input.

Good point. Would it make sense to make that a boolean flag? The reason I removed it, was the seemingly duplicate information, as types usually have the same string as their array key and their needs-data value.

A concern that was just voiced on IRC was that the suggested solution does not allow developers to add tokens to existing types. I want to make token_info() use NestedArray, so this functionality is still available.

eaton’s picture

A concern that was just voiced on IRC was that the suggested solution does not allow developers to add tokens to existing types. I want to make token_info() use NestedArray, so this functionality is still available.

That's precisely the reason that the two separate pools of hook data were initially defined. The set of "Tokenable things" and the set of "Discrete tokens" can be managed independently without explicitly digging in and altering someone else's data.

I don't have really strong feelings one way or another, as long as it doesn't prevent a dev from hucking arbitrary tokens into a given token space.

xano’s picture

See #1911768: Make token and token type descriptions optional for a related issue that touches the same code.

xano’s picture

token_info() uses module_invoke_all(), which was converted to use NestedArray a while ago.

This is critical information that tells us if the token is global, or requires input.

The only usage of needs-data I have found is Token.module. Core does not use the property. I opted to go for the boolean flag, because it prevents duplicate data and also makes it easier to fix #1920688: Support multiple instances of the same token type in token replacement more gracefully.

xano’s picture

Some data types have a "type" property. It doesn't seem to be used in core, but Token.module uses it to allow types to extend other types. Core uses it for the current-user data type, and the proposed patch for #943028: 'Date' token namespace is ambiguous uses it as well. If core should continue to use it, I believe we should also perform the actual merge in core, rather than in Token.module, and we should document the property in system.api.php.

dave reid’s picture

We should have a separate issue for renaming 'needs-data' to a 'needs-data' => TRUE/FALSE flag instead.

xano’s picture

StatusFileSize
new41.3 KB

This patch only changes the return value structure, and it adds documentation for tokens' "type" properties, and a few lines of code to actually support this in core. It leaves needs-data alone.

dave reid’s picture

This is looking really awesome. The only thing I can think of is that I actually prefer the tokens to be listed like they were before, but all in one array:

  // Core tokens for nodes.
  $tokens['node'] = array(
    'name' => t('Nodes'),
    'description' => t('Tokens related to individual content items, or "nodes".'),
    'needs-data' => 'node',
  );
  $tokens['node']['tokens']['nid'] = array(
    'name' => t("Content ID"),
    'description' => t('The unique ID of the content item, or "node".'),
  );
  $tokens['node']['tokens']['vid'] = array(
    'name' => t("Revision ID"),
    'description' => t("The unique ID of the node's latest revision."),
  );
  $tokens['node']['tokens']['tnid'] = array(
    'name' => t("Translation set ID"),
    'description' => t("The unique ID of the original-language version of this node, if one exists."),
  );
  ...

As compared to what #9 currently has in the hooks:

  // Core tokens for nodes.
  $tokens['node'] = array(
    'name' => t('Nodes'),
    'description' => t('Tokens related to individual content items, or "nodes".'),
    'needs-data' => 'node',
    'tokens' => array(
      'nid' => array(
        'name' => t('Content ID'),
        'description' => t('The unique ID of the content item, or "node".'),
      ),
      'vid' => array(
        'name' => t('Revision ID'),
        'description' => t("The unique ID of the node's latest revision."),
      ),
      'tnid' => array(
        'name' => t('Translation set ID'),
        'description' => t('The unique ID of the original-language version of this node, if one exists.'),
      ),
  );

The former is a little more verbose, but I find it easier to read and scan, especially for people that want to look at the info hooks to figure out which tokens to alter.

If we agree to go with the first syntax, I would prefer to have it addressed not in a followup issue but here.

dave reid’s picture

Status: Needs review » Needs work
+++ b/core/includes/token.incundefined
@@ -235,31 +237,24 @@ function token_find_with_prefix(array $tokens, $prefix, $delimiter = ':') {
 function token_info() {
-  $data = &drupal_static(__FUNCTION__);
-  if (!isset($data)) {
-    $data = module_invoke_all('token_info');
-    drupal_alter('token_info', $data);
+  $token_info = &drupal_static(__FUNCTION__);
+
+  if (is_null($token_info)) {
+    $token_info = module_invoke_all('token_info');
+    drupal_alter('token_info', $token_info);
+    // Expand data types that extend another type.
+    foreach ($token_info as &$type) {
+      if (isset($type['type']) && isset($token_info[$type['type']])) {
+        $type = NestedArray::MergeDeep($token_info[$type['type']], $type);
+      }
+    }
   }
-  return $data;
+
+  return $token_info;
 }

This is a functional change, and should be removed for now. This will also conflict with #1969540: Convert token.inc to a service

xano’s picture

Status: Needs work » Needs review
StatusFileSize
new32.3 KB

I opened #1969730: Token type 'type' property is used, but not supported for the base type bug. I also updated the syntax. Note that the patch still touches token.inc and conflicts with #1969540: Convert token.inc to a service. There's no way around that.

Status: Needs review » Needs work

The last submitted patch, drupal_1968214_03.patch, failed testing.

xano’s picture

Status: Needs work » Needs review
StatusFileSize
new32.21 KB

This patch depends on #1969540: Convert token.inc to a service. The test will obviously fail.

Status: Needs review » Needs work

The last submitted patch, drupal_1968214_04.patch, failed testing.

xano’s picture

Status: Needs work » Needs review

#14: drupal_1968214_04.patch queued for re-testing.

Status: Needs review » Needs work

The last submitted patch, drupal_1968214_04.patch, failed testing.

xano’s picture

Status: Needs work » Needs review
StatusFileSize
new31 KB

Re-roll now that #1969540: Convert token.inc to a service has been committed.

dave reid’s picture

+++ b/core/modules/system/system.api.phpundefined
@@ -3303,83 +3303,97 @@ function hook_tokens_alter(array &$replacements, array $context) {
+ *     - type (optional): Another data type that this type extends.
+ *   - type (optional): Another data type that this type extends.

This seems potentially confusing that 'type' is back to back. We should move the latter 'type' up above with the other first-level key/values before 'tokens'.

+++ b/core/modules/system/system.api.phpundefined
@@ -3303,83 +3303,97 @@ function hook_tokens_alter(array &$replacements, array $context) {
+ * For example:
+ * @code
+ *   $tokens['node'] = array(
+ *     'needs-data' => 'node,
+ *     'name' => t('Nodes'),
+ *     'tokens' => array(
+ *       'title' => array(
+ *         'label' => t('Title'),
+ *       ),
+ *       'author' => array(
+ *         'name' => t('Author'),
+ *         'description' => t('The author of the current node.'),
+ *         'type' => 'user',
+ *       ),
+ *     ),
+ *   );
+ * @endcode

Isn't this what the example code in hook_token_info() is for? This seems to be unnecessary. Also it's incorrect. The 'title' token uses 'label' instead of 'title' and the 'description' key/value is not optional yet.

We should probably just remove this chunk.

+++ b/core/modules/system/system.api.phpundefined
@@ -3303,83 +3303,97 @@ function hook_tokens_alter(array &$replacements, array $context) {
+ * @see token_info()

Function no longer exists, since it's the service now?

xano’s picture

StatusFileSize
new1.03 KB
new30.61 KB

Regarding the "type" properties for tokens and token types: I sorted the properties by name. You could also say the property has to come last, because it's optional.

xano’s picture

Version: 8.x-dev » 9.x-dev
Assigned: xano » Unassigned
tim.plunkett’s picture

Fixing tags

catch’s picture

Version: 9.x-dev » 8.1.x-dev
Issue summary: View changes
Status: Needs review » Postponed

This doesn't look impossible to implement with a bc layer - even if we had to do two info hooks for the different formats, so moving back to 8.x for now.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

joachim’s picture

I think this should probably be closed in favour of #2233353: Convert Token API into plugins?

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

darvanen’s picture

#33: I agree this should be closed in favour of #2233353: Convert Token API into plugins.

I'll leave it for 3 months for further discussion. If there is none I will close it after those three months have passed.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.