/** * Executes a rules expression. */ public function execute() { // If there is no state given, we have to assume no required context. $state = ExecutionState::create(); $result = $this->executeWithState($state); // Save specifically registered variables in the end after execution. $state->autoSave(); return $result; }
/** * Reacts on the given event and invokes configured reaction rules. * * @param \Symfony\Component\EventDispatcher\Event $event * The event object containing context for the event. * @param string $event_name * The event name. */ public function onRulesEvent(Event $event, $event_name) { // Load reaction rule config entities by $event_name. $storage = $this->entityTypeManager->getStorage('rules_reaction_rule'); // @todo Only load active reaction rules here. $configs = $storage->loadByProperties(['event' => $event_name]); // Set up an execution state with the event context. $event_definition = $this->eventManager->getDefinition($event_name); $state = ExecutionState::create(); foreach ($event_definition['context'] as $context_name => $context_definition) { // If this is a GenericEvent get the context for the rule from the event // arguments. if ($event instanceof GenericEvent) { $value = $event->getArgument($context_name); } else { $value = $event->{$context_name}; } $state->setVariable($context_name, $context_definition, $value); } // Loop over all rules and execute them. foreach ($configs as $config) { /** @var \Drupal\rules\Entity\ReactionRuleConfig $config */ $config->getExpression()->executeWithState($state); } $state->autoSave(); }
/** * Reacts on the given event and invokes configured reaction rules. * * @param \Symfony\Component\EventDispatcher\Event $event * The event object containing context for the event. * @param string $event_name * The event name. */ public function onRulesEvent(Event $event, $event_name) { $storage = $this->entityTypeManager->getStorage('rules_reaction_rule'); // Get event metadata and the to be triggered events. $event_definition = $this->eventManager->getDefinition($event_name); $handler_class = $event_definition['class']; $triggered_events = [$event_name]; if (is_subclass_of($handler_class, RulesConfigurableEventHandlerInterface::class)) { $qualified_event_suffixes = $handler_class::determineQualifiedEvents($event, $event_name, $event_definition); foreach ($qualified_event_suffixes as $qualified_event_suffix) { $triggered_events[] = "{$event_name}--{$qualified_event_suffix}"; } } // Setup the execution state. $state = ExecutionState::create(); foreach ($event_definition['context'] as $context_name => $context_definition) { // If this is a GenericEvent get the context for the rule from the event // arguments. if ($event instanceof GenericEvent) { $value = $event->getArgument($context_name); } else { $value = $event->{$context_name}; } $state->setVariable($context_name, $context_definition, $value); } // Invoke the rules. // @todo: Improve this by cloning the state after each rule, such that added // variables added by one rule are not interfering with the variables of // another rule. foreach ($triggered_events as $triggered_event) { // @todo Only load active reaction rules here. $configs = $storage->loadByProperties(['events.*.event_name' => $triggered_event]); // Loop over all rules and execute them. foreach ($configs as $config) { /** @var \Drupal\rules\Entity\ReactionRuleConfig $config */ $config->getExpression()->executeWithState($state); } } $state->autoSave(); }
/** * Tests that multiple actions can consume and provide context variables. */ public function testActionProvidedContext() { // @todo: Convert the test to make use of actions instead of conditions. $rule = $this->expressionManager->createRule(); // The condition provides a "provided_text" variable. $rule->addCondition('rules_test_provider'); // The action provides a "concatenated" variable. $rule->addAction('rules_test_string', ContextConfig::create()->map('text', 'provided_text')); // Add the same action again which will provide a "concatenated2" variable // now. $rule->addAction('rules_test_string', ContextConfig::create()->map('text', 'concatenated')->provideAs('concatenated', 'concatenated2')); $state = ExecutionState::create(); $rule->executeWithState($state); // Check that the created variables exists and have the provided values. $concatenated = $state->getVariable('concatenated'); $this->assertEqual($concatenated->getValue(), 'test valuetest value'); $concatenated2 = $state->getVariable('concatenated2'); $this->assertEqual($concatenated2->getValue(), 'test valuetest valuetest valuetest value'); }
/** * Executes the component with the given values. * * @param mixed[] $arguments * The array of arguments; i.e., an array keyed by name of the defined * context and the context value as argument. * * @return mixed[] * The array of provided context values, keyed by context name. * * @throws \LogicException * Thrown if the context is not defined. * @throws \Drupal\rules\Exception\RulesEvaluationException * Thrown if the Rules expression triggers errors during execution. */ public function executeWithArguments(array $arguments) { $this->state = ExecutionState::create(); foreach ($arguments as $name => $value) { $this->setContextValue($name, $value); } return $this->execute(); }