Providing global context variables

Last updated on
11 December 2021

Global context variables are available to all Rules conditions and actions. These variables show up in the data selector with a "@" at the beginning of their name. Drupal core provides only four global context variables:

  1. @language.current_language_context:language_interface
  2. @language.current_language_context:language_content
  3. @user.current_user_context:current_user - This is the "user" object for the current user.
  4. @node.node_route_context:node

You can define your own context provider if you need additional global information not readily available through your event or condition contexts. Be careful not to over-use this feature - remember that these context variables will be defined and populated for every page request, whether needed or not, so you should only add to this list if your variable is truly global and there is no other way to easily obtain it within Rules.

The Rules module defines three new global context variables. You may use these as examples of how to define your own global context variables:

  1. @rules.current_path_context:current_path
  2. @rules.rules_date_context:current_date
  3. @rules.rules_site_context:site

Let's examine the first implementation in detail. We will be writing a context provider called CurrentPathContext.php to give us access to the requested page's path from within Rules. With this variable, we may execute Rules based on the exact path requested. Use cases might be ...

First, we need to tell Drupal about our context provider. In rules.services.yml, we have declared a service for our context provider:

services:
  rules.current_path_context:
    class: Drupal\rules\ContextProvider\CurrentPathContext
    arguments: ['@path.current']
    tags:
      - { name: 'context_provider' }

The four things to note are:

  1. The name we choose for the service (in this case rules.current_path_context) will be the prefix of the context variable.
  2. The implementation class will perform the work.
  3. Any needed services are passed in via arguments.
  4. All context providers must be tagged with the name 'context_provider'.

Second, we need to write the implementation class. The important part here is that you implement \Drupal\Core\Plugin\Context\ContextProviderInterface and that you try to cache your results so the context may be re-used.

namespace Drupal\rules\ContextProvider;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Path\CurrentPathStack;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\Plugin\Context\ContextProviderInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;

/**
 * Makes the current path available as a context variable.
 */
class CurrentPathContext implements ContextProviderInterface {
  use StringTranslationTrait;

  /**
   * The current path service.
   *
   * @var \Drupal\Core\Path\CurrentPathStack
   */
  protected $currentPathStack;

  /**
   * Constructs a new CurrentPathContext.
   *
   * @param \Drupal\Core\Path\CurrentPathStack $current_path_stack
   *   The current path stack service.
   */
  public function __construct(CurrentPathStack $current_path_stack) {
    $this->currentPathStack = $current_path_stack;
  }

  /**
   * {@inheritdoc}
   */
  public function getRuntimeContexts(array $unqualified_context_ids) {
    $values = [
      'path' => $this->currentPathStack->getPath(),
      'url' => Url::fromRoute('', [], ['absolute' => TRUE])->toString(),
    ];

    $context_definition = new ContextDefinition('current_path', $this->t('Current path'));
    $context = new Context($context_definition, $values);
    $cacheability = new CacheableMetadata();
    $cacheability->setCacheContexts(['url.path']);
    $context->addCacheableDependency($cacheability);

    $result = [
      'current_path' => $context,
    ];

    return $result;
  }

  /**
   * {@inheritdoc}
   */
  public function getAvailableContexts() {
    return $this->getRuntimeContexts([]);
  }

} 

After you have written this implementation class clear your Drupal caches. If your service and class are error-free you should now have a new global context variable available to you for use in Rules.

The complete code for the 'rules.current_path_context' service may be found at https://git.drupalcode.org/project/rules/-/blob/8.x-3.x/src/ContextProvi...

Help improve this page

Page status: No known problems

You can: