Security update for Core, with self-updated composer
[yaffs-website] / web / core / modules / content_moderation / tests / src / Kernel / ContentModerationStateTest.php
index 0f8469921378fcbcb656b1ae28a9c92448971c57..00e364419a1a66e375ebf995d7078296ab3af03f 100644 (file)
@@ -3,11 +3,11 @@
 namespace Drupal\Tests\content_moderation\Kernel;
 
 use Drupal\content_moderation\Entity\ContentModerationState;
+use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityPublishedInterface;
 use Drupal\Core\Entity\EntityStorageException;
-use Drupal\entity_test\Entity\EntityTestBundle;
-use Drupal\entity_test\Entity\EntityTestWithBundle;
-use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Language\LanguageInterface;
+use Drupal\entity_test\Entity\EntityTestRev;
 use Drupal\KernelTests\KernelTestBase;
 use Drupal\language\Entity\ConfigurableLanguage;
 use Drupal\node\Entity\Node;
@@ -27,7 +27,13 @@ class ContentModerationStateTest extends KernelTestBase {
   public static $modules = [
     'entity_test',
     'node',
+    'block',
     'block_content',
+    'media',
+    'media_test_source',
+    'image',
+    'file',
+    'field',
     'content_moderation',
     'user',
     'system',
@@ -51,13 +57,16 @@ class ContentModerationStateTest extends KernelTestBase {
     $this->installSchema('node', 'node_access');
     $this->installEntitySchema('node');
     $this->installEntitySchema('user');
-    $this->installEntitySchema('entity_test_with_bundle');
     $this->installEntitySchema('entity_test_rev');
     $this->installEntitySchema('entity_test_no_bundle');
     $this->installEntitySchema('entity_test_mulrevpub');
     $this->installEntitySchema('block_content');
+    $this->installEntitySchema('media');
+    $this->installEntitySchema('file');
     $this->installEntitySchema('content_moderation_state');
     $this->installConfig('content_moderation');
+    $this->installSchema('file', 'file_usage');
+    $this->installConfig(['field', 'system', 'image', 'file', 'media']);
 
     $this->entityTypeManager = $this->container->get('entity_type.manager');
   }
@@ -68,33 +77,7 @@ class ContentModerationStateTest extends KernelTestBase {
    * @dataProvider basicModerationTestCases
    */
   public function testBasicModeration($entity_type_id) {
-    // Make the 'entity_test_with_bundle' entity type revisionable.
-    if ($entity_type_id == 'entity_test_with_bundle') {
-      $this->setEntityTestWithBundleKeys(['revision' => 'revision_id']);
-    }
-
-    $entity_storage = $this->entityTypeManager->getStorage($entity_type_id);
-    $bundle_id = $entity_type_id;
-    $bundle_entity_type_id = $this->entityTypeManager->getDefinition($entity_type_id)->getBundleEntityType();
-    if ($bundle_entity_type_id) {
-      $bundle_entity_type_definition = $this->entityTypeManager->getDefinition($bundle_entity_type_id);
-      $entity_type_storage = $this->entityTypeManager->getStorage($bundle_entity_type_id);
-
-      $entity_type = $entity_type_storage->create([
-        $bundle_entity_type_definition->getKey('id') => 'example',
-      ]);
-      $entity_type->save();
-      $bundle_id = $entity_type->id();
-    }
-
-    $workflow = Workflow::load('editorial');
-    $workflow->getTypePlugin()->addEntityTypeAndBundle($entity_type_id, $bundle_id);
-    $workflow->save();
-
-    $entity = $entity_storage->create([
-      'title' => 'Test title',
-      $this->entityTypeManager->getDefinition($entity_type_id)->getKey('bundle') => $bundle_id,
-    ]);
+    $entity = $this->createEntity($entity_type_id);
     if ($entity instanceof EntityPublishedInterface) {
       $entity->setUnpublished();
     }
@@ -145,6 +128,7 @@ class ContentModerationStateTest extends KernelTestBase {
     $entity->save();
 
     // Revert to the previous (published) revision.
+    $entity_storage = $this->entityTypeManager->getStorage($entity_type_id);
     $previous_revision = $entity_storage->loadRevision(4);
     $previous_revision->isDefaultRevision(TRUE);
     $previous_revision->setNewRevision(TRUE);
@@ -174,8 +158,8 @@ class ContentModerationStateTest extends KernelTestBase {
       'Block content' => [
         'block_content',
       ],
-      'Test Entity with Bundle' => [
-        'entity_test_with_bundle',
+      'Media' => [
+        'media',
       ],
       'Test entity - revisions, data table, and published interface' => [
         'entity_test_mulrevpub',
@@ -189,6 +173,62 @@ class ContentModerationStateTest extends KernelTestBase {
     ];
   }
 
+  /**
+   * Tests removal of content moderation state entity field data.
+   *
+   * @dataProvider basicModerationTestCases
+   */
+  public function testContentModerationStateDataRemoval($entity_type_id) {
+    // Test content moderation state deletion.
+    /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
+    $entity = $this->createEntity($entity_type_id);
+    $entity->save();
+    $entity = $this->reloadEntity($entity);
+    $entity->delete();
+    $content_moderation_state = ContentModerationState::loadFromModeratedEntity($entity);
+    $this->assertFalse($content_moderation_state);
+
+    // Test content moderation state revision deletion.
+    /** @var \Drupal\Core\Entity\ContentEntityInterface $entity2 */
+    $entity2 = $this->createEntity($entity_type_id);
+    $entity2->save();
+    $revision = clone $entity2;
+    $revision->isDefaultRevision(FALSE);
+    $content_moderation_state = ContentModerationState::loadFromModeratedEntity($revision);
+    $this->assertTrue($content_moderation_state);
+    $entity2 = $this->reloadEntity($entity2);
+    $entity2->setNewRevision(TRUE);
+    $entity2->save();
+    $entity_storage = $this->entityTypeManager->getStorage($entity_type_id);
+    $entity_storage->deleteRevision($revision->getRevisionId());
+    $content_moderation_state = ContentModerationState::loadFromModeratedEntity($revision);
+    $this->assertFalse($content_moderation_state);
+    $content_moderation_state = ContentModerationState::loadFromModeratedEntity($entity2);
+    $this->assertTrue($content_moderation_state);
+
+    // Test content moderation state translation deletion.
+    if ($this->entityTypeManager->getDefinition($entity_type_id)->isTranslatable()) {
+      /** @var \Drupal\Core\Entity\ContentEntityInterface $entity3 */
+      $entity3 = $this->createEntity($entity_type_id);
+      $langcode = 'it';
+      ConfigurableLanguage::createFromLangcode($langcode)
+        ->save();
+      $entity3->save();
+      $translation = $entity3->addTranslation($langcode, ['title' => 'Titolo test']);
+      // Make sure we add values for all of the required fields.
+      if ($entity_type_id == 'block_content') {
+        $translation->info = $this->randomString();
+      }
+      $translation->save();
+      $content_moderation_state = ContentModerationState::loadFromModeratedEntity($entity3);
+      $this->assertTrue($content_moderation_state->hasTranslation($langcode));
+      $entity3->removeTranslation($langcode);
+      $entity3->save();
+      $content_moderation_state = ContentModerationState::loadFromModeratedEntity($entity3);
+      $this->assertFalse($content_moderation_state->hasTranslation($langcode));
+    }
+  }
+
   /**
    * Tests basic multilingual content moderation through the API.
    */
@@ -306,92 +346,114 @@ class ContentModerationStateTest extends KernelTestBase {
   }
 
   /**
-   * Tests that a non-translatable entity type with a langcode can be moderated.
+   * Tests moderation when the moderation_state field has a config override.
    */
-  public function testNonTranslatableEntityTypeModeration() {
-    // Make the 'entity_test_with_bundle' entity type revisionable.
-    $this->setEntityTestWithBundleKeys(['revision' => 'revision_id']);
+  public function testModerationWithFieldConfigOverride() {
+    NodeType::create([
+      'type' => 'test_type',
+    ])->save();
 
-    // Create a test bundle.
-    $entity_test_bundle = EntityTestBundle::create([
-      'id' => 'example',
+    $workflow = Workflow::load('editorial');
+    $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'test_type');
+    $workflow->save();
+
+    $fields = $this->container->get('entity_field.manager')->getFieldDefinitions('node', 'test_type');
+    $field_config = $fields['moderation_state']->getConfig('test_type');
+    $field_config->setLabel('Field Override!');
+    $field_config->save();
+
+    $node = Node::create([
+      'title' => 'Test node',
+      'type' => 'test_type',
     ]);
-    $entity_test_bundle->save();
+    $node->save();
+    $this->assertFalse($node->isPublished());
+    $this->assertEquals('draft', $node->moderation_state->value);
+
+    $node->moderation_state = 'published';
+    $node->save();
+    $this->assertTrue($node->isPublished());
+    $this->assertEquals('published', $node->moderation_state->value);
+  }
 
+  /**
+   * Tests that entities with special languages can be moderated.
+   */
+  public function testModerationWithSpecialLanguages() {
     $workflow = Workflow::load('editorial');
-    $workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_with_bundle', 'example');
+    $workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev');
     $workflow->save();
 
-    // Check that the tested entity type is not translatable.
-    $entity_type = \Drupal::entityTypeManager()->getDefinition('entity_test_with_bundle');
-    $this->assertFalse($entity_type->isTranslatable(), 'The test entity type is not translatable.');
-
     // Create a test entity.
-    $entity_test_with_bundle = EntityTestWithBundle::create([
-      'type' => 'example'
+    $entity = EntityTestRev::create([
+      'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
     ]);
-    $entity_test_with_bundle->save();
-    $this->assertEquals('draft', $entity_test_with_bundle->moderation_state->value);
+    $entity->save();
+    $this->assertEquals('draft', $entity->moderation_state->value);
 
-    $entity_test_with_bundle->moderation_state->value = 'published';
-    $entity_test_with_bundle->save();
+    $entity->moderation_state->value = 'published';
+    $entity->save();
 
-    $this->assertEquals('published', EntityTestWithBundle::load($entity_test_with_bundle->id())->moderation_state->value);
+    $this->assertEquals('published', EntityTestRev::load($entity->id())->moderation_state->value);
   }
 
   /**
-   * Tests that a non-translatable entity type without a langcode can be
-   * moderated.
+   * Tests that a non-translatable entity type with a langcode can be moderated.
    */
-  public function testNonLangcodeEntityTypeModeration() {
-    // Make the 'entity_test_with_bundle' entity type revisionable and unset
-    // the langcode entity key.
-    $this->setEntityTestWithBundleKeys(['revision' => 'revision_id'], ['langcode']);
-
-    // Create a test bundle.
-    $entity_test_bundle = EntityTestBundle::create([
-      'id' => 'example',
-    ]);
-    $entity_test_bundle->save();
-
+  public function testNonTranslatableEntityTypeModeration() {
     $workflow = Workflow::load('editorial');
-    $workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_with_bundle', 'example');
+    $workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev');
     $workflow->save();
 
     // Check that the tested entity type is not translatable.
-    $entity_type = \Drupal::entityTypeManager()->getDefinition('entity_test_with_bundle');
+    $entity_type = \Drupal::entityTypeManager()->getDefinition('entity_test_rev');
     $this->assertFalse($entity_type->isTranslatable(), 'The test entity type is not translatable.');
 
     // Create a test entity.
-    $entity_test_with_bundle = EntityTestWithBundle::create([
-      'type' => 'example'
-    ]);
-    $entity_test_with_bundle->save();
-    $this->assertEquals('draft', $entity_test_with_bundle->moderation_state->value);
+    $entity = EntityTestRev::create();
+    $entity->save();
+    $this->assertEquals('draft', $entity->moderation_state->value);
 
-    $entity_test_with_bundle->moderation_state->value = 'published';
-    $entity_test_with_bundle->save();
+    $entity->moderation_state->value = 'published';
+    $entity->save();
 
-    $this->assertEquals('published', EntityTestWithBundle::load($entity_test_with_bundle->id())->moderation_state->value);
+    $this->assertEquals('published', EntityTestRev::load($entity->id())->moderation_state->value);
   }
 
   /**
-   * Set the keys on the test entity type.
-   *
-   * @param array $keys
-   *   The entity keys to override
-   * @param array $remove_keys
-   *   Keys to remove.
+   * Tests that a non-translatable entity type without a langcode can be
+   * moderated.
    */
-  protected function setEntityTestWithBundleKeys($keys, $remove_keys = []) {
-    $entity_type = clone \Drupal::entityTypeManager()->getDefinition('entity_test_with_bundle');
-    $original_keys = $entity_type->getKeys();
-    foreach ($remove_keys as $remove_key) {
-      unset($original_keys[$remove_key]);
-    }
-    $entity_type->set('entity_keys', $keys + $original_keys);
-    \Drupal::state()->set('entity_test_with_bundle.entity_type', $entity_type);
+  public function testNonLangcodeEntityTypeModeration() {
+    // Unset the langcode entity key for 'entity_test_rev'.
+    $entity_type = clone \Drupal::entityTypeManager()->getDefinition('entity_test_rev');
+    $keys = $entity_type->getKeys();
+    unset($keys['langcode']);
+    $entity_type->set('entity_keys', $keys);
+    \Drupal::state()->set('entity_test_rev.entity_type', $entity_type);
+
+    // Update the entity type in order to remove the 'langcode' field.
     \Drupal::entityDefinitionUpdateManager()->applyUpdates();
+
+    $workflow = Workflow::load('editorial');
+    $workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev');
+    $workflow->save();
+
+    // Check that the tested entity type is not translatable and does not have a
+    // 'langcode' entity key.
+    $entity_type = \Drupal::entityTypeManager()->getDefinition('entity_test_rev');
+    $this->assertFalse($entity_type->isTranslatable(), 'The test entity type is not translatable.');
+    $this->assertFalse($entity_type->getKey('langcode'), "The test entity type does not have a 'langcode' entity key.");
+
+    // Create a test entity.
+    $entity = EntityTestRev::create();
+    $entity->save();
+    $this->assertEquals('draft', $entity->moderation_state->value);
+
+    $entity->moderation_state->value = 'published';
+    $entity->save();
+
+    $this->assertEquals('published', EntityTestRev::load($entity->id())->moderation_state->value);
   }
 
   /**
@@ -439,6 +501,98 @@ class ContentModerationStateTest extends KernelTestBase {
     $this->assertEquals([], $entity_types);
   }
 
+  /**
+   * Test the content moderation workflow dependencies for non-config bundles.
+   */
+  public function testWorkflowNonConfigBundleDependencies() {
+    // Create a bundle not based on any particular configuration.
+    entity_test_create_bundle('test_bundle');
+
+    $workflow = Workflow::load('editorial');
+    $workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test', 'test_bundle');
+    $workflow->save();
+
+    // Ensure the bundle is correctly added to the workflow.
+    $this->assertEquals([
+      'module' => [
+        'content_moderation',
+        'entity_test',
+      ],
+    ], $workflow->getDependencies());
+    $this->assertEquals([
+      'test_bundle',
+    ], $workflow->getTypePlugin()->getBundlesForEntityType('entity_test'));
+
+    // Delete the test bundle to ensure the workflow entity responds
+    // appropriately.
+    entity_test_delete_bundle('test_bundle');
+
+    $workflow = Workflow::load('editorial');
+    $this->assertEquals([], $workflow->getTypePlugin()->getBundlesForEntityType('entity_test'));
+    $this->assertEquals([
+      'module' => [
+        'content_moderation',
+      ],
+    ], $workflow->getDependencies());
+  }
+
+  /**
+   * Creates an entity.
+   *
+   * The entity will have required fields populated and the corresponding bundle
+   * will be enabled for content moderation.
+   *
+   * @param string $entity_type_id
+   *   The entity type ID.
+   *
+   * @return \Drupal\Core\Entity\ContentEntityInterface
+   *   The created entity.
+   */
+  protected function createEntity($entity_type_id) {
+    $entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
+
+    $bundle_id = $entity_type_id;
+    // Set up a bundle entity type for the specified entity type, if needed.
+    if ($bundle_entity_type_id = $entity_type->getBundleEntityType()) {
+      $bundle_entity_type = $this->entityTypeManager->getDefinition($bundle_entity_type_id);
+      $bundle_entity_storage = $this->entityTypeManager->getStorage($bundle_entity_type_id);
+
+      $bundle_id = 'example';
+      if (!$bundle_entity_storage->load($bundle_id)) {
+        $bundle_entity = $bundle_entity_storage->create([
+          $bundle_entity_type->getKey('id') => 'example',
+        ]);
+        if ($entity_type_id == 'media') {
+          $bundle_entity->set('source', 'test');
+          $bundle_entity->save();
+          $source_field = $bundle_entity->getSource()->createSourceField($bundle_entity);
+          $source_field->getFieldStorageDefinition()->save();
+          $source_field->save();
+          $bundle_entity->set('source_configuration', [
+            'source_field' => $source_field->getName(),
+          ]);
+        }
+        $bundle_entity->save();
+      }
+    }
+
+    $workflow = Workflow::load('editorial');
+    $workflow->getTypePlugin()->addEntityTypeAndBundle($entity_type_id, $bundle_id);
+    $workflow->save();
+
+    /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
+    $entity_storage = $this->entityTypeManager->getStorage($entity_type_id);
+    $entity = $entity_storage->create([
+      $entity_type->getKey('label') => 'Test title',
+      $entity_type->getKey('bundle') => $bundle_id,
+    ]);
+    // Make sure we add values for all of the required fields.
+    if ($entity_type_id == 'block_content') {
+      $entity->info = $this->randomString();
+    }
+    return $entity;
+  }
+
   /**
    * Reloads the entity after clearing the static cache.
    *