Score:0

Context Definition for Taxonomy Term Not Working

cn flag

For the life of me, I can not get the taxomony term context definition to work for me. I'm trying to extend the ConditionPluginBase. I can get it working for nodes, but not for terms. I want to show a block on certain node and term pages.

When I just use the node context, it works for nodes.

When I add the term context, it doesn't work at all - not for nodes or terms.

Works

/**
 * @Condition(
 *   id = "blog_content",
 *   label = @Translation("Blog Content"),
 *   context_definitions = {
 *     "node" = @ContextDefinition("entity:node", label = @Translation("node")),
 *   }
 * )
 */

Does Not Work

/**
 * @Condition(
 *   id = "blog_content",
 *   label = @Translation("Blog Content"),
 *   context_definitions = {
 *     "node" = @ContextDefinition("entity:node", label = @Translation("node")),
 *     "taxonomy_term" = @ContextDefinition("entity:taxonomy_term", label = @Translation("Taxonomy Term"))
 *   }
 * )
 */

I see the TermRouteContext class. I know this exist. I just can't figure out why I can't trigger it.

Full Code

<?php

namespace Drupal\admin_helper\Plugin\Condition;

use Drupal\Core\Condition\ConditionPluginBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * @Condition(
 *   id = "blog_content",
 *   label = @Translation("Blog Content"),
 *   context_definitions = {
 *     "node" = @ContextDefinition("entity:node", label = @Translation("node")),
 *     "taxonomy_term" = @ContextDefinition("entity:taxonomy_term", label = @Translation("Taxonomy Term"))
 *   }
 * )
 */
class BlogContent extends ConditionPluginBase implements ContainerFactoryPluginInterface {

  /**
   * {@inheritdoc}
   */
  public static function create(
    ContainerInterface $container,
    array $configuration,
    $plugin_id,
    $plugin_definition
  ) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition
    );
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return ['show' => 0] + parent::defaultConfiguration();
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(
    array $form,
    FormStateInterface $form_state
  ) {
    $form['show'] = [
      '#title' => $this->t(
        'Display for blog post nodes and pages marked as "Blog Landing."'
      ),
      '#type' => 'checkbox',
      '#default_value' => $this->configuration['show'],
    ];

    return parent::buildConfigurationForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(
    array &$form,
    FormStateInterface $form_state
  ) {
    $this->configuration['show'] = $form_state->getValue('show');
    parent::submitConfigurationForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function evaluate() {
    if (empty($this->configuration['show']) && !$this->isNegated()) {
      return TRUE;
    }

    $node = $this->getContextValue('node');

    if (
      ($node->getType() == "blog_post") ||
      (
        $node->hasField('field_page_type') &&
        $node->get('field_page_type')->target_id === '597'
      )
    ) {
      return TRUE;
    }

    $term = $this->getContextValue('taxonomy_term');

    if ($term) {
      return TRUE;
    }

    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function summary() {
    if ($this->configuration['show']) {
      // Check if the 'negate condition' checkbox was enabled.
      if ($this->isNegated()) {
        // The condition is enabled and negated.
        return $this->t(
          'The block will be shown on all pages except the Blog-related pages.'
        );
      }
      else {
        // The condition is only enabled.
        return $this->t('The block will be shown only on Blog-related pages.');
      }
    }
    // The condition is not enabled.
    return $this->t('The block will be shown on all pages.');
  }

}
Score:1
in flag

Context depends on the presence of one or more context providers and how they extract that data. In this case of TermRouteContext, it extracts Term information from the route.

if ($route_object = $this->routeMatch->getRouteObject()) {
  $route_parameters = $route_object->getOption('parameters');

  if (isset($route_parameters['taxonomy_term']) && $term = $this->routeMatch->getParameter('taxonomy_term')) {
    $value = $term;
  }
  elseif ($this->routeMatch->getRouteName() == 'entity.taxonomy_term.add_form') {
    $vocabulary = $this->routeMatch->getParameter('taxonomy_vocabulary');
    $value = Term::create(['vid' => $vocabulary->id()]);
  }
}

(Quick aside, you can debug the context provider's getRuntimeContexts() and walk through how and if it's getting the information. They always execute iirc.)

This means that in order for TermRouteContext to extract Term information and provide it to your condition plugin, your code must be executing from a route where a parameter named taxonomy_term is present and has a value (most likely the term ID). If any of the context values are empty, your condition plugin's context requirements are not satisfied and Drupal won't execute your plugin.

If you still intend to run your plugin knowing full well that the term from context can be empty, missing, or just not provided, you can set required = FALSE on your @ContextDefinition for entity:taxonomy_term. In your case, you want to execute this condition on node or term pages, you can set required = FALSE on both and you deal with when either value is present or empty.

/**
 * @Condition(
 *   id = "blog_content",
 *   label = @Translation("Blog Content"),
 *   context_definitions = {
 *     "node" = @ContextDefinition("entity:node", required = FALSE, label = @Translation("node")),
 *     "taxonomy_term" = @ContextDefinition("entity:taxonomy_term", required = FALSE, label = @Translation("Taxonomy Term"))
 *   }
 * )
 */

If TermRouteContext doesn't fit your use case (e.g. the term isn't on the route, or if you have to dig it out of some field on the current node), you can always build your own context provider.

xpersonas avatar
cn flag
Oh my god. Thank you. I was stuck on that one. The `required = FALSE` was the key.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.