diff --git a/core/modules/content_moderation/src/EntityTypeInfo.php b/core/modules/content_moderation/src/EntityTypeInfo.php index 25abf6af3b7..f7226dc7822 100644 --- a/core/modules/content_moderation/src/EntityTypeInfo.php +++ b/core/modules/content_moderation/src/EntityTypeInfo.php @@ -123,9 +123,16 @@ class EntityTypeInfo implements ContainerInjectionInterface { * @see hook_entity_type_alter() */ public function entityTypeAlter(array &$entity_types) { - foreach ($this->filterNonRevisionableEntityTypes($entity_types) as $type_name => $type) { - $entity_types[$type_name] = $this->addModerationToEntityType($type); - $entity_types[$type->get('bundle_of')] = $this->addModerationToEntity($entity_types[$type->get('bundle_of')]); + foreach ($entity_types as $entity_type_id => $entity_type) { + // The ContentModerationState entity type should never be moderated. + if ($entity_type->isRevisionable() && $entity_type_id != 'content_moderation_state') { + $entity_types[$entity_type_id] = $this->addModerationToEntityType($entity_type); + // Add additional moderation support to entity types whose bundles are + // managed by a config entity type. + if ($entity_type->getBundleEntityType()) { + $entity_types[$entity_type->getBundleEntityType()] = $this->addModerationToBundleEntityType($entity_types[$entity_type->getBundleEntityType()]); + } + } } } @@ -141,7 +148,7 @@ class EntityTypeInfo implements ContainerInjectionInterface { * @return \Drupal\Core\Entity\ContentEntityTypeInterface * The modified content entity definition. */ - protected function addModerationToEntity(ContentEntityTypeInterface $type) { + protected function addModerationToEntityType(ContentEntityTypeInterface $type) { if (!$type->hasHandlerClass('moderation')) { $handler_class = !empty($this->moderationHandlers[$type->id()]) ? $this->moderationHandlers[$type->id()] : ModerationHandler::class; $type->setHandlerClass('moderation', $handler_class); @@ -175,7 +182,7 @@ class EntityTypeInfo implements ContainerInjectionInterface { * @return \Drupal\Core\Config\Entity\ConfigEntityTypeInterface * The modified config entity definition. */ - protected function addModerationToEntityType(ConfigEntityTypeInterface $type) { + protected function addModerationToBundleEntityType(ConfigEntityTypeInterface $type) { if ($type->hasLinkTemplate('edit-form') && !$type->hasLinkTemplate('moderation-form')) { $type->setLinkTemplate('moderation-form', $type->getLinkTemplate('edit-form') . '/moderation'); } @@ -398,21 +405,4 @@ class EntityTypeInfo implements ContainerInjectionInterface { } } - /** - * Filters entity type lists to return only revisionable entity types. - * - * @param EntityTypeInterface[] $entity_types - * The master entity type list filter. - * - * @return \Drupal\Core\Config\Entity\ConfigEntityTypeInterface[] - * An array of revisionable entity types which are configuration entities. - */ - protected function filterNonRevisionableEntityTypes(array $entity_types) { - return array_filter($entity_types, function (EntityTypeInterface $type) use ($entity_types) { - return ($type instanceof ConfigEntityTypeInterface) - && ($bundle_of = $type->get('bundle_of')) - && $entity_types[$bundle_of]->isRevisionable(); - }); - } - } diff --git a/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php b/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php index 6850631043d..d059e7265d5 100644 --- a/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php +++ b/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php @@ -4,6 +4,7 @@ namespace Drupal\Tests\content_moderation\Kernel; use Drupal\content_moderation\Entity\ContentModerationState; use Drupal\entity_test\Entity\EntityTestBundle; +use Drupal\entity_test\Entity\EntityTestRev; use Drupal\entity_test\Entity\EntityTestWithBundle; use Drupal\KernelTests\KernelTestBase; use Drupal\language\Entity\ConfigurableLanguage; @@ -44,6 +45,7 @@ class ContentModerationStateTest extends KernelTestBase { $this->installEntitySchema('node'); $this->installEntitySchema('user'); $this->installEntitySchema('entity_test_with_bundle'); + $this->installEntitySchema('entity_test_rev'); $this->installEntitySchema('content_moderation_state'); $this->installConfig('content_moderation'); } @@ -314,6 +316,32 @@ class ContentModerationStateTest extends KernelTestBase { $this->assertEquals('published', EntityTestWithBundle::load($entity_test_with_bundle->id())->moderation_state->value); } + /** + * Tests that entity types without config bundles can be moderated. + */ + public function testNonBundleConfigEntityTypeModeration() { + $workflow = Workflow::load('editorial'); + $workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev'); + $workflow->save(); + + // Check that the tested entity type does not have bundles managed by a + // config entity type. + $entity_type = \Drupal::entityTypeManager()->getDefinition('entity_test_rev'); + $this->assertNull($entity_type->getBundleEntityType(), 'The test entity type does not have config bundles.'); + + // Create a test entity. + $entity_test = EntityTestRev::create([ + 'type' => 'entity_test_rev' + ]); + $entity_test->save(); + $this->assertEquals('draft', $entity_test->moderation_state->value); + + $entity_test->moderation_state->value = 'published'; + $entity_test->save(); + + $this->assertEquals('published', EntityTestRev::load($entity_test->id())->moderation_state->value); + } + /** * Reloads the node after clearing the static cache. *