diff --git a/core/modules/content_moderation/content_moderation.module b/core/modules/content_moderation/content_moderation.module index b67fbd3dfc..ed5fa267e4 100644 --- a/core/modules/content_moderation/content_moderation.module +++ b/core/modules/content_moderation/content_moderation.module @@ -13,6 +13,7 @@ use Drupal\Core\Access\AccessResult; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityPublishedInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemListInterface; @@ -20,7 +21,6 @@ use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Session\AccountInterface; use Drupal\workflows\WorkflowInterface; -use Drupal\node\NodeInterface; use Drupal\node\Plugin\Action\PublishNode; use Drupal\node\Plugin\Action\UnpublishNode; use Drupal\workflows\Entity\Workflow; @@ -131,34 +131,34 @@ function content_moderation_entity_view(array &$build, EntityInterface $entity, } /** - * Implements hook_node_access(). + * Implements hook_entity_access(). * - * Nodes in particular should be viewable if unpublished and the user has - * the appropriate permission. This permission is therefore effectively - * mandatory for any user that wants to moderate things. + * Entities should be viewable if unpublished and the user has the appropriate + * permission. This permission is therefore effectively mandatory for any user + * that wants to moderate things. */ -function content_moderation_node_access(NodeInterface $node, $operation, AccountInterface $account) { +function content_moderation_entity_access(EntityInterface $entity, $operation, AccountInterface $account) { /** @var \Drupal\content_moderation\ModerationInformationInterface $moderation_info */ $moderation_info = Drupal::service('content_moderation.moderation_information'); $access_result = NULL; if ($operation === 'view') { - $access_result = (!$node->isPublished()) + $access_result = (($entity instanceof EntityPublishedInterface) && !$entity->isPublished()) ? AccessResult::allowedIfHasPermission($account, 'view any unpublished content') : AccessResult::neutral(); - $access_result->addCacheableDependency($node); + $access_result->addCacheableDependency($entity); } - elseif ($operation === 'update' && $moderation_info->isModeratedEntity($node) && $node->moderation_state) { + elseif ($operation === 'update' && $moderation_info->isModeratedEntity($entity) && $entity->moderation_state) { /** @var \Drupal\content_moderation\StateTransitionValidation $transition_validation */ $transition_validation = \Drupal::service('content_moderation.state_transition_validation'); - $valid_transition_targets = $transition_validation->getValidTransitions($node, $account); + $valid_transition_targets = $transition_validation->getValidTransitions($entity, $account); $access_result = $valid_transition_targets ? AccessResult::neutral() : AccessResult::forbidden(); - $access_result->addCacheableDependency($node); + $access_result->addCacheableDependency($entity); $access_result->addCacheableDependency($account); - $workflow = \Drupal::service('content_moderation.moderation_information')->getWorkflowForEntity($node); + $workflow = $moderation_info->getWorkflowForEntity($entity); $access_result->addCacheableDependency($workflow); foreach ($valid_transition_targets as $valid_transition_target) { $access_result->addCacheableDependency($valid_transition_target); diff --git a/core/modules/content_moderation/src/Entity/Handler/ModerationHandler.php b/core/modules/content_moderation/src/Entity/Handler/ModerationHandler.php index 62e504e4c0..e793c338fa 100644 --- a/core/modules/content_moderation/src/Entity/Handler/ModerationHandler.php +++ b/core/modules/content_moderation/src/Entity/Handler/ModerationHandler.php @@ -33,6 +33,9 @@ public function onPresave(ContentEntityInterface $entity, $default_revision, $pu // This is probably not necessary if configuration is setup correctly. $entity->setNewRevision(TRUE); $entity->isDefaultRevision($default_revision); + if ($entity->hasField('revision_translation_affected')) { + $entity->set('revision_translation_affected', TRUE); + } // Update publishing status if it can be updated and if it needs updating. if (($entity instanceof EntityPublishedInterface) && $entity->isPublished() !== $published_state) { diff --git a/core/modules/content_moderation/src/EntityOperations.php b/core/modules/content_moderation/src/EntityOperations.php index 26f88bc8ec..48fe678ed9 100644 --- a/core/modules/content_moderation/src/EntityOperations.php +++ b/core/modules/content_moderation/src/EntityOperations.php @@ -237,6 +237,13 @@ public function entityView(array &$build, EntityInterface $entity, EntityViewDis if ($this->moderationInfo->isLiveRevision($entity)) { return; } + // Don't display the moderation form when when: + // - The revision is not translation affected. + // - There are more than one translation languages. + // - The entity has forward revisions. + if (!$entity->isRevisionTranslationAffected() && count($entity->getTranslationLanguages()) > 1 && $this->moderationInfo->hasForwardRevision($entity)) { + return; + } $component = $display->getComponent('content_moderation_control'); if ($component) { diff --git a/core/modules/content_moderation/src/EntityTypeInfo.php b/core/modules/content_moderation/src/EntityTypeInfo.php index 8f6ac4d79e..ee154998d4 100644 --- a/core/modules/content_moderation/src/EntityTypeInfo.php +++ b/core/modules/content_moderation/src/EntityTypeInfo.php @@ -7,11 +7,13 @@ use Drupal\Core\Entity\ContentEntityFormInterface; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Entity\ContentEntityTypeInterface; +use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeBundleInfoInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Render\Markup; use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\TranslationInterface; @@ -60,6 +62,13 @@ class EntityTypeInfo implements ContainerInjectionInterface { protected $currentUser; /** + * The state transition validation service. + * + * @var \Drupal\content_moderation\StateTransitionValidationInterface + */ + protected $validator; + + /** * A keyed array of custom moderation handlers for given entity types. * * Any entity not specified will use a common default. @@ -85,12 +94,13 @@ class EntityTypeInfo implements ContainerInjectionInterface { * @param \Drupal\Core\Session\AccountInterface $current_user * Current user. */ - public function __construct(TranslationInterface $translation, ModerationInformationInterface $moderation_information, EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $bundle_info, AccountInterface $current_user) { + public function __construct(TranslationInterface $translation, ModerationInformationInterface $moderation_information, EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $bundle_info, AccountInterface $current_user, StateTransitionValidationInterface $validator) { $this->stringTranslation = $translation; $this->moderationInfo = $moderation_information; $this->entityTypeManager = $entity_type_manager; $this->bundleInfo = $bundle_info; $this->currentUser = $current_user; + $this->validator = $validator; } /** @@ -102,7 +112,8 @@ public static function create(ContainerInterface $container) { $container->get('content_moderation.moderation_information'), $container->get('entity_type.manager'), $container->get('entity_type.bundle.info'), - $container->get('current_user') + $container->get('current_user'), + $container->get('content_moderation.state_transition_validation') ); } @@ -282,12 +293,54 @@ public function formAlter(array &$form, FormStateInterface $form_state, $form_id $this->entityTypeManager->getHandler($type->getBundleOf(), 'moderation')->enforceRevisionsBundleFormAlter($form, $form_state, $form_id); } } - elseif ($form_object instanceof ContentEntityFormInterface) { + elseif ($form_object instanceof ContentEntityFormInterface && in_array($form_object->getOperation(), ['edit', 'default'])) { $entity = $form_object->getEntity(); if ($this->moderationInfo->isModeratedEntity($entity)) { $this->entityTypeManager ->getHandler($entity->getEntityTypeId(), 'moderation') ->enforceRevisionsEntityFormAlter($form, $form_state, $form_id); + + // Prevent saving and display error when: + // - The revision is not translation affected. + // - There are more than one translation languages. + // - The entity has forward revisions. + if (!$entity->isRevisionTranslationAffected() && count($entity->getTranslationLanguages()) > 1 && $this->moderationInfo->hasForwardRevision($entity)) { + $latest_revision = $this->moderationInfo->getLatestRevision($entity->getEntityTypeId(), $entity->id()); + if ($entity->bundle()) { + $bundle_type_id = $entity->getEntityType()->getBundleEntityType(); + $bundle = $this->entityTypeManager->getStorage($bundle_type_id)->load($entity->bundle()); + $type_label = $bundle->label(); + } + else { + $type_label = $entity->getEntityType()->getLabel(); + } + $label = $this->t('Unable to save this @type_label.', ['@type_label' => $type_label]); + $translation = $this->moderationInfo->getRevisionTranslationAffectedTranslation($latest_revision); + $message = $this->t('Publish or delete the latest draft revision to allow all workflow transitions.', ['@latest_revision_edit_url' => $translation->toUrl('edit-form', ['language' => $translation->language()])->toString(), '@latest_revision_delete_url' => $translation->toUrl('delete-form', ['language' => $translation->language()])->toString()]); + + drupal_set_message(Markup::create($label . ' ' . $message), 'error'); + $form['actions']['#access'] = FALSE; + $form['invalid_transitions'] = [ + 'label' => [ + '#type' => 'item', + '#prefix' => '', + '#markup' => $label, + '#suffix' => '', + ], + 'message' => [ + '#type' => 'item', + '#markup' => $message, + ], + '#weight' => 999, + '#no_valid_transitions' => TRUE, + ]; + + if ($form['footer']) { + $form['footer']['invalid_transitions'] = $form['invalid_transitions']; + unset($form['invalid_transitions']); + } + } + // Submit handler to redirect to the latest version, if available. $form['actions']['submit']['#submit'][] = [EntityTypeInfo::class, 'bundleFormRedirect']; } diff --git a/core/modules/content_moderation/src/ModerationInformation.php b/core/modules/content_moderation/src/ModerationInformation.php index 1294bc1ec6..f86e484987 100644 --- a/core/modules/content_moderation/src/ModerationInformation.php +++ b/core/modules/content_moderation/src/ModerationInformation.php @@ -115,6 +115,18 @@ public function getDefaultRevisionId($entity_type_id, $entity_id) { /** * {@inheritdoc} */ + public function getRevisionTranslationAffectedTranslation(ContentEntityInterface $entity) { + foreach ($entity->getTranslationLanguages() as $language) { + $translation = $entity->getTranslation($language->getId()); + if ($translation->isRevisionTranslationAffected()) { + return $translation; + } + } + } + + /** + * {@inheritdoc} + */ public function isLatestRevision(ContentEntityInterface $entity) { return $entity->getRevisionId() == $this->getLatestRevisionId($entity->getEntityTypeId(), $entity->id()); } diff --git a/core/modules/content_moderation/src/ModerationInformationInterface.php b/core/modules/content_moderation/src/ModerationInformationInterface.php index cf3adce02a..53d4750309 100644 --- a/core/modules/content_moderation/src/ModerationInformationInterface.php +++ b/core/modules/content_moderation/src/ModerationInformationInterface.php @@ -90,6 +90,17 @@ public function getLatestRevisionId($entity_type_id, $entity_id); public function getDefaultRevisionId($entity_type_id, $entity_id); /** + * Returns the revision translation affected translation of a revision. + * + * @param \Drupal\Core\Entity\ContentEntityInterface $entity + * The content entity. + * + * @return \Drupal\Core\Entity\ContentEntityInterface + * The revision translation affected translation. + */ + public function getRevisionTranslationAffectedTranslation(ContentEntityInterface $entity); + + /** * Determines if an entity is a latest revision. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity diff --git a/core/modules/content_moderation/src/ParamConverter/EntityRevisionConverter.php b/core/modules/content_moderation/src/ParamConverter/EntityRevisionConverter.php index eac1913fca..786d45f23d 100644 --- a/core/modules/content_moderation/src/ParamConverter/EntityRevisionConverter.php +++ b/core/modules/content_moderation/src/ParamConverter/EntityRevisionConverter.php @@ -92,13 +92,12 @@ public function convert($value, $definition, $name, array $defaults) { $entity_type_id = $this->getEntityTypeFromDefaults($definition, $name, $defaults); $latest_revision = $this->moderationInformation->getLatestRevision($entity_type_id, $value); - // If the entity type is translatable, ensure we return the proper - // translation object for the current context. - if ($latest_revision instanceof EntityInterface && $entity instanceof TranslatableInterface) { - $latest_revision = $this->entityManager->getTranslationFromContext($latest_revision, NULL, ['operation' => 'entity_upcast']); - } - - if ($latest_revision instanceof EntityInterface && $latest_revision->isRevisionTranslationAffected()) { + if ($latest_revision instanceof EntityInterface) { + // If the entity type is translatable, ensure we return the proper + // translation object for the current context. + if ($entity instanceof TranslatableInterface) { + $latest_revision = $this->entityManager->getTranslationFromContext($latest_revision, NULL, ['operation' => 'entity_upcast']); + } $entity = $latest_revision; } } diff --git a/core/modules/content_moderation/tests/src/Functional/ModerationFormTest.php b/core/modules/content_moderation/tests/src/Functional/ModerationFormTest.php index 3882c764f1..61805768f7 100644 --- a/core/modules/content_moderation/tests/src/Functional/ModerationFormTest.php +++ b/core/modules/content_moderation/tests/src/Functional/ModerationFormTest.php @@ -12,6 +12,18 @@ class ModerationFormTest extends ModerationStateTestBase { /** + * Modules to enable. + * + * @var array + */ + public static $modules = [ + 'node', + 'content_moderation', + 'locale', + 'content_translation', + ]; + + /** * {@inheritdoc} */ protected function setUp() { @@ -205,4 +217,200 @@ public function testModerationFormSetsRevisionAuthor() { $this->assertText('by ' . $another_user->getAccountName()); } + /** + * Tests translated and moderated nodes. + */ + public function testContentTranslationNodeForm() { + $this->drupalLogin($this->rootUser); + + // Add French language. + $edit = [ + 'predefined_langcode' => 'fr', + ]; + $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language')); + + // Enable content translation on articles. + $this->drupalGet('admin/config/regional/content-language'); + $edit = [ + 'entity_types[node]' => TRUE, + 'settings[node][moderated_content][translatable]' => TRUE, + 'settings[node][moderated_content][settings][language][language_alterable]' => TRUE, + ]; + $this->drupalPostForm(NULL, $edit, t('Save configuration')); + + // Adding languages requires a container rebuild in the test running + // environment so that multilingual services are used. + $this->rebuildContainer(); + + // Create new moderated content in draft (revision 1). + $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')); + + $node = $this->drupalGetNodeByTitle('Some moderated content'); + $this->assertTrue($node->language(), 'en'); + $edit_path = sprintf('node/%d/edit', $node->id()); + $translate_path = sprintf('node/%d/translations/add/en/fr', $node->id()); + $french = \Drupal::languageManager()->getLanguage('fr'); + + // 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->drupalPostForm(NULL, [ + 'body[0][value]' => 'Second version of the content.', + ], t('Save and Publish (this translation)')); + + // 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->drupalPostForm(NULL, [ + 'body[0][value]' => 'Third version of the content.', + ], t('Save and Create New Draft (this translation)')); + + // 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()->pageTextContains('Unable to save this Moderated content.'); + + // 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->drupalPostForm(NULL, [ + 'body[0][value]' => 'Fifth version of the content.', + ], t('Save and Publish (this translation)')); + + // 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->drupalPostForm(NULL, [ + 'body[0][value]' => 'Sixth version of the content.', + ], t('Save and Publish (this translation)')); + + // 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)"]')); + + // 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->drupalPostForm(NULL, [ + 'body[0][value]' => 'Seventh version of the content.', + ], t('Save and Create New Draft (this translation)')); + + // 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()->pageTextContains('Unable to save this Moderated content.'); + + // 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->drupalPostForm(NULL, [ + 'body[0][value]' => 'Eighth version of the content.', + ], t('Save and Publish (this translation)')); + + // 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)"]')); + + // 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)"]')); + + // 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')); + + $node = $this->drupalGetNodeByTitle('Second moderated content'); + $this->assertTrue($node->language(), 'en'); + $edit_path = sprintf('node/%d/edit', $node->id()); + $translate_path = sprintf('node/%d/translations/add/en/fr', $node->id()); + + // 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->drupalPostForm(NULL, [ + 'body[0][value]' => 'Second version of the content.', + ], t('Save and Create New Draft (this translation)')); + + // 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()->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')); + + $node = $this->drupalGetNodeByTitle('Third moderated content'); + $this->assertTrue($node->language(), 'en'); + $edit_path = sprintf('node/%d/edit', $node->id()); + $translate_path = sprintf('node/%d/translations/add/en/fr', $node->id()); + + // 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)')); + + // 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)')); + + // 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()->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)')); + + // 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)')); + } + } diff --git a/core/modules/content_moderation/tests/src/Functional/ModerationLocaleTest.php b/core/modules/content_moderation/tests/src/Functional/ModerationLocaleTest.php index a9d95f0b9f..8516e87871 100644 --- a/core/modules/content_moderation/tests/src/Functional/ModerationLocaleTest.php +++ b/core/modules/content_moderation/tests/src/Functional/ModerationLocaleTest.php @@ -144,12 +144,9 @@ public function testTranslateModeratedContent() { $this->assertTrue($french_node->isPublished()); $this->assertEqual($french_node->getTitle(), 'Translated node', 'The default revision of the published translation remains the same.'); - // Publish the draft. - $edit = [ - 'new_state' => 'published', - ]; - $this->drupalPostForm('fr/node/' . $english_node->id() . '/latest', $edit, t('Apply')); - $this->assertText(t('The moderation state has been updated.')); + // Publish the French article before testing the archive transition. + $this->drupalPostForm('fr/node/' . $english_node->id() . '/edit', [], t('Save and Publish (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'); $this->assertEqual($french_node->moderation_state->value, 'published'); @@ -173,43 +170,6 @@ public function testTranslateModeratedContent() { $this->assertFalse($english_node->isPublished()); $this->assertEqual($french_node->moderation_state->value, 'archived'); $this->assertFalse($french_node->isPublished()); - - // Create another article with its translation. This time publishing english - // after creating a forward french revision. - $edit = [ - 'title[0][value]' => 'An english node', - ]; - $this->drupalPostForm('node/add/article', $edit, t('Save and Create New Draft')); - $this->assertText(t('Article An english node has been created.')); - $english_node = $this->drupalGetNodeByTitle('An english node'); - $this->assertFalse($english_node->isPublished()); - - // Add a French translation. - $this->drupalGet('node/' . $english_node->id() . '/translations'); - $this->clickLink(t('Add')); - $edit = [ - 'title[0][value]' => 'A french node', - ]; - $this->drupalPostForm(NULL, $edit, t('Save and Publish (this translation)')); - $english_node = $this->drupalGetNodeByTitle('An english node', TRUE); - $french_node = $english_node->getTranslation('fr'); - $this->assertTrue($french_node->isPublished()); - $this->assertFalse($english_node->isPublished()); - - // Create a forward revision - $this->drupalPostForm('fr/node/' . $english_node->id() . '/edit', [], t('Save and Create New Draft (this translation)')); - $english_node = $this->drupalGetNodeByTitle('An english node', TRUE); - $french_node = $english_node->getTranslation('fr'); - $this->assertTrue($french_node->isPublished()); - $this->assertFalse($english_node->isPublished()); - - // Publish the english node and the default french node not the latest - // french node should be used. - $this->drupalPostForm('/node/' . $english_node->id() . '/edit', [], t('Save and Publish (this translation)')); - $english_node = $this->drupalGetNodeByTitle('An english node', TRUE); - $french_node = $english_node->getTranslation('fr'); - $this->assertTrue($french_node->isPublished()); - $this->assertTrue($english_node->isPublished()); } }