From a917ab3a1b171d850e37f17922df5d3a90a19aec Mon Sep 17 00:00:00 2001
From: catch <6915-catch@users.noreply.drupalcode.org>
Date: Fri, 15 Nov 2024 16:57:29 +0000
Subject: [PATCH] Issue #3487482 by amateescu, catch, benjifisher, ekes, finn
 lewis, fabianx, larowlan: Creating a published moderated entity in a
 workspace shouldn't make it published in Live

(cherry picked from commit 9aaa66646ad9f4511d46f26c9cbb5b19bfdbcec8)
---
 .../WorkspaceContentModerationIntegrationTest.php    | 12 ++++++++----
 core/modules/workspaces/src/EntityOperations.php     |  8 ++++++++
 core/modules/workspaces/workspaces.module            |  7 +++++++
 3 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/core/modules/content_moderation/tests/src/Functional/WorkspaceContentModerationIntegrationTest.php b/core/modules/content_moderation/tests/src/Functional/WorkspaceContentModerationIntegrationTest.php
index 5829390ecc6b..f7124598d835 100644
--- a/core/modules/content_moderation/tests/src/Functional/WorkspaceContentModerationIntegrationTest.php
+++ b/core/modules/content_moderation/tests/src/Functional/WorkspaceContentModerationIntegrationTest.php
@@ -70,15 +70,19 @@ public function testModerationInWorkspace(): void {
 
     $first_article = $this->drupalGetNodeByTitle('First article - published', TRUE);
     $this->assertEquals('published', $first_article->moderation_state->value);
+    $this->assertTrue($first_article->isPublished());
 
     $second_article = $this->drupalGetNodeByTitle('Second article - draft', TRUE);
     $this->assertEquals('draft', $second_article->moderation_state->value);
+    $this->assertFalse($second_article->isPublished());
 
-    // Check that neither of them are visible in Live.
+    // Check that neither of them are published in Live.
     $this->switchToLive();
-    $this->drupalGet('<front>');
-    $this->assertSession()->pageTextNotContains('First article');
-    $this->assertSession()->pageTextNotContains('Second article');
+    $first_article = $this->drupalGetNodeByTitle('First article - published', TRUE);
+    $this->assertFalse($first_article->isPublished());
+
+    $second_article = $this->drupalGetNodeByTitle('Second article - draft', TRUE);
+    $this->assertFalse($second_article->isPublished());
 
     // Switch back to Stage.
     $this->switchToWorkspace($stage);
diff --git a/core/modules/workspaces/src/EntityOperations.php b/core/modules/workspaces/src/EntityOperations.php
index 4324d30f703e..5caccf4a34ff 100644
--- a/core/modules/workspaces/src/EntityOperations.php
+++ b/core/modules/workspaces/src/EntityOperations.php
@@ -4,6 +4,7 @@
 
 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityPublishedInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Entity\RevisionableInterface;
 use Drupal\Core\Form\FormStateInterface;
@@ -189,6 +190,7 @@ public function entityInsert(EntityInterface $entity) {
       return;
     }
 
+    assert($entity instanceof RevisionableInterface && $entity instanceof EntityPublishedInterface);
     $this->workspaceAssociation->trackEntity($entity, $this->workspaceManager->getActiveWorkspace());
 
     // When a published entity is created in a workspace, it should remain
@@ -200,6 +202,12 @@ public function entityInsert(EntityInterface $entity) {
     // entities where there is already a valid default revision for the live
     // workspace.
     if (isset($entity->_initialPublished)) {
+      // Ensure that the default revision of an entity saved in a workspace is
+      // unpublished.
+      if ($entity->isPublished()) {
+        throw new \RuntimeException('The default revision of an entity created in a workspace cannot be published.');
+      }
+
       $entity->setPublished();
       $entity->isDefaultRevision(FALSE);
       $entity->save();
diff --git a/core/modules/workspaces/workspaces.module b/core/modules/workspaces/workspaces.module
index cc8cf8e1dabd..571db19817c0 100644
--- a/core/modules/workspaces/workspaces.module
+++ b/core/modules/workspaces/workspaces.module
@@ -45,6 +45,13 @@ function workspaces_module_implements_alter(&$implementations, $hook): void {
   if ($hook === 'entity_presave') {
     $implementation = $implementations['workspaces'];
     $implementations = ['workspaces' => $implementation] + $implementations;
+
+    // Move Content Moderation's implementation before Workspaces, so we can
+    // alter the publishing status for the default revision.
+    if (isset($implementations['content_moderation'])) {
+      $implementation = $implementations['content_moderation'];
+      $implementations = ['content_moderation' => $implementation] + $implementations;
+    }
   }
 
   // Move our 'hook_entity_insert' implementation at the end to ensure that
-- 
GitLab