function system_update_10201

Clear left over entries in the revision data table.

File

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

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.