2

After upgrading a site to Drupal 9, I started seeing the following error when visiting the site:

Drupal\Core\Entity\Exception\UnsupportedEntityTypeDefinitionException: The entity type banner does not have an "revision_created" entity revision metadata key. in Drupal\Core\Entity\RevisionableContentEntityBase::revisionLogBaseFieldDefinitions() (line 35 of core/lib/Drupal/Core/Entity/RevisionLogEntityTrait.php).

The site has a custom entity, banner.

I rolled back to Drupal 8.9, created a module to make the same entity revisionable, and added the following code in module.install.

/**
 * Implements hook_update_dependencies().
 */
function mirum_entity_revision_update_dependencies() {
  // The update function that adds the status field must run after
  // content_translation_update_8400() which fixes NULL values for the
  // 'content_translation_status' field.
  if (\Drupal::moduleHandler()->moduleExists('content_translation')) {
    $dependencies['mirum_entity_revision'][8400] = [
      'content_translation' => 8400,
    ];

    return $dependencies;
  }
}

/**
 * Add the 'published' and revisionable metadata fields to banner.
 */
function mirum_entity_revision_update_8400() {
  $definition_update_manager = \Drupal::entityDefinitionUpdateManager();

  // Add the published entity key and revisionable metadata fields to the
  // banner entity type.
  $entity_type = $definition_update_manager->getEntityType('banner');
  $entity_type_id = $entity_type->id();

  $entity_keys = $entity_type->getKeys();
  $entity_keys['published'] = 'status';
  $entity_type->set('entity_keys', $entity_keys);

  $revision_metadata_keys = [
    'revision_user' => 'revision_user',
    'revision_created' => 'revision_created',
    'revision_log_message' => 'revision_log_message'
  ];
  $entity_type->set('revision_metadata_keys', $revision_metadata_keys);

  $definition_update_manager->updateEntityType($entity_type);

  // Add the status field.
  $status = BaseFieldDefinition::create('boolean')
    ->setLabel(t('Publishing status'))
    ->setDescription(t('A boolean indicating the published state.'))
    ->setRevisionable(TRUE)
    ->setTranslatable(TRUE)
    ->setDefaultValue(TRUE);

  $has_content_translation_status_field = \Drupal::moduleHandler()->moduleExists('content_translation') && $definition_update_manager->getFieldStorageDefinition('content_translation_status', $entity_type_id);
  if ($has_content_translation_status_field) {
    $status->setInitialValueFromField('content_translation_status');
  }
  else {
    $status->setInitialValue(TRUE);
  }
  $definition_update_manager->installFieldStorageDefinition('status', $entity_type_id, $entity_type_id, $status);

  // Add the revision metadata fields.
  $revision_created = BaseFieldDefinition::create('created')
    ->setLabel(t('Revision create time'))
    ->setDescription(t('The time that the current revision was created.'))
    ->setRevisionable(TRUE);
  $definition_update_manager->installFieldStorageDefinition('revision_created', $entity_type_id, $entity_type_id, $revision_created);

  $revision_user = BaseFieldDefinition::create('entity_reference')
    ->setLabel(t('Revision user'))
    ->setDescription(t('The user ID of the author of the current revision.'))
    ->setSetting('target_type', 'user')
    ->setRevisionable(TRUE);
  $definition_update_manager->installFieldStorageDefinition('revision_user', $entity_type_id, $entity_type_id, $revision_user);

  $revision_log_message = BaseFieldDefinition::create('string_long')
    ->setLabel(t('Revision log message'))
    ->setDescription(t('Briefly describe the changes you have made.'))
    ->setRevisionable(TRUE)
    ->setDefaultValue('')
    ->setDisplayOptions('form', [
      'type' => 'string_textarea',
      'weight' => 25,
      'settings' => [
        'rows' => 4,
      ],
    ]);
  $definition_update_manager->installFieldStorageDefinition('revision_log_message', $entity_type_id, $entity_type_id, $revision_log_message);

  // Uninstall the 'content_translation_status' field if needed.
  $database = \Drupal::database();
  if ($has_content_translation_status_field) {
    // First we have to remove the field data.
    $database->update($entity_type->getDataTable())
      ->fields(['content_translation_status' => NULL])
      ->execute();

    // A site may have disabled revisionability for this entity type.
    if ($entity_type->isRevisionable()) {
      $database->update($entity_type->getRevisionDataTable())
        ->fields(['content_translation_status' => NULL])
        ->execute();
    }

    $content_translation_status = $definition_update_manager->getFieldStorageDefinition('content_translation_status', $entity_type_id);
    $definition_update_manager->uninstallFieldStorageDefinition($content_translation_status);
  }

  return t('@entity_type_label has been converted to revisionable and publishable.', ['@entity_type_label' => $entity_type->getLabel()]);
}

I activated the module and upgraded again to Drupal 9, but the error persists.

I am using Drush and Composer but because of this error with the entity, none of the Drush commands work.

For example, running drush cr returns the following error.

The entity type banner does not have an "revision_created" entity revision metadata key.

1 Answer 1

4

You have set the missing metakey already in the update hook, but this is not stored in the entity definitions permanently, this is only temporary for the update process:

  $revision_metadata_keys = [
    'revision_user' => 'revision_user',
    'revision_created' => 'revision_created',
    'revision_log_message' => 'revision_log_message'
  ];
  $entity_type->set('revision_metadata_keys', $revision_metadata_keys);

For this you need to include them in the entity annotations:

/mymodule/src/Entity/Banner.php

 * @ContentEntityType(
 *   id = "banner",
 *   ...
 *   revision_metadata_keys = {
 *     "revision_user" = "revision_user",
 *     "revision_created" = "revision_created",
 *     "revision_log_message" = "revision_log_message",
 *   },

Then the command drush cr should update the entity definition without error.

6
  • may you please clarify, which file do I add this snippet to? does this go somewhere in the new module I created inside the .install file, or do I add it somewhere in the existing banner module? Commented Feb 3, 2021 at 10:53
  • In the annotations of the entity class, see the edit. Didn't you work on that class while making the entity revisionable?
    – 4uk4
    Commented Feb 3, 2021 at 11:01
  • no #4k4. I already found the class when given the site. So the entity was created through a module since Drupal 8.6.16. Commented Feb 3, 2021 at 13:20
  • OK, my answer is for the error message. You probably need to change more things in the entity class to make it revisionable, but perhaps it is already and only the metadata is missing. Who knows :-).
    – 4uk4
    Commented Feb 3, 2021 at 13:37
  • The fields are revisionable because there is a method(setRevisionable) set to true on all fields. But when I check the database table, the banner table does not have the revision_created attribute. Am thinking of adding it through a sql query but am not sure what the data type it is nor if its a recommended approach. Commented Feb 3, 2021 at 13:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.