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); }