首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Drupal的上下文API创建自定义上下文?

如何使用Drupal的上下文API创建自定义上下文?
EN

Drupal用户
提问于 2019-07-30 15:39:35
回答 1查看 2.1K关注 0票数 10

通过添加以下内容,可以访问块插件中的当前节点上下文:

代码语言:javascript
复制
 *  context_definitions = {
 *    "node" = @ContextDefinition("entity:node", label = @Translation("Node"), required=FALSE)
 *  }

它的注释。然后使用以下方法访问节点对象:

代码语言:javascript
复制
$context = $this->getContext('node');

/** @var NodeInterface $node */
$node = $context->getContextData()->getValue();

只要它是可用的。但是,假设我希望创建只有在节点有特定字段时才处于活动状态的上下文。

我目前正在尝试反向工程,因为在上下文API上没有我能找到的资源,但是也许有人有一些有用的例子要分享?

EN

回答 1

Drupal用户

回答已采纳

发布于 2019-07-31 10:22:42

好吧,我弄明白了,我在这里描述它。到目前为止,它还没有在其他任何地方被解释,这对我来说真的很令人惊讶。

假设我们有一个内容类型news,其中有一个字段field_section存储来自sections词汇表的术语的引用。现在,每当我们在节点的页面上,而这个节点引用一个节时,我们想要触发上下文,这个上下文将作为表示我们节的Term对象来提供。此外,我们有一个块插件,它取决于本节的可用性,并且只有在当前页面上可用的时候才能看到。

我们可以使用node上下文来实现这一点,但是接下来我们必须在每个需要这些信息的上下文感知插件中添加检查节点field_section内容的逻辑,我们希望将其简化为在当前页面上可用部分时激活上下文--这就是关键所在。

因此,首先,我们必须提供一个实现Drupal\Core\Plugin\Context\ContextProviderInterface的服务,并使用context_provider标记标记它,如下所示:

代码语言:javascript
复制
  mymodule.section_context:
    class: Drupal\mymodule\ContextProvider\SectionContextProvider
    arguments: ['@context.repository']
    tags:
      - { name: context_provider }

注意,我们正在注入@context.repository服务,我们将能够从它中提取node上下文。首先,我们依赖于节点是否可用,所以我们也可以重用这个上下文。我们也可以在这里直接注入@node.node_route_context服务,并且具有更明确的依赖关系,但是我觉得通过存储库服务来完成这个任务会更干净。由你决定。

现在,我们的上下文提供程序的代码:

代码语言:javascript
复制
namespace Drupal\mymodule\ContextProvider;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextInterface;
use Drupal\Core\Plugin\Context\ContextProviderInterface;
use Drupal\Core\Plugin\Context\ContextRepositoryInterface;
use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\Core\Plugin\Context\EntityContextDefinition;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\node\NodeInterface;

/**
 * Class SectionContextProvider
 */
class SectionContextProvider implements ContextProviderInterface {

  use StringTranslationTrait;

  /**
   * @var ContextRepositoryInterface
   */
  private $contextRepository;

  /**
   * @param ContextRepositoryInterface $contextRepository
   */
  public function __construct(ContextRepositoryInterface $contextRepository) {
    $this->contextRepository = $contextRepository;
  }

  /**
   * {@inheritdoc}
   */
  public function getRuntimeContexts(array $unqualified_context_ids) {

    $nodeContextId = '@node.node_route_context:node';

    /** @var ContextInterface $nodeContext */
    $nodeContext = $this->contextRepository->getRuntimeContexts([$nodeContextId])[$nodeContextId];
    $value = NULL;

    /** @var NodeInterface $node */
    $node = $nodeContext->getContextData()->getValue();
    if ($node && $node->hasField('field_section')) {
      $value = $node->get('field_section')->entity;
    }

    // We are reusing cache contexts.
    $cacheContexts = $nodeContext->getCacheContexts();
    $cacheability = new CacheableMetadata();
    $cacheability->setCacheContexts($cacheContexts);

    $contextDefinition = EntityContextDefinition::create('taxonomy_term');

    $context = new Context($contextDefinition, $value);
    $context->addCacheableDependency($cacheability);
    $result['mymodule_section'] = $context;

    return $result;
  }

  /**
   * {@inheritdoc}
   */
  public function getAvailableContexts() {
    $context = EntityContext::fromEntityTypeId('taxonomy_term', $this->t('Mywebsite Section from Node'));
    return ['mymodule_section' => $context];
  }

}

基本上是从node上下文中获取当前节点,然后提取可用的节数据。

但这还不是全部。

我们希望使插件块依赖于上下文,因此我们正在添加它的注释:

代码语言:javascript
复制
 *  context_definitions = {
 *    "mymodule_section" = @ContextDefinition("entity:taxonomy_term:sections", label = @Translation("Mywebsite Section"))
 *  }

但它还是行不通的,这是最棘手的部分。我们还必须配置插件块的上下文映射。我们可以这样做,将其作为默认配置的一部分,如下所示:

代码语言:javascript
复制
  /**
   * @return array
   */
  public function defaultConfiguration() {
    return [
      'context_mapping' => [
        'mymodule_section' => '@mymodule.section_context:mymodule_section',
      ],
    ] + parent::defaultConfiguration();
  }

只有这样它才能起作用。如果上下文不可用,则不会呈现块,如果可用,则可以通过以下方式访问节点的field_section字段引用的术语:

代码语言:javascript
复制
$sectionTerm = $this->getContext('mymodule_section')->getContextData()->getValue();

这太复杂了,不可能没有任何文档,但我希望这个描述能对某些人有所帮助。

如果有人知道,在drupal.org网站上,我可以写一个文档,请告诉我,我们必须改进这些东西。

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

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

复制
相关文章

相似问题

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