/** * Creates or updates the moderation state of an entity. * * @param \Drupal\Core\Entity\EntityInterface $entity * The entity to update or create a moderation state for. */ protected function updateOrCreateFromEntity(EntityInterface $entity) { $moderation_state = $entity->moderation_state->target_id; /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ if (!$moderation_state) { $moderation_state = $this->moderationInfo->loadBundleEntity($entity->getEntityType()->getBundleEntityType(), $entity->bundle())->getThirdPartySetting('content_moderation', 'default_moderation_state'); } // @todo what if $entity->moderation_state->target_id is null at this point? $entity_type_id = $entity->getEntityTypeId(); $entity_id = $entity->id(); $entity_revision_id = $entity->getRevisionId(); $entity_langcode = $entity->language()->getId(); $storage = $this->entityTypeManager->getStorage('content_moderation_state'); $entities = $storage->loadByProperties(['content_entity_type_id' => $entity_type_id, 'content_entity_id' => $entity_id]); /** @var \Drupal\content_moderation\ContentModerationStateInterface $content_moderation_state */ $content_moderation_state = reset($entities); if (!$content_moderation_state instanceof ContentModerationStateInterface) { $content_moderation_state = $storage->create(['content_entity_type_id' => $entity_type_id, 'content_entity_id' => $entity_id]); } else { // Create a new revision. $content_moderation_state->setNewRevision(TRUE); } // Sync translations. if (!$content_moderation_state->hasTranslation($entity_langcode)) { $content_moderation_state->addTranslation($entity_langcode); } if ($content_moderation_state->language()->getId() !== $entity_langcode) { $content_moderation_state = $content_moderation_state->getTranslation($entity_langcode); } // Create the ContentModerationState entity for the inserted entity. $content_moderation_state->set('content_entity_revision_id', $entity_revision_id); $content_moderation_state->set('moderation_state', $moderation_state); ContentModerationState::updateOrCreateFromEntity($content_moderation_state); }
/** * Tests basic multilingual content moderation through the API. */ public function testMultilingualModeration() { // Enable French. ConfigurableLanguage::createFromLangcode('fr')->save(); $node_type = NodeType::create(['type' => 'example']); $node_type->setThirdPartySetting('content_moderation', 'enabled', TRUE); $node_type->setThirdPartySetting('content_moderation', 'allowed_moderation_states', ['draft', 'published']); $node_type->setThirdPartySetting('content_moderation', 'default_moderation_state', 'draft'); $node_type->save(); $english_node = Node::create(['type' => 'example', 'title' => 'Test title']); // Revision 1 (en). $english_node->setPublished(FALSE)->save(); $this->assertEquals('draft', $english_node->moderation_state->entity->id()); $this->assertFalse($english_node->isPublished()); // Create a French translation. $french_node = $english_node->addTranslation('fr', ['title' => 'French title']); $french_node->setPublished(FALSE); // Revision 1 (fr). $french_node->save(); $french_node = $this->reloadNode($english_node)->getTranslation('fr'); $this->assertEquals('draft', $french_node->moderation_state->entity->id()); $this->assertFalse($french_node->isPublished()); // Move English node to create another draft. $english_node = $this->reloadNode($english_node); $english_node->moderation_state->target_id = 'draft'; // Revision 2 (en, fr). $english_node->save(); $english_node = $this->reloadNode($english_node); $this->assertEquals('draft', $english_node->moderation_state->entity->id()); // French node should still be in draft. $french_node = $this->reloadNode($english_node)->getTranslation('fr'); $this->assertEquals('draft', $french_node->moderation_state->entity->id()); // Publish the French node. $french_node->moderation_state->target_id = 'published'; // Revision 3 (en, fr). $french_node->save(); $french_node = $this->reloadNode($french_node)->getTranslation('fr'); $this->assertTrue($french_node->isPublished()); $this->assertEquals('published', $french_node->moderation_state->entity->id()); $this->assertTrue($french_node->isPublished()); $english_node = $french_node->getTranslation('en'); $this->assertEquals('draft', $english_node->moderation_state->entity->id()); // Publish the English node. $english_node->moderation_state->target_id = 'published'; // Revision 4 (en, fr). $english_node->save(); $english_node = $this->reloadNode($english_node); $this->assertTrue($english_node->isPublished()); // Move the French node back to draft. $french_node = $this->reloadNode($english_node)->getTranslation('fr'); $this->assertTrue($french_node->isPublished()); $french_node->moderation_state->target_id = 'draft'; // Revision 5 (en, fr). $french_node->save(); $french_node = $this->reloadNode($english_node, 5)->getTranslation('fr'); $this->assertFalse($french_node->isPublished()); $this->assertTrue($french_node->getTranslation('en')->isPublished()); // Republish the French node. $french_node->moderation_state->target_id = 'published'; // Revision 6 (en, fr). $french_node->save(); $french_node = $this->reloadNode($english_node)->getTranslation('fr'); $this->assertTrue($french_node->isPublished()); // Change the EN state without saving the node. $content_moderation_state = ContentModerationState::load(1); $content_moderation_state->set('moderation_state', 'draft'); $content_moderation_state->setNewRevision(TRUE); // Revision 7 (en, fr). $content_moderation_state->save(); $english_node = $this->reloadNode($french_node, $french_node->getRevisionId() + 1); $this->assertEquals('draft', $english_node->moderation_state->entity->id()); $french_node = $this->reloadNode($english_node)->getTranslation('fr'); $this->assertEquals('published', $french_node->moderation_state->entity->id()); // This should unpublish the French node. $content_moderation_state = ContentModerationState::load(1); $content_moderation_state = $content_moderation_state->getTranslation('fr'); $content_moderation_state->set('moderation_state', 'draft'); $content_moderation_state->setNewRevision(TRUE); // Revision 8 (en, fr). $content_moderation_state->save(); $english_node = $this->reloadNode($english_node, $english_node->getRevisionId()); $this->assertEquals('draft', $english_node->moderation_state->entity->id()); $french_node = $this->reloadNode($english_node, '8')->getTranslation('fr'); $this->assertEquals('draft', $french_node->moderation_state->entity->id()); // Switching the moderation state to an unpublished state should update the // entity. $this->assertFalse($french_node->isPublished()); // Get the default english node. $english_node = $this->reloadNode($english_node); $this->assertTrue($english_node->isPublished()); $this->assertEquals(6, $english_node->getRevisionId()); }
/** * Creates or updates an entity's moderation state whilst saving that entity. * * @param \Drupal\content_moderation\Entity\ContentModerationState $content_moderation_state * The content moderation entity content entity to create or save. * * @internal * This method should only be called as a result of saving the related * content entity. */ public static function updateOrCreateFromEntity(ContentModerationState $content_moderation_state) { $content_moderation_state->realSave(); }