You are here

function drush_acsf_site_scrub in Acquia Cloud Site Factory Connector 8

Command callback. Scrubs the site database and/or other storage.

Note that 'scrubbing' in our case doesn't mean just clearing configuration values but also initializing them for use in a new website.

drush acsf-site-scrub is called by a 'db-copy' hosting task, which in turn seems to be called (only?) by the staging process.

File

./acsf.drush.inc, line 85
Provides drush commands for site related operations.

Code

function drush_acsf_site_scrub() {
  drush_print(dt('Flushing all caches ... '));
  drupal_flush_all_caches();
  drush_print(dt('Caches flushed.'));
  $connection = \Drupal::database();

  // Ensure that we are testing the scrub cleanly.
  \Drupal::state()
    ->delete('acsf_site_scrubbed');
  drush_print(dt('Preparing to scrub users ... '));

  // Get a list of roles whose users should be preserved during staging
  // scrubbing.  Both lists are implemented as "alters" for consistency with
  // hook_acsf_duplication_scrub_preserved_users_alter.
  $preserved_roles = [];
  \Drupal::moduleHandler()
    ->alter('acsf_staging_scrub_admin_roles', $preserved_roles);
  if (!empty($preserved_roles)) {
    drush_print(dt('Preserving roles: @rids', [
      '@rids' => implode(', ', $preserved_roles),
    ]));
  }

  // Get a list of UIDs to preserve during staging scrubbing.  UIDs are first
  // obtained by the preserved roles, then can be altered to add or remove UIDs.
  if (!empty($preserved_roles)) {
    $preserved_users = \Drupal::entityQuery('user')
      ->condition('roles', $preserved_roles, 'IN')
      ->execute();
  }
  else {
    $preserved_users = [];
  }
  \Drupal::moduleHandler()
    ->alter('acsf_staging_scrub_preserved_users', $preserved_users);

  // Always preserve the anonymous user.
  $preserved_users[] = 0;
  $preserved_users = array_unique($preserved_users);

  // The anonymous user makes the size of this array always at least 1.
  drush_print(dt('Preserving users: @uids', [
    '@uids' => implode(', ', $preserved_users),
  ]));

  // Avoid collisions between the Factory and site users when scrubbing.
  $connection
    ->update('users_field_data')
    ->expression('mail', "CONCAT('user', uid, '@', MD5(mail), '.example.com')")
    ->expression('init', "CONCAT('user', uid, '@', MD5(init), '.example.com')")
    ->condition('uid', $preserved_users, 'NOT IN')
    ->execute();

  // Reset the cron key.
  \Drupal::state()
    ->set('system.cron_key', md5(mt_rand()));

  // Reset the drupal private key.
  \Drupal::service('private_key')
    ->set('');

  // Reset the local site data and run acsf-site-sync to fetch factory data
  // about the site.
  $site = AcsfSite::load();
  $site
    ->clean();
  drush_acsf_site_sync();
  drush_log(dt('Executed acsf-site-sync to gather site data from factory and reset all acsf variables.'), 'ok');

  // Trigger a rebuild of router paths (formerly 'menu paths').
  \Drupal::service("router.builder")
    ->rebuild();

  // Clear sessions and log tables that might have stale data, and whose
  // implementing classes have no dedicated 'clear()' or equivalent mechanism.
  $truncate_tables = [
    'sessions',
    'watchdog',
    'acsf_theme_notifications',
  ];
  foreach ($truncate_tables as $table) {
    if ($connection
      ->schema()
      ->tableExists($table)) {
      $connection
        ->truncate($table)
        ->execute();
    }
  }

  // Clear caches and key-value store.
  $bins = [
    'bootstrap',
    'config',
    'data',
    'default',
    'discovery',
    'dynamic_page_cache',
    'entity',
    'menu',
    'migrate',
    'render',
    'rest',
    'toolbar',
  ];
  foreach ($bins as $bin) {
    if (\Drupal::hasService("cache.{$bin}")) {
      \Drupal::cache($bin)
        ->deleteAll();
    }
  }
  $bins = [
    'form',
    'form_state',
  ];
  foreach ($bins as $bin) {
    \Drupal::keyValueExpirable($bin)
      ->deleteAll();
  }

  // Raise the database connection wait timeout (default 10 minutes) so mysql
  // will not have "gone away" after the separate sql-sanitize process ends.
  \Drupal::database()
    ->query('SET session wait_timeout=3600');

  // Run the sql-sanitize which allows customers to use custom scrubbing. We
  // will handle email addresses and passwords ourselves.
  drush_invoke_process('@self', 'sql-sanitize', [], [
    'sanitize-email' => 'no',
    'sanitize-password' => 'no',
  ]);

  // Mark this database as scrubbed.
  \Drupal::state()
    ->set('acsf_site_scrubbed', 'scrubbed');
}