Commit 6ea03e36 authored by catch's avatar catch

Issue #2883868 by amateescu, Sam152, timmillwood, plach: Content Moderation...

Issue #2883868 by amateescu, Sam152, timmillwood, plach: Content Moderation decides to set a new revision as the default one way too late in the entity update process
parent e1e21613
......@@ -9,9 +9,7 @@
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\TypedData\TranslatableInterface;
use Drupal\content_moderation\Form\EntityModerationForm;
use Drupal\workflows\WorkflowInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -110,7 +108,7 @@ public function entityPresave(EntityInterface $entity) {
$update_default_revision = $entity->isNew()
|| $entity->isNewTranslation()
|| $current_state->isDefaultRevisionState()
|| !$this->isDefaultRevisionPublished($entity, $workflow);
|| !$this->moderationInfo->isDefaultRevisionPublished($entity);
// Fire per-entity-type logic for handling the save process.
$this->entityTypeManager->getHandler($entity->getEntityTypeId(), 'moderation')->onPresave($entity, $update_default_revision, $current_state->isPublishedState());
......@@ -247,38 +245,4 @@ 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, check if any of the
* translations are published.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity being saved.
* @param \Drupal\workflows\WorkflowInterface $workflow
* The workflow being applied to the entity.
*
* @return bool
* TRUE if the default revision is published. FALSE otherwise.
*/
protected function isDefaultRevisionPublished(EntityInterface $entity, WorkflowInterface $workflow) {
$default_revision = $this->entityTypeManager->getStorage($entity->getEntityTypeId())->load($entity->id());
// Ensure we are checking all translations of the default revision.
if ($default_revision instanceof TranslatableInterface && $default_revision->isTranslatable()) {
// 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;
}
}
}
return $workflow->getState($default_revision->moderation_state->value)->isPublishedState();
}
}
......@@ -7,6 +7,7 @@
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\TypedData\TranslatableInterface;
/**
* General service for moderation-related questions about Entity API.
......@@ -137,6 +138,29 @@ public function isLiveRevision(ContentEntityInterface $entity) {
&& $workflow->getState($entity->moderation_state->value)->isPublishedState();
}
/**
* {@inheritdoc}
*/
public function isDefaultRevisionPublished(ContentEntityInterface $entity) {
$workflow = $this->getWorkflowForEntity($entity);
$default_revision = \Drupal::entityTypeManager()->getStorage($entity->getEntityTypeId())->load($entity->id());
// Ensure we are checking all translations of the default revision.
if ($default_revision instanceof TranslatableInterface && $default_revision->isTranslatable()) {
// 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;
}
}
}
return $workflow->getState($default_revision->moderation_state->value)->isPublishedState();
}
/**
* {@inheritdoc}
*/
......
......@@ -126,6 +126,21 @@ public function hasForwardRevision(ContentEntityInterface $entity);
*/
public function isLiveRevision(ContentEntityInterface $entity);
/**
* Determines 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, check if any of the
* translations are published.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* The entity being saved.
*
* @return bool
* TRUE if the default revision is published. FALSE otherwise.
*/
public function isDefaultRevisionPublished(ContentEntityInterface $entity);
/**
* Gets the workflow for the given content entity.
*
......
......@@ -3,6 +3,7 @@
namespace Drupal\content_moderation\Plugin\Field;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityPublishedInterface;
use Drupal\Core\Field\FieldItemList;
/**
......@@ -117,4 +118,41 @@ protected function computeModerationFieldItemList() {
}
}
/**
* {@inheritdoc}
*/
public function onChange($delta) {
$entity = $this->getEntity();
/** @var \Drupal\content_moderation\ModerationInformationInterface $content_moderation_info */
$content_moderation_info = \Drupal::service('content_moderation.moderation_information');
$workflow = $content_moderation_info->getWorkflowForEntity($entity);
$current_state_id = $this->list[0]->value;
// Change the entity's default revision flag and the publishing status only
// if the new workflow state is a valid one.
if ($workflow->hasState($current_state_id)) {
/** @var \Drupal\content_moderation\ContentModerationState $current_state */
$current_state = $workflow->getState($current_state_id);
// This entity is default if it is new, a new translation, the default
// revision state, or the default revision is not published.
$update_default_revision = $entity->isNew()
|| $entity->isNewTranslation()
|| $current_state->isDefaultRevisionState()
|| !$content_moderation_info->isDefaultRevisionPublished($entity);
$entity->isDefaultRevision($update_default_revision);
// Update publishing status if it can be updated and if it needs updating.
$published_state = $current_state->isPublishedState();
if (($entity instanceof EntityPublishedInterface) && $entity->isPublished() !== $published_state) {
$published_state ? $entity->setPublished() : $entity->setUnpublished();
}
}
parent::onChange($delta);
}
}
......@@ -79,4 +79,24 @@ public function testArrayIteration() {
$this->assertEquals(['draft'], $states);
}
/**
* Tests that moderation state changes also change the related entity state.
*/
public function testModerationStateChanges() {
// Change the moderation state and check that the entity's
// 'isDefaultRevision' flag and the publishing status have also been
// updated.
$this->testNode->moderation_state->value = 'published';
$this->assertTrue($this->testNode->isPublished());
$this->assertTrue($this->testNode->isDefaultRevision());
$this->testNode->save();
// Repeat the checks using an 'unpublished' state.
$this->testNode->moderation_state->value = 'draft';
$this->assertFalse($this->testNode->isPublished());
$this->assertFalse($this->testNode->isDefaultRevision());
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment