From ed2a37f9dc84ebf27d22153049eb838c1ac29adb Mon Sep 17 00:00:00 2001 From: milkovsky Date: Fri, 26 Feb 2016 17:44:15 +0100 Subject: [PATCH 1/9] Entity Save Deriver WIP, --- src/Plugin/RulesAction/EntitySave.php | 31 ++--- src/Plugin/RulesAction/EntitySaveDeriver.php | 111 ++++++++++++++++++ .../Integration/Action/EntityCreateTest.php | 20 ++-- 3 files changed, 137 insertions(+), 25 deletions(-) create mode 100644 src/Plugin/RulesAction/EntitySaveDeriver.php diff --git a/src/Plugin/RulesAction/EntitySave.php b/src/Plugin/RulesAction/EntitySave.php index e2743959..500ee6b2 100644 --- a/src/Plugin/RulesAction/EntitySave.php +++ b/src/Plugin/RulesAction/EntitySave.php @@ -8,32 +8,21 @@ namespace Drupal\rules\Plugin\RulesAction; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\rules\Core\RulesActionBase; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides a 'Save entity' action. * * @RulesAction( * id = "rules_entity_save", - * label = @Translation("Save entity"), - * category = @Translation("Entity"), - * context = { - * "entity" = @ContextDefinition("entity", - * label = @Translation("Entity"), - * description = @Translation("Specifies the entity, which should be saved permanently.") - * ), - * "immediate" = @ContextDefinition("boolean", - * label = @Translation("Force saving immediately"), - * description = @Translation("Usually saving is postponed till the end of the evaluation, so that multiple saves can be fold into one. If this set, saving is forced to happen immediately."), - * default_value = NULL, - * required = FALSE - * ) - * } + * deriver = "Drupal\rules\Plugin\RulesAction\EntitySaveDeriver", * ) * * @todo: Add access callback information from Drupal 7. */ -class EntitySave extends RulesActionBase { +class EntitySave extends RulesActionBase implements ContainerFactoryPluginInterface{ /** * Flag that indicates if the entity should be auto-saved later. @@ -42,6 +31,18 @@ class EntitySave extends RulesActionBase { */ protected $saveLater = TRUE; + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity_type.manager')->getStorage($plugin_definition['entity_type_id']) + ); + } + /** * Saves the Entity. * diff --git a/src/Plugin/RulesAction/EntitySaveDeriver.php b/src/Plugin/RulesAction/EntitySaveDeriver.php new file mode 100644 index 00000000..0791921a --- /dev/null +++ b/src/Plugin/RulesAction/EntitySaveDeriver.php @@ -0,0 +1,111 @@ +entityTypeManager = $entity_type_manager; + $this->entityFieldManager = $entity_field_manager; + $this->stringTranslation = $string_translation; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, $base_plugin_id) { + return new static($container->get('entity_type.manager'), $container->get('entity_field.manager'), $container->get('string_translation')); + } + + /** + * {@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('Save @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'); + $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; + } + + $is_bundle = ($field_name == $bundle_key); + $multiple = ($definition->getCardinality() === 1) ? FALSE : TRUE; + $context_definition = ContextDefinition::create($definition->getType()) + ->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; + } + +} diff --git a/tests/src/Integration/Action/EntityCreateTest.php b/tests/src/Integration/Action/EntityCreateTest.php index cbb8a75f..210aa3c3 100644 --- a/tests/src/Integration/Action/EntityCreateTest.php +++ b/tests/src/Integration/Action/EntityCreateTest.php @@ -47,31 +47,31 @@ public function setUp() { // and the mocked field definition is instantiated without the necessary // information. $bundle_field_definition->getCardinality()->willReturn(1) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(2); $bundle_field_definition->getType()->willReturn('string') - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(2); $bundle_field_definition->getLabel()->willReturn('Bundle') - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(2); $bundle_field_definition->getDescription() ->willReturn('Bundle mock description') - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(2); $bundle_field_definition_required->getCardinality()->willReturn(1) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(2); $bundle_field_definition_required->getType()->willReturn('string') - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(2); $bundle_field_definition_required->getLabel()->willReturn('Required field') - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(2); $bundle_field_definition_required->getDescription() ->willReturn('Required field mock description') - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(2); $bundle_field_definition_required->isRequired() ->willReturn(TRUE) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(2); $bundle_field_definition_optional->isRequired() ->willReturn(FALSE) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(2); // Prepare mocked entity storage. $entity_type_storage = $this->prophesize(EntityStorageBase::class); From 9b52169f07fb867710bdae68c0a239ac8c82ad6c Mon Sep 17 00:00:00 2001 From: milkovsky Date: Fri, 4 Mar 2016 17:42:52 +0100 Subject: [PATCH 2/9] Added test. WIP. --- src/Plugin/RulesAction/EntitySave.php | 33 ++++++++ .../Integration/Action/EntityCreateTest.php | 20 ++--- .../src/Integration/Action/EntitySaveTest.php | 83 ++++++++++++++++++- 3 files changed, 125 insertions(+), 11 deletions(-) diff --git a/src/Plugin/RulesAction/EntitySave.php b/src/Plugin/RulesAction/EntitySave.php index 500ee6b2..dafadf03 100644 --- a/src/Plugin/RulesAction/EntitySave.php +++ b/src/Plugin/RulesAction/EntitySave.php @@ -11,6 +11,7 @@ use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\rules\Core\RulesActionBase; use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Entity\EntityStorageInterface; /** * Provides a 'Save entity' action. @@ -24,6 +25,20 @@ */ class EntitySave extends RulesActionBase implements ContainerFactoryPluginInterface{ + /** + * The entity storage service. + * + * @var \Drupal\Core\Entity\EntityStorageInterface + */ + protected $storage; + + /** + * The entity type id. + * + * @var string + */ + protected $entityTypeId; + /** * Flag that indicates if the entity should be auto-saved later. * @@ -31,6 +46,24 @@ class EntitySave extends RulesActionBase implements ContainerFactoryPluginInterf */ protected $saveLater = TRUE; + /** + * Constructs an EntitySave object. + * + * @param array $configuration + * A configuration array containing information about the plugin instance. + * @param string $plugin_id + * The plugin ID for the plugin instance. + * @param mixed $plugin_definition + * The plugin implementation definition. + * @param \Drupal\Core\Entity\EntityStorageInterface $storage + * The entity storage service. + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityStorageInterface $storage) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + $this->storage = $storage; + $this->entityTypeId = $plugin_definition['entity_type_id']; + } + /** * {@inheritdoc} */ diff --git a/tests/src/Integration/Action/EntityCreateTest.php b/tests/src/Integration/Action/EntityCreateTest.php index c90dff2c..61f7c64e 100644 --- a/tests/src/Integration/Action/EntityCreateTest.php +++ b/tests/src/Integration/Action/EntityCreateTest.php @@ -47,31 +47,31 @@ public function setUp() { // and the mocked field definition is instantiated without the necessary // information. $bundle_field_definition->getCardinality()->willReturn(1) - ->shouldBeCalledTimes(2); + ->shouldBeCalled(); $bundle_field_definition->getType()->willReturn('string') - ->shouldBeCalledTimes(2); + ->shouldBeCalled(); $bundle_field_definition->getLabel()->willReturn('Bundle') - ->shouldBeCalledTimes(2); + ->shouldBeCalled(); $bundle_field_definition->getDescription() ->willReturn('Bundle mock description') - ->shouldBeCalledTimes(2); + ->shouldBeCalled(); $bundle_field_definition_required->getCardinality()->willReturn(1) - ->shouldBeCalledTimes(2); + ->shouldBeCalled(); $bundle_field_definition_required->getType()->willReturn('string') - ->shouldBeCalledTimes(2); + ->shouldBeCalled(); $bundle_field_definition_required->getLabel()->willReturn('Required field') - ->shouldBeCalledTimes(2); + ->shouldBeCalled(); $bundle_field_definition_required->getDescription() ->willReturn('Required field mock description') - ->shouldBeCalledTimes(2); + ->shouldBeCalled(); $bundle_field_definition_required->isRequired() ->willReturn(TRUE) - ->shouldBeCalledTimes(2); + ->shouldBeCalled(); $bundle_field_definition_optional->isRequired() ->willReturn(FALSE) - ->shouldBeCalledTimes(2); + ->shouldBeCalled(); // Prepare mocked entity storage. $entity_type_storage = $this->prophesize(EntityStorageBase::class); diff --git a/tests/src/Integration/Action/EntitySaveTest.php b/tests/src/Integration/Action/EntitySaveTest.php index 026884cc..62cbb6c9 100644 --- a/tests/src/Integration/Action/EntitySaveTest.php +++ b/tests/src/Integration/Action/EntitySaveTest.php @@ -8,6 +8,9 @@ namespace Drupal\Tests\rules\Integration\Action; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\TypedData\EntityDataDefinition; +use Drupal\Core\Entity\EntityStorageBase; +use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Tests\rules\Integration\RulesEntityIntegrationTestBase; /** @@ -30,6 +33,11 @@ class EntitySaveTest extends RulesEntityIntegrationTestBase { */ protected $entity; + /** + * A constant that will be used instead of an entity. + */ + const ENTITY_REPLACEMENT = 'This is a fake entity'; + /** * {@inheritdoc} */ @@ -38,7 +46,63 @@ public function setUp() { $this->entity = $this->prophesizeEntity(EntityInterface::class); - $this->action = $this->actionManager->createInstance('rules_entity_save'); + // Prepare some mocked bundle field definitions. This is needed because + // EntityCreateDeriver adds required contexts for required fields, and + // assumes that the bundle field is required. + $entity_definition = $this->prophesize(EntityDataDefinition::class); + $bundle_field_definition = $this->prophesize(BaseFieldDefinition::class); + $bundle_field_definition_optional = $this->prophesize(BaseFieldDefinition::class); + $bundle_field_definition_required = $this->prophesize(BaseFieldDefinition::class); + + // The next methods are mocked because EntitySaveDeriver executes them, + // and the mocked field definition is instantiated without the necessary + // information. + $bundle_field_definition->getCardinality()->willReturn(1) + ->shouldBeCalled(); + $bundle_field_definition->getType()->willReturn('string') + ->shouldBeCalled(); + $bundle_field_definition->getLabel()->willReturn('Bundle') + ->shouldBeCalled(); + $bundle_field_definition->getDescription() + ->willReturn('Bundle mock description') + ->shouldBeCalled(); + + $bundle_field_definition_required->getCardinality()->willReturn(1) + ->shouldBeCalled(); + $bundle_field_definition_required->getType()->willReturn('string') + ->shouldBeCalled(); + $bundle_field_definition_required->getLabel()->willReturn('Required field') + ->shouldBeCalled(); + $bundle_field_definition_required->getDescription() + ->willReturn('Required field mock description') + ->shouldBeCalled(); + $bundle_field_definition_required->isRequired() + ->willReturn(TRUE) + ->shouldBeCalled(); + + $bundle_field_definition_optional->isRequired() + ->willReturn(FALSE) + ->shouldBeCalled(); + + // Prepare mocked entity storage. + $entity_type_storage = $this->prophesize(EntityStorageBase::class); + $entity_type_storage->save(['entity' => $this->entity, 'bundle' => 'test', 'field_required' => NULL]) + ->willReturn(self::ENTITY_REPLACEMENT); + + // Return the mocked storage controller. + $this->entityTypeManager->getStorage('test') + ->willReturn($entity_type_storage->reveal()); + + // Return a mocked list of base fields definitions. + $this->entityFieldManager->getBaseFieldDefinitions('test') + ->willReturn([ + 'bundle' => $bundle_field_definition->reveal(), + 'field_required' => $bundle_field_definition_required->reveal(), + 'field_optional' => $bundle_field_definition_optional->reveal(), + ]); + + // Instantiate the action we are testing. + $this->action = $this->actionManager->createInstance('rules_entity_save:test'); } /** @@ -50,6 +114,23 @@ public function testSummary() { $this->assertEquals('Save entity', $this->action->summary()); } + /** + * Tests the action execution. + * + * @covers ::execute + */ + public function testActionExecution() { + $this->entity->save()->shouldBeCalledTimes(1); + + // @todo Exception: The entity context is not a valid context. + $this->action->setContextValue('entity', $this->entity->reveal()) + ->setContextValue('immediate', TRUE); + + $this->action->execute(); + $entity = $this->action->getProvidedContext('entity')->getContextValue(); + $this->assertEquals(self::ENTITY_REPLACEMENT, $entity); + } + /** * Tests the action execution when saving immediately. * From 1714d7c108d01b9fc9867afc5a013f41ada43883 Mon Sep 17 00:00:00 2001 From: milkovsky Date: Mon, 7 Mar 2016 13:28:07 +0100 Subject: [PATCH 3/9] Fixed test, context. --- src/Plugin/RulesAction/EntitySaveDeriver.php | 39 ++++--------- .../src/Integration/Action/EntitySaveTest.php | 58 ------------------- 2 files changed, 12 insertions(+), 85 deletions(-) diff --git a/src/Plugin/RulesAction/EntitySaveDeriver.php b/src/Plugin/RulesAction/EntitySaveDeriver.php index 0791921a..910325fb 100644 --- a/src/Plugin/RulesAction/EntitySaveDeriver.php +++ b/src/Plugin/RulesAction/EntitySaveDeriver.php @@ -55,7 +55,11 @@ public function __construct(EntityTypeManagerInterface $entity_type_manager, Ent * {@inheritdoc} */ public static function create(ContainerInterface $container, $base_plugin_id) { - return new static($container->get('entity_type.manager'), $container->get('entity_field.manager'), $container->get('string_translation')); + return new static( + $container->get('entity_type.manager'), + $container->get('entity_field.manager'), + $container->get('string_translation') + ); } /** @@ -72,37 +76,18 @@ public function getDerivativeDefinitions($base_plugin_definition) { 'label' => $this->t('Save @entity_type', ['@entity_type' => $entity_type->getLowercaseLabel()]), 'category' => $entity_type->getLabel(), 'entity_type_id' => $entity_type_id, - 'context' => [], - 'provides' => [ + 'context' => [ 'entity' => ContextDefinition::create("entity:$entity_type_id") ->setLabel($entity_type->getLabel()) + ->setDescription($this->t('Specifies the entity, which should be saved permanently.')) ->setRequired(TRUE), + 'immediate' => ContextDefinition::create('boolean') + ->setLabel($this->t('Force saving immediately')) + ->setDescription($this->t('Usually saving is postponed till the end of the evaluation, so that multiple saves can be fold into one. If this set, saving is forced to happen immediately.')) + ->setDefaultValue(NULL) + ->setRequired(FALSE), ], ] + $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'); - $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; - } - - $is_bundle = ($field_name == $bundle_key); - $multiple = ($definition->getCardinality() === 1) ? FALSE : TRUE; - $context_definition = ContextDefinition::create($definition->getType()) - ->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; diff --git a/tests/src/Integration/Action/EntitySaveTest.php b/tests/src/Integration/Action/EntitySaveTest.php index 62cbb6c9..2e6ad5b3 100644 --- a/tests/src/Integration/Action/EntitySaveTest.php +++ b/tests/src/Integration/Action/EntitySaveTest.php @@ -8,9 +8,7 @@ namespace Drupal\Tests\rules\Integration\Action; use Drupal\Core\Entity\EntityInterface; -use Drupal\Core\Entity\TypedData\EntityDataDefinition; use Drupal\Core\Entity\EntityStorageBase; -use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Tests\rules\Integration\RulesEntityIntegrationTestBase; /** @@ -33,11 +31,6 @@ class EntitySaveTest extends RulesEntityIntegrationTestBase { */ protected $entity; - /** - * A constant that will be used instead of an entity. - */ - const ENTITY_REPLACEMENT = 'This is a fake entity'; - /** * {@inheritdoc} */ @@ -46,61 +39,13 @@ public function setUp() { $this->entity = $this->prophesizeEntity(EntityInterface::class); - // Prepare some mocked bundle field definitions. This is needed because - // EntityCreateDeriver adds required contexts for required fields, and - // assumes that the bundle field is required. - $entity_definition = $this->prophesize(EntityDataDefinition::class); - $bundle_field_definition = $this->prophesize(BaseFieldDefinition::class); - $bundle_field_definition_optional = $this->prophesize(BaseFieldDefinition::class); - $bundle_field_definition_required = $this->prophesize(BaseFieldDefinition::class); - - // The next methods are mocked because EntitySaveDeriver executes them, - // and the mocked field definition is instantiated without the necessary - // information. - $bundle_field_definition->getCardinality()->willReturn(1) - ->shouldBeCalled(); - $bundle_field_definition->getType()->willReturn('string') - ->shouldBeCalled(); - $bundle_field_definition->getLabel()->willReturn('Bundle') - ->shouldBeCalled(); - $bundle_field_definition->getDescription() - ->willReturn('Bundle mock description') - ->shouldBeCalled(); - - $bundle_field_definition_required->getCardinality()->willReturn(1) - ->shouldBeCalled(); - $bundle_field_definition_required->getType()->willReturn('string') - ->shouldBeCalled(); - $bundle_field_definition_required->getLabel()->willReturn('Required field') - ->shouldBeCalled(); - $bundle_field_definition_required->getDescription() - ->willReturn('Required field mock description') - ->shouldBeCalled(); - $bundle_field_definition_required->isRequired() - ->willReturn(TRUE) - ->shouldBeCalled(); - - $bundle_field_definition_optional->isRequired() - ->willReturn(FALSE) - ->shouldBeCalled(); - // Prepare mocked entity storage. $entity_type_storage = $this->prophesize(EntityStorageBase::class); - $entity_type_storage->save(['entity' => $this->entity, 'bundle' => 'test', 'field_required' => NULL]) - ->willReturn(self::ENTITY_REPLACEMENT); // Return the mocked storage controller. $this->entityTypeManager->getStorage('test') ->willReturn($entity_type_storage->reveal()); - // Return a mocked list of base fields definitions. - $this->entityFieldManager->getBaseFieldDefinitions('test') - ->willReturn([ - 'bundle' => $bundle_field_definition->reveal(), - 'field_required' => $bundle_field_definition_required->reveal(), - 'field_optional' => $bundle_field_definition_optional->reveal(), - ]); - // Instantiate the action we are testing. $this->action = $this->actionManager->createInstance('rules_entity_save:test'); } @@ -122,13 +67,10 @@ public function testSummary() { public function testActionExecution() { $this->entity->save()->shouldBeCalledTimes(1); - // @todo Exception: The entity context is not a valid context. $this->action->setContextValue('entity', $this->entity->reveal()) ->setContextValue('immediate', TRUE); $this->action->execute(); - $entity = $this->action->getProvidedContext('entity')->getContextValue(); - $this->assertEquals(self::ENTITY_REPLACEMENT, $entity); } /** From c2c4c017f6ebb6063542488bb7602bfd2ad25526 Mon Sep 17 00:00:00 2001 From: milkovsky Date: Mon, 7 Mar 2016 13:29:53 +0100 Subject: [PATCH 4/9] Fixed formatting. --- src/Plugin/RulesAction/EntitySave.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plugin/RulesAction/EntitySave.php b/src/Plugin/RulesAction/EntitySave.php index dafadf03..ba18c0f2 100644 --- a/src/Plugin/RulesAction/EntitySave.php +++ b/src/Plugin/RulesAction/EntitySave.php @@ -23,7 +23,7 @@ * * @todo: Add access callback information from Drupal 7. */ -class EntitySave extends RulesActionBase implements ContainerFactoryPluginInterface{ +class EntitySave extends RulesActionBase implements ContainerFactoryPluginInterface { /** * The entity storage service. From 6fb10ed3387fc6ccfddaa90beb97859f1e42edd1 Mon Sep 17 00:00:00 2001 From: milkovsky Date: Mon, 7 Mar 2016 15:17:30 +0100 Subject: [PATCH 5/9] After merge. --- src/Plugin/RulesAction/EntitySaveDeriver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plugin/RulesAction/EntitySaveDeriver.php b/src/Plugin/RulesAction/EntitySaveDeriver.php index 910325fb..eef8e077 100644 --- a/src/Plugin/RulesAction/EntitySaveDeriver.php +++ b/src/Plugin/RulesAction/EntitySaveDeriver.php @@ -84,7 +84,7 @@ public function getDerivativeDefinitions($base_plugin_definition) { 'immediate' => ContextDefinition::create('boolean') ->setLabel($this->t('Force saving immediately')) ->setDescription($this->t('Usually saving is postponed till the end of the evaluation, so that multiple saves can be fold into one. If this set, saving is forced to happen immediately.')) - ->setDefaultValue(NULL) + ->setDefaultValue(FALSE) ->setRequired(FALSE), ], ] + $base_plugin_definition; From ba09b7e480a359798cefbd75ebd3e39023813285 Mon Sep 17 00:00:00 2001 From: milkovsky Date: Mon, 21 Mar 2016 11:59:21 +0100 Subject: [PATCH 6/9] PR fixes. --- src/Plugin/RulesAction/EntitySaveDeriver.php | 6 +++++- tests/src/Integration/Action/EntitySaveTest.php | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Plugin/RulesAction/EntitySaveDeriver.php b/src/Plugin/RulesAction/EntitySaveDeriver.php index eef8e077..94acaa76 100644 --- a/src/Plugin/RulesAction/EntitySaveDeriver.php +++ b/src/Plugin/RulesAction/EntitySaveDeriver.php @@ -23,6 +23,7 @@ * @see \Drupal\rules\Plugin\RulesAction\EntitySave */ class EntitySaveDeriver extends DeriverBase implements ContainerDeriverInterface { + use StringTranslationTrait; /** @@ -30,13 +31,16 @@ class EntitySaveDeriver extends DeriverBase implements ContainerDeriverInterface * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ + protected $entityTypeManager; + /** * The entity field manager. * * @var \Drupal\Core\Entity\EntityFieldManagerInterface; */ protected $entityFieldManager; + /** * Saves a new EntitySaveDeriver object. * @@ -79,7 +83,7 @@ public function getDerivativeDefinitions($base_plugin_definition) { 'context' => [ 'entity' => ContextDefinition::create("entity:$entity_type_id") ->setLabel($entity_type->getLabel()) - ->setDescription($this->t('Specifies the entity, which should be saved permanently.')) + ->setDescription($this->t('Specifies the @entity_type_label that should be saved permanently.', ['@entity_type_label' => $entity_type->getLabel()])) ->setRequired(TRUE), 'immediate' => ContextDefinition::create('boolean') ->setLabel($this->t('Force saving immediately')) diff --git a/tests/src/Integration/Action/EntitySaveTest.php b/tests/src/Integration/Action/EntitySaveTest.php index 2e6ad5b3..f9f4eca8 100644 --- a/tests/src/Integration/Action/EntitySaveTest.php +++ b/tests/src/Integration/Action/EntitySaveTest.php @@ -56,7 +56,7 @@ public function setUp() { * @covers ::summary */ public function testSummary() { - $this->assertEquals('Save entity', $this->action->summary()); + $this->assertEquals('Save test', $this->action->summary()); } /** From 4b10458ab0713b07a321f3a3fc5adcbc2385f17c Mon Sep 17 00:00:00 2001 From: milkovsky Date: Wed, 6 Apr 2016 10:11:04 +0200 Subject: [PATCH 7/9] Fixed "The rules_entity_save plugin does not exist.". --- .../Action/RulesComponentActionTest.php | 20 +++++++++++++--- tests/src/Integration/Engine/AutoSaveTest.php | 16 ++++++++++++- .../Integration/Engine/IntegrityCheckTest.php | 24 +++++++++++++++---- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/tests/src/Integration/Action/RulesComponentActionTest.php b/tests/src/Integration/Action/RulesComponentActionTest.php index 67a7f1c8..abc8e3e0 100644 --- a/tests/src/Integration/Action/RulesComponentActionTest.php +++ b/tests/src/Integration/Action/RulesComponentActionTest.php @@ -9,6 +9,7 @@ use Drupal\Core\Config\Entity\ConfigEntityStorageInterface; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityStorageBase; use Drupal\rules\Context\ContextConfig; use Drupal\rules\Context\ContextDefinition; use Drupal\rules\Engine\RulesComponent; @@ -22,6 +23,19 @@ */ class RulesComponentActionTest extends RulesEntityIntegrationTestBase { + /** + * {@inheritdoc} + */ + public function setUp() { + parent::setUp(); + // Prepare mocked entity storage. + $entity_type_storage = $this->prophesize(EntityStorageBase::class); + + // Return the mocked storage controller. + $this->entityTypeManager->getStorage('test') + ->willReturn($entity_type_storage->reveal()); + } + /** * Tests that a rule can be used as action. */ @@ -47,7 +61,7 @@ public function testActionAvailable() { public function testExecute() { // Set up a rules component that will just save an entity. $nested_rule = $this->rulesExpressionManager->createRule(); - $nested_rule->addAction('rules_entity_save', ContextConfig::create() + $nested_rule->addAction('rules_entity_save:test', ContextConfig::create() ->map('entity', 'entity') ); @@ -144,7 +158,7 @@ public function testAutosaveOnlyOnce() { $entity = $this->prophesizeEntity(EntityInterface::class); $nested_rule = $this->rulesExpressionManager->createRule(); - $nested_rule->addAction('rules_entity_save', ContextConfig::create() + $nested_rule->addAction('rules_entity_save:test', ContextConfig::create() ->map('entity', 'entity') ); @@ -163,7 +177,7 @@ public function testAutosaveOnlyOnce() { $rule->addAction('rules_component:test_rule', ContextConfig::create() ->map('entity', 'entity') ); - $rule->addAction('rules_entity_save', ContextConfig::create() + $rule->addAction('rules_entity_save:test', ContextConfig::create() ->map('entity', 'entity') ); diff --git a/tests/src/Integration/Engine/AutoSaveTest.php b/tests/src/Integration/Engine/AutoSaveTest.php index c651173b..13e46256 100644 --- a/tests/src/Integration/Engine/AutoSaveTest.php +++ b/tests/src/Integration/Engine/AutoSaveTest.php @@ -8,6 +8,7 @@ namespace Drupal\Tests\rules\Integration\Engine; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityStorageBase; use Drupal\rules\Context\ContextConfig; use Drupal\rules\Context\ContextDefinition; use Drupal\rules\Engine\RulesComponent; @@ -20,13 +21,26 @@ */ class AutoSaveTest extends RulesEntityIntegrationTestBase { + /** + * {@inheritdoc} + */ + public function setUp() { + parent::setUp(); + // Prepare mocked entity storage. + $entity_type_storage = $this->prophesize(EntityStorageBase::class); + + // Return the mocked storage controller. + $this->entityTypeManager->getStorage('test') + ->willReturn($entity_type_storage->reveal()); + } + /** * 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() + $rule->addAction('rules_entity_save:test', ContextConfig::create() ->map('entity', 'entity') ); diff --git a/tests/src/Integration/Engine/IntegrityCheckTest.php b/tests/src/Integration/Engine/IntegrityCheckTest.php index ebb731ae..b05293d5 100644 --- a/tests/src/Integration/Engine/IntegrityCheckTest.php +++ b/tests/src/Integration/Engine/IntegrityCheckTest.php @@ -8,6 +8,7 @@ namespace Drupal\Tests\rules\Integration\Engine; use Drupal\rules\Context\ContextConfig; +use Drupal\Core\Entity\EntityStorageBase; use Drupal\rules\Context\ContextDefinition; use Drupal\rules\Engine\RulesComponent; use Drupal\Tests\rules\Integration\RulesEntityIntegrationTestBase; @@ -19,12 +20,25 @@ */ class IntegrityCheckTest extends RulesEntityIntegrationTestBase { + /** + * {@inheritdoc} + */ + public function setUp() { + parent::setUp(); + // Prepare mocked entity storage. + $entity_type_storage = $this->prophesize(EntityStorageBase::class); + + // Return the mocked storage controller. + $this->entityTypeManager->getStorage('test') + ->willReturn($entity_type_storage->reveal()); + } + /** * Tests that the integrity check can be invoked. */ public function testIntegrityCheck() { $rule = $this->rulesExpressionManager->createRule(); - $rule->addAction('rules_entity_save', ContextConfig::create() + $rule->addAction('rules_entity_save:test', ContextConfig::create() ->map('entity', 'entity') ); @@ -39,7 +53,7 @@ public function testIntegrityCheck() { */ public function testUnknownVariable() { $rule = $this->rulesExpressionManager->createRule(); - $action = $this->rulesExpressionManager->createAction('rules_entity_save', ContextConfig::create() + $action = $this->rulesExpressionManager->createAction('rules_entity_save:test', ContextConfig::create() ->map('entity', 'unknown_variable') ->toArray() ); @@ -50,7 +64,7 @@ public function testUnknownVariable() { $this->assertEquals(1, iterator_count($violation_list)); $violation = $violation_list[0]; $this->assertEquals( - 'Data selector unknown_variable for context Entity is invalid. Unable to get variable unknown_variable, it is not defined.', + 'Data selector unknown_variable for context Test is invalid. Unable to get variable unknown_variable, it is not defined.', (string) $violation->getMessage() ); $this->assertEquals($action->getUuid(), $violation->getUuid()); @@ -64,7 +78,7 @@ public function testCheckUuid() { // Just use a rule with 2 dummy actions. $rule->addAction('rules_entity_save', ContextConfig::create() ->map('entity', 'unknown_variable_1')); - $second_action = $this->rulesExpressionManager->createAction('rules_entity_save', ContextConfig::create() + $second_action = $this->rulesExpressionManager->createAction('rules_entity_save:test', ContextConfig::create() ->map('entity', 'unknown_variable_2') ->toArray() ); @@ -80,7 +94,7 @@ public function testCheckUuid() { $this->assertEquals(1, count($uuid_violations)); $violation = $uuid_violations[0]; $this->assertEquals( - 'Data selector unknown_variable_2 for context Entity is invalid. Unable to get variable unknown_variable_2, it is not defined.', + 'Data selector unknown_variable_2 for context Test is invalid. Unable to get variable unknown_variable_2, it is not defined.', (string) $violation->getMessage() ); $this->assertEquals($second_action->getUuid(), $violation->getUuid()); From 47244f82456971921d6f984831d7f514709bc592 Mon Sep 17 00:00:00 2001 From: milkovsky Date: Mon, 11 Apr 2016 17:23:53 +0200 Subject: [PATCH 8/9] Fixed context definition in tests for entity save plugin. --- tests/src/Integration/Action/RulesComponentActionTest.php | 8 ++++---- tests/src/Integration/Engine/AutoSaveTest.php | 2 +- tests/src/Integration/Engine/IntegrityCheckTest.php | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/src/Integration/Action/RulesComponentActionTest.php b/tests/src/Integration/Action/RulesComponentActionTest.php index afc4c536..a0ae6210 100644 --- a/tests/src/Integration/Action/RulesComponentActionTest.php +++ b/tests/src/Integration/Action/RulesComponentActionTest.php @@ -65,7 +65,7 @@ public function testExecute() { 'label' => 'Test rule', ], 'rules_component'); $rules_config->setExpression($nested_rule); - $rules_config->setContextDefinitions(['entity' => ContextDefinition::create('entity')]); + $rules_config->setContextDefinitions(['entity' => ContextDefinition::create('entity:test')]); $this->prophesizeStorage([$rules_config]); @@ -80,7 +80,7 @@ public function testExecute() { $entity->save()->shouldBeCalledTimes(1); RulesComponent::create($rule) - ->addContextDefinition('entity', ContextDefinition::create('entity')) + ->addContextDefinition('entity', ContextDefinition::create('entity:test')) ->setContextValue('entity', $entity->reveal()) ->execute(); } @@ -162,7 +162,7 @@ public function testAutosaveOnlyOnce() { 'label' => 'Test rule', ], 'rules_component'); $rules_config->setExpression($nested_rule); - $rules_config->setContextDefinitions(['entity' => ContextDefinition::create('entity')]); + $rules_config->setContextDefinitions(['entity' => ContextDefinition::create('entity:test')]); $this->prophesizeStorage([$rules_config]); @@ -180,7 +180,7 @@ public function testAutosaveOnlyOnce() { $entity->save()->shouldBeCalledTimes(1); RulesComponent::create($rule) - ->addContextDefinition('entity', ContextDefinition::create('entity')) + ->addContextDefinition('entity', ContextDefinition::create('entity:test')) ->setContextValue('entity', $entity->reveal()) ->execute(); } diff --git a/tests/src/Integration/Engine/AutoSaveTest.php b/tests/src/Integration/Engine/AutoSaveTest.php index 63708d7b..a2af62d3 100644 --- a/tests/src/Integration/Engine/AutoSaveTest.php +++ b/tests/src/Integration/Engine/AutoSaveTest.php @@ -43,7 +43,7 @@ public function testActionAutoSave() { $entity->save()->shouldBeCalledTimes(1); RulesComponent::create($rule) - ->addContextDefinition('entity', ContextDefinition::create('entity')) + ->addContextDefinition('entity', ContextDefinition::create('entity:test')) ->setContextValue('entity', $entity->reveal()) ->execute(); } diff --git a/tests/src/Integration/Engine/IntegrityCheckTest.php b/tests/src/Integration/Engine/IntegrityCheckTest.php index 74c8a135..a609a6fc 100644 --- a/tests/src/Integration/Engine/IntegrityCheckTest.php +++ b/tests/src/Integration/Engine/IntegrityCheckTest.php @@ -38,7 +38,7 @@ public function testIntegrityCheck() { ); $violation_list = RulesComponent::create($rule) - ->addContextDefinition('entity', ContextDefinition::create('entity')) + ->addContextDefinition('entity', ContextDefinition::create('entity:test')) ->checkIntegrity(); $this->assertEquals(0, iterator_count($violation_list)); } @@ -80,7 +80,7 @@ public function testCheckUuid() { $rule->addExpressionObject($second_action); $all_violations = RulesComponent::create($rule) - ->addContextDefinition('entity', ContextDefinition::create('entity')) + ->addContextDefinition('entity', ContextDefinition::create('entity:test')) ->checkIntegrity(); $this->assertEquals(2, iterator_count($all_violations)); From 889098a207aac56504b8027decb8bec0cbdb7020 Mon Sep 17 00:00:00 2001 From: milkovsky Date: Mon, 11 Apr 2016 17:36:53 +0200 Subject: [PATCH 9/9] Removed unnecessary file doc comment. --- src/Plugin/RulesAction/EntitySaveDeriver.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Plugin/RulesAction/EntitySaveDeriver.php b/src/Plugin/RulesAction/EntitySaveDeriver.php index 94acaa76..668dafef 100644 --- a/src/Plugin/RulesAction/EntitySaveDeriver.php +++ b/src/Plugin/RulesAction/EntitySaveDeriver.php @@ -1,10 +1,5 @@