function system_update_10201

Clear left over entries in the revision data table.

File

core/modules/system/system.install, line 1861

Code

function system_update_10201(&$sandbox) {
  $entity_type_manager = \Drupal::entityTypeManager();
  $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager();
  $database = \Drupal::database();
  // Initialize the sandbox. Store a list of entity types that need to be
  // cleaned up in a list, then keep track of the current entity type by
  // its numeric index.
  if (!isset($sandbox['current_key'])) {
    // This must be the first run. Initialize the sandbox.
    $sandbox['current_key'] = 0;
    // Filter the entity types for those that need to be cleaned up.
    $definitions = array_filter($entity_type_manager->getDefinitions(), function (EntityTypeInterface $entity_type) use ($entity_definition_update_manager, $database) {
      // Use the last installed entity type definition for the filtering, as
      // some might not have been installed yet or are only being made
      // revisionable or translatable in a later update function.
      $entity_type = $entity_definition_update_manager->getEntityType($entity_type->id());
      if (!$entity_type) {
        // New entity type that is not installed yet, nothing to clean up, skip.
        return FALSE;
      }
      if (!$entity_type->isRevisionable() || !$entity_type->isTranslatable()) {
        // Entity type is either not revisionable or not translatable.
        return FALSE;
      }
      // Ensure the revision and revision data tables really exist.
      $entity_type_id = $entity_type->id();
      $revision_table = $entity_type->getRevisionTable() ?: $entity_type_id . '_revision';
      $revision_data_table = $entity_type->getRevisionDataTable() ?: $entity_type_id . '_field_revision';
      return $database->schema()
        ->tableExists($revision_table) && $database->schema()
        ->tableExists($revision_data_table);
    });
    if (empty($definitions)) {
      $sandbox['#finished'] = TRUE;
      return;
    }
    $sandbox['entity_type_ids'] = array_keys($definitions);
    $sandbox['max'] = count($sandbox['entity_type_ids']);
  }
  // Get the current entity type. Fetch 100 records that should be deleted.
  // Order them by entity ID to optimize the amount of delete queries that need
  // to be executed.
  $entity_type_id = $sandbox['entity_type_ids'][$sandbox['current_key']];
  /** @var \Drupal\Core\Entity\ContentEntityTypeInterface $entity_type */
  $entity_type = $entity_definition_update_manager->getEntityType($entity_type_id);
  $revision_table = $entity_type->getRevisionTable() ?: $entity_type_id . '_revision';
  $revision_data_table = $entity_type->getRevisionDataTable() ?: $entity_type_id . '_field_revision';
  $revision_field = $entity_type->getKey('revision');
  $query = $database->select($revision_data_table, 'rd');
  $query->leftJoin($revision_table, 'r', 'r.' . $revision_field . ' = rd.' . $revision_field);
  $query->addField('rd', $revision_field, 'revision');
  $revision_ids = $query->isNull('r.' . $revision_field)
    ->range(0, 100)
    ->execute()
    ->fetchCol();
  if ($revision_ids) {
    $database->delete($revision_data_table)
      ->condition($revision_field, $revision_ids, 'IN')
      ->execute();
  }
  // If there are less than 100 rows, the entity type was cleaned up, move on to
  // the next one.
  if (count($revision_ids) < 100) {
    $sandbox['current_key']++;
  }
  $sandbox['#finished'] = $sandbox['current_key'] == $sandbox['max'];
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.