You are here

protected function ContextHandlerTrait::prepareContext in Rules 8.3

Prepares plugin context based upon the set context configuration.

The plugin is prepared for execution by mapping the variables from the execution state into the plugin context and applying data processors. In addition, it is ensured that all required context is basically available as defined. This include the following checks:

  • Required context must have a value set.
  • Context may not have NULL values unless the plugin allows it.

Parameters

\Drupal\Core\Plugin\ContextAwarePluginInterface $plugin: The plugin that is populated with context values.

\Drupal\rules\Context\ExecutionStateInterface $state: The execution state containing available variables.

Throws

\Drupal\rules\Exception\EvaluationException Thrown if some context is not satisfied; e.g. a required context is missing.

See also

::prepareContextWithMetadata()

2 calls to ContextHandlerTrait::prepareContext()
ActionExpression::executeWithState in src/Plugin/RulesExpression/ActionExpression.php
Execute the expression with a given Rules state.
ConditionExpression::executeWithState in src/Plugin/RulesExpression/ConditionExpression.php
Execute the expression with a given Rules state.

File

src/Context/ContextHandlerTrait.php, line 48

Class

ContextHandlerTrait
Provides methods for handling context based on the plugin configuration.

Namespace

Drupal\rules\Context

Code

protected function prepareContext(CoreContextAwarePluginInterface $plugin, ExecutionStateInterface $state) {
  if (isset($this->configuration['context_values'])) {
    foreach ($this->configuration['context_values'] as $name => $value) {
      $plugin
        ->setContextValue($name, $value);
    }
  }
  $selected_data = [];

  // Map context by applying data selectors and collected the definitions of
  // selected data for refining context definitions later. Note, that we must
  // refine context definitions on execution time also, such that provided
  // context gets the right metadata attached.
  if (isset($this->configuration['context_mapping'])) {
    foreach ($this->configuration['context_mapping'] as $name => $selector) {
      $typed_data = $state
        ->fetchDataByPropertyPath($selector);
      $plugin
        ->setContextValue($name, $typed_data);
      $selected_data[$name] = $typed_data
        ->getDataDefinition();
    }
  }
  if ($plugin instanceof ContextAwarePluginInterface) {

    // Getting context values may lead to undocumented exceptions if context
    // is not set right now. So catch those exceptions.
    // @todo Remove once https://www.drupal.org/node/2677162 is fixed in core.
    try {
      $plugin
        ->refineContextDefinitions($selected_data);
    } catch (ContextException $e) {
      if (strpos($e
        ->getMessage(), 'context is required') === FALSE) {
        throw new EvaluationException($e
          ->getMessage());
      }
    }
  }

  // Apply data processors.
  $this
    ->processData($plugin, $state);

  // Finally, ensure all contexts are set as expected now.
  foreach ($plugin
    ->getContextDefinitions() as $name => $definition) {
    if ($plugin
      ->getContextValue($name) === NULL && $definition
      ->isRequired()) {

      // If a context mapping has been specified, the value might end up NULL
      // but valid (e.g. a reference on an empty property). In that case
      // isAllowedNull determines whether the context is conform.
      if (!isset($this->configuration['context_mapping'][$name])) {
        throw new EvaluationException("Required context '{$name}' is missing for plugin '" . $plugin
          ->getPluginId() . "'.");
      }
      elseif (!$definition
        ->isAllowedNull()) {
        throw new EvaluationException("The context for '{$name}' is NULL, but the context '{$name}' in '" . $plugin
          ->getPluginId() . "' requires a value.");
      }
    }
  }
}