Issue #2803717 by Sam152, timmillwood, dawehner, Berdir, yogeshmpawar, amateescu: Allow 'syncing' content to be updated in content moderation without forcing the creation of a new revision
parent
ddd413c853
commit
961c2b1ccb
|
@ -32,9 +32,15 @@ class ModerationHandler implements ModerationHandlerInterface, EntityHandlerInte
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function onPresave(ContentEntityInterface $entity, $default_revision, $published_state) {
|
||||
// This is probably not necessary if configuration is setup correctly.
|
||||
$entity->setNewRevision(TRUE);
|
||||
$entity->isDefaultRevision($default_revision);
|
||||
// When entities are syncing, content moderation should not force a new
|
||||
// revision to be created and should not update the default status of a
|
||||
// revision. This is useful if changes are being made to entities or
|
||||
// revisions which are not part of editorial updates triggered by normal
|
||||
// content changes.
|
||||
if (!$entity->isSyncing()) {
|
||||
$entity->setNewRevision(TRUE);
|
||||
$entity->isDefaultRevision($default_revision);
|
||||
}
|
||||
|
||||
// Update publishing status if it can be updated and if it needs updating.
|
||||
if (($entity instanceof EntityPublishedInterface) && $entity->isPublished() !== $published_state) {
|
||||
|
|
|
@ -157,11 +157,13 @@ class ModerationStateFieldItemList extends FieldItemList {
|
|||
|
||||
// This entity is default if it is new, the default revision state, or the
|
||||
// default revision is not published.
|
||||
$update_default_revision = $entity->isNew()
|
||||
|| $current_state->isDefaultRevisionState()
|
||||
|| !$content_moderation_info->isDefaultRevisionPublished($entity);
|
||||
if (!$entity->isSyncing()) {
|
||||
$update_default_revision = $entity->isNew()
|
||||
|| $current_state->isDefaultRevisionState()
|
||||
|| !$content_moderation_info->isDefaultRevisionPublished($entity);
|
||||
|
||||
$entity->isDefaultRevision($update_default_revision);
|
||||
$entity->isDefaultRevision($update_default_revision);
|
||||
}
|
||||
|
||||
// Update publishing status if it can be updated and if it needs updating.
|
||||
$published_state = $current_state->isPublishedState();
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\content_moderation\Kernel;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTestMulRevPub;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
|
||||
|
||||
/**
|
||||
* Test content moderation when an entity is marked as 'syncing'.
|
||||
*
|
||||
* @group content_moderation
|
||||
*/
|
||||
class ContentModerationSyncingTest extends KernelTestBase {
|
||||
|
||||
use ContentModerationTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'user',
|
||||
'workflows',
|
||||
'content_moderation',
|
||||
'entity_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('workflow');
|
||||
$this->installEntitySchema('content_moderation_state');
|
||||
$this->installEntitySchema('entity_test_mulrevpub');
|
||||
|
||||
$workflow = $this->createEditorialWorkflow();
|
||||
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_mulrevpub', 'entity_test_mulrevpub');
|
||||
$workflow->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test no new revision is forced during a sync.
|
||||
*/
|
||||
public function testNoRevisionForcedDuringSync() {
|
||||
$entity = EntityTestMulRevPub::create([
|
||||
'moderation_state' => 'draft',
|
||||
'name' => 'foo',
|
||||
]);
|
||||
$entity->save();
|
||||
$initial_revision_id = $entity->getRevisionId();
|
||||
|
||||
$entity->setSyncing(TRUE);
|
||||
$entity->name = 'bar';
|
||||
$entity->save();
|
||||
|
||||
$this->assertEquals($entity->getRevisionId(), $initial_revision_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test changing the moderation state during a sync.
|
||||
*/
|
||||
public function testSingleRevisionStateChangedDuringSync() {
|
||||
$entity = EntityTestMulRevPub::create([
|
||||
'moderation_state' => 'published',
|
||||
'name' => 'foo',
|
||||
]);
|
||||
$entity->save();
|
||||
$initial_revision_id = $entity->getRevisionId();
|
||||
$this->assertTrue($entity->isDefaultRevision());
|
||||
$this->assertTrue($entity->isPublished());
|
||||
|
||||
$entity->setSyncing(TRUE);
|
||||
$entity->moderation_state = 'draft';
|
||||
$entity->save();
|
||||
|
||||
// If a moderation state is changed to a draft while syncing, it will revert
|
||||
// to the same properties of an item of content that was initially created
|
||||
// as a draft.
|
||||
$this->assertEquals($initial_revision_id, $entity->getRevisionId());
|
||||
$this->assertFalse($entity->isPublished());
|
||||
$this->assertTrue($entity->isDefaultRevision());
|
||||
$this->assertEquals('draft', $entity->moderation_state->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test state changes with multiple revisions during a sync.
|
||||
*/
|
||||
public function testMultipleRevisionStateChangedDuringSync() {
|
||||
$entity = EntityTestMulRevPub::create([
|
||||
'moderation_state' => 'published',
|
||||
'name' => 'foo',
|
||||
]);
|
||||
$entity->save();
|
||||
|
||||
$entity->name = 'bar';
|
||||
$entity->save();
|
||||
$latest_revision_id = $entity->getRevisionId();
|
||||
|
||||
$entity->setSyncing(TRUE);
|
||||
$entity->moderation_state = 'draft';
|
||||
$entity->save();
|
||||
|
||||
$this->assertEquals($latest_revision_id, $entity->getRevisionId());
|
||||
$this->assertEquals('draft', $entity->moderation_state->value);
|
||||
$this->assertEquals('bar', $entity->name->value);
|
||||
// The default revision will not automatically be assigned to another
|
||||
// revision, so a draft unpublished revision will be created when syncing
|
||||
// 'published' to 'draft'.
|
||||
$this->assertFalse($entity->isPublished());
|
||||
$this->assertTrue($entity->isDefaultRevision());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test modifying a previous revision during a sync.
|
||||
*/
|
||||
public function testUpdatingPreviousRevisionDuringSync() {
|
||||
$storage = $this->container->get('entity_type.manager')->getStorage('entity_test_mulrevpub');
|
||||
|
||||
$entity = EntityTestMulRevPub::create([
|
||||
'moderation_state' => 'published',
|
||||
'name' => 'foo',
|
||||
]);
|
||||
$entity->save();
|
||||
$original_revision_id = $entity->getRevisionId();
|
||||
|
||||
$entity->name = 'bar';
|
||||
$entity->save();
|
||||
|
||||
// Sync a change to the 'name' on the original revision ID.
|
||||
$original_revision = $storage->loadRevision($original_revision_id);
|
||||
$original_revision->setSyncing(TRUE);
|
||||
$original_revision->name = 'baz';
|
||||
$original_revision->save();
|
||||
|
||||
// The names of each revision should reflect two revisions, the original one
|
||||
// having been updated during a sync.
|
||||
$this->assertEquals(['baz', 'bar'], $this->getAllRevisionNames($entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a moderation state changed on a previous revision during a sync.
|
||||
*/
|
||||
public function testStateChangedPreviousRevisionDuringSync() {
|
||||
$storage = $this->container->get('entity_type.manager')->getStorage('entity_test_mulrevpub');
|
||||
|
||||
$entity = EntityTestMulRevPub::create([
|
||||
'moderation_state' => 'published',
|
||||
'name' => 'foo',
|
||||
]);
|
||||
$entity->save();
|
||||
|
||||
$entity->moderation_state = 'draft';
|
||||
$entity->name = 'bar';
|
||||
$entity->save();
|
||||
$draft_revision_id = $entity->getRevisionId();
|
||||
|
||||
$entity->name = 'baz';
|
||||
$entity->moderation_state = 'published';
|
||||
$entity->save();
|
||||
$default_revision_id = $entity->getRevisionId();
|
||||
|
||||
// Update the draft revision moderation state to published, which would
|
||||
// typically change the default status of a revision during moderation.
|
||||
$draft_revision = $storage->loadRevision($draft_revision_id);
|
||||
$draft_revision->setSyncing(TRUE);
|
||||
$draft_revision->name = 'qux';
|
||||
$draft_revision->moderation_state = 'published';
|
||||
$draft_revision->save();
|
||||
|
||||
// Ensure the default revision is not changed during the sync.
|
||||
$reloaded_default_revision = $storage->load($entity->id());
|
||||
$this->assertEquals($default_revision_id, $reloaded_default_revision->getRevisionId());
|
||||
$this->assertEquals([
|
||||
'foo',
|
||||
'qux',
|
||||
'baz',
|
||||
], $this->getAllRevisionNames($reloaded_default_revision));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the revision names in order of the revision ID.
|
||||
*
|
||||
* @param \Drupal\entity_test\Entity\EntityTestMulRevPub $entity
|
||||
* The entity.
|
||||
*
|
||||
* @return array
|
||||
* An array of revision names.
|
||||
*/
|
||||
protected function getAllRevisionNames(EntityTestMulRevPub $entity) {
|
||||
$storage = $this->container->get('entity_type.manager')->getStorage('entity_test_mulrevpub');
|
||||
return array_map(function($revision_id) use ($storage) {
|
||||
return $storage->loadRevision($revision_id)->name->value;
|
||||
}, array_keys($storage->getQuery()
|
||||
->allRevisions()
|
||||
->condition('id', $entity->id())
|
||||
->sort('revision_id', 'ASC')
|
||||
->execute())
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue