1

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.');
  }

}

1 Answer 1

2

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.

1
  • Oh my god. Thank you. I was stuck on that one. The required = FALSE was the key.
    – xpersonas
    Commented Dec 1, 2022 at 16:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.