diff --git a/core/modules/content_moderation/tests/src/Functional/WorkspaceContentModerationIntegrationTest.php b/core/modules/content_moderation/tests/src/Functional/WorkspaceContentModerationIntegrationTest.php index 5829390ecc6b334bbe3e9654925754f9e6304f87..f7124598d835ef1342e28e5117ef8242f6f049f8 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 4324d30f703e169a245dabdfe73578c1f2f2d4ab..5caccf4a34ff46097cf7c733c798f519c7a3a5d5 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 cc8cf8e1dabdf76000f7b4a3b7887a77c633e8f3..571db19817c04cae898303e121cc41559d5481f2 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