首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用“节点实体不能有URI”错误在节点保存上中断自定义令牌

使用“节点实体不能有URI”错误在节点保存上中断自定义令牌
EN

Drupal用户
提问于 2020-05-26 12:59:27
回答 2查看 310关注 0票数 0

当我的节点包含一个自定义令牌时,我会在节点上保存一个崩溃。我使用令牌过滤器模块在节点内容中显示令牌。

为了制作令牌,我遵循了本教程,它类似于令牌文档

现在,在Drupal 8.8中,当我保存一个包含自定义令牌之一的新节点时,我将得到一个WSOD,其中包含以下错误:

Drupal\Core\EntityStorageException:“节点”实体不能具有URI,因为它在Drupal\Core\Entity\Sql\SqlContentEntityStorage->save()中没有ID ( core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).的第846行)

但真正的错误似乎来自令牌:

代码语言:javascript
复制
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令牌工作得很好;导致错误的只是我的自定义令牌。

以下是相关代码:

代码语言:javascript
复制
/**
 * 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";
  }
}

我该怎么解决这个问题?

EN

回答 2

Drupal用户

回答已采纳

发布于 2020-05-26 14:31:35

如果令牌是在保存节点之前生成的,这将导致WSOD,因为不能为节点创建URI。实体URI需要一个实体ID来构建实体的路径。

因此,我会将您的代码更改为:

代码语言:javascript
复制
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";
    }
  }
}
票数 1
EN

Drupal用户

发布于 2020-05-26 14:57:54

进一步的调试和4k4的注释以及Jaypan的回答为我提供了解决这个问题所需的提示。

首先,虽然这是由令牌引起的,但它也是由hook_node_presave()中的以下调用引起的:

代码语言:javascript
复制
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。

票数 1
EN
页面原文内容由Drupal提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://drupal.stackexchange.com/questions/293981

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档