From 55e309fc33895bf2d629825b08486c40d07212fc Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Fri, 14 Apr 2017 07:36:40 +0100
Subject: [PATCH] Issue #2862988 by timmillwood, catch:
 EntityOperations::entityPresave doesn't always set the correct default
 revision

---
 .../src/EntityOperations.php                  |  30 ++---
 .../src/Kernel/DefaultRevisionStateTest.php   | 109 ++++++++++++++++++
 2 files changed, 125 insertions(+), 14 deletions(-)
 create mode 100644 core/modules/content_moderation/tests/src/Kernel/DefaultRevisionStateTest.php

diff --git a/core/modules/content_moderation/src/EntityOperations.php b/core/modules/content_moderation/src/EntityOperations.php
index af87f6fc329c..5c8d5c0f0872 100644
--- a/core/modules/content_moderation/src/EntityOperations.php
+++ b/core/modules/content_moderation/src/EntityOperations.php
@@ -105,9 +105,10 @@ public function entityPresave(EntityInterface $entity) {
       /** @var \Drupal\content_moderation\ContentModerationState $current_state */
       $current_state = $workflow->getState($entity->moderation_state->value);
 
-      // This entity is default if it is new, the default revision, or the
-      // default revision is not published.
+      // This entity is default if it is new, a new translation, the default
+      // revision, or the default revision is not published.
       $update_default_revision = $entity->isNew()
+        || $entity->isNewTranslation()
         || $current_state->isDefaultRevisionState()
         || !$this->isDefaultRevisionPublished($entity, $workflow);
 
@@ -250,8 +251,8 @@ public function entityView(array &$build, EntityInterface $entity, EntityViewDis
    * Check if the default revision for the given entity is published.
    *
    * The default revision is the same as the entity retrieved by "default" from
-   * the storage handler. If the entity is translated, use the default revision
-   * of the same language as the given entity.
+   * the storage handler. If the entity is translated, check if any of the
+   * translations are published.
    *
    * @param \Drupal\Core\Entity\EntityInterface $entity
    *   The entity being saved.
@@ -262,21 +263,22 @@ public function entityView(array &$build, EntityInterface $entity, EntityViewDis
    *   TRUE if the default revision is published. FALSE otherwise.
    */
   protected function isDefaultRevisionPublished(EntityInterface $entity, WorkflowInterface $workflow) {
-    $storage = $this->entityTypeManager->getStorage($entity->getEntityTypeId());
-    $default_revision = $storage->load($entity->id());
+    $default_revision = $this->entityTypeManager->getStorage($entity->getEntityTypeId())->load($entity->id());
 
-    // Ensure we are comparing the same translation as the current entity.
+    // Ensure we are checking all translations of the default revision.
     if ($default_revision instanceof TranslatableInterface && $default_revision->isTranslatable()) {
-      // If there is no translation, then there is no default revision and is
-      // therefore not published.
-      if (!$default_revision->hasTranslation($entity->language()->getId())) {
-        return FALSE;
+      // Loop through each language that has a translation.
+      foreach ($default_revision->getTranslationLanguages() as $language) {
+        // Load the translated revision.
+        $language_revision = $default_revision->getTranslation($language->getId());
+        // Return TRUE if a translation with a published state is found.
+        if ($workflow->getState($language_revision->moderation_state->value)->isPublishedState()) {
+          return TRUE;
+        }
       }
-
-      $default_revision = $default_revision->getTranslation($entity->language()->getId());
     }
 
-    return $default_revision && $workflow->getState($default_revision->moderation_state->value)->isPublishedState();
+    return $workflow->getState($default_revision->moderation_state->value)->isPublishedState();
   }
 
 }
diff --git a/core/modules/content_moderation/tests/src/Kernel/DefaultRevisionStateTest.php b/core/modules/content_moderation/tests/src/Kernel/DefaultRevisionStateTest.php
new file mode 100644
index 000000000000..274e8b525dc1
--- /dev/null
+++ b/core/modules/content_moderation/tests/src/Kernel/DefaultRevisionStateTest.php
@@ -0,0 +1,109 @@
+<?php
+
+namespace Drupal\Tests\content_moderation\Kernel;
+
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\language\Entity\ConfigurableLanguage;
+use Drupal\node\Entity\Node;
+use Drupal\node\Entity\NodeType;
+use Drupal\workflows\Entity\Workflow;
+
+/**
+ * Tests the correct default revision is set.
+ *
+ * @group content_moderation
+ */
+class DefaultRevisionStateTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'entity_test',
+    'node',
+    'block_content',
+    'content_moderation',
+    'user',
+    'system',
+    'language',
+    'content_translation',
+    'text',
+    'workflows',
+  ];
+
+  /**
+   * @var \Drupal\Core\Entity\EntityTypeManager
+   */
+  protected $entityTypeManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->installSchema('node', 'node_access');
+    $this->installEntitySchema('node');
+    $this->installEntitySchema('user');
+    $this->installEntitySchema('entity_test_with_bundle');
+    $this->installEntitySchema('entity_test_rev');
+    $this->installEntitySchema('entity_test_mulrevpub');
+    $this->installEntitySchema('block_content');
+    $this->installEntitySchema('content_moderation_state');
+    $this->installConfig('content_moderation');
+
+    $this->entityTypeManager = $this->container->get('entity_type.manager');
+  }
+
+  /**
+   * Tests a translatable Node.
+   */
+  public function testMultilingual() {
+    // Enable French.
+    ConfigurableLanguage::createFromLangcode('fr')->save();
+    $node_type = NodeType::create([
+      'type' => 'example',
+    ]);
+    $node_type->save();
+
+    $this->container->get('content_translation.manager')->setEnabled('node', 'example', TRUE);
+
+    $workflow = Workflow::load('editorial');
+    $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
+    $workflow->save();
+
+    $english_node = Node::create([
+      'type' => 'example',
+      'title' => 'Test title',
+    ]);
+    // Revision 1 (en).
+    $english_node
+      ->setUnpublished()
+      ->save();
+    $this->assertEquals('draft', $english_node->moderation_state->value);
+    $this->assertFalse($english_node->isPublished());
+    $this->assertTrue($english_node->isDefaultRevision());
+
+    // Revision 2 (fr)
+    $french_node = $english_node->addTranslation('fr', ['title' => 'French title']);
+    $french_node->moderation_state->value = 'published';
+    $french_node->save();
+    $this->assertTrue($french_node->isPublished());
+    $this->assertTrue($french_node->isDefaultRevision());
+
+    // Revision 3 (fr)
+    $node = Node::load($english_node->id())->getTranslation('fr');
+    $node->moderation_state->value = 'draft';
+    $node->save();
+    $this->assertFalse($node->isPublished());
+    $this->assertFalse($node->isDefaultRevision());
+
+    // Revision 4 (en)
+    $latest_revision = $this->entityTypeManager->getStorage('node')->loadRevision(3);
+    $latest_revision->moderation_state->value = 'draft';
+    $latest_revision->save();
+    $this->assertFalse($latest_revision->isPublished());
+    $this->assertFalse($latest_revision->isDefaultRevision());
+  }
+
+}
-- 
GitLab