I'm getting a crash on node save when my node contains a custom token. I'm using the Token Filter module to display tokens in node content.
To make the tokens I followed this tutorial, which is similar to the Token documentation.
Now, with Drupal 8.8, when I save a new node that contains one of my custom tokens, I get a WSOD with this error:
Drupal\Core\Entity\EntityStorageException: The "node" entity cannot have a URI as it does not have an ID in Drupal\Core\Entity\Sql\SqlContentEntityStorage->save() (line 846 of core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).
But the real error appears to be from token:
Drupal\Core\Utility\Token->generate('ebook', Array, Array, Array, Object) (Line: 196)
Drupal\Core\Utility\Token->replace('
Test [ebook:custom-type] 2
', Array, Array, Object) (Line: 130)
Drupal\token_filter\Plugin\Filter\TokenFilter->process('
Test [ebook:custom-type] 2
', 'ja') (Line: 118)
Drupal\filter\Element\ProcessedText::preRenderText(Array)
call_user_func_array(Array, Array) (Line: 100)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. Support for this callback implementation is deprecated in 8.8.0 and will be removed in Drupal 9.0.0. See https://www.drupal.org/node/2966725', 'silenced_deprecation', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 781)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 372)
Weirdly, if I remove the token from the body field when I save the node, the node saves properly-- and then I can edit the node and add the token back in without any error. The error only occurs when the node is saved and it has a token in it.
Drupal tokens like [site:name]
work fine; it's just my custom token that causes an error.
Here's the relevant code:
/**
* Implements hook_token_info().
*/
function MYMODULE_token_info() {
$ebook_type = [
'name' => t('Custom Tokens'),
'description' => t('Tokens to make upgrading to D9 harder.'),
];
$ebook['custom-type'] = [
'name' => t("Custom type"),
'description' => t('Apples or oranges'),
];
return [
'types' => ['ebook' => $ebook_type],
'tokens' => ['ebook' => $ebook],
];
}
/**
* Implements hook_tokens().
*/
function MYMODULE_tokens($type, $tokens, array $data, array $options, \Drupal\Core\Render\BubbleableMetadata $bubbleable_metadata) {
$replacements = [];
if ($type == 'ebook' && !empty($data['node'])) {
foreach ($tokens as $name => $original) {
switch ($name) {
case 'custom-type':
$replacements[$original] = MYMODULE_token_set_custom_type($data['node']);
break;
}
}
return $replacements;
}
function MYMODULE_token_set_custom_type($node) {
$alias = $node->toURL()->toString();
preg_match('(/.*/)', $alias, $matches);
if ($matches[0] == '/apples/') {
return "Apples";
}
else {
return "Oranges";
}
}
How do I resolve this?