diff --git a/core/modules/content_moderation/src/EntityTypeInfo.php b/core/modules/content_moderation/src/EntityTypeInfo.php
index 487cac057f..fcd37bbc96 100644
--- a/core/modules/content_moderation/src/EntityTypeInfo.php
+++ b/core/modules/content_moderation/src/EntityTypeInfo.php
@@ -320,6 +320,7 @@ public function formAlter(array &$form, FormStateInterface $form_state, $form_id
$full_message = $this->t('Unable to save this @type_label. Publish or delete the latest draft revision to allow all workflow transitions.', $args);
drupal_set_message($full_message, 'error');
+ $form['moderation_state']['#access'] = FALSE;
$form['actions']['#access'] = FALSE;
$form['invalid_transitions'] = [
'label' => [
diff --git a/core/modules/content_moderation/tests/src/Functional/ModerationFormTest.php b/core/modules/content_moderation/tests/src/Functional/ModerationFormTest.php
index d385a86791..a7d73308b2 100644
--- a/core/modules/content_moderation/tests/src/Functional/ModerationFormTest.php
+++ b/core/modules/content_moderation/tests/src/Functional/ModerationFormTest.php
@@ -250,7 +250,8 @@ public function testContentTranslationNodeForm() {
$this->drupalPostForm('node/add/moderated_content', [
'title[0][value]' => 'Some moderated content',
'body[0][value]' => 'First version of the content.',
- ], t('Save and Create New Draft'));
+ 'moderation_state[0][state]' => 'draft',
+ ], t('Save'));
$this->assertTrue($this->xpath('//ul[@class="entity-moderation-form"]'));
$node = $this->drupalGetNodeByTitle('Some moderated content');
@@ -266,12 +267,13 @@ public function testContentTranslationNodeForm() {
// Add french translation (revision 2).
$this->drupalGet($translate_path);
- $this->assertTrue($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertFalse($this->xpath('//input[@value="Save and Archive (this translation)"]'));
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'draft');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'published');
+ $this->assertSession()->optionNotExists('moderation_state[0][state]', 'archived');
$this->drupalPostForm(NULL, [
'body[0][value]' => 'Second version of the content.',
- ], t('Save and Publish (this translation)'));
+ 'moderation_state[0][state]' => 'published',
+ ], t('Save (this translation)'));
$this->drupalGet($latest_version_path, ['language' => $french]);
$this->assertSession()->statusCodeEquals('403');
@@ -279,21 +281,20 @@ public function testContentTranslationNodeForm() {
// Add french forward revision (revision 3).
$this->drupalGet($edit_path, ['language' => $french]);
- $this->assertTrue($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Archive (this translation)"]'));
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'draft');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'published');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'archived');
$this->drupalPostForm(NULL, [
'body[0][value]' => 'Third version of the content.',
- ], t('Save and Create New Draft (this translation)'));
+ 'moderation_state[0][state]' => 'draft',
+ ], t('Save (this translation)'));
$this->drupalGet($latest_version_path, ['language' => $french]);
$this->assertTrue($this->xpath('//ul[@class="entity-moderation-form"]'));
// It should not be possible to add a new english revision.
$this->drupalGet($edit_path);
- $this->assertFalse($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertFalse($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertFalse($this->xpath('//input[@value="Save and Archive (this translation)"]'));
+ $this->assertSession()->fieldNotExists('moderation_state[0][state]');
$this->assertSession()->pageTextContains('Unable to save this Moderated content.');
$this->clickLink('Publish');
@@ -308,51 +309,52 @@ public function testContentTranslationNodeForm() {
// Publish the french forward revision (revision 4).
$this->drupalGet($edit_path, ['language' => $french]);
- $this->assertTrue($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertFalse($this->xpath('//input[@value="Save and Archive (this translation)"]'));
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'draft');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'published');
+ $this->assertSession()->optionNotExists('moderation_state[0][state]', 'archived');
$this->drupalPostForm(NULL, [
'body[0][value]' => 'Fifth version of the content.',
- ], t('Save and Publish (this translation)'));
+ 'moderation_state[0][state]' => 'published',
+ ], t('Save (this translation)'));
$this->drupalGet($latest_version_path, ['language' => $french]);
$this->assertFalse($this->xpath('//ul[@class="entity-moderation-form"]'));
// Now we can publish the english (revision 5).
$this->drupalGet($edit_path);
- $this->assertTrue($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertFalse($this->xpath('//input[@value="Save and Archive (this translation)"]'));
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'draft');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'published');
+ $this->assertSession()->optionNotExists('moderation_state[0][state]', 'archived');
$this->drupalPostForm(NULL, [
'body[0][value]' => 'Sixth version of the content.',
- ], t('Save and Publish (this translation)'));
+ 'moderation_state[0][state]' => 'published',
+ ], t('Save (this translation)'));
$this->drupalGet($latest_version_path);
$this->assertFalse($this->xpath('//ul[@class="entity-moderation-form"]'));
// Make sure we're allowed to create a forward french revision.
$this->drupalGet($edit_path, ['language' => $french]);
- $this->assertTrue($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Archive (this translation)"]'));
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'draft');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'published');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'archived');
// Add a english forward revision (revision 6).
$this->drupalGet($edit_path);
- $this->assertTrue($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Archive (this translation)"]'));
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'draft');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'published');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'archived');
$this->drupalPostForm(NULL, [
'body[0][value]' => 'Seventh version of the content.',
- ], t('Save and Create New Draft (this translation)'));
+ 'moderation_state[0][state]' => 'draft',
+ ], t('Save (this translation)'));
$this->drupalGet($latest_version_path);
$this->assertTrue($this->xpath('//ul[@class="entity-moderation-form"]'));
// Make sure we're not allowed to create a forward french revision.
$this->drupalGet($edit_path, ['language' => $french]);
- $this->assertFalse($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertFalse($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertFalse($this->xpath('//input[@value="Save and Archive (this translation)"]'));
+ $this->assertSession()->fieldNotExists('moderation_state[0][state]');
$this->assertSession()->pageTextContains('Unable to save this Moderated content.');
$this->drupalGet($latest_version_path, ['language' => $french]);
@@ -360,33 +362,35 @@ public function testContentTranslationNodeForm() {
// We should be able to publish the english forward revision (revision 7)
$this->drupalGet($edit_path);
- $this->assertTrue($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertFalse($this->xpath('//input[@value="Save and Archive (this translation)"]'));
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'draft');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'published');
+ $this->assertSession()->optionNotExists('moderation_state[0][state]', 'archived');
$this->drupalPostForm(NULL, [
'body[0][value]' => 'Eighth version of the content.',
- ], t('Save and Publish (this translation)'));
+ 'moderation_state[0][state]' => 'published',
+ ], t('Save (this translation)'));
$this->drupalGet($latest_version_path);
$this->assertFalse($this->xpath('//ul[@class="entity-moderation-form"]'));
// Make sure we're allowed to create a forward french revision.
$this->drupalGet($edit_path, ['language' => $french]);
- $this->assertTrue($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Archive (this translation)"]'));
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'draft');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'published');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'archived');
// Make sure we're allowed to create a forward english revision.
$this->drupalGet($edit_path);
- $this->assertTrue($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Archive (this translation)"]'));
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'draft');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'published');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'archived');
// Create new moderated content. (revision 1).
$this->drupalPostForm('node/add/moderated_content', [
'title[0][value]' => 'Second moderated content',
'body[0][value]' => 'First version of the content.',
- ], t('Save and Publish'));
+ 'moderation_state[0][state]' => 'published',
+ ], t('Save'));
$node = $this->drupalGetNodeByTitle('Second moderated content');
$this->assertTrue($node->language(), 'en');
@@ -395,24 +399,24 @@ public function testContentTranslationNodeForm() {
// Add a forward revision (revision 2).
$this->drupalGet($edit_path);
- $this->assertTrue($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Archive (this translation)"]'));
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'draft');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'published');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'archived');
$this->drupalPostForm(NULL, [
'body[0][value]' => 'Second version of the content.',
- ], t('Save and Create New Draft (this translation)'));
+ 'moderation_state[0][state]' => 'draft',
+ ], t('Save'));
// It shouldn't be possible to translate as we have a forward revision.
$this->drupalGet($translate_path);
- $this->assertFalse($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertFalse($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertFalse($this->xpath('//input[@value="Save and Archive (this translation)"]'));
+ $this->assertSession()->fieldNotExists('moderation_state[0][state]');
$this->assertSession()->pageTextContains('Unable to save this Moderated content.');
// Create new moderated content (revision 1).
$this->drupalPostForm('node/add/moderated_content', [
'title[0][value]' => 'Third moderated content',
- ], t('Save and Publish'));
+ 'moderation_state[0][state]' => 'published',
+ ], t('Save'));
$node = $this->drupalGetNodeByTitle('Third moderated content');
$this->assertTrue($node->language(), 'en');
@@ -421,38 +425,44 @@ public function testContentTranslationNodeForm() {
// Translate it, without updating data (revision 2).
$this->drupalGet($translate_path);
- $this->assertTrue($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Archive (this translation)"]'));
- $this->drupalPostForm(NULL, [], t('Save and Create New Draft (this translation)'));
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'draft');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'published');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'archived');
+ $this->drupalPostForm(NULL, [
+ 'moderation_state[0][state]' => 'draft',
+ ], t('Save (this translation)'));
// Add another draft for the translation (revision 3).
$this->drupalGet($edit_path, ['language' => $french]);
- $this->assertTrue($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertFalse($this->xpath('//input[@value="Save and Archive (this translation)"]'));
- $this->drupalPostForm(NULL, [], t('Save and Create New Draft (this translation)'));
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'draft');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'published');
+ $this->assertSession()->optionNotExists('moderation_state[0][state]', 'archived');
+ $this->drupalPostForm(NULL, [
+ 'moderation_state[0][state]' => 'draft',
+ ], t('Save (this translation)'));
// Editing the original translation should not be possible.
$this->drupalGet($edit_path);
- $this->assertFalse($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertFalse($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertFalse($this->xpath('//input[@value="Save and Archive (this translation)"]'));
+ $this->assertSession()->fieldNotExists('moderation_state[0][state]');
$this->assertSession()->pageTextContains('Unable to save this Moderated content.');
// Updating and publishing the french translation is still possible.
$this->drupalGet($edit_path, ['language' => $french]);
- $this->assertTrue($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertFalse($this->xpath('//input[@value="Save and Archive (this translation)"]'));
- $this->drupalPostForm(NULL, [], t('Save and Publish (this translation)'));
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'draft');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'published');
+ $this->assertSession()->optionNotExists('moderation_state[0][state]', 'archived');
+ $this->drupalPostForm(NULL, [
+ 'moderation_state[0][state]' => 'published',
+ ], t('Save (this translation)'));
// Now the french translation is published, an english draft can be added.
$this->drupalGet($edit_path);
- $this->assertTrue($this->xpath('//input[@value="Save and Create New Draft (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Publish (this translation)"]'));
- $this->assertTrue($this->xpath('//input[@value="Save and Archive (this translation)"]'));
- $this->drupalPostForm(NULL, [], t('Save and Create New Draft (this translation)'));
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'draft');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'published');
+ $this->assertSession()->optionExists('moderation_state[0][state]', 'archived');
+ $this->drupalPostForm(NULL, [
+ 'moderation_state[0][state]' => 'draft',
+ ], t('Save (this translation)'));
}
}
diff --git a/core/modules/content_moderation/tests/src/Functional/ModerationLocaleTest.php b/core/modules/content_moderation/tests/src/Functional/ModerationLocaleTest.php
index 88ba3a2f9a..3104450fce 100644
--- a/core/modules/content_moderation/tests/src/Functional/ModerationLocaleTest.php
+++ b/core/modules/content_moderation/tests/src/Functional/ModerationLocaleTest.php
@@ -156,7 +156,9 @@ public function testTranslateModeratedContent() {
$this->assertEqual($french_node->getTitle(), 'Translated node', 'The default revision of the published translation remains the same.');
// Publish the French article before testing the archive transition.
- $this->drupalPostForm('fr/node/' . $english_node->id() . '/edit', [], t('Save and Publish (this translation)'));
+ $this->drupalPostForm('fr/node/' . $english_node->id() . '/edit', [
+ 'moderation_state[0][state]' => 'published',
+ ], t('Save (this translation)'));
$this->assertText(t('Article New draft of translated node has been updated.'));
$english_node = $this->drupalGetNodeByTitle('Another node', TRUE);
$french_node = $english_node->getTranslation('fr');
diff --git a/core/modules/content_moderation/tests/src/Functional/ModerationStateNodeTest.php b/core/modules/content_moderation/tests/src/Functional/ModerationStateNodeTest.php
index 3218241be9..82695bdf49 100644
--- a/core/modules/content_moderation/tests/src/Functional/ModerationStateNodeTest.php
+++ b/core/modules/content_moderation/tests/src/Functional/ModerationStateNodeTest.php
@@ -144,4 +144,45 @@ public function testPagers() {
$this->assertEqual(0, $query['page']);
}
+ /**
+ * Tests the workflow is a user has no Content Moderation permissions.
+ */
+ public function testNoContentModerationPermissions() {
+ // Create a user with quite advanced node permissions but no content
+ // moderation permissions.
+ $limited_user = $this->createUser([
+ 'administer nodes',
+ 'bypass node access',
+ ]);
+ $this->drupalLogin($limited_user);
+
+ // Check the user can add content, but can't see the moderation state
+ // select.
+ $this->drupalGet('node/add/moderated_content');
+ $this->assertSession()->statusCodeEquals(200);
+ $this->assertFalse($this->xpath('//select[@name="moderation_state[0][state]"]'));
+ $this->drupalPostForm(NULL, [
+ 'title[0][value]' => 'moderated content',
+ ], t('Save'));
+
+ // Manually move the content to archived because the user doesn't have
+ // permission to do this.
+ $node = $this->getNodeByTitle('moderated content');
+ $node->moderation_state->value = 'archived';
+ $node->save();
+
+ // Check the user can see the current state but not the select.
+ $this->drupalGet('node/' . $node->id() . '/edit');
+ $this->assertSession()->statusCodeEquals(200);
+ $this->assertSession()->pageTextContains('Archived');
+ $this->assertTrue($this->xpath('//label[@for="edit-moderation-state-0-current"]'));
+ $this->assertFalse($this->xpath('//select[@name="moderation_state[0][state]"]'));
+ $this->drupalPostForm(NULL, [], t('Save'));
+
+ // When saving they should still be on the edit form, and see the validation
+ // error message.
+ $this->assertSession()->pageTextContains('Edit Moderated content moderated content');
+ $this->assertSession()->pageTextContains('Invalid state transition from Archived to Archived');
+ }
+
}