/**
  * Maps provided context values from the plugin to the Rules state.
  *
  * @param ContextProviderInterface $plugin
  *   The plugin where the context values are extracted.
  * @param \Drupal\rules\Engine\RulesStateInterface $state
  *   The Rules state where the context variables are added.
  */
 protected function mapProvidedContext(ContextProviderInterface $plugin, RulesStateInterface $state)
 {
     $provides = $plugin->getProvidedContextDefinitions();
     foreach ($provides as $name => $provided_definition) {
         // Avoid name collisions in the rules state: provided variables can be
         // renamed.
         if (isset($this->configuration['provides_mapping'][$name])) {
             $state->addVariable($this->configuration['provides_mapping'][$name], $plugin->getProvidedContext($name));
         } else {
             $state->addVariable($name, $plugin->getProvidedContext($name));
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function process($value, RulesStateInterface $rules_state)
 {
     $replacements = [];
     // The Token API requires this metadata object, but it is useless for us
     // here so we just always pass the same instance and ignore it.
     $bubbleable_metdata = new BubbleableMetadata();
     // We only use the token service to scan for tokens in the text. The
     // replacements are done by using the data selector logic.
     foreach ($this->tokenService->scan($value) as $var_name => $tokens) {
         foreach ($tokens as $token) {
             // Remove the opening and closing bracket to form a data selector.
             $data_selector = substr($token, 1, -1);
             try {
                 $replacement_data = $rules_state->applyDataSelector($data_selector);
                 $replacements[$token] = $replacement_data->getString();
             } catch (RulesEvaluationException $exception) {
                 // Data selector is invalid, so try to resolve the token with the
                 // token service.
                 if ($rules_state->hasVariable($var_name)) {
                     $variable = $rules_state->getVariable($var_name);
                     $token_type = $variable->getContextDefinition()->getDataType();
                     // The Token system does not know about "enity:" data type prefixes,
                     // so we have to remove them.
                     $token_type = str_replace('entity:', '', $token_type);
                     $data = [$token_type => $variable->getContextValue()];
                     $replacements += $this->tokenService->generate($token_type, $tokens, $data, ['sanitize' => FALSE], $bubbleable_metdata);
                 } else {
                     $replacements += $this->tokenService->generate($var_name, $tokens, [], ['sanitize' => FALSE], $bubbleable_metdata);
                 }
                 // Remove tokens if no replacement value is found.
                 $replacements += array_fill_keys($tokens, '');
             }
         }
     }
     // Apply the replacements now.
     $tokens = array_keys($replacements);
     $values = array_values($replacements);
     return str_replace($tokens, $values, $value);
 }