In a custom module, how can I create a custom token? (Transcribing @bwpanda's answer to this question in Zulip for posterity.)
Accepted answer
Comments
/** * Implements hook_token_info(). */ function surg_token_info() { return array( 'types' => array( 'species' => array( 'name' => t('Species'), 'description' => t('Tokens related to Species nodes.'), 'needs-data' => 'node', ), ), 'tokens' => array( 'species' => array( 'title' => array( 'name' => t('Title'), 'description' => t('The title of the Species node.'), 'type' => 'node', ), ), ), ); } /** * Implements hook_tokens(). */ function surg_tokens($type, $tokens, array $data = array(), array $options = array()) { $langcode = isset($options['language']) ? $options['language']->langcode : LANGUAGE_NONE; $sanitize = !empty($options['sanitize']); $replacements = array(); if ($type == 'species' && !empty($node = $data['node'])) { foreach ($tokens as $name => $original) { if ($name == 'title') { // Create a title of the form: 'GENUS SPECIES [(NOTATION)]'. $genus = taxonomy_term_load($node->field_genus[$langcode][0]['tid']); $title = $genus->name . ' ' . $node->field_species[$langcode][0]['value']; if (!empty($notation = $node->field_notation[$langcode][0]['value'])) { $title .= ' (' . $notation . ')'; } $replacements[$original] = $sanitize ? filter_xss($title) : $title; } } } return $replacements; }
BWPanda: I first create a token type called 'Species' which holds all the tokens (in this case just 1) for my Species nodes (and it requires 'node' data to work properly). I then create a token in the Species group called 'title' which I will use as my Species node titles (I did all this because in D7 I was using custom PHP code in auto nodetitle, which isn't available in Backdrop since the PHP module was (rightly) removed). So that's the hook_token_info() implementation.
BWPanda: Now for the token code itself (in hook_tokens(): I make sure I'm only dealing with 'Species' tokens where node data is available. Then, for each token (again, in this case just 'title') I generate the title based on the different node field values. I get the term ID from the term reference field, and use it to load the full term, where I add the term name to the beginning of my title. Then I add the value of my Species textfield. Finally, if the Notation field has a value, I append it in brackets on the end. I then add that to the array and return it.