Commit 2d5e8d11 authored by larowlan's avatar larowlan

Issue #2753717 by timmillwood, amateescu, alexpott, mtodor, boaloysius, Jo...

Issue #2753717 by timmillwood, amateescu, alexpott, mtodor, boaloysius, Jo Fitzgerald, phenaproxima, plach, gaurav.kapoor, tkoleary, yoroy, larowlan, karlos007, Berdir, Sam152: Add select field to choose moderation state on entity forms
parent 2983a0d4
......@@ -43,10 +43,10 @@ protected function setUp() {
*/
public function testBookWithPendingRevisions() {
// Create two books.
$book_1_nodes = $this->createBook(t('Save and Publish'));
$book_1_nodes = $this->createBook(['moderation_state[0][state]' => 'published']);
$book_1 = $this->book;
$this->createBook(t('Save and Publish'));
$this->createBook(['moderation_state[0][state]' => 'published']);
$book_2 = $this->book;
$this->drupalLogin($this->bookAuthor);
......@@ -58,21 +58,37 @@ public function testBookWithPendingRevisions() {
// Create a new book page without actually attaching it to a book and create
// a draft.
$edit = ['title[0][value]' => $this->randomString()];
$this->drupalPostForm('node/add/book', $edit, t('Save and Publish'));
$edit = [
'title[0][value]' => $this->randomString(),
'moderation_state[0][state]' => 'published',
];
$this->drupalPostForm('node/add/book', $edit, t('Save'));
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
$this->assertTrue($node);
$this->drupalPostForm('node/' . $node->id() . '/edit', [], t('Save and Create New Draft'));
$edit = [
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
$this->assertSession()->pageTextNotContains('You can only change the book outline for the published version of this content.');
// Create a book draft with no changes, then publish it.
$this->drupalPostForm('node/' . $book_1->id() . '/edit', [], t('Save and Create New Draft'));
$edit = [
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm('node/' . $book_1->id() . '/edit', $edit, t('Save'));
$this->assertSession()->pageTextNotContains('You can only change the book outline for the published version of this content.');
$this->drupalPostForm('node/' . $book_1->id() . '/edit', [], t('Save and Publish'));
$edit = [
'moderation_state[0][state]' => 'published',
];
$this->drupalPostForm('node/' . $book_1->id() . '/edit', $edit, t('Save'));
// Try to move Node 2 to a different parent.
$edit['book[pid]'] = $book_1_nodes[3]->id();
$this->drupalPostForm('node/' . $book_1_nodes[1]->id() . '/edit', $edit, t('Save and Create New Draft'));
$edit = [
'book[pid]' => $book_1_nodes[3]->id(),
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm('node/' . $book_1_nodes[1]->id() . '/edit', $edit, t('Save'));
$this->assertSession()->pageTextContains('You can only change the book outline for the published version of this content.');
......@@ -82,8 +98,11 @@ public function testBookWithPendingRevisions() {
$this->checkBookNode($book_1_nodes[0], [$book_1_nodes[1], $book_1_nodes[2]], $book_1, $book_1, $book_1_nodes[1], [$book_1]);
// Try to move Node 2 to a different book.
$edit['book[bid]'] = $book_2->id();
$this->drupalPostForm('node/' . $book_1_nodes[1]->id() . '/edit', $edit, t('Save and Create New Draft'));
$edit = [
'book[bid]' => $book_2->id(),
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm('node/' . $book_1_nodes[1]->id() . '/edit', $edit, t('Save'));
$this->assertSession()->pageTextContains('You can only change the book outline for the published version of this content.');
......@@ -93,8 +112,11 @@ public function testBookWithPendingRevisions() {
$this->checkBookNode($book_1_nodes[0], [$book_1_nodes[1], $book_1_nodes[2]], $book_1, $book_1, $book_1_nodes[1], [$book_1]);
// Try to change the weight of Node 2.
$edit['book[weight]'] = 2;
$this->drupalPostForm('node/' . $book_1_nodes[1]->id() . '/edit', $edit, t('Save and Create New Draft'));
$edit = [
'book[weight]' => 2,
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm('node/' . $book_1_nodes[1]->id() . '/edit', $edit, t('Save'));
$this->assertSession()->pageTextContains('You can only change the book outline for the published version of this content.');
......@@ -105,7 +127,10 @@ public function testBookWithPendingRevisions() {
// Save a new draft revision for the node without any changes and check that
// the error message is not displayed.
$this->drupalPostForm('node/' . $book_1_nodes[1]->id() . '/edit', [], t('Save and Create New Draft'));
$edit = [
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm('node/' . $book_1_nodes[1]->id() . '/edit', $edit, t('Save'));
$this->assertSession()->pageTextNotContains('You can only change the book outline for the published version of this content.');
}
......
......@@ -27,17 +27,18 @@ trait BookTestTrait {
/**
* Creates a new book with a page hierarchy.
*
* @param string $submit
* (optional) Value of the submit button whose click is to be emulated.
* Defaults to 'Save'.
* @param array $edit
* (optional) Field data in an associative array. Changes the current input
* fields (where possible) to the values indicated. Defaults to an empty
* array.
*
* @return \Drupal\node\NodeInterface[]
*/
public function createBook($submit = NULL) {
public function createBook($edit = []) {
// Create new book.
$this->drupalLogin($this->bookAuthor);
$this->book = $this->createBookNode('new', NULL, $submit);
$this->book = $this->createBookNode('new', NULL, $edit);
$book = $this->book;
/*
......@@ -50,11 +51,11 @@ public function createBook($submit = NULL) {
* |- Node 4
*/
$nodes = [];
$nodes[] = $this->createBookNode($book->id(), NULL, $submit); // Node 0.
$nodes[] = $this->createBookNode($book->id(), $nodes[0]->book['nid'], $submit); // Node 1.
$nodes[] = $this->createBookNode($book->id(), $nodes[0]->book['nid'], $submit); // Node 2.
$nodes[] = $this->createBookNode($book->id(), NULL, $submit); // Node 3.
$nodes[] = $this->createBookNode($book->id(), NULL, $submit); // Node 4.
$nodes[] = $this->createBookNode($book->id(), NULL, $edit); // Node 0.
$nodes[] = $this->createBookNode($book->id(), $nodes[0]->book['nid'], $edit); // Node 1.
$nodes[] = $this->createBookNode($book->id(), $nodes[0]->book['nid'], $edit); // Node 2.
$nodes[] = $this->createBookNode($book->id(), NULL, $edit); // Node 3.
$nodes[] = $this->createBookNode($book->id(), NULL, $edit); // Node 4.
$this->drupalLogout();
......@@ -167,21 +168,19 @@ public function generateOutlinePattern($nodes) {
* A book node ID or set to 'new' to create a new book.
* @param int|null $parent
* (optional) Parent book reference ID. Defaults to NULL.
* @param string $submit
* (optional) Value of the submit button whose click is to be emulated.
* Defaults to 'Save'.
* @param array $edit
* (optional) Field data in an associative array. Changes the current input
* fields (where possible) to the values indicated. Defaults to an empty
* array.
*
* @return \Drupal\node\NodeInterface
* The created node.
*/
public function createBookNode($book_nid, $parent = NULL, $submit = NULL) {
public function createBookNode($book_nid, $parent = NULL, $edit = []) {
// $number does not use drupal_static as it should not be reset
// since it uniquely identifies each call to createBookNode().
static $number = 0; // Used to ensure that when sorted nodes stay in same order.
$submit = $submit ?: t('Save');
$edit = [];
$edit['title[0][value]'] = str_pad($number, 2, '0', STR_PAD_LEFT) . ' - SimpleTest test node ' . $this->randomMachineName(10);
$edit['body[0][value]'] = 'SimpleTest test body ' . $this->randomMachineName(32) . ' ' . $this->randomMachineName(32);
$edit['book[bid]'] = $book_nid;
......@@ -190,13 +189,13 @@ public function createBookNode($book_nid, $parent = NULL, $submit = NULL) {
$this->drupalPostForm('node/add/book', $edit, t('Change book (update list of parents)'));
$edit['book[pid]'] = $parent;
$this->drupalPostForm(NULL, $edit, $submit);
$this->drupalPostForm(NULL, $edit, t('Save'));
// Make sure the parent was flagged as having children.
$parent_node = \Drupal::entityManager()->getStorage('node')->loadUnchanged($parent);
$this->assertFalse(empty($parent_node->book['has_children']), 'Parent node is marked as having children');
}
else {
$this->drupalPostForm('node/add/book', $edit, $submit);
$this->drupalPostForm('node/add/book', $edit, t('Save'));
}
// Check to make sure the book node was created.
......
......@@ -261,11 +261,11 @@ public function entityBaseFieldInfo(EntityTypeInterface $entity_type) {
])
->setDisplayOptions('form', [
'type' => 'moderation_state_default',
'weight' => 5,
'weight' => 100,
'settings' => [],
])
->addConstraint('ModerationState', [])
->setDisplayConfigurable('form', FALSE)
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', FALSE)
->setReadOnly(FALSE)
->setTranslatable(TRUE);
......@@ -322,6 +322,7 @@ public function formAlter(array &$form, FormStateInterface $form_state, $form_id
$full_message = $this->t('Unable to save this @type_label. <a href="@latest_revision_edit_url">Publish</a> or <a href="@latest_revision_delete_url">delete</a> the latest 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' => [
......@@ -339,13 +340,24 @@ public function formAlter(array &$form, FormStateInterface $form_state, $form_id
];
if ($form['footer']) {
$form['footer']['invalid_transitions'] = $form['invalid_transitions'];
unset($form['invalid_transitions']);
$form['invalid_transitions']['#group'] = 'footer';
}
}
// Submit handler to redirect to the latest version, if available.
$form['actions']['submit']['#submit'][] = [EntityTypeInfo::class, 'bundleFormRedirect'];
// Move the 'moderation_state' field widget to the footer region, if
// available.
if (isset($form['footer'])) {
$form['moderation_state']['#group'] = 'footer';
}
// Duplicate the label of the current moderation state to the meta
// region, if available.
if (isset($form['meta']['published'])) {
$form['meta']['published']['#markup'] = $form['moderation_state']['widget'][0]['current']['#markup'];
}
}
}
}
......
......@@ -88,7 +88,7 @@ public function buildForm(array $form, FormStateInterface $form_state, ContentEn
if ($current_state) {
$form['current'] = [
'#type' => 'item',
'#title' => $this->t('Status'),
'#title' => $this->t('Moderation state'),
'#markup' => $workflow->getTypePlugin()->getState($current_state)->label(),
];
}
......@@ -98,7 +98,7 @@ public function buildForm(array $form, FormStateInterface $form_state, ContentEn
$form['new_state'] = [
'#type' => 'select',
'#title' => $this->t('Moderate'),
'#title' => $this->t('Change to'),
'#options' => $target_states,
];
......
......@@ -2,7 +2,7 @@
namespace Drupal\content_moderation\Plugin\Field\FieldWidget;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\content_moderation\Plugin\Field\ModerationStateFieldItemList;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
......@@ -75,7 +75,7 @@ class ModerationStateWidget extends OptionsSelectWidget implements ContainerFact
* @param \Drupal\content_moderation\ModerationInformation $moderation_information
* Moderation information service.
* @param \Drupal\content_moderation\StateTransitionValidation $validator
* Moderation state transition validation service
* Moderation state transition validation service.
*/
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, AccountInterface $current_user, EntityTypeManagerInterface $entity_type_manager, ModerationInformation $moderation_information, StateTransitionValidation $validator) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
......@@ -106,7 +106,7 @@ public static function create(ContainerInterface $container, array $configuratio
* {@inheritdoc}
*/
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
/** @var ContentEntityInterface $entity */
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $items->getEntity();
/* @var \Drupal\Core\Config\Entity\ConfigEntityInterface $bundle_entity */
......@@ -121,95 +121,53 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
/** @var \Drupal\workflows\Transition[] $transitions */
$transitions = $this->validator->getValidTransitions($entity, $this->currentUser);
$target_states = [];
$transition_labels = [];
$default_value = NULL;
foreach ($transitions as $transition) {
$target_states[$transition->to()->id()] = $transition->label();
$transition_to_state = $transition->to();
$transition_labels[$transition_to_state->id()] = $transition_to_state->label();
}
// @todo https://www.drupal.org/node/2779933 write a test for this.
$element += [
'#access' => FALSE,
'#type' => 'select',
'#options' => $target_states,
'#default_value' => $default->id(),
'#published' => $default->isPublishedState(),
'#key_column' => $this->column,
'#type' => 'container',
'current' => [
'#type' => 'item',
'#title' => $this->t('Current state'),
'#markup' => $default->label(),
'#access' => !$entity->isNew(),
'#wrapper_attributes' => [
'class' => ['container-inline'],
],
],
'state' => [
'#type' => 'select',
'#title' => $entity->isNew() ? $this->t('Save as') : $this->t('Change to'),
'#key_column' => $this->column,
'#options' => $transition_labels,
'#default_value' => $default_value,
'#access' => !empty($transition_labels),
'#wrapper_attributes' => [
'class' => ['container-inline'],
],
],
];
$element['#element_validate'][] = [get_class($this), 'validateElement'];
// Use the dropbutton.
$element['#process'][] = [get_called_class(), 'processActions'];
return $element;
}
/**
* Entity builder updating the node moderation state with the submitted value.
*
* @param string $entity_type_id
* The entity type identifier.
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* The entity updated with the submitted values.
* @param array $form
* The complete form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public static function updateStatus($entity_type_id, ContentEntityInterface $entity, array $form, FormStateInterface $form_state) {
$element = $form_state->getTriggeringElement();
if (isset($element['#moderation_state'])) {
$entity->moderation_state->value = $element['#moderation_state'];
}
}
/**
* Process callback to alter action buttons.
* {@inheritdoc}
*/
public static function processActions($element, FormStateInterface $form_state, array &$form) {
// We'll steal most of the button configuration from the default submit
// button. However, NodeForm also hides that button for admins (as it adds
// its own, too), so we have to restore it.
$default_button = $form['actions']['submit'];
$default_button['#access'] = TRUE;
// Add a custom button for each transition we're allowing. The #dropbutton
// property tells FAPI to cluster them all together into a single widget.
$options = $element['#options'];
$entity = $form_state->getFormObject()->getEntity();
$translatable = !$entity->isNew() && $entity->isTranslatable();
foreach ($options as $id => $label) {
$button = [
'#dropbutton' => 'save',
'#moderation_state' => $id,
'#weight' => -10,
];
$button['#value'] = $translatable
? t('Save and @transition (this translation)', ['@transition' => $label])
: t('Save and @transition', ['@transition' => $label]);
$form['actions']['moderation_state_' . $id] = $button + $default_button;
}
// Hide the default buttons, including the specialty ones added by
// NodeForm.
foreach (['publish', 'unpublish', 'submit'] as $key) {
$form['actions'][$key]['#access'] = FALSE;
unset($form['actions'][$key]['#dropbutton']);
}
// Setup a callback to translate the button selection back into field
// widget, so that it will get saved properly.
$form['#entity_builders']['update_moderation_state'] = [get_called_class(), 'updateStatus'];
return $element;
public static function validateElement(array $element, FormStateInterface $form_state) {
$form_state->setValueForElement($element, [$element['state']['#key_column'] => $element['state']['#value']]);
}
/**
* {@inheritdoc}
*/
public static function isApplicable(FieldDefinitionInterface $field_definition) {
return $field_definition->getName() === 'moderation_state';
return is_a($field_definition->getClass(), ModerationStateFieldItemList::class, TRUE);
}
}
......@@ -122,19 +122,40 @@ protected function computeModerationFieldItemList() {
* {@inheritdoc}
*/
public function onChange($delta) {
$this->updateModeratedEntity($this->list[$delta]->value);
parent::onChange($delta);
}
/**
* {@inheritdoc}
*/
public function setValue($values, $notify = TRUE) {
parent::setValue($values, $notify);
if (isset($this->list[0])) {
$this->updateModeratedEntity($this->list[0]->value);
}
}
/**
* Updates the default revision flag and the publishing status of the entity.
*
* @param string $moderation_state_id
* The ID of the new moderation state.
*/
protected function updateModeratedEntity($moderation_state_id) {
$entity = $this->getEntity();
/** @var \Drupal\content_moderation\ModerationInformationInterface $content_moderation_info */
$content_moderation_info = \Drupal::service('content_moderation.moderation_information');
$workflow = $content_moderation_info->getWorkflowForEntity($entity);
$current_state_id = $this->list[0]->value;
// Change the entity's default revision flag and the publishing status only
// if the new workflow state is a valid one.
if ($workflow->getTypePlugin()->hasState($current_state_id)) {
if ($workflow->getTypePlugin()->hasState($moderation_state_id)) {
/** @var \Drupal\content_moderation\ContentModerationState $current_state */
$current_state = $workflow->getTypePlugin()->getState($current_state_id);
$current_state = $workflow->getTypePlugin()->getState($moderation_state_id);
// This entity is default if it is new, a new translation, the default
// revision state, or the default revision is not published.
......@@ -151,8 +172,6 @@ public function onChange($delta) {
$published_state ? $entity->setPublished() : $entity->setUnpublished();
}
}
parent::onChange($delta);
}
}
......@@ -53,8 +53,9 @@ public function testTranslateModeratedContent() {
$edit = [
'title[0][value]' => 'Published English node',
'langcode[0][value]' => 'en',
'moderation_state[0][state]' => 'published',
];
$this->drupalPostForm('node/add/article', $edit, t('Save and Publish'));
$this->drupalPostForm('node/add/article', $edit, t('Save'));
$this->assertText(t('Article Published English node has been created.'));
$english_node = $this->drupalGetNodeByTitle('Published English node');
......@@ -63,8 +64,9 @@ public function testTranslateModeratedContent() {
$this->clickLink(t('Add'));
$edit = [
'title[0][value]' => 'French node Draft',
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm(NULL, $edit, t('Save and Create New Draft (this translation)'));
$this->drupalPostForm(NULL, $edit, t('Save (this translation)'));
// Here the error has occurred "The website encountered an unexpected error.
// Please try again later."
// If the translation has got lost.
......@@ -74,8 +76,9 @@ public function testTranslateModeratedContent() {
$edit = [
'title[0][value]' => 'English node',
'langcode[0][value]' => 'en',
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm('node/add/article', $edit, t('Save and Create New Draft'));
$this->drupalPostForm('node/add/article', $edit, t('Save'));
$this->assertText(t('Article English node has been created.'));
$english_node = $this->drupalGetNodeByTitle('English node');
......@@ -84,14 +87,17 @@ public function testTranslateModeratedContent() {
$this->clickLink(t('Add'));
$edit = [
'title[0][value]' => 'French node',
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm(NULL, $edit, t('Save and Create New Draft (this translation)'));
$this->drupalPostForm(NULL, $edit, t('Save (this translation)'));
$this->assertText(t('Article French node has been updated.'));
$english_node = $this->drupalGetNodeByTitle('English node', TRUE);
// Publish the English article and check that the translation stays
// unpublished.
$this->drupalPostForm('node/' . $english_node->id() . '/edit', [], t('Save and Publish (this translation)'));
$this->drupalPostForm('node/' . $english_node->id() . '/edit', [
'moderation_state[0][state]' => 'published',
], t('Save (this translation)'));
$this->assertText(t('Article English node has been updated.'));
$english_node = $this->drupalGetNodeByTitle('English node', TRUE);
$french_node = $english_node->getTranslation('fr');
......@@ -106,8 +112,9 @@ public function testTranslateModeratedContent() {
// the translation first.
$edit = [
'title[0][value]' => 'Another node',
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm('node/add/article', $edit, t('Save and Create New Draft'));
$this->drupalPostForm('node/add/article', $edit, t('Save'));
$this->assertText(t('Article Another node has been created.'));
$english_node = $this->drupalGetNodeByTitle('Another node');
......@@ -116,14 +123,17 @@ public function testTranslateModeratedContent() {
$this->clickLink(t('Add'));
$edit = [
'title[0][value]' => 'Translated node',
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm(NULL, $edit, t('Save and Create New Draft (this translation)'));
$this->drupalPostForm(NULL, $edit, t('Save (this translation)'));
$this->assertText(t('Article Translated node has been updated.'));
$english_node = $this->drupalGetNodeByTitle('Another node', TRUE);
// Publish the translation and check that the source language version stays
// unpublished.
$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 Translated node has been updated.'));
$english_node = $this->drupalGetNodeByTitle('Another node', TRUE);
$french_node = $english_node->getTranslation('fr');
......@@ -135,8 +145,9 @@ public function testTranslateModeratedContent() {
// Now check that we can create a new draft of the translation.
$edit = [
'title[0][value]' => 'New draft of translated node',
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm('fr/node/' . $english_node->id() . '/edit', $edit, t('Save and Create New Draft (this translation)'));
$this->drupalPostForm('fr/node/' . $english_node->id() . '/edit', $edit, 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');
......@@ -145,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');
......@@ -154,15 +167,21 @@ public function testTranslateModeratedContent() {
$this->assertEqual($french_node->getTitle(), 'New draft of translated node', 'The draft has replaced the published revision.');
// Publish the English article before testing the archive transition.
$this->drupalPostForm('node/' . $english_node->id() . '/edit', [], t('Save and Publish (this translation)'));
$this->drupalPostForm('node/' . $english_node->id() . '/edit', [
'moderation_state[0][state]' => 'published',
], t('Save (this translation)'));
$this->assertText(t('Article Another node has been updated.'));
$english_node = $this->drupalGetNodeByTitle('Another node', TRUE);
$this->assertEqual($english_node->moderation_state->value, 'published');
// Archive the node and its translation.
$this->drupalPostForm('node/' . $english_node->id() . '/edit', [], t('Save and Archive (this translation)'));
$this->drupalPostForm('node/' . $english_node->id() . '/edit', [
'moderation_state[0][state]' => 'archived',
], t('Save (this translation)'));
$this->assertText(t('Article Another node has been updated.'));
$this->drupalPostForm('fr/node/' . $english_node->id() . '/edit', [], t('Save and Archive (this translation)'));
$this->drupalPostForm('fr/node/' . $english_node->id() . '/edit', [
'moderation_state[0][state]' => 'archived',
], 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');
......
......@@ -55,10 +55,16 @@ public function setUp() {
*/
public function testEditingAfterRevertRevision() {
// Create a draft.
$this->drupalPostForm('node/add/moderated_bundle', ['title[0][value]' => 'First draft node'], t('Save and Create New Draft'));
$this->drupalPostForm('node/add/moderated_bundle', [
'title[0][value]' => 'First draft node',
'moderation_state[0][state]' => 'draft',
], t('Save'));
// Now make it published.
$this->drupalPostForm('node/1/edit', ['title[0][value]' => 'Published node'], t('Save and Publish'));
$this->drupalPostForm('node/1/edit', [
'title[0][value]' => 'Published node',
'moderation_state[0][state]' => 'published',
], t('Save'));
// Check the editing form that show the published title.
$this->drupalGet('node/1/edit');
......@@ -76,7 +82,9 @@ public function testEditingAfterRevertRevision() {
$this->assertSession()
->pageTextContains('First draft node');
// Try to save the node.
$this->click('.moderation-state-draft > input');
$this->drupalPostForm('node/1/edit', [
'moderation_state[0][state]' => 'draft',
], t('Save'));
// Check if the submission passed the EntityChangedConstraintValidator.
$this->assertSession()
......
......@@ -59,9 +59,10 @@ public function testCustomBlockModeration() {
$body = 'Body of moderated block';
$edit = [
'info[0][value]' => 'Moderated block',
'moderation_state[0][state]' => 'draft',
'body[0][value]' => $body,
];
$this->drupalPostForm('block/add', $edit, t('Save and Create New Draft'));
$this->drupalPostForm('block/add', $edit, t('Save'));
$this->assertText(t('basic Moderated block has been created.'));
// Place the block in the Sidebar First region.
......@@ -83,8 +84,9 @@ public function testCustomBlockModeration() {
$updated_body = 'This is the new body value';
$edit = [
'body[0][value]' => $updated_body,
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm('block/' . $block->id(), $edit, t('Save and Create New Draft'));
$this->drupalPostForm('block/' . $block->id(), $edit, t('Save'));
$this->assertText(t('basic Moderated block has been updated.'));
// Navigate to the home page and check that the block shows the updated
......@@ -94,14 +96,17 @@ public function testCustomBlockModeration() {
$this->assertText($updated_body);
// Publish the block so we can create a pending revision.
$this->drupalPostForm('block/' . $block->id(), [], t('Save and Publish'));
$this->drupalPostForm('block/' . $block->id(), [
'moderation_state[0][state]' => 'published',
], t('Save'));
// Create a pending revision.
$pending_revision_body = 'This is the pending revision body value';
$edit = [
'body[0][value]' => $pending_revision_body,
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm('block/' . $block->id(), $edit, t('Save and Create New Draft'));
$this->drupalPostForm('block/' . $block->id(), $edit, t('Save'));
$this->assertText(t('basic Moderated block has been updated.'));
// Navigate to home page and check that the pending revision doesn't show,
......
......@@ -28,7 +28,8 @@ protected function setUp() {
public function testCreatingContent() {
$this->drupalPostForm('node/add/moderated_content', [ </