function DatabaseUpdate::fixMissingSchema

Same name and namespace in other branches
  1. 11.x core/lib/Drupal/Core/Update/DatabaseUpdate.php \Drupal\Core\Update\DatabaseUpdate::fixMissingSchema()

Detect and fix 'missing' schema information with the helper.

Repairs the case where a module has no schema version recorded. This has to be done prior to updates being run, otherwise the update system would detect and attempt to run all historical updates for a module.

@todo remove in a major version after https://www.drupal.org/project/drupal/issues/3130037 has been fixed.

@internal

File

core/lib/Drupal/Core/Update/DatabaseUpdate.php, line 104

Class

DatabaseUpdate
Drupal database update API.

Namespace

Drupal\Core\Update

Code

public function fixMissingSchema() : void {
  $versions = $this->updateRegistry
    ->getAllInstalledVersions();
  $enabled_modules = $this->moduleHandler
    ->getModuleList();
  foreach (array_keys($enabled_modules) as $module) {
    // All modules should have a recorded schema version, but when they don't,
    // detect and fix the problem.
    if (!isset($versions[$module])) {
      // Ensure the .install file is loaded.
      $this->moduleHandler
        ->loadInclude($module, 'install');
      $all_updates = $this->updateRegistry
        ->getAvailableUpdates($module);
      // If the schema version of a module hasn't been recorded, we cannot
      // know the actual schema version a module is at, because no updates
      // will ever have been run on the site and it was not set correctly when
      // the module was installed, so instead set it to the same as the last
      // update. This means that updates will proceed again the next time the
      // module is updated and a new update is added. Updates added in between
      // the module being installed and the schema version being fixed here
      // (if any have been added) will never be run, but we have no way to
      // identify which updates these are.
      if ($all_updates) {
        $last_update = max($all_updates);
      }
      else {
        $last_update = \Drupal::CORE_MINIMUM_SCHEMA_VERSION;
      }
      // If the module implements hook_update_last_removed() use the value of
      // that if it's higher than the schema versions found so far. The hook
      // is procedural only and is not collected by the hook system, so call
      // the function directly.
      $function = $module . '_update_last_removed';
      if (function_exists($function) && $last_removed = $function()) {
        $last_update = max($last_update, $last_removed);
      }
      $this->updateRegistry
        ->setInstalledVersion($module, $last_update);
      $args = [
        '%module' => $module,
        '%last_update_hook' => $module . '_update_' . $last_update . '()',
      ];
      $this->messenger
        ->addWarning($this->t('Schema information for module %module was missing from the database. You should manually review the module updates and your database to check if any updates have been skipped up to, and including, %last_update_hook.', $args));
      $this->loggerChannelFactory
        ->get('update')
        ->warning('Schema information for module %module was missing from the database. You should manually review the module updates and your database to check if any updates have been skipped up to, and including, %last_update_hook.', $args);
    }
  }
}

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