class RuleExpression

Provides a rule, executing actions when conditions are met.

Actions added to a rule can also be rules themselves, so it is possible to nest several rules into one rule. This is the functionality of so called "rule sets" in Drupal 7.

Plugin annotation


@RulesExpression(
  id = "rules_rule",
  label = @Translation("Rule"),
  form_class = "\Drupal\rules\Form\Expression\RuleExpressionForm"
)

Hierarchy

Expanded class hierarchy of RuleExpression

2 files declare their use of RuleExpression
ConfigEntityTest.php in tests/src/Kernel/ConfigEntityTest.php
RuleExpressionTest.php in tests/src/Unit/RuleExpressionTest.php

File

src/Plugin/RulesExpression/RuleExpression.php, line 34

Namespace

Drupal\rules\Plugin\RulesExpression
View source
class RuleExpression extends ExpressionBase implements RuleExpressionInterface, ContainerFactoryPluginInterface {
    
    /**
     * The rules expression plugin manager.
     *
     * @var \Drupal\rules\Engine\ExpressionManagerInterface
     */
    protected $expressionManager;
    
    /**
     * List of conditions that must be met before actions are executed.
     *
     * @var \Drupal\rules\Engine\ConditionExpressionContainerInterface
     */
    protected $conditions;
    
    /**
     * List of actions that get executed if the conditions are met.
     *
     * @var \Drupal\rules\Engine\ActionExpressionContainerInterface
     */
    protected $actions;
    
    /**
     * The rules debug logger channel.
     *
     * @var \Drupal\Core\Logger\LoggerChannelInterface
     */
    protected $rulesDebugLogger;
    
    /**
     * Constructs a new class instance.
     *
     * @param array $configuration
     *   A configuration array containing information about the plugin instance.
     * @param string $plugin_id
     *   The plugin_id for the plugin instance.
     * @param array $plugin_definition
     *   The plugin implementation definition.
     * @param \Drupal\rules\Engine\ExpressionManagerInterface $expression_manager
     *   The rules expression plugin manager.
     * @param \Drupal\Core\Logger\LoggerChannelInterface $logger
     *   The Rules debug logger channel.
     */
    public function __construct(array $configuration, $plugin_id, array $plugin_definition, ExpressionManagerInterface $expression_manager, LoggerChannelInterface $logger) {
        parent::__construct($configuration, $plugin_id, $plugin_definition);
        $configuration += [
            'conditions' => [],
            'actions' => [],
        ];
        // Per default the outer condition container of a rule is initialized as
        // conjunction (AND), meaning that all conditions in it must evaluate to
        // TRUE to fire the actions.
        $this->conditions = $expression_manager->createInstance('rules_and', $configuration['conditions']);
        $this->conditions
            ->setRoot($this->getRoot());
        $this->actions = $expression_manager->createInstance('rules_action_set', $configuration['actions']);
        $this->actions
            ->setRoot($this->getRoot());
        $this->expressionManager = $expression_manager;
        $this->rulesDebugLogger = $logger;
    }
    
    /**
     * {@inheritdoc}
     */
    public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
        return new static($configuration, $plugin_id, $plugin_definition, $container->get('plugin.manager.rules_expression'), $container->get('logger.channel.rules_debug'));
    }
    
    /**
     * {@inheritdoc}
     */
    public function executeWithState(ExecutionStateInterface $state) {
        // Evaluate the rule's conditions.
        $this->rulesDebugLogger
            ->info('Evaluating conditions of rule %label.', [
            '%label' => $this->getLabel(),
            'element' => $this,
        ]);
        if (!$this->conditions
            ->isEmpty() && !$this->conditions
            ->executeWithState($state)) {
            // Do not run the actions if the conditions are not met.
            return;
        }
        $this->rulesDebugLogger
            ->info('Rule %label fires.', [
            '%label' => $this->getLabel(),
            'element' => $this,
            'scope' => TRUE,
        ]);
        $this->actions
            ->executeWithState($state);
        $this->rulesDebugLogger
            ->info('Rule %label has fired.', [
            '%label' => $this->getLabel(),
            'element' => $this,
            'scope' => FALSE,
        ]);
    }
    
    /**
     * {@inheritdoc}
     */
    public function addCondition($condition_id, ContextConfig $config = NULL) {
        return $this->conditions
            ->addCondition($condition_id, $config);
    }
    
    /**
     * {@inheritdoc}
     */
    public function getConditions() {
        return $this->conditions;
    }
    
    /**
     * {@inheritdoc}
     */
    public function setConditions(ConditionExpressionContainerInterface $conditions) {
        $this->conditions = $conditions;
        return $this;
    }
    
    /**
     * {@inheritdoc}
     */
    public function addAction($action_id, ContextConfig $config = NULL) {
        return $this->actions
            ->addAction($action_id, $config);
    }
    
    /**
     * {@inheritdoc}
     */
    public function getActions() {
        return $this->actions;
    }
    
    /**
     * {@inheritdoc}
     */
    public function setActions(ActionExpressionContainerInterface $actions) {
        $this->actions = $actions;
        return $this;
    }
    
    /**
     * {@inheritdoc}
     */
    public function addExpressionObject(ExpressionInterface $expression) {
        if ($expression instanceof ConditionExpressionInterface) {
            $this->conditions
                ->addExpressionObject($expression);
        }
        elseif ($expression instanceof ActionExpressionInterface) {
            $this->actions
                ->addExpressionObject($expression);
        }
        else {
            throw new InvalidExpressionException();
        }
        return $this;
    }
    
    /**
     * {@inheritdoc}
     */
    public function addExpression($plugin_id, ContextConfig $config = NULL) {
        return $this->addExpressionObject($this->expressionManager
            ->createInstance($plugin_id, $config ? $config->toArray() : []));
    }
    
    /**
     * {@inheritdoc}
     */
    public function getConfiguration() {
        $configuration = parent::getConfiguration();
        // We need to update the configuration in case actions/conditions have been
        // added or changed.
        $configuration['conditions'] = $this->conditions
            ->getConfiguration();
        $configuration['actions'] = $this->actions
            ->getConfiguration();
        return $configuration;
    }
    
    /**
     * {@inheritdoc}
     */
    public function getIterator() : \Traversable {
        // Just pass up the actions for iterating over.
        return $this->actions
            ->getIterator();
    }
    
    /**
     * {@inheritdoc}
     */
    public function getExpression($uuid) {
        $condition = $this->conditions
            ->getExpression($uuid);
        if ($condition) {
            return $condition;
        }
        return $this->actions
            ->getExpression($uuid);
    }
    
    /**
     * {@inheritdoc}
     */
    public function deleteExpression($uuid) {
        $deleted = $this->conditions
            ->deleteExpression($uuid);
        if (!$deleted) {
            $deleted = $this->actions
                ->deleteExpression($uuid);
        }
        return $deleted;
    }
    
    /**
     * {@inheritdoc}
     */
    public function checkIntegrity(ExecutionMetadataStateInterface $metadata_state, $apply_assertions = TRUE) {
        $violation_list = $this->conditions
            ->checkIntegrity($metadata_state, $apply_assertions);
        $violation_list->addAll($this->actions
            ->checkIntegrity($metadata_state, $apply_assertions));
        return $violation_list;
    }
    
    /**
     * {@inheritdoc}
     */
    public function prepareExecutionMetadataState(ExecutionMetadataStateInterface $metadata_state, ExpressionInterface $until = NULL, $apply_assertions = TRUE) {
        // @todo If the rule is nested, we may not pass assertions to following
        // expressions as we do not know whether the rule fires at all. Should we
        // clone the metadata state to ensure modifications stay local?
        $found = $this->conditions
            ->prepareExecutionMetadataState($metadata_state, $until, $apply_assertions);
        if ($found) {
            return TRUE;
        }
        return $this->actions
            ->prepareExecutionMetadataState($metadata_state, $until, $apply_assertions);
    }
    
    /**
     * PHP magic __clone function.
     */
    public function __clone() {
        $this->actions = clone $this->actions;
        $this->actions
            ->setRoot($this->getRoot());
        $this->conditions = clone $this->conditions;
        $this->conditions
            ->setRoot($this->getRoot());
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
ExpressionBase::$configEntityId protected property The config entity this expression is associated with, if any.
ExpressionBase::$configuration protected property The plugin configuration.
ExpressionBase::$root protected property The root expression if this object is nested.
ExpressionBase::$uuid protected property The UUID of this expression.
ExpressionBase::$weight protected property The weight (list order) of this expression.
ExpressionBase::calculateDependencies public function Calculates dependencies for the configured plugin. Overrides DependentPluginInterface::calculateDependencies
ExpressionBase::defaultConfiguration public function Gets default configuration for this plugin. Overrides ConfigurableInterface::defaultConfiguration 2
ExpressionBase::execute public function Executes a rules expression. Overrides ExecutableInterface::execute
ExpressionBase::getFormHandler public function Returns the form handling class for this expression. Overrides ExpressionInterface::getFormHandler 2
ExpressionBase::getLabel public function The label of this expression element that can be shown in the UI. Overrides ExpressionInterface::getLabel 2
ExpressionBase::getRoot public function Returns the root expression if this expression is nested. Overrides ExpressionInterface::getRoot
ExpressionBase::getUuid public function Returns the UUID of this expression if it is nested in another expression. Overrides ExpressionInterface::getUuid
ExpressionBase::getWeight public function Returns the list order of this expression. Overrides ExpressionInterface::getWeight
ExpressionBase::setConfiguration public function Sets the configuration for this plugin instance. Overrides ConfigurableInterface::setConfiguration 2
ExpressionBase::setRoot public function Set the root expression for this expression if it is nested. Overrides ExpressionInterface::setRoot
ExpressionBase::setUuid public function Sets the UUID of this expression in an expression tree. Overrides ExpressionInterface::setUuid
ExpressionBase::setWeight public function Sets the list order of this expression in an expression tree. Overrides ExpressionInterface::setWeight
PluginInspectionInterface::getPluginDefinition public function Gets the definition of the plugin implementation. 6
PluginInspectionInterface::getPluginId public function Gets the plugin_id of the plugin instance. 2
RuleExpression::$actions protected property List of actions that get executed if the conditions are met.
RuleExpression::$conditions protected property List of conditions that must be met before actions are executed.
RuleExpression::$expressionManager protected property The rules expression plugin manager.
RuleExpression::$rulesDebugLogger protected property The rules debug logger channel.
RuleExpression::addAction public function Creates an action expression and adds it to the container. Overrides RuleExpressionInterface::addAction
RuleExpression::addCondition public function Creates a condition expression and adds it to the container. Overrides RuleExpressionInterface::addCondition
RuleExpression::addExpression public function Creates and adds an expression. Overrides ExpressionContainerInterface::addExpression
RuleExpression::addExpressionObject public function Adds an expression object. Overrides ExpressionContainerInterface::addExpressionObject
RuleExpression::checkIntegrity public function Verifies that this expression is configured correctly. Overrides ExpressionInterface::checkIntegrity
RuleExpression::create public static function Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface::create
RuleExpression::deleteExpression public function Deletes an expression identified by the specified UUID in the container. Overrides ExpressionContainerInterface::deleteExpression
RuleExpression::executeWithState public function Execute the expression with a given Rules state. Overrides ExpressionInterface::executeWithState
RuleExpression::getActions public function Returns the actions of this rule. Overrides RuleExpressionInterface::getActions
RuleExpression::getConditions public function Returns the conditions container of this rule. Overrides RuleExpressionInterface::getConditions
RuleExpression::getConfiguration public function Gets this plugin's configuration. Overrides ExpressionBase::getConfiguration
RuleExpression::getExpression public function Looks up the expression by UUID in this container. Overrides ExpressionContainerInterface::getExpression
RuleExpression::getIterator public function Returns an iterator for expressions in this container. Overrides ExpressionContainerInterface::getIterator
RuleExpression::prepareExecutionMetadataState public function Prepares the execution metadata state by adding metadata to it. Overrides ExpressionInterface::prepareExecutionMetadataState
RuleExpression::setActions public function Sets the action container. Overrides RuleExpressionInterface::setActions
RuleExpression::setConditions public function Sets the condition container. Overrides RuleExpressionInterface::setConditions
RuleExpression::__clone public function PHP magic __clone function.
RuleExpression::__construct public function Constructs a new class instance. Overrides ExpressionBase::__construct