/**
  * {@inheritdoc}
  */
 protected function getEditedExpression(RulesComponent $component)
 {
     $component_expression = $component->getExpression();
     if (!$component_expression instanceof ExpressionContainerInterface) {
         throw new \LogicException('Cannot add expression to expression of type ' . $component_expression->getPluginId());
     }
     if ($this->uuid && ($expression = $component_expression->getExpression($this->uuid))) {
         return $expression;
     } else {
         $expression = $this->expressionManager->createInstance($this->expressionId);
         $rule_expression = $component->getExpression();
         $rule_expression->addExpressionObject($expression);
         return $expression;
     }
 }
 /**
  * Tests auto saving after an action execution.
  */
 public function testActionAutoSave()
 {
     $rule = $this->rulesExpressionManager->createRule();
     // Just leverage the entity save action, which by default uses auto-saving.
     $rule->addAction('rules_entity_save', ContextConfig::create()->map('entity', 'entity'));
     $entity = $this->prophesizeEntity(EntityInterface::class);
     $entity->save()->shouldBeCalledTimes(1);
     RulesComponent::create($rule)->addContextDefinition('entity', ContextDefinition::create('entity'))->setContextValue('entity', $entity->reveal())->execute();
 }
 /**
  * @cover ::getState()
  */
 public function testGetState()
 {
     $rule = $this->rulesExpressionManager->createRule();
     $component = RulesComponent::create($rule);
     $this->assertInstanceOf(ExecutionStateInterface::class, $component->getState());
     // Test that set context values are available in the state.
     $component->addContextDefinition('foo', ContextDefinition::create('string'))->setContextValue('foo', 'bar');
     $this->assertEquals($component->getState()->getVariableValue('foo'), 'bar');
 }
 /**
  * Tests that NULL values for contexts are allowed if specified.
  */
 public function testAllowNullValue()
 {
     // Configure a simple rule with the data set action which allows NULL
     // values.
     $action = $this->expressionManager->createInstance('rules_action', ContextConfig::create()->setConfigKey('action_id', 'rules_data_set')->map('data', 'null_variable')->map('value', 'new_value')->toArray());
     $rule = $this->expressionManager->createRule()->addExpressionObject($action);
     $component = RulesComponent::create($rule)->addContextDefinition('null_variable', ContextDefinition::create('string'))->addContextDefinition('new_value', ContextDefinition::create('string'))->setContextValue('null_variable', NULL)->setContextValue('new_value', 'new value');
     $component->execute();
     $this->assertEquals('new value', $component->getState()->getVariableValue('null_variable'));
 }
 /**
  * Tests that the loop list item is removed after the loop.
  */
 public function testPrepareAfterLoop()
 {
     $rule = $this->rulesExpressionManager->createRule();
     $loop = $this->rulesExpressionManager->createInstance('rules_loop', ['list' => 'string_list']);
     $action = $this->rulesExpressionManager->createAction('rules_test_string')->setConfiguration(ContextConfig::create()->setValue('text', 'x')->toArray());
     $loop->addExpressionObject($action);
     $rule->addExpressionObject($loop);
     $state = RulesComponent::create($rule)->addContextDefinition('string_list', ContextDefinition::create('string')->setMultiple())->getMetadataState();
     $found = $rule->prepareExecutionMetadataState($state);
     $this->assertFalse($state->hasDataDefinition('list_item'));
     $this->assertNull($found);
 }
 /**
  * Tests that the numeric offset plugin works.
  */
 public function testNumericOffset()
 {
     // Configure a simple rule with one action.
     $action = $this->expressionManager->createInstance('rules_action', ContextConfig::create()->map('message', 'message')->map('type', 'type')->process('message', 'rules_numeric_offset', ['offset' => 1])->setConfigKey('action_id', 'rules_system_message')->toArray());
     $component = RulesComponent::create($this->expressionManager->createRule())->addContextDefinition('message', ContextDefinition::create('string'))->addContextDefinition('type', ContextDefinition::create('string'))->setContextValue('message', 1)->setContextValue('type', 'status');
     $component->getExpression()->addExpressionObject($action);
     $component->execute();
     $messages = drupal_set_message();
     // The original value was 1 and the processor adds 1, so the result should
     // be 2.
     $this->assertEquals((string) $messages['status'][0], '2');
 }
 /**
  * Make sure that expressions using context definitions can be exported.
  */
 public function testContextDefinitionExport()
 {
     $component = RulesComponent::create($this->expressionManager->createRule())->addContextDefinition('test', ContextDefinition::create('string')->setLabel('Test string'));
     $config_entity = $this->storage->create(['id' => 'test_rule'])->updateFromComponent($component);
     $config_entity->save();
     $loaded_entity = $this->storage->load('test_rule');
     // Create the Rules expression object from the configuration.
     $expression = $loaded_entity->getExpression();
     $this->assertInstanceOf(Rule::class, $expression);
     $context_definitions = $loaded_entity->getContextDefinitions();
     $this->assertEquals($context_definitions['test']->getDataType(), 'string', 'Data type of context definition is correct.');
     $this->assertEquals($context_definitions['test']->getLabel(), 'Test string', 'Label of context definition is correct.');
 }
 /**
  * Tests that date tokens are formatted correctly.
  */
 public function testSystemDateToken()
 {
     // Configure a simple rule with one action. and token replacements enabled.
     $action = $this->expressionManager->createInstance('rules_action', ContextConfig::create()->setValue('message', "The date is {{ date | format_date('custom', 'Y-m') }}!")->setValue('type', 'status')->process('message', 'rules_tokens')->setConfigKey('action_id', 'rules_system_message')->toArray());
     $rule = $this->expressionManager->createRule();
     $rule->addExpressionObject($action);
     RulesComponent::create($rule)->addContextDefinition('date', ContextDefinition::create('timestamp'))->setContextValue('date', REQUEST_TIME)->execute();
     $messages = drupal_set_message();
     /** @var \Drupal\Core\Datetime\DateFormatterInterface $date_formatter */
     $date_formatter = $this->container->get('date.formatter');
     $date = $date_formatter->format(REQUEST_TIME, 'custom', 'Y-m');
     $this->assertEquals("The date is {$date}!", (string) $messages['status'][0]);
 }
 /**
  * Tests that a condition can provide a value and another one can consume it.
  */
 public function testProvidedVariables()
 {
     $rule = $this->expressionManager->createRule();
     // The first condition provides a "provided_text" variable.
     $rule->addCondition('rules_test_provider');
     // The second condition consumes the variable.
     $rule->addCondition('rules_test_string_condition', ContextConfig::create()->map('text', 'provided_text'));
     $rule->addAction('rules_test_log');
     $component = RulesComponent::create($rule);
     $violations = $component->checkIntegrity();
     $this->assertEquals(0, iterator_count($violations));
     $component->execute();
     // Test that the action logged something.
     $this->assertRulesLogEntryExists('action called');
 }
 /**
  * {@inheritdoc}
  */
 public function validateForm(array &$form, FormStateInterface $form_state)
 {
     $this->lockValidateForm($form, $form_state);
     // In order to validdate the whole rule we need to invoke the submission
     // handler of the expression form. That way the expression is changed and we
     // can validate the change for integrity afterwards.
     $validation_config = clone $this->ruleConfig;
     $rule_expression = $validation_config->getExpression();
     $expression = $rule_expression->getExpression($this->uuid);
     $form_handler = $expression->getFormHandler();
     $form_handler->submitForm($form, $form_state);
     $all_violations = RulesComponent::create($rule_expression)->addContextDefinitionsFrom($validation_config)->checkIntegrity();
     $local_violations = $all_violations->getFor($this->uuid);
     foreach ($local_violations as $violation) {
         $form_state->setError($form, $violation->getMessage());
     }
 }
 /**
  * Tests using provided variables with refined context.
  */
 public function testUsingRefinedProvidedVariables()
 {
     $rule = $this->rulesExpressionManager->createRule();
     $rule->addAction('rules_variable_add', ContextConfig::create()->setValue('type', 'string')->setValue('value', 'foo'));
     $rule->addAction('rules_system_message', ContextConfig::create()->map('message', 'variable_added')->setValue('type', 'status'));
     // The message action requires a string, thus if the context is not refined
     // it will end up as "any" and integrity check would fail.
     $violation_list = RulesComponent::create($rule)->checkIntegrity();
     $this->assertEquals(0, iterator_count($violation_list));
 }
 /**
  * {@inheritdoc}
  */
 public function updateFromComponent(RulesComponent $component)
 {
     // Note that the available context definitions stem from the configured
     // events, which are handled separately.
     $this->setExpression($component->getExpression());
     return $this;
 }
 /**
  * Tests asserted metadata of negated conditions is ignored.
  */
 public function testAssertingOfNegatedConditions()
 {
     // Negate the condition only and make sure it is ignored.
     $rule = $this->expressionManager->createRule();
     $rule->addCondition('rules_entity_is_of_bundle', ContextConfig::create()->map('entity', 'node')->setValue('type', 'node')->setValue('bundle', 'page'))->negate(TRUE);
     $rule->addAction('rules_system_message', ContextConfig::create()->map('message', 'node.field_text.value')->setValue('type', 'status'));
     $violation_list = RulesComponent::create($rule)->addContextDefinition('node', ContextDefinition::create('entity:node'))->checkIntegrity();
     $this->assertEquals(1, iterator_count($violation_list));
     // Add an negated AND and make sure it is ignored.
     $rule = $this->expressionManager->createRule();
     $and = $this->expressionManager->createAnd();
     $and->addCondition('rules_entity_is_of_bundle', ContextConfig::create()->map('entity', 'node')->setValue('type', 'node')->setValue('bundle', 'page'));
     $and->negate(TRUE);
     $rule->addExpressionObject($and);
     $rule->addAction('rules_system_message', ContextConfig::create()->map('message', 'node.field_text.value')->setValue('type', 'status'));
     $violation_list = RulesComponent::create($rule)->addContextDefinition('node', ContextDefinition::create('entity:node'))->checkIntegrity();
     $this->assertEquals(1, iterator_count($violation_list));
 }
 /**
  * Sets the Rules component to be stored.
  *
  * @param \Drupal\rules\Engine\RulesComponent $component
  *   The component.
  *
  * @return $this
  */
 public function setComponent(\Drupal\rules\Engine\RulesComponent $component)
 {
     $this->setExpression($component->getExpression());
     $this->setContextDefinitions($component->getContextDefinitions());
     return $this;
 }
 /**
  * Tests that an absent required context triggers a violation.
  */
 public function testMissingRequiredContext()
 {
     $rule = $this->rulesExpressionManager->createRule();
     // The condition is completely unconfigured, missing 2 required contexts.
     $rule->addCondition('rules_node_is_of_type');
     $violation_list = RulesComponent::create($rule)->checkIntegrity();
     $this->assertEquals(2, iterator_count($violation_list));
     $this->assertEquals('The required context <em class="placeholder">Node</em> is missing.', (string) $violation_list[0]->getMessage());
     $this->assertEquals('The required context <em class="placeholder">Content types</em> is missing.', (string) $violation_list[1]->getMessage());
 }
 /**
  * Tests using global context.
  */
 public function testGlobalContext()
 {
     $account = User::create(['name' => 'hubert']);
     $account->save();
     $this->container->get('current_user')->setAccount($account);
     $rule = $this->expressionManager->createRule()->addAction('rules_system_message', ContextConfig::create()->map('message', '@user.current_user_context:current_user.name.value')->setValue('type', 'status'));
     $component = RulesComponent::create($rule);
     $this->assertEquals(0, $component->checkIntegrity()->count());
     // Ensure the execution-state is aware of global context.
     $result = $component->getState()->hasVariable('@user.current_user_context:current_user');
     $this->assertTrue($result);
     // Test asking for non-existing variables.
     $this->assertFalse($component->getState()->hasVariable('@user.current_user_context:invalid'));
     $this->assertFalse($component->getState()->hasVariable('@user.invalid_service'));
     $this->assertFalse($component->getState()->hasVariable('invalid-var'));
     // Test using global context during execution.
     $component->execute();
     $messages = drupal_set_message();
     $this->assertEquals((string) $messages['status'][0], 'hubert');
 }
 /**
  * {@inheritdoc}
  */
 public function getComponent()
 {
     $config = $this->getConfig();
     if ($config instanceof RulesUiComponentProviderInterface) {
         return $config->getComponent();
     } else {
         $configuration = $config->get($this->pluginDefinition->settings['config_key']);
         return RulesComponent::createFromConfiguration($configuration);
     }
 }
 /**
  * Tests that auto saving is only triggered once with nested components.
  */
 public function testAutosaveOnlyOnce()
 {
     $entity = $this->prophesizeEntity(EntityInterface::class);
     $nested_rule = $this->rulesExpressionManager->createRule();
     $nested_rule->addAction('rules_entity_save', ContextConfig::create()->map('entity', 'entity'));
     $rules_config = new RulesComponentConfig(['id' => 'test_rule', 'label' => 'Test rule'], 'rules_component');
     $rules_config->setExpression($nested_rule);
     $rules_config->setContextDefinitions(['entity' => ContextDefinition::create('entity')]);
     $this->prophesizeStorage([$rules_config]);
     // Create a rule with a nested rule. Overall there are 2 actions to set the
     // entity then.
     $rule = $this->rulesExpressionManager->createRule();
     $rule->addAction('rules_component:test_rule', ContextConfig::create()->map('entity', 'entity'));
     $rule->addAction('rules_entity_save', ContextConfig::create()->map('entity', 'entity'));
     // Auto-saving should only be triggered once on the entity.
     $entity->save()->shouldBeCalledTimes(1);
     RulesComponent::create($rule)->addContextDefinition('entity', ContextDefinition::create('entity'))->setContextValue('entity', $entity->reveal())->execute();
 }
 /**
  * {@inheritdoc}
  */
 public function updateFromComponent(RulesComponent $component)
 {
     $this->component = $component->getConfiguration();
     $this->componentObject = $component;
     return $this;
 }
 /**
  * Gets the currently edited expression from the given component.
  *
  * @param \Drupal\rules\Engine\RulesComponent $component
  *   The component from which to get the expression.
  *
  * @return \Drupal\rules\Engine\ExpressionInterface|null
  *   The expression object.
  */
 protected function getEditedExpression(RulesComponent $component)
 {
     $rule_expression = $component->getExpression();
     return $rule_expression->getExpression($this->uuid);
 }
Exemple #21
0
 /**
  * Tests that the loop list item variable is not available after the loop.
  *
  * @expectedException \Drupal\rules\Exception\RulesEvaluationException
  *
  * @expectedExceptionMessage Unable to get variable list_item, it is not defined.
  */
 public function testOutOfScopeVariableExecution()
 {
     $rule = $this->rulesExpressionManager->createRule();
     $loop = $this->rulesExpressionManager->createInstance('rules_loop', ['list' => 'string_list']);
     $rule->addExpressionObject($loop);
     $rule->addAction('rules_test_string', ContextConfig::create()->map('text', 'list_item'));
     RulesComponent::create($rule)->addContextDefinition('string_list', ContextDefinition::create('string')->setMultiple())->setContextValue('string_list', ['one', 'two'])->execute();
 }