class ExecutionState
The rules execution state.
A rule element may clone the state, so any added variables are only visible for elements in the current PHP-variable-scope.
Hierarchy
- class \Drupal\rules\Context\ExecutionState implements \Drupal\rules\Context\ExecutionStateInterface uses \Drupal\typed_data\DataFetcherTrait, \Drupal\rules\Context\GlobalContextRepositoryTrait, \Drupal\Core\TypedData\TypedDataTrait
Expanded class hierarchy of ExecutionState
4 files declare their use of ExecutionState
- ExpressionBase.php in src/
Engine/ ExpressionBase.php - GenericEventSubscriber.php in src/
EventSubscriber/ GenericEventSubscriber.php - RulesComponent.php in src/
Engine/ RulesComponent.php - RulesEngineTest.php in tests/
src/ Kernel/ RulesEngineTest.php
File
-
src/
Context/ ExecutionState.php, line 18
Namespace
Drupal\rules\ContextView source
class ExecutionState implements ExecutionStateInterface {
use DataFetcherTrait;
use GlobalContextRepositoryTrait;
use TypedDataTrait;
/**
* Globally keeps the ids of rules blocked due to recursion prevention.
*
* @var array
*
* @todo Implement recursion prevention from D7.
* @todo Move this out of Context namespace?
* @see https://www.drupal.org/project/rules/issues/2677094
*/
protected static $blocked = [];
/**
* The known variables.
*
* @var \Drupal\Core\TypedData\TypedDataInterface[]
*/
protected $variables = [];
/**
* Holds variables for auto-saving later.
*
* @var array
*/
protected $saveLater = [];
/**
* Variable for saving currently blocked configs for serialization.
*
* @var array
*/
protected $currentlyBlocked;
/**
* Creates the object.
*
* @param \Drupal\Core\TypedData\TypedDataInterface[] $variables
* (optional) Variables to initialize this state with.
*
* @return static
*/
public static function create(array $variables = []) {
return new static($variables);
}
/**
* Constructs the object.
*
* @param \Drupal\Core\TypedData\TypedDataInterface[] $variables
* (optional) Variables to initialize this state with.
*/
protected function __construct(array $variables) {
$this->variables = $variables;
}
/**
* {@inheritdoc}
*/
public function setVariable($name, ContextDefinitionInterface $definition, $value) {
$data = $this->getTypedDataManager()
->create($definition->getDataDefinition(), $value);
$this->setVariableData($name, $data);
return $this;
}
/**
* {@inheritdoc}
*/
public function setVariableData($name, TypedDataInterface $data) {
$this->variables[$name] = $data;
return $this;
}
/**
* {@inheritdoc}
*/
public function getVariable($name) {
if (!$this->hasVariable($name)) {
// @todo This crashes site in certain circumstances - for example if
// you're reacting on a "Drupal is initializing" event ... Need to handle
// a problem here gracefully - maybe disable the rule that caused the
// problem?
throw new EvaluationException("Unable to get variable '{$name}'; it is not defined.");
}
return $this->variables[$name];
}
/**
* {@inheritdoc}
*/
public function getVariableValue($name) {
return $this->getVariable($name)
->getValue();
}
/**
* {@inheritdoc}
*/
public function hasVariable($name) {
if (!array_key_exists($name, $this->variables)) {
// If there is no such variable, lazy-add global context variables. That
// way we can save time fetching global context if it is not needed.
if (!($name[0] === '@' && strpos($name, ':') !== FALSE)) {
return FALSE;
}
$contexts = $this->getGlobalContextRepository()
->getRuntimeContexts([
$name,
]);
if (!array_key_exists($name, $contexts)) {
return FALSE;
}
$this->setVariableData($name, $contexts[$name]->getContextData());
}
return TRUE;
}
/**
* {@inheritdoc}
*/
public function removeVariable($name) {
if (array_key_exists($name, $this->variables)) {
unset($this->variables[$name]);
}
return $this;
}
/**
* {@inheritdoc}
*/
public function fetchDataByPropertyPath($property_path, $langcode = NULL) {
try {
// Support global context names as variable name by ignoring points in
// the service name; e.g. @user.current_user_context:current_user.name.
if ($property_path[0] == '@') {
[
$service,
$property_path,
] = explode(':', $property_path, 2);
}
$parts = explode('.', $property_path);
$var_name = array_shift($parts);
if (isset($service)) {
$var_name = $service . ':' . $var_name;
}
return $this->getDataFetcher()
->fetchDataBySubPaths($this->getVariable($var_name), $parts, $langcode);
} catch (InvalidArgumentException $e) {
// Pass on the original exception in the exception trace.
throw new EvaluationException($e->getMessage(), 0, $e);
} catch (MissingDataException $e) {
// Pass on the original exception in the exception trace.
throw new EvaluationException($e->getMessage(), 0, $e);
}
}
/**
* {@inheritdoc}
*/
public function saveChangesLater($selector) {
$this->saveLater[$selector] = TRUE;
return $this;
}
/**
* {@inheritdoc}
*/
public function getAutoSaveSelectors() {
return array_keys($this->saveLater);
}
/**
* {@inheritdoc}
*/
public function autoSave() {
// Make changes permanent.
foreach ($this->saveLater as $selector => $flag) {
$typed_data = $this->fetchDataByPropertyPath($selector);
// Things that can be saved must have a save() method, right?
// Saving is always done at the root of the typed data tree, for example
// on the entity level.
$typed_data->getRoot()
->getValue()
->save();
}
return $this;
}
}
Members
Title Sort descending | Modifiers | Object type | Summary | Overriden Title | Overrides |
---|---|---|---|---|---|
ExecutionState::$blocked | protected static | property | Globally keeps the ids of rules blocked due to recursion prevention. | ||
ExecutionState::$currentlyBlocked | protected | property | Variable for saving currently blocked configs for serialization. | ||
ExecutionState::$saveLater | protected | property | Holds variables for auto-saving later. | ||
ExecutionState::$variables | protected | property | The known variables. | ||
ExecutionState::autoSave | public | function | Saves all variables that have been marked for auto saving. | Overrides ExecutionStateInterface::autoSave | |
ExecutionState::create | public static | function | Creates the object. | ||
ExecutionState::fetchDataByPropertyPath | public | function | Returns a value as specified in the selector. | Overrides ExecutionStateInterface::fetchDataByPropertyPath | |
ExecutionState::getAutoSaveSelectors | public | function | Returns the list of variables that should be auto-saved after execution. | Overrides ExecutionStateInterface::getAutoSaveSelectors | |
ExecutionState::getVariable | public | function | Gets a variable. | Overrides ExecutionStateInterface::getVariable | |
ExecutionState::getVariableValue | public | function | Gets the value of a variable. | Overrides ExecutionStateInterface::getVariableValue | |
ExecutionState::hasVariable | public | function | Checks if a variable exists by name in the execution state. | Overrides ExecutionStateInterface::hasVariable | |
ExecutionState::removeVariable | public | function | Removes a variable from the state if it is set. | Overrides ExecutionStateInterface::removeVariable | |
ExecutionState::saveChangesLater | public | function | Mark a variable to be saved later when the execution is finished. | Overrides ExecutionStateInterface::saveChangesLater | |
ExecutionState::setVariable | public | function | Sets a state variable based on its definition and value. | Overrides ExecutionStateInterface::setVariable | |
ExecutionState::setVariableData | public | function | Sets a state variable with some typed data object. | Overrides ExecutionStateInterface::setVariableData | |
ExecutionState::__construct | protected | function | Constructs the object. | ||
GlobalContextRepositoryTrait::$contextRepository | protected | property | The global context repository. | ||
GlobalContextRepositoryTrait::getGlobalContextRepository | public | function | Gets the global context repository. | ||
GlobalContextRepositoryTrait::setGlobalContextRepository | public | function | Sets the global context repository. | ||
TypedDataTrait::$typedDataManager | protected | property | The typed data manager used for creating the data types. | ||
TypedDataTrait::getTypedDataManager | public | function | Gets the typed data manager. | 2 | |
TypedDataTrait::setTypedDataManager | public | function | Sets the typed data manager. | 2 |