From 469003db9e16a42cd45dee9a5a4769f6821cd2c5 Mon Sep 17 00:00:00 2001 From: Alex Pott <alex.a.pott@googlemail.com> Date: Mon, 8 May 2017 11:50:29 +0100 Subject: [PATCH] Issue #2817835 by timmillwood, Sam152, alexpott: When enabling moderation apply a relative state --- .../src/EntityOperations.php | 2 +- .../FieldWidget/ModerationStateWidget.php | 2 +- .../Field/ModerationStateFieldItemList.php | 4 +- .../Plugin/WorkflowType/ContentModeration.php | 11 +++ .../src/StateTransitionValidation.php | 2 +- .../src/Kernel/ContentModerationStateTest.php | 3 + .../tests/src/Kernel/InitialStateTest.php | 82 +++++++++++++++++++ .../ModerationStateFieldItemListTest.php | 4 +- .../modules/workflows/src/Entity/Workflow.php | 8 -- .../workflows/src/Plugin/WorkflowTypeBase.php | 8 ++ .../workflows/src/WorkflowInterface.php | 8 -- .../workflows/src/WorkflowTypeInterface.php | 11 +++ .../tests/src/Functional/WorkflowUiTest.php | 4 +- .../workflows/tests/src/Unit/WorkflowTest.php | 19 ----- 14 files changed, 124 insertions(+), 44 deletions(-) create mode 100644 core/modules/content_moderation/tests/src/Kernel/InitialStateTest.php diff --git a/core/modules/content_moderation/src/EntityOperations.php b/core/modules/content_moderation/src/EntityOperations.php index 3e34d141ec93..3f66100581bd 100644 --- a/core/modules/content_moderation/src/EntityOperations.php +++ b/core/modules/content_moderation/src/EntityOperations.php @@ -158,7 +158,7 @@ protected function updateOrCreateFromEntity(EntityInterface $entity) { $workflow = $this->moderationInfo->getWorkflowForEntity($entity); /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ if (!$moderation_state) { - $moderation_state = $workflow->getInitialState()->id(); + $moderation_state = $workflow->getTypePlugin()->getInitialState($workflow, $entity)->id(); } // @todo what if $entity->moderation_state is null at this point? diff --git a/core/modules/content_moderation/src/Plugin/Field/FieldWidget/ModerationStateWidget.php b/core/modules/content_moderation/src/Plugin/Field/FieldWidget/ModerationStateWidget.php index 970ac33a5dcc..ab5a5613609a 100644 --- a/core/modules/content_moderation/src/Plugin/Field/FieldWidget/ModerationStateWidget.php +++ b/core/modules/content_moderation/src/Plugin/Field/FieldWidget/ModerationStateWidget.php @@ -117,7 +117,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen } $workflow = $this->moderationInformation->getWorkflowForEntity($entity); - $default = $items->get($delta)->value ? $workflow->getState($items->get($delta)->value) : $workflow->getInitialState(); + $default = $items->get($delta)->value ? $workflow->getState($items->get($delta)->value) : $workflow->getTypePlugin()->getInitialState($workflow, $entity); if (!$default) { throw new \UnexpectedValueException(sprintf('The %s bundle has an invalid moderation state configuration, moderation states are enabled but no default is set.', $bundle_entity->label())); } diff --git a/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php b/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php index 0444644f9326..2d93f5a7c2a9 100644 --- a/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php +++ b/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php @@ -37,8 +37,8 @@ protected function getModerationStateId() { // It is possible that the bundle does not exist at this point. For example, // the node type form creates a fake Node entity to get default values. // @see \Drupal\node\NodeTypeForm::form() - $workflow = $moderation_info->getWorkflowForEntity($entity); - return $workflow ? $workflow->getInitialState()->id() : NULL; + $workflow = $moderation_info->getWorkFlowForEntity($entity); + return $workflow ? $workflow->getTypePlugin()->getInitialState($workflow, $entity)->id() : NULL; } /** diff --git a/core/modules/content_moderation/src/Plugin/WorkflowType/ContentModeration.php b/core/modules/content_moderation/src/Plugin/WorkflowType/ContentModeration.php index 31f1c18c682b..51605d5383d6 100644 --- a/core/modules/content_moderation/src/Plugin/WorkflowType/ContentModeration.php +++ b/core/modules/content_moderation/src/Plugin/WorkflowType/ContentModeration.php @@ -4,6 +4,7 @@ use Drupal\Core\Access\AccessResult; use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Entity\EntityPublishedInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Session\AccountInterface; @@ -289,4 +290,14 @@ public function getConfiguration() { return $configuration; } + /** + * {@inheritdoc} + */ + public function getInitialState(WorkflowInterface $workflow, $entity = NULL) { + if ($entity instanceof EntityPublishedInterface) { + return $workflow->getState($entity->isPublished() ? 'published' : 'draft'); + } + return parent::getInitialState($workflow); + } + } diff --git a/core/modules/content_moderation/src/StateTransitionValidation.php b/core/modules/content_moderation/src/StateTransitionValidation.php index c4e26c26ff9b..4952f2e7154c 100644 --- a/core/modules/content_moderation/src/StateTransitionValidation.php +++ b/core/modules/content_moderation/src/StateTransitionValidation.php @@ -40,7 +40,7 @@ public function __construct(ModerationInformationInterface $moderation_info) { */ public function getValidTransitions(ContentEntityInterface $entity, AccountInterface $user) { $workflow = $this->moderationInfo->getWorkflowForEntity($entity); - $current_state = $entity->moderation_state->value ? $workflow->getState($entity->moderation_state->value) : $workflow->getInitialState(); + $current_state = $entity->moderation_state->value ? $workflow->getState($entity->moderation_state->value) : $workflow->getTypePlugin()->getInitialState($workflow, $entity); return array_filter($current_state->getTransitions(), function(Transition $transition) use ($workflow, $user) { return $user->hasPermission('use ' . $workflow->id() . ' transition ' . $transition->id()); diff --git a/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php b/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php index 70a5df5bcd6b..0f8469921378 100644 --- a/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php +++ b/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php @@ -95,6 +95,9 @@ public function testBasicModeration($entity_type_id) { 'title' => 'Test title', $this->entityTypeManager->getDefinition($entity_type_id)->getKey('bundle') => $bundle_id, ]); + if ($entity instanceof EntityPublishedInterface) { + $entity->setUnpublished(); + } $entity->save(); $entity = $this->reloadEntity($entity); $this->assertEquals('draft', $entity->moderation_state->value); diff --git a/core/modules/content_moderation/tests/src/Kernel/InitialStateTest.php b/core/modules/content_moderation/tests/src/Kernel/InitialStateTest.php new file mode 100644 index 000000000000..0150d3c6e5f5 --- /dev/null +++ b/core/modules/content_moderation/tests/src/Kernel/InitialStateTest.php @@ -0,0 +1,82 @@ +<?php + +namespace Drupal\Tests\content_moderation\Kernel; + +use Drupal\entity_test\Entity\EntityTestRev; +use Drupal\KernelTests\KernelTestBase; +use Drupal\node\Entity\Node; +use Drupal\node\Entity\NodeType; +use Drupal\workflows\Entity\Workflow; + +/** + * Tests the correct initial states are set on install. + * + * @group content_moderation + */ +class InitialStateTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = [ + 'entity_test', + 'node', + 'user', + 'system', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->installSchema('node', 'node_access'); + $this->installEntitySchema('node'); + $this->installEntitySchema('user'); + $this->installEntitySchema('entity_test_rev'); + } + + /** + * Tests the correct initial state. + */ + public function testInitialState() { + $node_type = NodeType::create([ + 'type' => 'example', + ]); + $node_type->save(); + + // Test with an entity type that implements EntityPublishedInterface. + $unpublished_node = Node::create([ + 'type' => 'example', + 'title' => 'Unpublished node', + 'status' => 0, + ]); + $unpublished_node->save(); + + $published_node = Node::create([ + 'type' => 'example', + 'title' => 'Published node', + 'status' => 1, + ]); + $published_node->save(); + + // Test with an entity type that doesn't implement EntityPublishedInterface. + $entity_test = EntityTestRev::create(); + $entity_test->save(); + + \Drupal::service('module_installer')->install(['content_moderation'], TRUE); + $workflow = Workflow::load('editorial'); + $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example'); + $workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev'); + $workflow->save(); + + $loaded_unpublished_node = Node::load($unpublished_node->id()); + $loaded_published_node = Node::load($published_node->id()); + $loaded_entity_test = EntityTestRev::load($entity_test->id()); + $this->assertEquals('draft', $loaded_unpublished_node->moderation_state->value); + $this->assertEquals('published', $loaded_published_node->moderation_state->value); + $this->assertEquals('draft', $loaded_entity_test->moderation_state->value); + } + +} diff --git a/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php b/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php index 3f984da45524..7e9a75c3f412 100644 --- a/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php +++ b/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php @@ -64,7 +64,7 @@ protected function setUp() { * Test the field item list when accessing an index. */ public function testArrayIndex() { - $this->assertEquals('draft', $this->testNode->moderation_state[0]->value); + $this->assertEquals('published', $this->testNode->moderation_state[0]->value); } /** @@ -75,7 +75,7 @@ public function testArrayIteration() { foreach ($this->testNode->moderation_state as $item) { $states[] = $item->value; } - $this->assertEquals(['draft'], $states); + $this->assertEquals(['published'], $states); } } diff --git a/core/modules/workflows/src/Entity/Workflow.php b/core/modules/workflows/src/Entity/Workflow.php index c6b1ce6a4358..51b8d174f7ea 100644 --- a/core/modules/workflows/src/Entity/Workflow.php +++ b/core/modules/workflows/src/Entity/Workflow.php @@ -243,14 +243,6 @@ public function deleteState($state_id) { return $this; } - /** - * {@inheritdoc} - */ - public function getInitialState() { - $ordered_states = $this->getStates(); - return reset($ordered_states); - } - /** * {@inheritdoc} */ diff --git a/core/modules/workflows/src/Plugin/WorkflowTypeBase.php b/core/modules/workflows/src/Plugin/WorkflowTypeBase.php index 59c6b961371b..e87e4d79452a 100644 --- a/core/modules/workflows/src/Plugin/WorkflowTypeBase.php +++ b/core/modules/workflows/src/Plugin/WorkflowTypeBase.php @@ -145,4 +145,12 @@ public function onDependencyRemoval(array $dependencies) { return FALSE; } + /** + * {@inheritdoc} + */ + public function getInitialState(WorkflowInterface $workflow) { + $ordered_states = $workflow->getStates(); + return reset($ordered_states); + } + } diff --git a/core/modules/workflows/src/WorkflowInterface.php b/core/modules/workflows/src/WorkflowInterface.php index d014ddb781de..d156918a6f18 100644 --- a/core/modules/workflows/src/WorkflowInterface.php +++ b/core/modules/workflows/src/WorkflowInterface.php @@ -105,14 +105,6 @@ public function setStateWeight($state_id, $weight); */ public function deleteState($state_id); - /** - * Gets the initial state for the workflow. - * - * @return \Drupal\workflows\StateInterface - * The initial state. - */ - public function getInitialState(); - /** * Adds a transition to the workflow. * diff --git a/core/modules/workflows/src/WorkflowTypeInterface.php b/core/modules/workflows/src/WorkflowTypeInterface.php index 0fe668547ce8..2412bf99f438 100644 --- a/core/modules/workflows/src/WorkflowTypeInterface.php +++ b/core/modules/workflows/src/WorkflowTypeInterface.php @@ -93,6 +93,17 @@ public function decorateTransition(TransitionInterface $transition); */ public function deleteTransition($transition_id); + /** + * Gets the initial state for the workflow. + * + * @param \Drupal\workflows\WorkflowInterface $workflow + * The workflow entity. + * + * @return \Drupal\workflows\StateInterface + * The initial state. + */ + public function getInitialState(WorkflowInterface $workflow); + /** * Builds a form to be added to the Workflow state edit form. * diff --git a/core/modules/workflows/tests/src/Functional/WorkflowUiTest.php b/core/modules/workflows/tests/src/Functional/WorkflowUiTest.php index 3014dd739750..209e9865b5f5 100644 --- a/core/modules/workflows/tests/src/Functional/WorkflowUiTest.php +++ b/core/modules/workflows/tests/src/Functional/WorkflowUiTest.php @@ -170,11 +170,11 @@ public function testWorkflowCreation() { // Ensure that weight changes the state ordering. $workflow = $workflow_storage->loadUnchanged('test'); - $this->assertEquals('published', $workflow->getInitialState()->id()); + $this->assertEquals('published', $workflow->getTypePlugin()->getInitialState($workflow)->id()); $this->drupalGet('admin/config/workflow/workflows/manage/test'); $this->submitForm(['states[draft][weight]' => '-1'], 'Save'); $workflow = $workflow_storage->loadUnchanged('test'); - $this->assertEquals('draft', $workflow->getInitialState()->id()); + $this->assertEquals('draft', $workflow->getTypePlugin()->getInitialState($workflow)->id()); // Verify that we are still on the workflow edit page. $this->assertSession()->addressEquals('admin/config/workflow/workflows/manage/test'); diff --git a/core/modules/workflows/tests/src/Unit/WorkflowTest.php b/core/modules/workflows/tests/src/Unit/WorkflowTest.php index e2a7401cec11..51cb91207007 100644 --- a/core/modules/workflows/tests/src/Unit/WorkflowTest.php +++ b/core/modules/workflows/tests/src/Unit/WorkflowTest.php @@ -263,25 +263,6 @@ public function testDeleteOnlyStateException() { $workflow->deleteState('draft'); } - /** - * @covers ::getInitialState - */ - public function testGetInitialState() { - $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow'); - - // By default states are ordered in the order added. - $workflow - ->addState('draft', 'Draft') - ->addState('published', 'Published') - ->addState('archived', 'Archived'); - - $this->assertEquals('draft', $workflow->getInitialState()->id()); - - // Make published the first state. - $workflow->setStateWeight('published', -1); - $this->assertEquals('published', $workflow->getInitialState()->id()); - } - /** * @covers ::addTransition * @covers ::hasTransition -- GitLab