2

When on a node, the following annotation will obtain the node from the context:

/**
 * @Condition(
 *   id = "node_type",
 *   label = @Translation("Node Bundle"),
 *   context = {
 *     "node" = @ContextDefinition("entity:node", label = @Translation("Node"))
 *   }
 * )
 */

As shown here: https://www.drupal.org/docs/8/api/plugin-api/plugin-contexts

Is there an equivalent way to do this with taxonomy terms when on /taxonomy/term/%?

The code below certainly works but I'm wondering if there is a cleaner method like for nodes. Note that I'm also aware of the Term::load($tid) method but that still requires parsing the URL to obtain the tid and isn't portable (the code can be used only when run on a page).

  /**
   * Return current term.
   */
  public function getCurrentTerm() {
    $term = null;

    // Below we are using the general method to obtain the objects.
    // \Drupal\taxonomy\Entity\Term::load($tid) is the other

    // Get the unaliased path in the form /taxonomy/term/tid.
    $current_path = \Drupal::service('path.current')->getPath();

    preg_match('/\/taxonomy\/term\/\d+/', $current_path, $matches);

    // Return null if not in proper form.
    if (count($matches)) {
      // Find the parameters for this route.
      $params = \Drupal\Core\Url::fromUri("internal:" . $current_path)
        ->getRouteParameters();

      // Fetch the taxonomy object.
      $entity_type = key($params);
      $term = \Drupal::entityTypeManager()
        ->getStorage($entity_type)
        ->load($params[$entity_type]);
    }

    return $term;
  }
}
4
  • 3
    You can replace the code example with $term = \Drupal::routeMatch()->getParameter('taxonomy_term')
    – 4uk4
    May 5, 2017 at 19:35
  • 1
    The question is a little confusing. The first annotation you are showing is for a condition, which isn't used when viewing a node, but rather when defining a condition used for a block. What exactly are you trying to achieve?
    – apaderno
    May 5, 2017 at 20:42
  • I was just using that as an example. Your answer was perfect, thank you. May 5, 2017 at 23:53
  • Sorry didn't realize the question was from you, kiamlaluno. May 6, 2017 at 0:14

2 Answers 2

1

Update 10.05.2019:

There is an unresolved issue about that on drupal.org: Term route context.

It uses the same solution as in my answer below.

Original answer:

You can create a custom context provider "Taxonomy term from URL".

service definition in MYMODULE.services.yml:

  MYMODULE.taxonomy_term_context:
    class: Drupal\MYMODULE\ContextProvider\TaxonomyTermContext
    arguments: ['@current_route_match']
    tags:
      - { name: 'context_provider' }

The /src/ContextProvider/TaxonomyTermContext.php

<?php

namespace Drupal\MYMODULE\ContextProvider;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\Plugin\Context\ContextProviderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;

/**
 * Sets the current taxonomy term as a context on taxonomy term routes.
 */
class TaxonomyTermContext implements ContextProviderInterface {

  use StringTranslationTrait;

  /**
   * The route match object.
   *
   * @var \Drupal\Core\Routing\RouteMatchInterface
   */
  protected $routeMatch;

  /**
   * Constructs a new object.
   *
   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
   *   The route match object.
   */
  public function __construct(RouteMatchInterface $route_match) {
    $this->routeMatch = $route_match;
  }

  /**
   * {@inheritdoc}
   */
  public function getRuntimeContexts(array $unqualified_context_ids) {
    $result = [];
    $context_definition = new ContextDefinition('entity:taxonomy_term', $this->t('Taxonomy term from URL'));
    $value = NULL;
    if (
      ($route_object = $this->routeMatch->getRouteObject())
      && ($route_contexts = $route_object->getOption('parameters'))
      && isset($route_contexts['taxonomy_term'])
    ) {
      if ($term = $this->routeMatch->getParameter('taxonomy_term')) {
        $value = $term;
      }
    }

    $cacheability = new CacheableMetadata();
    $cacheability->setCacheContexts(['route']);

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

    return $result;
  }

  /**
   * {@inheritdoc}
   */
  public function getAvailableContexts() {
    $context = new Context(new ContextDefinition('entity:taxonomy_term', $this->t('Taxonomy term from URL')));
    return ['taxonomy_term' => $context];
  }

}

The ctools module provides already the condition plugin for entity bundles:ctools/src/Plugin/Condition/EntityBundle.php. You can use it together with the new service.

See also config block visibility by vocabulary, but it not show block access fail(miss context).

1

This feature will be available in Drupal 9.1. See this issue

/**
 * @Condition(
 *   id = "node_type",
 *   label = @Translation("Node Bundle"),
 *   context = {
 *     "taxonomy_term" = @ContextDefinition("entity:taxonomy_term", label = @Translation("Term"))
 *   }
 * )
 */

Your Answer

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

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