Index: dba.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/dba/dba.module,v
retrieving revision 1.54
diff -u -r1.54 dba.module
--- dba.module	24 Jun 2007 03:41:12 -0000	1.54
+++ dba.module	29 Jul 2007 13:41:23 -0000
@@ -77,12 +77,14 @@
     );
   }
   elseif (strstr(drupal_get_path_alias($_GET['q']), 'admin/build/database')) {
-    // You can only view or describe one table at a time.
-    $tables = dba_get_active_tables(0);
-    if (!empty($tables)) {
+    $tables = dba_get_active_tables(FALSE);
+    if (count($tables) == 1) {
+      // You can only view or describe one table at a time.
+      $table = reset($tables);
+
       // Regular subtabs.
       $items[] = array(
-        'path' => "admin/build/database/table/$tables/view",
+        'path' => "admin/build/database/table/$table/view",
         'title' => t('View'),
         'callback' => 'dba_admin_tables_view',
         'access' => $access,
@@ -90,7 +92,7 @@
         'weight' => 0,
       );
       $items[] = array(
-        'path' => "admin/build/database/table/$tables/describe",
+        'path' => "admin/build/database/table/$table/describe",
         'title' => t('Describe'),
         'callback' => 'dba_admin_tables_describe',
         'access' => $access,
@@ -99,7 +101,7 @@
       );
       if (_is_mysql()) {
         $items[] = array(
-          'path' => "admin/build/database/table/$tables/check",
+          'path' => "admin/build/database/table/$table/check",
           'title' => t('Check'),
           'callback' => 'dba_admin_tables_check',
           'access' => $access,
@@ -107,7 +109,7 @@
           'weight' => 4,
         );
         $items[] = array(
-          'path' => "admin/build/database/table/$tables/optimize",
+          'path' => "admin/build/database/table/$table/optimize",
           'title' => t('Optimize'),
           'callback' => 'dba_admin_tables_optimize',
           'access' => $access,
@@ -117,7 +119,7 @@
       }
       // Subtabs for dbas with administer permissions.
       $items[] = array(
-        'path' => "admin/build/database/table/$tables/backup",
+        'path' => "admin/build/database/table/$table/backup",
         'title' => t('Backup'),
         'callback' => 'dba_admin_tables_verify_op',
         'callback arguments' => array('backup'),
@@ -126,7 +128,7 @@
         'weight' => 8,
       );
       $items[] = array(
-        'path' => "admin/build/database/table/$tables/empty",
+        'path' => "admin/build/database/table/$table/empty",
         'title' => t('Empty'),
         'callback' => 'dba_admin_tables_verify_op',
         'callback arguments' => array('empty'),
@@ -135,7 +137,7 @@
         'weight' => 8,
       );
       $items[] = array(
-        'path' => "admin/build/database/table/$tables/drop",
+        'path' => "admin/build/database/table/$table/drop",
         'title' => t('Drop'),
         'callback' => 'dba_admin_tables_verify_op',
         'callback arguments' => array('drop'),
@@ -421,7 +423,7 @@
  * MySQL only: check the selected table(s).
  */
 function dba_admin_tables_check() {
-  return drupal_get_form('dba_check_tables');
+  return drupal_get_form('dba_check_tables_form');
 }
 
 /**
@@ -441,15 +443,9 @@
  * drop the selected table(s) by means of a confirm form.
  */
 function dba_admin_tables_verify_op($op) {
-  $tables = dba_get_active_tables(0);
+  $tables = dba_get_active_tables(FALSE);
   unset($_SESSION['dba_tables']);
-  if (empty($tables)) {
-    drupal_set_message(t('You must select the tables to !op.', array('!op' => _dba_ops($op))), 'error');
-    drupal_goto('admin/build/database');
-  }
-  $edit['tables'] = $tables;
-  
-  return drupal_get_form('dba_verify', $edit, $op);
+  return drupal_get_form('dba_verify', $tables, $op);
 }
 
 function theme_dba_database_overview_form($form) {
@@ -463,7 +459,7 @@
   $tables = dba_get_tables();
   foreach ($tables as $table) {
     $count = dba_get_row_count($table);
-    $checkbox = drupal_render($form[$table]);
+    $checkbox = drupal_render($form['tables'][$table]);
     $rows[] = array($checkbox, l($table, "admin/build/database/table/$table/view"), $count);
   }
   $output .= dba_select_all_js();
@@ -476,8 +472,11 @@
 
 function dba_database_overview_form() {
   $tables = dba_get_tables();
+  $form = array();
+  $form['#tree'] = TRUE;
+  $form['tables'] = array();
   foreach ($tables as $table) {
-    $form[$table] = array(
+    $form['tables'][$table] = array(
       '#type' => 'checkbox',
       '#title' => '',
       '#default_value' => 0,
@@ -495,15 +494,18 @@
   return $form;
 }
 
-function dba_database_overview_form_submit($form_id, $form_values) {
-  $op = isset($_POST['op']) ? $_POST['op'] : '';
-  $tables = dba_get_active_tables(0, $form_values);
-  if (empty($tables)) {
-    drupal_set_message(t('You must select the table(s) to %op.', array('%op' => theme('placeholder', $op))), 'error');
-    return;
+function dba_database_overview_form_validate($form_id, $form_values) {
+  if (!array_filter($form_values['tables'])) {
+    form_set_error('tables', t('You must select the table(s) to @op.', array('@op' => strtolower($form_values['op']))));
   }
-  $_SESSION['dba_tables'] = $tables;
-  switch ($op) {
+}
+
+function dba_database_overview_form_submit($form_id, $form_values) {
+  // We already validated the overview form, so we know we have tables.
+  $form_tables = array_keys(array_filter($form_values['tables']));
+  $_SESSION['dba_tables'] = dba_get_active_tables(FALSE, $form_tables);
+
+  switch ($form_values['op']) {
     case t('Check'):
       return 'admin/build/database/check';
 
@@ -660,7 +662,7 @@
 function dba_table_overview($table) {
   $rows = array();
   $tables = dba_get_active_tables();
-  $quantity = sizeof(explode(',', $tables));
+  $quantity = count($tables);
   if ($quantity == 1) {
     drupal_set_title(t('View table %table', array('%table' => $table)));
 
@@ -717,7 +719,7 @@
   if (_is_mysql()) {
     $rows = array();
     $tables = dba_get_active_tables();
-    $quantity = sizeof(explode(',', $tables));
+    $quantity = count($tables);
     if ($quantity == 1) {
       $result = dba_describe_table($table, FALSE);
       while ($row = db_fetch_array($result)) {
@@ -740,7 +742,7 @@
 function dba_table_describe($table) {
   $rows = array();
   $tables = dba_get_active_tables();
-  $quantity = sizeof(explode(',', $tables));
+  $quantity = count($tables);
   if ($quantity == 1) {
     drupal_set_title(t('Describe table %table', array('%table' => $table)));
     $result = dba_describe_table($table);
@@ -899,25 +901,25 @@
   }
 }
 
-function dba_check_tables() {
+function dba_check_tables_form() {
 
   // Setup a form value to remember what table(s) we're operating on.
   $form['check_tables']['tables']['#type'] = 'hidden';
   // First, see if we what the active table is, based solely on
   // $_SESSION and the URL.
-  $tables = dba_get_active_tables(0);
+  $tables = dba_get_active_tables(FALSE);
   unset($_SESSION['dba_tables']);
   if (!empty($tables)) {
     // We already know, so this is easy...
-    $form['check_tables']['tables']['#default_value'] = $tables;
+    $form['check_tables']['tables']['#value'] = implode(',', $tables);
   }
   else {
     // It must be in the form values, then.  In this case, we need to
     // call form_builder() to safely grab the data out of $_POST.
-    $form['check_tables'] = form_builder('dba_check_tables', $form['check_tables']);
+    $form['check_tables'] = form_builder('dba_check_tables_form', $form['check_tables']);
     if (!empty($form['check_tables']['tables']['#value'])) {
-      $form_tables['tables'] = $form['check_tables']['tables']['#value'];
-      $tables = dba_get_active_tables(0, $form_tables);
+      $form_tables = explode(',', $form['check_tables']['tables']['#value']);
+      $tables = dba_get_active_tables(FALSE, $form_tables);
     }
   }
   // Make sure we have something to do.
@@ -958,7 +960,7 @@
   // We don't want to get redirected, which would run the queries twice.
   $form['#redirect'] = false;
 
-  return drupal_get_form('dba_check_tables', $form);
+  return $form;
 }
 
 function dba_check_table_form_pre_render($form_id, &$form) {
@@ -969,17 +971,17 @@
     return;
   }
 
-  $action = isset($_POST['op']) ? $_POST['op'] : 'check';
-  $type = $form_values['check_type'];
-  $tables = $form_values['tables'];
+  $action = isset($form['#post']['op']) ? $form['#post']['op'] : 'check';
+  $type = $form['check_options']['check_type']['#value'];
+  $tables = explode(',', $form['check_tables']['tables']['#value']);
 
   if ($action == t('Repair')) {
     drupal_set_title(t('Performing table repair.'));
-    $result = dba_repair_table($tables);
+    $result = dba_repair_tables($tables);
   }
   else {
-    drupal_set_title(t('Performing %type table check', array('%type' => check_plain($type))));
-    $result = dba_check_table($tables, $type);
+    drupal_set_title(t('Performing %type table check', array('%type' => $type)));
+    $result = dba_check_tables($tables, $type);
   }
 
   // Construct the output of the operation as a table, and see if any
@@ -1054,20 +1056,17 @@
 }
 
 function dba_tables_optimize() {
-  $tables = dba_get_active_tables(0);
-  if (empty($tables)) {
-    $quantity = 0;
-  }
-  else {
-    $quantity = sizeof(explode(',', $tables));
-  }
-  drupal_set_title(t('Optimizing %table', array('%table' => format_plural($quantity, 'table', 'tables'))));
+  $tables = dba_get_active_tables(FALSE);
+  $quantity = (empty($tables) ? 0 : count($tables));
+
   if (!$quantity) {
     drupal_set_message(t('You must select the tables to optimize.'), 'error');
     drupal_goto('admin/build/database');
   }
   else {
-    $query = 'OPTIMIZE TABLE '. str_replace(',', ', ', $tables) .';';
+    drupal_set_title(t('Optimizing !table', array('!table' => format_plural($quantity, 'table', 'tables'))));
+
+    $query = 'OPTIMIZE TABLE '. implode(', ', $tables) .';';
     drupal_set_message(check_plain($query));
     $result = db_query($query);
 
@@ -1081,52 +1080,62 @@
   return $output;
 }
 
-function dba_get_active_tables($default = 1, $edit = array()) {
+/**
+ * Figure out what table(s) are currently selected.
+ *
+ * There are various ways in the dba UI to select tables for each of the
+ * possible operations. The table name could be imbedded in the menu path, a
+ * set of tables could be selected via the checkboxes on the overview page, or
+ * a set of tables might be saved in a special form value to remember
+ * previously selected tables.
+ *
+ * In all cases, this function will validate the table names by comparing them
+ * against the actual names of the tables in the DB, so it is essential to
+ * always use this function, even if you already have a list of tables.
+ *
+ * @param $use_all
+ *   Boolean to specify that if no active tables are found, return all tables.
+ *
+ * @param $form_tables
+ *   Array of active table names that we got from a form element.
+ *
+ */
+function dba_get_active_tables($use_all = TRUE, $form_tables = array()) {
   static $all_tables = array();
   if (empty($all_tables)) {
     $all_tables = dba_get_tables();
   }
 
   $tables = array();
-  if (!empty($edit['tables'])) {
-    $tables = $edit['tables'];
+  if (!empty($form_tables)) {
+    $tables = $form_tables;
   }
-  else if (arg(5) && arg(4)) {
-    $tables = arg(4);
+  elseif (arg(5) && arg(4)) {
+    $tables[] = arg(4);
   }
-  else {
-    foreach ($all_tables as $table) {
-      if (!empty($edit[$table])) {
-        $tables[] = $table;
-      }
-    }
-    if (sizeof($tables)) {
-      return implode(',', $tables);
-    }
+  elseif ($use_all) {
     // No tables were set, by default we will return a list of all tables.
-    else if ($default) {
-      return implode(',', $all_tables);
-    }
+    return $all_tables;
   }
-  if (empty($tables) && (isset($_SESSION['dba_tables']))) {
+  elseif (isset($_SESSION['dba_tables'])) {
     $tables = $_SESSION['dba_tables'];
   }
+
   // Final sanity/security check to prevent malicious table names.
-  $table_array = explode(',', $tables);
-  foreach ($table_array as $table) {
+  $safe_tables = array();
+  foreach ($tables as $table) {
     if (isset($all_tables[$table])) {
       $safe_tables[] = $table;
     }
   }
-  return empty($safe_tables) ? '' : implode(',', $safe_tables);
+  return $safe_tables;
 }
 
-function dba_verify($edit, $action) {
-  $tables = dba_get_active_tables(0, $edit);
-  $quantity = sizeof(explode(',', $tables));
+function dba_verify($tables, $action) {
+  $quantity = count($tables);
   if ($quantity) {
     $form = array();
-    $table_list = theme('placeholder', str_replace(',', ', ', $tables));
+    $table_list = theme('placeholder', implode(', ', $tables));
     $table_id = format_plural($quantity, 'table', 'tables');
     $substitutions = array(
       '!tables' => $table_list,
@@ -1135,10 +1144,18 @@
       '!itself' => format_plural($quantity, 'itself', 'themselves'),
       '!its' => format_plural($quantity, 'its', 'their'),
     );
-    $form['tables'] = array('#type' => 'hidden', '#value' => $tables);
+    $form['tables'] = array(
+      '#type' => 'value',
+      '#value' => implode(',', $tables),
+    );
     switch ($action) {
       case 'backup':
-        $filename = ($quantity == 1 ? $tables .'.sql' : variable_get('dba_default_filename', 'backup.sql'));
+        if ($quantity == 1) {
+          $filename = reset($tables) .'.sql';
+        }
+        else {
+          $filename = variable_get('dba_default_filename', 'backup.sql');
+        }
         $form['file_name'] = array(
           '#type' => 'textfield',
           '#title' => t('Backup filename'),
@@ -1156,7 +1173,7 @@
         $form = confirm_form($form,
           t('Backup !table to local computer?', array('!table' => $table_id)),
           'admin/build/database',
-          t('By clicking "Backup !table" you will be prompted to save the following !table to your local computer: !tables', array('!tables' => $display, '!table' => $table_id)),
+          t('By clicking "Backup !table" you will be prompted to save the following !table to your local computer: !tables', array('!tables' => $table_list, '!table' => $table_id)),
           t('Backup !table', array('!table' => $table_id)),
           t('Cancel')
         );
@@ -1208,7 +1225,7 @@
     foreach ($tables as $table) {
       dba_backup_table($table, $form_values['add_drop_table']);
     }
-    $quantity = sizeof($tables);
+    $quantity = count($tables);
     $display = implode(', ', $tables);
     drupal_set_message(t("Saved %tables to %filename.", array('%filename' => $file_name, '%tables' => $display)));
     exit(0);
@@ -1227,7 +1244,7 @@
       dba_delete_table($table);
     }
   }
-  if (sizeof($tables) > 1) {
+  if (count($tables) > 1) {
     return 'admin/build/database';
   }
   return "admin/build/database/table/$table/view";
@@ -1349,19 +1366,19 @@
 }
 
 /**
- * Perform specified check type on specified table (MySQL specific).
+ * Perform specified check type on specified table(s) (MySQL specific).
  */
-function dba_check_table($table, $type = 'MEDIUM') {
-  $query = 'CHECK TABLE '. str_replace(',', ', ', $table) .' '. db_escape_string($type) . ';';
+function dba_check_tables($tables, $type = 'MEDIUM') {
+  $query = 'CHECK TABLE '. implode(', ', $tables) .' '. db_escape_string($type) . ';';
   drupal_set_message(check_plain($query));
   return db_query($query);
 }
 
 /**
- * Repair specified table (MySQL specific).
+ * Repair specified table(s) (MySQL specific).
  */
-function dba_repair_table($table) {
-  $query = 'REPAIR TABLE '. str_replace(',', ', ', $table) .';';
+function dba_repair_tables($tables) {
+  $query = 'REPAIR TABLE '. implode(', ', $tables) .';';
   drupal_set_message(check_plain($query));
   return db_query($query);
 }

