/**
  * Gets the moderation state entity linked to a content entity revision.
  *
  * @return \Drupal\content_moderation\ModerationStateInterface|null
  *   The moderation state configuration entity linked to a content entity
  *   revision.
  */
 protected function getModerationState()
 {
     $entity = $this->getEntity();
     if (!\Drupal::service('content_moderation.moderation_information')->shouldModerateEntitiesOfBundle($entity->getEntityType(), $entity->bundle())) {
         return NULL;
     }
     if ($entity->id() && $entity->getRevisionId()) {
         $revisions = \Drupal::service('entity.query')->get('content_moderation_state')->condition('content_entity_type_id', $entity->getEntityTypeId())->condition('content_entity_id', $entity->id())->condition('content_entity_revision_id', $entity->getRevisionId())->allRevisions()->sort('revision_id', 'DESC')->execute();
         if ($revision_to_load = key($revisions)) {
             /** @var \Drupal\content_moderation\ContentModerationStateInterface $content_moderation_state */
             $content_moderation_state = \Drupal::entityTypeManager()->getStorage('content_moderation_state')->loadRevision($revision_to_load);
             // Return the correct translation.
             $langcode = $entity->language()->getId();
             if (!$content_moderation_state->hasTranslation($langcode)) {
                 $content_moderation_state->addTranslation($langcode);
             }
             if ($content_moderation_state->language()->getId() !== $langcode) {
                 $content_moderation_state = $content_moderation_state->getTranslation($langcode);
             }
             return $content_moderation_state->get('moderation_state')->entity;
         }
     }
     // It is possible that the bundle does not exist at this point. For example,
     // the node type form creates a fake Node entity to get default values.
     // @see \Drupal\node\NodeTypeForm::form()
     $bundle_entity = \Drupal::entityTypeManager()->getStorage($entity->getEntityType()->getBundleEntityType())->load($entity->bundle());
     if ($bundle_entity && ($default = $bundle_entity->getThirdPartySetting('content_moderation', 'default_moderation_state'))) {
         return ModerationState::load($default);
     }
 }
 /**
  * Verify moderation state methods based on entity properties.
  *
  * @covers ::isPublishedState
  * @covers ::isDefaultRevisionState
  *
  * @dataProvider moderationStateProvider
  */
 public function testModerationStateProperties($published, $default_revision, $is_published, $is_default)
 {
     $moderation_state_id = $this->randomMachineName();
     $moderation_state = ModerationState::create(['id' => $moderation_state_id, 'label' => $this->randomString(), 'published' => $published, 'default_revision' => $default_revision]);
     $moderation_state->save();
     $moderation_state = ModerationState::load($moderation_state_id);
     $this->assertEquals($is_published, $moderation_state->isPublishedState());
     $this->assertEquals($is_default, $moderation_state->isDefaultRevisionState());
 }
 /**
  * {@inheritdoc}
  */
 public function calculateDependencies()
 {
     parent::calculateDependencies();
     if ($this->stateFrom) {
         $this->addDependency('config', ModerationState::load($this->stateFrom)->getConfigDependencyName());
     }
     if ($this->stateTo) {
         $this->addDependency('config', ModerationState::load($this->stateTo)->getConfigDependencyName());
     }
     return $this;
 }
Exemple #4
0
 /**
  * Returns an array of transition permissions.
  *
  * @return array
  *   The transition permissions.
  */
 public function transitionPermissions()
 {
     // @todo https://www.drupal.org/node/2779933 write a test for this.
     $perms = [];
     /* @var \Drupal\content_moderation\ModerationStateInterface[] $states */
     $states = ModerationState::loadMultiple();
     /* @var \Drupal\content_moderation\ModerationStateTransitionInterface $transition */
     foreach (ModerationStateTransition::loadMultiple() as $id => $transition) {
         $perms['use ' . $id . ' transition'] = ['title' => $this->t('Use the %transition_name transition', ['%transition_name' => $transition->label()]), 'description' => $this->t('Move content from %from state to %to state.', ['%from' => $states[$transition->getFromState()]->label(), '%to' => $states[$transition->getToState()]->label()])];
     }
     return $perms;
 }
 /**
  * Tests content moderation third party schema for block content types.
  */
 public function testContentModerationBlockContentTypeConfig()
 {
     $this->installEntitySchema('block_content');
     $this->installEntitySchema('user');
     $this->installConfig(['content_moderation']);
     $typed_config = \Drupal::service('config.typed');
     $moderation_states = ModerationState::loadMultiple();
     $block_content_type = BlockContentType::create(['id' => 'basic', 'label' => 'basic', 'revision' => TRUE]);
     $block_content_type->setThirdPartySetting('content_moderation', 'enabled', TRUE);
     $block_content_type->setThirdPartySetting('content_moderation', 'allowed_moderation_states', array_keys($moderation_states));
     $block_content_type->setThirdPartySetting('content_moderation', 'default_moderation_state', '');
     $block_content_type->save();
     $this->assertConfigSchema($typed_config, $block_content_type->getEntityType()->getConfigPrefix() . '.' . $block_content_type->id(), $block_content_type->toArray());
 }
 /**
  * Tests basic monolingual content moderation through the API.
  */
 public function testBasicModeration()
 {
     $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();
     $node = Node::create(['type' => 'example', 'title' => 'Test title']);
     $node->save();
     $node = $this->reloadNode($node);
     $this->assertEquals('draft', $node->moderation_state->entity->id());
     $published = ModerationState::load('published');
     $node->moderation_state->entity = $published;
     $node->save();
     $node = $this->reloadNode($node);
     $this->assertEquals('published', $node->moderation_state->entity->id());
     // Change the state without saving the node.
     $content_moderation_state = ContentModerationState::load(1);
     $content_moderation_state->set('moderation_state', 'draft');
     $content_moderation_state->setNewRevision(TRUE);
     $content_moderation_state->save();
     $node = $this->reloadNode($node, 3);
     $this->assertEquals('draft', $node->moderation_state->entity->id());
     $this->assertFalse($node->isPublished());
     // Get the default revision.
     $node = $this->reloadNode($node);
     $this->assertTrue($node->isPublished());
     $this->assertEquals(2, $node->getRevisionId());
     $node->moderation_state->target_id = 'published';
     $node->save();
     $node = $this->reloadNode($node, 4);
     $this->assertEquals('published', $node->moderation_state->entity->id());
     // Get the default revision.
     $node = $this->reloadNode($node);
     $this->assertTrue($node->isPublished());
     $this->assertEquals(4, $node->getRevisionId());
 }
 /**
  * {@inheritdoc}
  */
 public function validate($value, Constraint $constraint)
 {
     /** @var \Drupal\Core\Entity\EntityInterface $entity */
     $entity = $value->getEntity();
     // Ignore entities that are not subject to moderation anyway.
     if (!$this->moderationInformation->isModeratedEntity($entity)) {
         return;
     }
     // Ignore entities that are being created for the first time.
     if ($entity->isNew()) {
         return;
     }
     // Ignore entities that are being moderated for the first time, such as
     // when they existed before moderation was enabled for this entity type.
     if ($this->isFirstTimeModeration($entity)) {
         return;
     }
     $original_entity = $this->moderationInformation->getLatestRevision($entity->getEntityTypeId(), $entity->id());
     if (!$entity->isDefaultTranslation() && $original_entity->hasTranslation($entity->language()->getId())) {
         $original_entity = $original_entity->getTranslation($entity->language()->getId());
     }
     if ($entity->moderation_state->target_id) {
         $new_state_id = $entity->moderation_state->target_id;
     } else {
         $new_state_id = $default = $this->moderationInformation->loadBundleEntity($entity->getEntityType()->getBundleEntityType(), $entity->bundle())->getThirdPartySetting('content_moderation', 'default_moderation_state');
     }
     if ($new_state_id) {
         $new_state = ModerationStateEntity::load($new_state_id);
     }
     // @todo - what if $new_state_id references something that does not exist or
     //   is null.
     if (!$this->validation->isTransitionAllowed($original_entity->moderation_state->entity, $new_state)) {
         $this->context->addViolation($constraint->message, ['%from' => $original_entity->moderation_state->entity->label(), '%to' => $new_state->label()]);
     }
 }
 /**
  * Verifies that an unpublished state may be made the default revision.
  */
 public function testArchive()
 {
     $published_id = $this->randomMachineName();
     $published_state = ModerationState::create(['id' => $published_id, 'label' => $this->randomString(), 'published' => TRUE, 'default_revision' => TRUE]);
     $published_state->save();
     $archived_id = $this->randomMachineName();
     $archived_state = ModerationState::create(['id' => $archived_id, 'label' => $this->randomString(), 'published' => FALSE, 'default_revision' => TRUE]);
     $archived_state->save();
     $page = Node::create(['type' => 'page', 'title' => $this->randomString()]);
     $page->moderation_state->target_id = $published_id;
     $page->save();
     $id = $page->id();
     // The newly-created page should already be published.
     $page = Node::load($id);
     $this->assertTrue($page->isPublished());
     // When the page is moderated to the archived state, then the latest
     // revision should be the default revision, and it should be unpublished.
     $page->moderation_state->target_id = $archived_id;
     $page->save();
     $new_revision_id = $page->getRevisionId();
     $storage = \Drupal::entityTypeManager()->getStorage('node');
     $new_revision = $storage->loadRevision($new_revision_id);
     $this->assertFalse($new_revision->isPublished());
     $this->assertTrue($new_revision->isDefaultRevision());
 }
 /**
  * Enable moderation for a specified content type, using the UI.
  *
  * @param string $content_type_id
  *   Machine name.
  * @param string[] $allowed_states
  *   Array of allowed state IDs.
  * @param string $default_state
  *   Default state.
  */
 protected function enableModerationThroughUi($content_type_id, array $allowed_states, $default_state)
 {
     $this->drupalGet('admin/structure/types');
     $this->assertLinkByHref('admin/structure/types/manage/' . $content_type_id . '/moderation');
     $this->drupalGet('admin/structure/types/manage/' . $content_type_id);
     $this->assertLinkByHref('admin/structure/types/manage/' . $content_type_id . '/moderation');
     $this->drupalGet('admin/structure/types/manage/' . $content_type_id . '/moderation');
     $this->assertFieldByName('enable_moderation_state');
     $this->assertNoFieldChecked('edit-enable-moderation-state');
     $edit['enable_moderation_state'] = 1;
     /** @var ModerationState $state */
     foreach (ModerationState::loadMultiple() as $state) {
         $key = $state->isPublishedState() ? 'allowed_moderation_states_published[' . $state->id() . ']' : 'allowed_moderation_states_unpublished[' . $state->id() . ']';
         $edit[$key] = in_array($state->id(), $allowed_states, TRUE) ? $state->id() : FALSE;
     }
     $edit['default_moderation_state'] = $default_state;
     $this->drupalPostForm(NULL, $edit, t('Save'));
 }