Пример #1
0
 /**
  * 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();
 }
Пример #2
0
 /**
  * Tests passing a string context to a condition.
  */
 public function testContextPassing()
 {
     $rule = $this->expressionManager->createRule();
     $rule->addCondition('rules_test_string_condition', ContextConfig::create()->map('text', 'test'));
     $rule->addAction('rules_test_log');
     RulesComponent::create($rule)->addContextDefinition('test', ContextDefinition::create('string'))->setContextValue('test', 'test value')->execute();
     // Test that the action logged something.
     $this->assertRulesLogEntryExists('action called');
 }
Пример #3
0
 /**
  * @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');
 }
Пример #4
0
 /**
  * {@inheritdoc}
  */
 public function __construct(array $values)
 {
     // Filter out any @Translation annotation objects.
     foreach ($values as $key => $value) {
         if ($value instanceof Translation) {
             $values[$key] = $value->get();
         }
     }
     $this->definition = RulesContextDefinition::createFromArray($values);
 }
Пример #5
0
 /**
  * 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'));
 }
Пример #6
0
 /**
  * {@inheritdoc}
  */
 public function processDefinition(&$definition, $plugin_id)
 {
     parent::processDefinition($definition, $plugin_id);
     if (!isset($definition['context'])) {
         $definition['context'] = [];
     }
     // Convert the flat context arrays into ContextDefinition objects.
     foreach ($definition['context'] as $context_name => $values) {
         $definition['context'][$context_name] = ContextDefinition::createFromArray($values);
     }
 }
 /**
  * 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);
 }
Пример #8
0
 /**
  * Make sure that expressions using context definitions can be exported.
  */
 public function testContextDefinitionExport()
 {
     $rule = $this->expressionManager->createRule(['context_definitions' => ['test' => ContextDefinition::create('string')->setLabel('Test string')->toArray()]]);
     $config_entity = $this->storage->create(['id' => 'test_rule'])->setExpression($rule);
     $config_entity->save();
     $loaded_entity = $this->storage->load('test_rule');
     // Create the Rules expression object from the configuration.
     $expression = $loaded_entity->getExpression();
     $context_definitions = $expression->getContextDefinitions();
     $this->assertEqual($context_definitions['test']->getDataType(), 'string', 'Data type of context definition is correct.');
     $this->assertEqual($context_definitions['test']->getLabel(), 'Test string', 'Label of context definition is correct.');
 }
Пример #9
0
 /**
  * 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');
 }
Пример #10
0
 /**
  * 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.');
 }
Пример #11
0
 /**
  * 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]);
 }
Пример #12
0
 /**
  * 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()->map('message', 'message')->map('type', 'type')->process('message', 'rules_tokens')->setConfigKey('action_id', 'rules_system_message')->toArray());
     $rule = $this->expressionManager->createRule(['context_definitions' => ['message' => ContextDefinition::create('string')->toArray(), 'type' => ContextDefinition::create('string')->toArray()]]);
     $rule->setContextValue('message', 'The date is [date:custom:Y-m]!');
     $rule->setContextValue('type', 'status');
     $rule->addExpressionObject($action);
     $rule->execute();
     $messages = drupal_set_message();
     $date = format_date(time(), 'custom', 'Y-m');
     $this->assertEqual((string) $messages['status'][0], "The date is {$date}!");
 }
Пример #13
0
 /**
  * Creates a component based on the given configuration array.
  *
  * @param array $configuration
  *   The component configuration, as returned from ::getConfiguration().
  *
  * @return static
  */
 public static function createFromConfiguration(array $configuration)
 {
     $configuration += ['context_definitions' => [], 'provided_context_definitions' => []];
     // @todo: Can we improve this use dependency injection somehow?
     $expression_manager = \Drupal::service('plugin.manager.rules_expression');
     $expression = $expression_manager->createInstance($configuration['expression']['id'], $configuration['expression']);
     $component = static::create($expression);
     foreach ($configuration['context_definitions'] as $name => $definition) {
         $component->addContextDefinition($name, ContextDefinition::createFromArray($definition));
     }
     foreach ($configuration['provided_context_definitions'] as $name => $definition) {
         $component->provideContext($name);
     }
     return $component;
 }
Пример #14
0
 /**
  * Tests that the data set action works on entities.
  */
 public function testDataSetEntities()
 {
     $entity_type_manager = $this->container->get('entity_type.manager');
     $entity_type_manager->getStorage('node_type')->create(['type' => 'page'])->save();
     $node = $entity_type_manager->getStorage('node')->create(['title' => 'test', 'type' => 'page']);
     // Configure a simple rule with one action.
     $action = $this->expressionManager->createInstance('rules_action', ContextConfig::create()->setConfigKey('action_id', 'rules_data_set')->map('data', 'node.title')->map('value', 'new_title')->toArray());
     $rule = $this->expressionManager->createRule()->addExpressionObject($action);
     RulesComponent::create($rule)->addContextDefinition('node', ContextDefinition::create('entity:node'))->addContextDefinition('new_title', ContextDefinition::create('string'))->setContextValue('node', $node)->setContextValue('new_title', 'new title')->execute();
     $this->assertEquals('new title', $node->getTitle());
     $this->assertNotNull($node->id(), 'Node ID is set, which means that the node has been auto-saved.');
 }
Пример #15
0
 /**
  * Tests that provided context definitons are created from configuration.
  */
 public function testProvidedDefinitionFromConfig()
 {
     $rule = new Rule(['provided_definitions' => ['node' => ContextDefinition::create('entity:node')->setLabel('node')->toArray()]], 'rules_rule', [], $this->expressionManager->reveal());
     $provided_definition = $rule->getProvidedContextDefinition('node');
     $this->assertSame($provided_definition->getDataType(), 'entity:node');
 }
Пример #16
0
 /**
  * Tests that a complex data context is assigned something that matches.
  */
 public function testComplexTypeViolation()
 {
     $rule = $this->rulesExpressionManager->createRule();
     // The condition expects a node context but gets a list instead which cause
     // the violation.
     $rule->addCondition('rules_node_is_of_type', ContextConfig::create()->map('node', 'list_variable')->map('types', 'list_variable'));
     $violation_list = RulesComponent::create($rule)->addContextDefinition('list_variable', ContextDefinition::create('list'))->checkIntegrity();
     $this->assertEquals(1, iterator_count($violation_list));
     $this->assertEquals('Expected a complex data type for context <em class="placeholder">Node</em> but got a list data type instead.', (string) $violation_list[0]->getMessage());
 }
 /**
  * Helper to mock a context definition with a mocked data definition.
  *
  * @param string $data_type
  *   The data type, example "entity:node".
  * @param \Prophecy\Prophecy\ProphecyInterface $data_definition
  *   A prophecy that represents a data definition object.
  *
  * @return \Drupal\rules\Context\ContextDefinition
  *   The context definition with the data definition prophecy in it.
  */
 protected function getContextDefinitionFor($data_type, ProphecyInterface $data_definition)
 {
     // Mock all the setter calls on the data definition that can be ignored.
     $data_definition->setLabel(Argument::any())->willReturn($data_definition->reveal());
     $data_definition->setDescription(Argument::any())->willReturn($data_definition->reveal());
     $data_definition->setRequired(Argument::any())->willReturn($data_definition->reveal());
     $data_definition->setLabel(Argument::any())->willReturn($data_definition->reveal());
     $data_definition->setConstraints(Argument::any())->willReturn($data_definition->reveal());
     $data_definition->getConstraints()->willReturn([]);
     $data_definition->getDataType()->willReturn($data_type);
     $original_definition = $this->typedDataManager->getDefinition($data_type);
     $data_definition->getClass()->willReturn($original_definition['class']);
     $context_definition = ContextDefinition::create($data_type);
     // Inject a fake typed data manger that will return our data definition
     // prophecy if asked for it in the ContextDefinition class.
     $typed_data_manager = $this->prophesize(TypedDataManagerInterface::class);
     $typed_data_manager->createDataDefinition($data_type)->willReturn($data_definition->reveal());
     $context_definition->setTypedDataManager($typed_data_manager->reveal());
     return $context_definition;
 }
 /**
  * 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));
 }
Пример #19
0
 /**
  * Gets the definitions of the used context.
  *
  * @return \Drupal\rules\Context\ContextDefinitionInterface[]
  *   The array of context definition, keyed by context name.
  */
 public function getContextDefinitions()
 {
     $definitions = [];
     foreach ($this->context_definitions as $name => $definition) {
         $definitions[$name] = ContextDefinition::createFromArray($definition);
     }
     return $definitions;
 }
 /**
  * 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();
 }
Пример #21
0
 /**
  * {@inheritdoc}
  */
 public function __construct(array $values)
 {
     $this->definition = RulesContextDefinition::createFromArray($values);
 }
Пример #22
0
 /**
  * Converts a context definition configuration array into objects.
  *
  * @param array $configuration
  *   The configuration properties for populating the context definition
  *   object.
  *
  * @return \Drupal\Core\Plugin\Context\ContextDefinitionInterface[]
  *   A list of context definitions with the same keys.
  */
 protected function createContextDefinitions(array $configuration)
 {
     return array_map(function ($definition_array) {
         return ContextDefinition::createFromArray($definition_array);
     }, $configuration);
 }
Пример #23
0
 /**
  * Tests context can be refined based upon mapped context.
  */
 public function testRefiningContextBasedonMappedContext()
 {
     // DataComparision condition refines context based on selected data. Thus
     // it for the test and ensure checking integrity passes when the comparison
     // value is of a compatible type and fails else.
     $rule = $this->rulesExpressionManager->createRule();
     $rule->addCondition('rules_data_comparison', ContextConfig::create()->map('data', 'text')->map('value', 'text2'));
     $violation_list = RulesComponent::create($rule)->addContextDefinition('text', ContextDefinition::create('string'))->addContextDefinition('text2', ContextDefinition::create('string'))->checkIntegrity();
     $this->assertEquals(0, iterator_count($violation_list));
     $violation_list = RulesComponent::create($rule)->addContextDefinition('text', ContextDefinition::create('string'))->addContextDefinition('text2', ContextDefinition::create('integer'))->checkIntegrity();
     $this->assertEquals(1, iterator_count($violation_list));
 }
Пример #24
0
 /**
  * Gets the definitions of the provided context.
  *
  * @return \Drupal\rules\Context\ContextDefinitionInterface[]
  *   The array of context definition, keyed by context name.
  */
 public function getProvidedContextDefinitions()
 {
     $definitions = [];
     if (!empty($this->component['provided_context_definitions'])) {
         foreach ($this->component['provided_context_definitions'] as $name => $definition) {
             $definitions[$name] = ContextDefinition::createFromArray($definition);
         }
     }
     return $definitions;
 }
Пример #25
0
 /**
  * {@inheritdoc}
  */
 public function getDerivativeDefinitions($base_plugin_definition)
 {
     foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) {
         // Only allow content entities and ignore configuration entities.
         if (!$entity_type instanceof ContentEntityTypeInterface) {
             continue;
         }
         $this->derivatives[$entity_type_id] = ['label' => $this->t('Create a new @entity_type', ['@entity_type' => $entity_type->getLowercaseLabel()]), 'category' => $entity_type->getLabel(), 'entity_type_id' => $entity_type_id, 'context' => [], 'provides' => ['entity' => ContextDefinition::create("entity:{$entity_type_id}")->setLabel($entity_type->getLabel())->setRequired(TRUE)]] + $base_plugin_definition;
         // Add a required context for the bundle key, and optional contexts for
         // other required base fields. This matches the storage create() behavior,
         // where only the bundle requirement is enforced.
         $bundle_key = $entity_type->getKey('bundle');
         $this->derivatives[$entity_type_id]['bundle_key'] = $bundle_key;
         $base_field_definitions = $this->entityFieldManager->getBaseFieldDefinitions($entity_type_id);
         foreach ($base_field_definitions as $field_name => $definition) {
             if ($field_name != $bundle_key && !$definition->isRequired()) {
                 continue;
             }
             $item_definition = $definition->getItemDefinition();
             $type_definition = $item_definition->getPropertyDefinition($item_definition->getMainPropertyName());
             // If this is an entity reference then we expect the target type as
             // context.
             if ($type_definition instanceof DataReferenceDefinitionInterface) {
                 $type_definition->getTargetDefinition();
             }
             $type = $type_definition->getDataType();
             $is_bundle = $field_name == $bundle_key;
             $multiple = $definition->getCardinality() === 1 ? FALSE : TRUE;
             $context_definition = ContextDefinition::create($type)->setLabel($definition->getLabel())->setRequired($is_bundle)->setMultiple($multiple)->setDescription($definition->getDescription());
             if ($is_bundle) {
                 $context_definition->setAssignmentRestriction(ContextDefinition::ASSIGNMENT_RESTRICTION_INPUT);
             }
             $this->derivatives[$entity_type_id]['context'][$field_name] = $context_definition;
         }
     }
     return $this->derivatives;
 }
Пример #26
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();
 }