当我的节点包含一个自定义令牌时,我会在节点上保存一个崩溃。我使用令牌过滤器模块在节点内容中显示令牌。
现在,在Drupal 8.8中,当我保存一个包含自定义令牌之一的新节点时,我将得到一个WSOD,其中包含以下错误:
Drupal\Core\EntityStorageException:“节点”实体不能具有URI,因为它在Drupal\Core\Entity\Sql\SqlContentEntityStorage->save()中没有ID ( core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).的第846行)
但真正的错误似乎来自令牌:
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)奇怪的是,如果我在保存节点时从body字段中删除令牌,节点就会正确地保存--然后我可以编辑节点并将令牌添加回去,而不会出现任何错误。只有当节点被保存并且其中包含一个令牌时,才会发生错误。
像[site:name]这样的Drupal令牌工作得很好;导致错误的只是我的自定义令牌。
以下是相关代码:
/**
* 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";
}
}我该怎么解决这个问题?
发布于 2020-05-26 14:31:35
如果令牌是在保存节点之前生成的,这将导致WSOD,因为不能为节点创建URI。实体URI需要一个实体ID来构建实体的路径。
因此,我会将您的代码更改为:
function MYMODULE_token_set_custom_type($node) {
if ($alias = $node->toURL()->toString()) {
preg_match('(/.*/)', $alias, $matches);
if ($matches[0] == '/apples/') {
return "Apples";
}
else {
return "Oranges";
}
}
}发布于 2020-05-26 14:57:54
进一步的调试和4k4的注释以及Jaypan的回答为我提供了解决这个问题所需的提示。
首先,虽然这是由令牌引起的,但它也是由hook_node_presave()中的以下调用引起的:
function MYMODULE_node_presave(NodeInterface $entity) {
$processed_display = \Drupal::service('renderer')->renderPlain($myspecialviewmode_render);
$entity->set('field_text_main_display', $processed_display);
$entity->field_text_main_display->format = 'processed';造成这一问题的不是标记或这个钩子,而是它们在一起的存在。
为了解决这个问题,我重写了我的令牌,使其完全不依赖URL。
https://drupal.stackexchange.com/questions/293981
复制相似问题