diff --git a/core/modules/content_moderation/content_moderation.module b/core/modules/content_moderation/content_moderation.module index 3481c243e1..347cbaf8aa 100644 --- a/core/modules/content_moderation/content_moderation.module +++ b/core/modules/content_moderation/content_moderation.module @@ -207,6 +207,15 @@ function content_moderation_entity_access(EntityInterface $entity, $operation, A } } + // Do not allow users to delete the state that is configured as the default + // state for the workflow. + if ($entity instanceof WorkflowInterface) { + $configuration = $entity->getTypePlugin()->getConfiguration(); + if (!empty($configuration['default_moderation_state']) && $operation === sprintf('delete-state:%s', $configuration['default_moderation_state'])) { + return AccessResult::forbidden()->addCacheableDependency($entity); + } + } + return $access_result; } diff --git a/core/modules/content_moderation/tests/src/Functional/DefaultModerationStateTest.php b/core/modules/content_moderation/tests/src/Functional/DefaultModerationStateTest.php new file mode 100644 index 0000000000..f5f6a5c004 --- /dev/null +++ b/core/modules/content_moderation/tests/src/Functional/DefaultModerationStateTest.php @@ -0,0 +1,56 @@ +drupalLogin($this->adminUser); + $this->createContentTypeFromUi('Moderated content', 'moderated_content', TRUE); + $this->grantUserPermissionToCreateContentOfType($this->adminUser, 'moderated_content'); + } + + /** + * Test a workflow with a default moderation state set. + */ + public function testPublishedDefaultState() { + // Set the default moderation state to be "published". + $this->drupalPostForm('admin/config/workflow/workflows/manage/' . $this->workflow->id(), [ + 'type_settings[workflow_settings][default_moderation_state]' => 'published', + ], 'Save'); + + $this->drupalGet('node/add/moderated_content'); + $this->assertEquals('published', $this->assertSession()->selectExists('moderation_state[0][state]')->getValue()); + $this->submitForm([ + 'title[0][value]' => 'moderated content', + ], 'Save'); + + $node = $this->getNodeByTitle('moderated content'); + $this->assertEquals('published', $node->moderation_state->value); + } + + /** + * Test access to deleting the default state. + */ + public function testDeleteDefaultStateAccess() { + $this->drupalGet('admin/config/workflow/workflows/manage/editorial/state/archived/delete'); + $this->assertSession()->statusCodeEquals(200); + + $this->drupalPostForm('admin/config/workflow/workflows/manage/' . $this->workflow->id(), [ + 'type_settings[workflow_settings][default_moderation_state]' => 'archived', + ], 'Save'); + + $this->drupalGet('admin/config/workflow/workflows/manage/editorial/state/archived/delete'); + $this->assertSession()->statusCodeEquals(403); + } + +} diff --git a/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php b/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php index af0bb4fd7d..844e77d930 100644 --- a/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php +++ b/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php @@ -6,6 +6,7 @@ use Drupal\node\Entity\Node; use Drupal\node\Entity\NodeType; use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait; +use Drupal\workflows\Entity\Workflow; /** * @coversDefaultClass \Drupal\content_moderation\Plugin\Field\ModerationStateFieldItemList @@ -281,4 +282,36 @@ public function moderatedEntityWithExistingIdTestCases() { ]; } + /** + * Test customising the default moderation state. + */ + public function testWorkflowCustomisedInitialState() { + $workflow = Workflow::load('editorial'); + $configuration = $workflow->getTypePlugin()->getConfiguration(); + + // Test a node for a workflow that hasn't been updated to include the + // 'default_moderation_state' setting. We must be backwards compatible with + // configuration that was exported before this change was introduced. + $this->assertFalse(isset($configuration['default_moderation_state'])); + $legacy_configuration_node = Node::create([ + 'title' => 'Test title', + 'type' => 'example', + ]); + $this->assertEquals('draft', $legacy_configuration_node->moderation_state->value); + $legacy_configuration_node->save(); + $this->assertEquals('draft', $legacy_configuration_node->moderation_state->value); + + $configuration['default_moderation_state'] = 'published'; + $workflow->getTypePlugin()->setConfiguration($configuration); + $workflow->save(); + + $updated_default_node = Node::create([ + 'title' => 'Test title', + 'type' => 'example', + ]); + $this->assertEquals('published', $updated_default_node->moderation_state->value); + $legacy_configuration_node->save(); + $this->assertEquals('published', $updated_default_node->moderation_state->value); + } + }