Index: modules/dba/dba.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/dba/dba.module,v retrieving revision 1.44.2.11 diff -u -p -r1.44.2.11 dba.module --- modules/dba/dba.module 24 Jun 2007 03:41:22 -0000 1.44.2.11 +++ modules/dba/dba.module 24 Jun 2007 09:05:12 -0000 @@ -68,12 +68,14 @@ function dba_menu($may_cache) { ); } elseif (strstr(drupal_get_path_alias($_GET['q']), 'admin/database')) { - // You can only view or describe one table at a time. $tables = dba_get_active_tables(0); - if (!empty($tables)) { + if (!empty($tables) && count($tables) == 1) { + // You can only view or describe one table at a time. + $table = reset($tables); + // Regular subtabs. $items[] = array( - 'path' => "admin/database/table/$tables/view", + 'path' => "admin/database/table/$table/view", 'title' => t('view'), 'callback' => 'dba_admin_tables_view', 'access' => $access, @@ -81,7 +83,7 @@ function dba_menu($may_cache) { 'weight' => 0, ); $items[] = array( - 'path' => "admin/database/table/$tables/describe", + 'path' => "admin/database/table/$table/describe", 'title' => t('describe'), 'callback' => 'dba_admin_tables_describe', 'access' => $access, @@ -90,7 +92,7 @@ function dba_menu($may_cache) { ); if (_is_mysql()) { $items[] = array( - 'path' => "admin/database/table/$tables/check", + 'path' => "admin/database/table/$table/check", 'title' => t('check'), 'callback' => 'dba_admin_tables_check', 'access' => $access, @@ -98,7 +100,7 @@ function dba_menu($may_cache) { 'weight' => 4, ); $items[] = array( - 'path' => "admin/database/table/$tables/optimize", + 'path' => "admin/database/table/$table/optimize", 'title' => t('optimize'), 'callback' => 'dba_admin_tables_optimize', 'access' => $access, @@ -108,7 +110,7 @@ function dba_menu($may_cache) { } // Subtabs for dbas with administer permissions. $items[] = array( - 'path' => "admin/database/table/$tables/backup", + 'path' => "admin/database/table/$table/backup", 'title' => t('backup'), 'callback' => 'dba_admin_tables_verify_op', 'callback arguments' => array('backup'), @@ -117,7 +119,7 @@ function dba_menu($may_cache) { 'weight' => 8, ); $items[] = array( - 'path' => "admin/database/table/$tables/empty", + 'path' => "admin/database/table/$table/empty", 'title' => t('empty'), 'callback' => 'dba_admin_tables_verify_op', 'callback arguments' => array('empty'), @@ -126,7 +128,7 @@ function dba_menu($may_cache) { 'weight' => 8, ); $items[] = array( - 'path' => "admin/database/table/$tables/drop", + 'path' => "admin/database/table/$table/drop", 'title' => t('drop'), 'callback' => 'dba_admin_tables_verify_op', 'callback arguments' => array('drop'), @@ -412,7 +414,7 @@ function dba_admin_tables_describe() { * MySQL only: check the selected table(s). */ function dba_admin_tables_check() { - return dba_check_tables(); + return dba_check_tables_form(); } /** @@ -434,13 +436,7 @@ function dba_admin_tables_optimize() { function dba_admin_tables_verify_op($op) { $tables = dba_get_active_tables(0); 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/database'); - } - $edit['tables'] = $tables; - - return dba_verify($edit, $op); + return dba_verify($tables, $op); } @@ -460,7 +456,7 @@ function theme_dba_database_overview_for $tables = dba_get_tables(); foreach ($tables as $table) { $count = dba_get_row_count($table); - $checkbox = form_render($form[$table]); + $checkbox = form_render($form['tables'][$table]); $rows[] = array($checkbox, l($table, "admin/database/table/$table/view"), $count); } $output .= dba_select_all_js(); @@ -473,8 +469,11 @@ function theme_dba_database_overview_for 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, @@ -492,14 +491,19 @@ function dba_database_overview_form() { return drupal_get_form('dba_database_overview_form', $form); } +function dba_database_overview_form_validate($form_id, $form_values) { + if (!array_filter($form_values['tables'])) { + $op = isset($_POST['op']) ? $_POST['op'] : ''; + form_set_error('tables', t('You must select the table(s) to %op.', array('%op' => theme('placeholder', $op)))); + } +} + 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; - } - $_SESSION['dba_tables'] = $tables; + // 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(0, $form_tables); + switch ($op) { case t('Check'): return 'admin/database/check'; @@ -659,7 +663,7 @@ function dba_delete_row_form_submit($for 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' => theme('placeholder', $table)))); @@ -716,7 +720,7 @@ function dba_get_primary_key($table) { 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)) { @@ -739,7 +743,7 @@ function dba_get_primary_key($table) { 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' => theme('placeholder', $table)))); $result = dba_describe_table($table); @@ -905,7 +909,7 @@ function dba_run_script_submit($form_id, } } -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'; @@ -915,14 +919,14 @@ function dba_check_tables() { 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']['#default_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']); if (!empty($form['check_tables']['tables']['#value'])) { - $form_tables['tables'] = $form['check_tables']['tables']['#value']; + $form_tables = explode(',', $form['check_tables']['tables']['#value']); $tables = dba_get_active_tables(0, $form_tables); } } @@ -977,15 +981,15 @@ function dba_check_table_form_pre_render $action = isset($_POST['op']) ? $_POST['op'] : 'check'; $type = $form_values['check_type']; - $tables = $form_values['tables']; + $tables = explode(',', $form_values['tables']); 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); + $result = dba_check_tables($tables, $type); } // Construct the output of the operation as a table, and see if any @@ -1061,19 +1065,16 @@ function dba_check_table_form_pre_render 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')))); + $quantity = (empty($tables) ? 0 : count($tables)); + if (!$quantity) { drupal_set_message(t('You must select the tables to optimize.'), 'error'); drupal_goto('admin/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); @@ -1087,52 +1088,62 @@ function dba_tables_optimize() { 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(4) && arg(3)) { - $tables = arg(3); + elseif (arg(4) && arg(3)) { + $tables[] = arg(3); } - 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)); - if ($quantity) { +function dba_verify($tables, $action) { + if (!empty($tables)) { + $quantity = count($tables); $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, @@ -1141,10 +1152,18 @@ function dba_verify($edit, $action) { '%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'), @@ -1162,7 +1181,7 @@ function dba_verify($edit, $action) { $output = confirm_form('dba_verify_backup_form', $form, t('Backup %table to local computer?', array('%table' => $table_id)), 'admin/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') ); @@ -1211,7 +1230,7 @@ function dba_verify_backup_form_submit($ 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' => theme('placeholder', $file_name), '%tables' => theme('placeholder', $display)))); exit(0); @@ -1230,7 +1249,7 @@ function dba_verify_empty_form_submit($f dba_delete_table($table); } } - if (sizeof($tables) > 1) { + if (count($tables) > 1) { return 'admin/database'; } return "admin/database/table/$table/view"; @@ -1352,19 +1371,19 @@ function dba_get_row_count($table) { } /** - * 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); }