You are here

function drush_paranoiasanitize_paranoia_build_sanitize_whitelist in Paranoia 7

Writes baseline sql sanitize whitelist hooks based on current db contents.

File

paranoiasanitize/paranoiasanitize.drush.inc, line 25
Drush integration for the paranoiasanitize module.

Code

function drush_paranoiasanitize_paranoia_build_sanitize_whitelist() {
  drush_log(dt('This command will build hooks based on current db contents. If a table is empty then it will suggest it be truncated as part of the paranoiasanitizing process. If you want to, you can truncate some tables and then there will be less manual adjusting of the output of this command.'), 'status');
  if (!drush_confirm(dt('Are you ready to continue?'))) {
    drush_die('Exiting');
  }

  // Get a list of tables that exist in the db.
  $existing_tables = db_query('SHOW TABLES;')
    ->fetchAllKeyed(0, 0);

  // Get a list of tables that Drupal knows about.
  $original_schema = drupal_get_complete_schema();
  global $databases;

  // Fix prefixes.
  $schema = array();
  foreach ($original_schema as $table_name => $data) {
    $schema[_paranoiasanitize_apply_db_prefix($table_name, $databases)] = $data;
  }

  // Group all tables by module.
  $tables_by_module = array();
  foreach ($existing_tables as $table) {
    if (array_key_exists($table, $schema)) {
      $tables_by_module[$schema[$table]['module']][] = $table;
    }
    else {
      $tables_by_module['PARANOIA_UNKNOWN'][] = $table;
    }
  }
  ksort($tables_by_module);

  // Now write some hooks.
  $whitelist_hooks = '';
  foreach ($tables_by_module as $module => $table_list) {
    if (function_exists($module . '_paranoiasanitize_sql_sanitize_operations')) {
      drush_log(dt("@module_paranoiasanitize_sql_sanitize_operations exists for @module.module, review that function and consider modifying or overriding it.", array(
        '@module' => $module,
      )), 'warning');
      continue;
    }
    $whitelist_hooks .= PHP_EOL . "/**\n * Implements hook_paranoiasanitize_sql_sanitize_operations().\n */\nfunction {$module}_paranoiasanitize_sql_sanitize_operations() {" . PHP_EOL;
    $whitelist_hooks .= '  return array(';
    foreach ($table_list as $table) {
      $count = db_query("SELECT COUNT(1) FROM " . $table)
        ->fetchField();
      $columns = implode("',\n        '", _paranoiasanitize_get_columns($table));

      // If the table is currently empty, suggest it be made empty.
      $empty_query = $count == 0 ? "'TRUNCATE {$table}'" : "";
      $whitelist_hooks .= "\n    '{$table}' => array(\n      'queries' => array({$empty_query}),\n      'fields' => array(\n        '{$columns}',\n       ),\n    ),";
    }
    if (!empty($whitelist_hooks)) {
      $whitelist_hooks .= PHP_EOL . '  );' . PHP_EOL . '}' . PHP_EOL;
    }
  }

  // If there is any output print it.
  if (!empty($whitelist_hooks)) {
    if (array_key_exists('PARANOIA_UNKNOWN', $tables_by_module)) {
      drush_log(dt("Your site has @count table(s) that are not associated with a hook_schema from a module currently enabled on the site. These tables have been added to a hook 'PARANOIA_UNKNOWN_paranoiasanitize_sql_sanitize_operations'. You should rename that function to match some real module on your site so that function will actually get called.", array(
        '@count' => count($tables_by_module['PARANOIA_UNKNOWN']),
      )), 'warning');
    }

    // Since there are likely relevant error messages above and this message
    // is long, prompt them to be sure they are ready to read it.
    if (!drush_confirm(dt('Your hooks are built. Please read any messages above and press Y to continue.'))) {
      drush_die('Exiting');
    }
    drush_print($whitelist_hooks);
    drush_log(dt('You can copy and paste that blob into a site-specific module or, ideally, help contrib authors by contributing this hook to their module.'), 'success');
  }
  else {
    drush_log(dt('All the tables in your db have a hook defined. You should now confirm they are actually good.'), 'success');
  }
}