Issue #3181439 by tstoeckler, Gauravvv, Tomefa, Sam152, smustgrave, larowlan: Content Moderation fatals when a moderated entity is re-saved on hook_insert()
parent
88be8b540b
commit
775b3cffe5
|
@ -134,12 +134,17 @@ class ContentModerationState extends ContentEntityBase implements ContentModerat
|
|||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
$storage = \Drupal::entityTypeManager()->getStorage('content_moderation_state');
|
||||
|
||||
// New entities may not have a loaded revision ID at this point, but the
|
||||
// creation of a content moderation state entity may have already been
|
||||
// triggered elsewhere. In this case we have to match on the revision ID
|
||||
// (instead of the loaded revision ID).
|
||||
$revision_id = $entity->getLoadedRevisionId() ?: $entity->getRevisionId();
|
||||
$ids = $storage->getQuery()
|
||||
->accessCheck(FALSE)
|
||||
->condition('content_entity_type_id', $entity->getEntityTypeId())
|
||||
->condition('content_entity_id', $entity->id())
|
||||
->condition('workflow', $moderation_info->getWorkflowForEntity($entity)->id())
|
||||
->condition('content_entity_revision_id', $entity->getLoadedRevisionId())
|
||||
->condition('content_entity_revision_id', $revision_id)
|
||||
->allRevisions()
|
||||
->execute();
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
name: 'Content moderation test re-save'
|
||||
type: module
|
||||
description: 'Re-saves moderated entities for testing purposes.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
dependencies:
|
||||
- drupal:content_moderation
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains install functions for the Content moderation test re-save module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_install().
|
||||
*/
|
||||
function content_moderation_test_resave_install() {
|
||||
// Make sure that this module's hooks are run before Content Moderation's
|
||||
// hooks.
|
||||
module_set_weight('content_moderation_test_resave', -10);
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains hook implementations for the Content moderation test re-save module.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_entity_insert().
|
||||
*/
|
||||
function content_moderation_test_resave_entity_insert(EntityInterface $entity) {
|
||||
/** @var \Drupal\content_moderation\ModerationInformationInterface $content_moderation */
|
||||
$content_moderation = \Drupal::service('content_moderation.moderation_information');
|
||||
if ($content_moderation->isModeratedEntity($entity)) {
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
// Saving the passed entity object would populate its loaded revision ID,
|
||||
// which we want to avoid. Thus, save a clone of the original object.
|
||||
$cloned_entity = clone $entity;
|
||||
// Set the entity's syncing status, as we do not want Content Moderation to
|
||||
// create new revisions for the re-saving. Without this call Content
|
||||
// Moderation would end up creating two separate content moderation state
|
||||
// entities: one for the re-save revision and one for the initial revision.
|
||||
$cloned_entity->setSyncing(TRUE)->save();
|
||||
|
||||
// Record the fact that a re-save happened.
|
||||
\Drupal::state()->set('content_moderation_test_resave', TRUE);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\content_moderation\Kernel;
|
||||
|
||||
use Drupal\content_moderation\Entity\ContentModerationState;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
|
||||
|
||||
/**
|
||||
* Tests Content Moderation with entities that get re-saved automatically.
|
||||
*
|
||||
* @group content_moderation
|
||||
*/
|
||||
class ContentModerationResaveTest extends KernelTestBase {
|
||||
|
||||
use ContentModerationTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
// Make sure the test module is listed first as module weights do not apply
|
||||
// for kernel tests.
|
||||
/* @see \content_moderation_test_resave_install() */
|
||||
'content_moderation_test_resave',
|
||||
'content_moderation',
|
||||
'entity_test',
|
||||
'user',
|
||||
'workflows',
|
||||
];
|
||||
|
||||
/**
|
||||
* The content moderation state entity storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $contentModerationStateStorage;
|
||||
|
||||
/**
|
||||
* The entity storage for the entity type used in the test.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $entityStorage;
|
||||
|
||||
/**
|
||||
* The state service.
|
||||
*
|
||||
* @var \Drupal\Core\State\StateInterface
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$entity_type_id = 'entity_test_rev';
|
||||
|
||||
$this->installEntitySchema('content_moderation_state');
|
||||
$this->installEntitySchema($entity_type_id);
|
||||
|
||||
$workflow = $this->createEditorialWorkflow();
|
||||
$this->addEntityTypeAndBundleToWorkflow($workflow, $entity_type_id, $entity_type_id);
|
||||
|
||||
/** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */
|
||||
$entity_type_manager = $this->container->get('entity_type.manager');
|
||||
$this->contentModerationStateStorage = $entity_type_manager->getStorage('content_moderation_state');
|
||||
$this->entityStorage = $entity_type_manager->getStorage($entity_type_id);
|
||||
$this->state = $this->container->get('state');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that Content Moderation works with entities being resaved.
|
||||
*/
|
||||
public function testContentModerationResave() {
|
||||
$entity = $this->entityStorage->create();
|
||||
$this->assertSame('draft', $entity->get('moderation_state')->value);
|
||||
$this->assertNull(\Drupal::state()->get('content_moderation_test_resave'));
|
||||
$this->assertNull(ContentModerationState::loadFromModeratedEntity($entity));
|
||||
$content_moderation_state_query = $this->contentModerationStateStorage
|
||||
->getQuery()
|
||||
->accessCheck(FALSE)
|
||||
->count();
|
||||
$this->assertSame(0, (int) $content_moderation_state_query->execute());
|
||||
$content_moderation_state_revision_query = $this->contentModerationStateStorage
|
||||
->getQuery()
|
||||
->accessCheck(FALSE)
|
||||
->allRevisions()
|
||||
->count();
|
||||
$this->assertSame(0, (int) $content_moderation_state_revision_query->execute());
|
||||
|
||||
// The test module will re-save the entity in its hook_insert()
|
||||
// implementation creating the content moderation state entity before
|
||||
// Content Moderation's hook_insert() has run for the initial save
|
||||
// operation.
|
||||
$entity->save();
|
||||
$this->assertSame('draft', $entity->get('moderation_state')->value);
|
||||
$this->assertTrue(\Drupal::state()->get('content_moderation_test_resave'));
|
||||
$content_moderation_state = ContentModerationState::loadFromModeratedEntity($entity);
|
||||
$this->assertInstanceOf(ContentModerationState::class, $content_moderation_state);
|
||||
$this->assertSame(1, (int) $content_moderation_state_query->execute());
|
||||
$this->assertSame(1, (int) $content_moderation_state_revision_query->execute());
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue