Parent Directory
|
Revision Log
|
Revision Graph
#343908 by foripepe: Fixed fatal error when checking tables.
| 1 | <?php |
| 2 | // $Id: dba.module,v 1.61 2008/12/11 02:42:12 dww Exp $ |
| 3 | |
| 4 | /** |
| 5 | * @file |
| 6 | * Allows administrators direct access to their Drupal database. |
| 7 | * Written by Jeremy Andrews <jeremy@kerneltrap.org>, June 2004. |
| 8 | * PostgreSQL functionality provided by AAM <aam@ugpl.de> |
| 9 | * Major security audit, porting, and maintenance by |
| 10 | * Derek "dww" Wright (http://drupal.org/user/46549) |
| 11 | */ |
| 12 | |
| 13 | define('DBA_BACKUP_EXCLUDE', 'accesslog, cache, search_index, search_total, watchdog'); |
| 14 | |
| 15 | |
| 16 | // Standard Drupal functions. |
| 17 | function dba_perm() { |
| 18 | return array('dba view database', 'dba administer database'); |
| 19 | } |
| 20 | |
| 21 | function dba_help($section = '') { |
| 22 | switch ($section) { |
| 23 | case 'admin/help#dba': |
| 24 | $output .= t('The dba module allows site administrators a method for direct database administration. This is a dangerous module, in that it gives unlimited access and control over the active database. With this module, it is possible to corrupt or delete an entire drupal database. Use at your own risk.'); |
| 25 | break; |
| 26 | } |
| 27 | return $output; |
| 28 | } |
| 29 | |
| 30 | function dba_menu($may_cache) { |
| 31 | $items = array(); |
| 32 | $admin_access = user_access('dba administer database'); |
| 33 | $access = user_access('dba view database') || $admin_access; |
| 34 | if ($may_cache) { |
| 35 | // Provide menus to dbas with view permissions. |
| 36 | $items[] = array( |
| 37 | 'path' => 'admin/build/database', |
| 38 | 'title' => t('Database'), |
| 39 | 'description' => t("View and edit your site's database directly."), |
| 40 | 'callback' => 'drupal_get_form', |
| 41 | 'callback arguments' => 'dba_database_overview_form', |
| 42 | 'access' => $access, |
| 43 | ); |
| 44 | // Tabs. |
| 45 | $items[] = array( |
| 46 | 'path' => 'admin/build/database/table', |
| 47 | 'title' => t('Tables'), |
| 48 | 'callback' => 'drupal_get_form', |
| 49 | 'callback arguments' => 'dba_database_overview_form', |
| 50 | 'type' => MENU_DEFAULT_LOCAL_TASK, |
| 51 | ); |
| 52 | $items[] = array( |
| 53 | 'path' => 'admin/build/database/query', |
| 54 | 'title' => t('Query database'), |
| 55 | 'callback' => 'drupal_get_form', |
| 56 | 'callback arguments' => array('dba_query_form'), |
| 57 | 'access' => $admin_access, |
| 58 | 'type' => MENU_LOCAL_TASK, |
| 59 | 'weight' => 8, |
| 60 | ); |
| 61 | $items[] = array( |
| 62 | 'path' => 'admin/build/database/script', |
| 63 | 'title' => t('Run script'), |
| 64 | 'callback' => 'drupal_get_form', |
| 65 | 'callback arguments' => array('dba_run_script'), |
| 66 | 'access' => $admin_access, |
| 67 | 'type' => MENU_LOCAL_TASK, |
| 68 | 'weight' => 10, |
| 69 | ); |
| 70 | $items[] = array( |
| 71 | 'path' => 'admin/settings/dba', |
| 72 | 'title' => t('Database administration'), |
| 73 | 'description' => t('Control automatic backups and other settings.'), |
| 74 | 'callback' => 'drupal_get_form', |
| 75 | 'callback arguments' => array('dba_settings_form'), |
| 76 | 'access' => $admin_access, |
| 77 | ); |
| 78 | } |
| 79 | elseif (strstr(drupal_get_path_alias($_GET['q']), 'admin/build/database')) { |
| 80 | $tables = dba_get_active_tables(0); |
| 81 | if (!empty($tables) && count($tables) == 1) { |
| 82 | // You can only view or describe one table at a time. |
| 83 | $table = reset($tables); |
| 84 | |
| 85 | // Regular subtabs. |
| 86 | $items[] = array( |
| 87 | 'path' => "admin/build/database/table/$table/view", |
| 88 | 'title' => t('View'), |
| 89 | 'callback' => 'dba_admin_tables_view', |
| 90 | 'access' => $access, |
| 91 | 'type' => MENU_LOCAL_TASK, |
| 92 | 'weight' => 0, |
| 93 | ); |
| 94 | $items[] = array( |
| 95 | 'path' => "admin/build/database/table/$table/describe", |
| 96 | 'title' => t('Describe'), |
| 97 | 'callback' => 'dba_admin_tables_describe', |
| 98 | 'access' => $access, |
| 99 | 'type' => MENU_LOCAL_TASK, |
| 100 | 'weight' => 2, |
| 101 | ); |
| 102 | if (_is_mysql()) { |
| 103 | $items[] = array( |
| 104 | 'path' => "admin/build/database/table/$table/check", |
| 105 | 'title' => t('Check'), |
| 106 | 'callback' => 'dba_admin_tables_check', |
| 107 | 'access' => $access, |
| 108 | 'type' => MENU_LOCAL_TASK, |
| 109 | 'weight' => 4, |
| 110 | ); |
| 111 | $items[] = array( |
| 112 | 'path' => "admin/build/database/table/$table/optimize", |
| 113 | 'title' => t('Optimize'), |
| 114 | 'callback' => 'dba_admin_tables_optimize', |
| 115 | 'access' => $access, |
| 116 | 'type' => MENU_LOCAL_TASK, |
| 117 | 'weight' => 4, |
| 118 | ); |
| 119 | } |
| 120 | // Subtabs for dbas with administer permissions. |
| 121 | $items[] = array( |
| 122 | 'path' => "admin/build/database/table/$table/backup", |
| 123 | 'title' => t('Backup'), |
| 124 | 'callback' => 'dba_admin_tables_verify_op', |
| 125 | 'callback arguments' => array('backup'), |
| 126 | 'access' => $admin_access, |
| 127 | 'type' => MENU_LOCAL_TASK, |
| 128 | 'weight' => 8, |
| 129 | ); |
| 130 | $items[] = array( |
| 131 | 'path' => "admin/build/database/table/$table/empty", |
| 132 | 'title' => t('Empty'), |
| 133 | 'callback' => 'dba_admin_tables_verify_op', |
| 134 | 'callback arguments' => array('empty'), |
| 135 | 'access' => $admin_access, |
| 136 | 'type' => MENU_LOCAL_TASK, |
| 137 | 'weight' => 8, |
| 138 | ); |
| 139 | $items[] = array( |
| 140 | 'path' => "admin/build/database/table/$table/drop", |
| 141 | 'title' => t('Drop'), |
| 142 | 'callback' => 'dba_admin_tables_verify_op', |
| 143 | 'callback arguments' => array('drop'), |
| 144 | 'access' => $admin_access, |
| 145 | 'type' => MENU_LOCAL_TASK, |
| 146 | 'weight' => 10, |
| 147 | ); |
| 148 | } |
| 149 | // Administrative callbacks. |
| 150 | $items[] = array( |
| 151 | 'path' => "admin/build/database/backup", |
| 152 | 'title' => t('Backup'), |
| 153 | 'callback' => 'dba_admin_tables_verify_op', |
| 154 | 'callback arguments' => array('backup'), |
| 155 | 'access' => $admin_access, |
| 156 | 'weight' => 15, |
| 157 | 'type' => (arg(3) == 'backup' ? MENU_LOCAL_TASK : MENU_CALLBACK), |
| 158 | ); |
| 159 | $items[] = array( |
| 160 | 'path' => "admin/build/database/empty", |
| 161 | 'title' => t('Empty'), |
| 162 | 'callback' => 'dba_admin_tables_verify_op', |
| 163 | 'callback arguments' => array('empty'), |
| 164 | 'access' => $admin_access, |
| 165 | 'weight' => 15, |
| 166 | 'type' => (arg(3) == 'empty' ? MENU_LOCAL_TASK : MENU_CALLBACK), |
| 167 | ); |
| 168 | $items[] = array( |
| 169 | 'path' => "admin/build/database/drop", |
| 170 | 'title' => t('Drop'), |
| 171 | 'callback' => 'dba_admin_tables_verify_op', |
| 172 | 'callback arguments' => array('drop'), |
| 173 | 'access' => $admin_access, |
| 174 | 'weight' => 15, |
| 175 | 'type' => (arg(3) == 'drop' ? MENU_LOCAL_TASK : MENU_CALLBACK), |
| 176 | ); |
| 177 | if (_is_mysql()) { |
| 178 | $items[] = array( |
| 179 | 'path' => "admin/build/database/check", |
| 180 | 'title' => t('Check'), |
| 181 | 'callback' => 'dba_admin_tables_check', |
| 182 | 'access' => $admin_access, |
| 183 | 'weight' => 15, |
| 184 | 'type' => (arg(3) == 'check' ? MENU_LOCAL_TASK : MENU_CALLBACK), |
| 185 | ); |
| 186 | $items[] = array( |
| 187 | 'path' => "admin/build/database/optimize", |
| 188 | 'title' => t('Optimize'), |
| 189 | 'callback' => 'dba_admin_tables_optimize', |
| 190 | 'access' => $admin_access, |
| 191 | 'weight' => 15, |
| 192 | 'type' => (arg(3) == 'optimize' ? MENU_LOCAL_TASK : MENU_CALLBACK), |
| 193 | ); |
| 194 | } |
| 195 | } |
| 196 | return $items; |
| 197 | } |
| 198 | |
| 199 | function dba_settings_form() { |
| 200 | if (!user_access('dba administer database')) { |
| 201 | drupal_access_denied(); |
| 202 | module_invoke_all('exit'); |
| 203 | exit; |
| 204 | } |
| 205 | // Backups |
| 206 | $form['backup'] = array( |
| 207 | '#type' => 'fieldset', |
| 208 | '#title' => t('Database backups'), |
| 209 | '#collapsible' => TRUE, |
| 210 | '#collapsed' => FALSE, |
| 211 | ); |
| 212 | $form['backup']['dba_default_filename'] = array( |
| 213 | '#type' => 'textfield', |
| 214 | '#title' => t('Default backup filename'), |
| 215 | '#description' => t('Default filename to use when backing up multiple tables. If backing up only one table, the filename will default to the name of the table. You will have an opportunity to modify this filename when you actually perform the backup. If automatically backing up tables, the name will be prepended with the current date and time.'), |
| 216 | '#default_value' => variable_get('dba_default_filename', 'backup.sql'), |
| 217 | '#size' => 30, |
| 218 | '#maxlength' => 64, |
| 219 | ); |
| 220 | |
| 221 | $period = drupal_map_assoc(array(0, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval'); |
| 222 | $period[0] = t('disabled'); |
| 223 | $form['backup']['dba_auto_backup_interval'] = array( |
| 224 | '#type' => 'select', |
| 225 | '#title' => t('Automatically backup database every'), |
| 226 | '#default_value' => variable_get('dba_auto_backup_interval', 0), |
| 227 | '#options' => $period, |
| 228 | '#description' => t('Select how often you wish to have your database automatically backed up. Requires crontab.'), |
| 229 | ); |
| 230 | $backup_interval = variable_get('dba_auto_backup_interval', 0); |
| 231 | $backup_path = variable_get('dba_auto_backup_path', file_directory_temp()); |
| 232 | $backup_exclude = variable_get('dba_auto_backup_exclude_tables', DBA_BACKUP_EXCLUDE); |
| 233 | |
| 234 | if ($backup_interval) { |
| 235 | $attributes = array('enabled' => 'enabled'); |
| 236 | } |
| 237 | else { |
| 238 | $attributes = array('disabled' => 'disabled'); |
| 239 | } |
| 240 | $form['backup']['dba_auto_backup_path'] = array( |
| 241 | '#type' => 'textfield', |
| 242 | '#title' => t('Automatic backup path'), |
| 243 | '#default_value' => $backup_path, |
| 244 | '#size' => 30, |
| 245 | '#maxlength' => 255, |
| 246 | '#description' => t('If automatic backups are enabled, you must specify a directory where you would like to store the backup files. The path must be absolute and for security reasons should not be accesible to the web.'), |
| 247 | '#attributes' => $attributes, |
| 248 | ); |
| 249 | |
| 250 | if (function_exists('bzcompress')) { |
| 251 | $form['backup']['dba_auto_backup_bzip2'] = array( |
| 252 | '#type' => 'checkbox', |
| 253 | '#title' => t('Compress automatic backups'), |
| 254 | '#return_value' => 1, |
| 255 | '#default_value' => variable_get('dba_auto_backup_bzip2', 0), |
| 256 | '#description' => t('Enable this option to compress automatic backups with <a href="http://sources.redhat.com/bzip2/">bzip2</a>.'), |
| 257 | '#attributes' => $attributes, |
| 258 | ); |
| 259 | } |
| 260 | else if (function_exists('gzencode')) { |
| 261 | $form['backup']['dba_auto_backup_gzip'] = array( |
| 262 | '#type' => 'checkbox', |
| 263 | '#title' => t('Compress automatic backups'), |
| 264 | '#return_value' => 1, |
| 265 | '#default_value' => variable_get('dba_auto_backup_gzip', 0), |
| 266 | '#description' => t('Enable this option to compress automatic backups with <a href="http://www.gzip.org/zlib/">zlib</a>.'), |
| 267 | '#attributes' => $attributes, |
| 268 | ); |
| 269 | } |
| 270 | $form['backup']['dba_auto_backup_mail'] = array( |
| 271 | '#type' => 'checkbox', |
| 272 | '#title' => t('Mail backup to administrator'), |
| 273 | '#return_value' => 1, |
| 274 | '#default_value' => variable_get('dba_auto_backup_mail', 0), |
| 275 | '#description' => t("Enable this option to have a copy of the database backup files mailed to your administrator's email address."), |
| 276 | '#attributes' => $attributes, |
| 277 | ); |
| 278 | $form['backup']['dba_auto_backup_exclude_tables'] = array( |
| 279 | '#type' => 'textfield', |
| 280 | '#title' => t('Automatic backup excluded tables'), |
| 281 | '#default_value' => $backup_exclude, |
| 282 | '#description' => t("If automatic backups are enabled, you can specify a space-separated list of table names where you only want the table definition (schema) backed up, but not the actual data. This is useful for tables that can be rebuilt (such as the tables related to search indexing) or the watchdog table, which holds log events but no actual site content. Only saving the schema and not the data for these tables can greatly reduce the size of the backups, without losing real content."), |
| 283 | '#attributes' => $attributes, |
| 284 | ); |
| 285 | |
| 286 | // MySQL |
| 287 | if (_is_mysql()) { |
| 288 | $form['mysql_options'] = array( |
| 289 | '#type' => 'fieldset', |
| 290 | '#title' => t('MySQL options'), |
| 291 | '#collapsible' => TRUE, |
| 292 | '#collapsed' => FALSE, |
| 293 | ); |
| 294 | $form['mysql_options']['dba_default_check_type'] = array( |
| 295 | '#type' => 'radios', |
| 296 | '#title' => t('Default check type'), |
| 297 | '#description' => t('MySQL databases support many types of database integrity checks. Select your preferred default type from the list above. Medium is the MySQL recommended default type.'), |
| 298 | '#default_value' => variable_get('dba_default_check_type', 'MEDIUM'), |
| 299 | '#options' => array('QUICK' => t('Quick'), 'FAST' => t('Fast'), 'CHANGED' => t('Changed'), 'MEDIUM' => t('Medium'), 'EXTENDED' => t('Extended')) |
| 300 | ); |
| 301 | $form['mysql_options']['dba_repair'] = array( |
| 302 | '#type' => 'radios', |
| 303 | '#title' => t('Repair option'), |
| 304 | '#description' => t('By default, the dba module will only display a repair button if a table has been determined to need a repair. Alternatively, you can make the module always display a repair button, or never display a repair button.'), |
| 305 | '#default_value' => variable_get('dba_repair', 0), |
| 306 | '#options' => array( |
| 307 | '0' => t('Automatic'), |
| 308 | '1' => t('Always'), |
| 309 | '2' => t('Never'), |
| 310 | ), |
| 311 | ); |
| 312 | } |
| 313 | // Add a validation callback to make sure the backup path is writable. |
| 314 | $setting_valid = array('dba_settings_validate' => array()); |
| 315 | $form['#validate'] = isset($form['#validate']) ? array_merge($form['#validate'], $setting_valid) : $setting_valid; |
| 316 | return system_settings_form($form); |
| 317 | } |
| 318 | |
| 319 | function dba_settings_validate($form_id, $form_values, $form) { |
| 320 | if (!file_check_directory($form_values['dba_auto_backup_path'])) { |
| 321 | form_set_error('dba_auto_backup_path', t('The automatic backup path does not exist, or is not writeable. Automatic backups will not begin until you fix this error.')); |
| 322 | } |
| 323 | elseif ($test = tempnam($form_values['dba_auto_backup_path'], 'dba.')) { |
| 324 | file_delete($test); |
| 325 | } |
| 326 | else { |
| 327 | form_set_error('dba_auto_backup_path', t('The automatic backup path exists, but is not writeable. Automatic backups will not begin until you fix this error.')); |
| 328 | } |
| 329 | } |
| 330 | |
| 331 | function dba_cron() { |
| 332 | if ($interval = variable_get('dba_auto_backup_interval', 0)) { |
| 333 | // See if it's time for another auto-backup. |
| 334 | if ((time() - $interval) >= variable_get('dba_auto_backup_last', 0)) { |
| 335 | dba_auto_backup(); |
| 336 | } |
| 337 | } |
| 338 | } |
| 339 | |
| 340 | function dba_auto_backup() { |
| 341 | $backup_started = time(); |
| 342 | $path = variable_get('dba_auto_backup_path', file_directory_temp()); |
| 343 | // See what tables (if any) the admin wants us to only backup |
| 344 | // the schema, not the actual data. we need it as an array, so we |
| 345 | // lookup the setting as a string, then split() it into an array. |
| 346 | $exclude_tables_str = variable_get('dba_auto_backup_exclude_tables', DBA_BACKUP_EXCLUDE); |
| 347 | $exclude_tables = split('[ ,]', $exclude_tables_str); |
| 348 | // Make sure we have permission to save our backup file. |
| 349 | if (file_check_directory($path, FILE_CREATE_DIRECTORY)) { |
| 350 | $database = dba_get_database(); |
| 351 | $filename = format_date(time(), 'custom', 'Y-md-Hi_') . variable_get('dba_default_filename', 'backup.sql'); |
| 352 | |
| 353 | $backup = "-- Drupal dba.module database dump\n"; |
| 354 | $backup .= "--\n"; |
| 355 | $backup .= "-- Database: $database\n"; |
| 356 | $backup .= "-- Date: ". format_date(time(), 'large') ."\n\n"; |
| 357 | |
| 358 | $tables = dba_get_tables(); |
| 359 | foreach ($tables as $table) { |
| 360 | $backup .= dba_backup_table($table, TRUE, FALSE, in_array($table, $exclude_tables) ? FALSE : TRUE); |
| 361 | } |
| 362 | |
| 363 | // Optionally bzip2 compress auto-backup file. |
| 364 | if (variable_get('dba_auto_backup_bzip2', 0)) { |
| 365 | $backup = bzcompress($backup, 9); |
| 366 | $filename = $filename .'.bz2'; |
| 367 | } |
| 368 | // Otherwise, optionally gzip compress auto-backup file. |
| 369 | else if (variable_get('dba_auto_backup_gzip', 0)) { |
| 370 | if (version_compare(phpversion(), '4.2', '>=')) { |
| 371 | $backup = gzencode($backup, 9, FORCE_GZIP); |
| 372 | } |
| 373 | else { |
| 374 | $backup = gzencode($backup, FORCE_GZIP); |
| 375 | } |
| 376 | $filename = $filename .'.gz'; |
| 377 | } |
| 378 | |
| 379 | if ($fp = fopen($path ."/$filename", 'wb')) { |
| 380 | fwrite($fp, $backup); |
| 381 | fclose($fp); |
| 382 | variable_set('dba_auto_backup_last', $backup_started); |
| 383 | |
| 384 | // If enabled, email a copy of the backup to the site administrator. |
| 385 | if (variable_get('dba_auto_backup_mail', 0)) { |
| 386 | $attachment = new stdClass(); |
| 387 | $attachment->path = $path ."/$filename"; |
| 388 | $attachment->filename = $filename; |
| 389 | dba_mail_backup($attachment); |
| 390 | } |
| 391 | } |
| 392 | } |
| 393 | } |
| 394 | |
| 395 | /** |
| 396 | * Display the contents of the selected table. |
| 397 | */ |
| 398 | function dba_admin_tables_view() { |
| 399 | if (user_access('dba administer database') && arg(6) && arg(7) && arg(8)) { |
| 400 | switch (arg(6)) { |
| 401 | case 'delete': |
| 402 | return drupal_get_form('dba_delete_row', arg(4), arg(7), arg(8)); |
| 403 | case 'edit': |
| 404 | return drupal_get_form('dba_edit_row', arg(4), arg(7), arg(8)); |
| 405 | } |
| 406 | } |
| 407 | else { |
| 408 | return dba_table_overview(arg(4)); |
| 409 | } |
| 410 | } |
| 411 | |
| 412 | /** |
| 413 | * Describe the schema of the selected table. |
| 414 | */ |
| 415 | function dba_admin_tables_describe() { |
| 416 | $output = ''; |
| 417 | if (user_access('dba view database')) { |
| 418 | $output = dba_table_describe(arg(4)); |
| 419 | } |
| 420 | print theme('page', $output); |
| 421 | } |
| 422 | |
| 423 | /** |
| 424 | * MySQL only: check the selected table(s). |
| 425 | */ |
| 426 | function dba_admin_tables_check() { |
| 427 | return drupal_get_form('dba_check_tables_form'); |
| 428 | } |
| 429 | |
| 430 | /** |
| 431 | * MySQL only: optimize the selected table(s). |
| 432 | */ |
| 433 | function dba_admin_tables_optimize() { |
| 434 | $output = ''; |
| 435 | if (user_access('dba administer database')) { |
| 436 | $output = dba_tables_optimize(); |
| 437 | unset($_SESSION['dba_tables']); |
| 438 | } |
| 439 | print theme('page', $output); |
| 440 | } |
| 441 | |
| 442 | /** |
| 443 | * Menu callback to verify the administrator wants to backup, empty or |
| 444 | * drop the selected table(s) by means of a confirm form. |
| 445 | */ |
| 446 | function dba_admin_tables_verify_op($op) { |
| 447 | $tables = dba_get_active_tables(0); |
| 448 | return drupal_get_form('dba_verify', $tables, $op); |
| 449 | } |
| 450 | |
| 451 | function theme_dba_database_overview_form($form) { |
| 452 | $output = ''; |
| 453 | $rows = array(); |
| 454 | $database = dba_get_database(); |
| 455 | drupal_set_title(t('View database %database', array('%database' => $database))); |
| 456 | |
| 457 | // It'd be great to use the pager and tablesort, but doesn't appear possible. |
| 458 | $header = array('', t('Tables'), t('Rows')); |
| 459 | $tables = dba_get_tables(); |
| 460 | foreach ($tables as $table) { |
| 461 | $count = dba_get_row_count($table); |
| 462 | $checkbox = drupal_render($form['tables'][$table]); |
| 463 | $rows[] = array($checkbox, l($table, "admin/build/database/table/$table/view"), $count); |
| 464 | } |
| 465 | $output .= dba_select_all_js(); |
| 466 | $output .= theme('table', $header, $rows); |
| 467 | $output .= dba_select_all_js(); |
| 468 | $output .= drupal_render($form); |
| 469 | drupal_set_html_head(checkoff_head()); |
| 470 | return $output; |
| 471 | } |
| 472 | |
| 473 | function dba_database_overview_form() { |
| 474 | $tables = dba_get_tables(); |
| 475 | $form = array(); |
| 476 | $form['#tree'] = TRUE; |
| 477 | $form['tables'] = array(); |
| 478 | foreach ($tables as $table) { |
| 479 | $form['tables'][$table] = array( |
| 480 | '#type' => 'checkbox', |
| 481 | '#title' => '', |
| 482 | '#default_value' => 0, |
| 483 | ); |
| 484 | } |
| 485 | if (_is_mysql()) { |
| 486 | $form['check'] = array('#type' => 'submit', '#value' => t('Check')); |
| 487 | $form['optimize'] = array('#type' => 'submit', '#value' => t('Optimize')); |
| 488 | } |
| 489 | if (user_access('dba administer database')) { |
| 490 | $form['backup'] = array('#type' => 'submit', '#value' => t('Backup')); |
| 491 | $form['empty'] = array('#type' => 'submit', '#value' => t('Empty')); |
| 492 | $form['drop'] = array('#type' => 'submit', '#value' => t('Drop')); |
| 493 | } |
| 494 | return $form; |
| 495 | } |
| 496 | |
| 497 | function dba_database_overview_form_validate($form_id, $form_values) { |
| 498 | if (!array_filter($form_values['tables'])) { |
| 499 | $op = isset($_POST['op']) ? $_POST['op'] : ''; |
| 500 | form_set_error('tables', t('You must select the table(s) to %op.', array('%op' => theme('placeholder', $op)))); |
| 501 | } |
| 502 | } |
| 503 | |
| 504 | function dba_database_overview_form_submit($form_id, $form_values) { |
| 505 | $op = isset($_POST['op']) ? $_POST['op'] : ''; |
| 506 | // We already validated the overview form, so we know we have tables. |
| 507 | $form_tables = array_keys(array_filter($form_values['tables'])); |
| 508 | $_SESSION['dba_tables'] = dba_get_active_tables(0, $form_tables); |
| 509 | |
| 510 | switch ($op) { |
| 511 | case t('Check'): |
| 512 | return 'admin/build/database/check'; |
| 513 | |
| 514 | case t('Optimize'): |
| 515 | return 'admin/build/database/optimize'; |
| 516 | |
| 517 | case t('Backup'): |
| 518 | return 'admin/build/database/backup'; |
| 519 | |
| 520 | case t('Empty'): |
| 521 | return 'admin/build/database/empty'; |
| 522 | |
| 523 | case t('Drop'): |
| 524 | return 'admin/build/database/drop'; |
| 525 | } |
| 526 | } |
| 527 | |
| 528 | function dba_select_all_js() { |
| 529 | $output = "<a href=\"javascript:checkoff('dba-database-overview-form',1)\">"; |
| 530 | $output .= t('select all'); |
| 531 | $output .= "</a> | "; |
| 532 | $output .= "<a href=\"javascript:checkoff('dba-database-overview-form',0)\">"; |
| 533 | $output .= t('clear all'); |
| 534 | $output .= "</a><br>"; |
| 535 | return $output; |
| 536 | } |
| 537 | |
| 538 | function dba_delete_row($table, $key, $keyid) { |
| 539 | $rows = array(); |
| 540 | $keyid = str_replace('__2F_', '/', $keyid); |
| 541 | $result = db_query("SELECT * FROM %s WHERE %s = '%s'", $table, $key, $keyid); |
| 542 | $row = db_fetch_array($result); |
| 543 | $rows[] = array_map('check_plain', (array)$row); |
| 544 | $header = array_map('check_plain', array_keys($row)); |
| 545 | $form = array(); |
| 546 | $form['row'] = array('#value' => theme('table', $header, $rows)); |
| 547 | $form['table'] = array('#type' => 'hidden', '#value' => $table); |
| 548 | $form['key'] = array('#type' => 'hidden', '#value' => $key); |
| 549 | $form['keyid'] = array('#type' => 'hidden', '#value' => $keyid); |
| 550 | $form = confirm_form($form, |
| 551 | t('Are you sure you want to delete this row from the "%table" table?', array('%table' => $table)), |
| 552 | "admin/build/database/table/$table/view", |
| 553 | t('By clicking "Delete row" you will permanently remove this row from the %table table. This action cannot be undone.', array('%table' => $table)), |
| 554 | t('Delete row'), |
| 555 | t('Cancel') |
| 556 | ); |
| 557 | return $form; |
| 558 | } |
| 559 | |
| 560 | function dba_edit_row($table, $key, $keyid) { |
| 561 | $rows = array(); |
| 562 | $keyid = str_replace('__2F_', '/', $keyid); |
| 563 | $result = db_query("SELECT * FROM %s WHERE %s = '%s'", $table, $key, $keyid); |
| 564 | $row = db_fetch_array($result); |
| 565 | $header = array_keys($row); |
| 566 | foreach ($row as $k => $value) { |
| 567 | if ($k == $key) { |
| 568 | $form['key'] = array('#type' => 'markup', '#value' => $value); |
| 569 | } |
| 570 | else { |
| 571 | // We store all fields in sub-array 'fields' to avoid naming collisions. |
| 572 | $size = strlen($value); |
| 573 | if ($size > 255) { |
| 574 | $form['field'][$k] = array( |
| 575 | '#type' => 'textarea', |
| 576 | '#default_value' => $value, |
| 577 | '#cols' => 70, '#rows' => 10, |
| 578 | ); |
| 579 | } |
| 580 | else { |
| 581 | $form['field'][$k] = array( |
| 582 | '#type' => 'textfield', |
| 583 | '#default_value' => $value, |
| 584 | '#size' => $size, '#maxlength' => 255, |
| 585 | ); |
| 586 | } |
| 587 | } |
| 588 | } |
| 589 | $form['header'] = array( |
| 590 | '#type' => 'hidden', |
| 591 | '#value' => implode(',', $header), |
| 592 | ); |
| 593 | $form['table'] = array('#type' => 'hidden', '#value' => $table); |
| 594 | $form['key'] = array('#type' => 'hidden', '#value' => $key); |
| 595 | $form['keyid'] = array('#type' => 'hidden', '#value' => $keyid); |
| 596 | return confirm_form($form, |
| 597 | t('Edit row from the "%table" table', array('%table' => $table)), |
| 598 | "admin/build/database/table/$table/view", |
| 599 | t('By clicking "Edit row" you will save any changes you make to this row of the %table table. This action cannot be undone.', array('%table' => $table)), |
| 600 | t('Edit row'), |
| 601 | t('Cancel') |
| 602 | ); |
| 603 | } |
| 604 | |
| 605 | function theme_dba_edit_row($form) { |
| 606 | $header = explode(',', $form['header']['#value']); |
| 607 | $key = $form['key']['#value']; |
| 608 | $keyid = $form['keyid']['#value']; |
| 609 | $rows = array(); |
| 610 | $row = array(); |
| 611 | foreach ($header as $k => $name) { |
| 612 | if ($name == $key) { |
| 613 | $row[] = $keyid; |
| 614 | } |
| 615 | else { |
| 616 | $row[] = drupal_render($form['field'][$name]); |
| 617 | } |
| 618 | } |
| 619 | $rows[] = $row; |
| 620 | $output = theme('table', $header, $rows); |
| 621 | $output .= drupal_render($form); |
| 622 | return $output; |
| 623 | } |
| 624 | |
| 625 | function dba_edit_row_submit($form_id, $form_values) { |
| 626 | if (user_access('dba administer database')) { |
| 627 | $key = $form_values['key']; |
| 628 | $keyid = $form_values['keyid']; |
| 629 | $table = $form_values['table']; |
| 630 | $fields = dba_get_fields($table); |
| 631 | foreach ($fields as $field) { |
| 632 | if ($field != $key) { |
| 633 | $value = "{$form_values[$field]}"; |
| 634 | if (isset($query)) { |
| 635 | $query .= ", $field = '". db_escape_string($value) ."'"; |
| 636 | } |
| 637 | else { |
| 638 | $query = "$field = '". db_escape_string($value) ."'"; |
| 639 | } |
| 640 | } |
| 641 | } |
| 642 | // @todo Manual prefixing |
| 643 | $query = "UPDATE $table SET $query WHERE $key = '$keyid'"; |
| 644 | drupal_set_message(check_plain($query)); |
| 645 | // Use _db_query so we preserve {}'s. |
| 646 | _db_query($query); |
| 647 | } |
| 648 | return "admin/build/database/table/$table/view"; |
| 649 | } |
| 650 | |
| 651 | function dba_delete_row_submit($form_id, $form_values) { |
| 652 | if (user_access('dba administer database')) { |
| 653 | $key = $form_values['key']; |
| 654 | $keyid = $form_values['keyid']; |
| 655 | $table = $form_values['table']; |
| 656 | $query = "DELETE FROM $table WHERE $key = '$keyid'"; |
| 657 | drupal_set_message(check_plain($query)); |
| 658 | $query = "DELETE FROM %s WHERE %s = '%s'"; |
| 659 | db_query($query, $table, $key, $keyid); |
| 660 | } |
| 661 | return "admin/build/database/table/$table/view"; |
| 662 | } |
| 663 | |
| 664 | function dba_table_overview($table) { |
| 665 | $rows = array(); |
| 666 | $tables = dba_get_active_tables(); |
| 667 | $quantity = count($tables); |
| 668 | if ($quantity == 1) { |
| 669 | drupal_set_title(t('View table %table', array('%table' => $table))); |
| 670 | |
| 671 | if (user_access('dba administer database')) { |
| 672 | $primary = dba_get_primary_key($table); |
| 673 | } |
| 674 | else { |
| 675 | $primary = NULL; |
| 676 | } |
| 677 | |
| 678 | $fields = dba_get_fields($table); |
| 679 | foreach ($fields as $field) { |
| 680 | $header[] = array('data' => "$field", 'field' => "$field"); |
| 681 | } |
| 682 | |
| 683 | $sql = "SELECT * FROM {$table}"; |
| 684 | $sql .= tablesort_sql($header); |
| 685 | $result = pager_query($sql, 20); |
| 686 | |
| 687 | if (!is_null($primary)) { |
| 688 | $header[] = t('actions'); |
| 689 | } |
| 690 | |
| 691 | if (db_num_rows($result)) { |
| 692 | while ($row = db_fetch_array($result)) { |
| 693 | $line = array_map('check_plain', array_values($row)); |
| 694 | if (!is_null($primary)) { |
| 695 | $id = "{$row[$primary]}"; |
| 696 | $id = str_replace('/', '__2F_', $id); |
| 697 | $actions = '['. l(t('edit'), "admin/build/database/table/$table/view/edit/$primary/$id") .']'; |
| 698 | $actions .= ' ['. l(t('delete'), "admin/build/database/table/$table/view/delete/$primary/$id") .']'; |
| 699 | $line[] = $actions; |
| 700 | } |
| 701 | $rows[] = $line; |
| 702 | unset($line); |
| 703 | } |
| 704 | if ($pager = theme('pager', NULL, 20, 0)) { |
| 705 | $rows[] = array(array('data' => $pager, 'colspan' => sizeof($fields))); |
| 706 | } |
| 707 | $output = theme('table', $header, $rows); |
| 708 | } |
| 709 | else { |
| 710 | $output = t('The table is empty.'); |
| 711 | } |
| 712 | } |
| 713 | else { |
| 714 | drupal_set_message(t('Unable to view more than one table at a time.'), 'error'); |
| 715 | $output .= dba_database_overview_form(); |
| 716 | } |
| 717 | return $output; |
| 718 | } |
| 719 | |
| 720 | function dba_get_primary_key($table) { |
| 721 | if (_is_mysql()) { |
| 722 | $rows = array(); |
| 723 | $tables = dba_get_active_tables(); |
| 724 | $quantity = count($tables); |
| 725 | if ($quantity == 1) { |
| 726 | $result = dba_describe_table($table, FALSE); |
| 727 | while ($row = db_fetch_array($result)) { |
| 728 | if ($row['Key'] == "PRI") { |
| 729 | return ($row['Field']); |
| 730 | } |
| 731 | } |
| 732 | } |
| 733 | else { |
| 734 | drupal_set_message(t('Unable to return the primary key for more than one table at a time.'), 'error'); |
| 735 | } |
| 736 | } |
| 737 | else { |
| 738 | // Not MySQL, so currently unsupported. |
| 739 | return; |
| 740 | } |
| 741 | return; |
| 742 | } |
| 743 | |
| 744 | function dba_table_describe($table) { |
| 745 | $rows = array(); |
| 746 | $tables = dba_get_active_tables(); |
| 747 | $quantity = count($tables); |
| 748 | if ($quantity == 1) { |
| 749 | drupal_set_title(t('Describe table %table', array('%table' => $table))); |
| 750 | $result = dba_describe_table($table); |
| 751 | while ($row = db_fetch_array($result)) { |
| 752 | if (!$header) { |
| 753 | $header = array_keys($row); |
| 754 | } |
| 755 | $rows[] = (array)($row); |
| 756 | } |
| 757 | return (theme('table', $header, $rows)); |
| 758 | } |
| 759 | else { |
| 760 | drupal_set_message(t('Unable to describe more than one table at a time.'), 'error'); |
| 761 | $output .= dba_database_overview(); |
| 762 | } |
| 763 | return $output; |
| 764 | } |
| 765 | |
| 766 | function dba_query_form() { |
| 767 | // Now, add a text area for the admin to enter a query. |
| 768 | $form['query'] = array('#type' => 'fieldset', '#title' => t('Query')); |
| 769 | $form['query']['dba_query'] = array( |
| 770 | '#type' => 'textarea', |
| 771 | '#title' => t('Database query'), |
| 772 | '#cols' => 70, '#rows' => 10, |
| 773 | '#description' => t('Enter the text of your database query. This will be executed directly in your database, so the action can not be undone. Do not wrap your tables in {}, as direct database queries do not support Drupal\'s database prefixing. If you are using a database prefix, you will need to manually include the prefix in your table name. Separate multiple queries with a ";". A sample query: \'SELECT COUNT(*) FROM accesslog;\''), |
| 774 | ); |
| 775 | $form['query']['actions'] = array( |
| 776 | '#prefix' => '<div class="container-inline">', |
| 777 | '#suffix' => '</div>', |
| 778 | ); |
| 779 | $form['query']['actions']['submit'] = array( |
| 780 | '#type' => 'submit', |
| 781 | '#value' => t('Execute query'), |
| 782 | ); |
| 783 | $form['query']['actions']['cancel'] = array( |
| 784 | '#type' => 'markup', |
| 785 | '#value' => l(t('Cancel'), 'admin/database'), |
| 786 | ); |
| 787 | |
| 788 | // We use #pre_render, so that we can safely use validated form values |
| 789 | // to see if a query has been entered, and if so, run the query and |
| 790 | // dynamically generate other form elements to display the results. |
| 791 | $form['#pre_render'][] = 'dba_query_form_pre_render'; |
| 792 | |
| 793 | // We don't want to get redirected, which would run the queries twice. |
| 794 | $form['#redirect'] = false; |
| 795 | |
| 796 | return $form; |
| 797 | } |
| 798 | |
| 799 | function dba_query_form_pre_render($form_id, &$form) { |
| 800 | // If there are no validation errors and there's already a query, |
| 801 | // run it and display the results. |
| 802 | $dba_query = $form['query']['dba_query']['#value']; |
| 803 | if (!form_get_errors() && !empty($dba_query)) { |
| 804 | // Execute each sql statement individually. |
| 805 | $i = 0; |
| 806 | foreach (explode(';', $dba_query) as $sql) { |
| 807 | $header = NULL; |
| 808 | if (trim($sql) == '') { |
| 809 | break; |
| 810 | } |
| 811 | $result = dba_execute_query($sql); |
| 812 | if ($result && $result != 1 && db_num_rows($result)) { |
| 813 | while ($row = db_fetch_array($result)) { |
| 814 | if (!$header) { |
| 815 | $header = array_map('check_plain', array_keys($row)); |
| 816 | } |
| 817 | $rows[] = array_map('check_plain', array_values($row)); |
| 818 | } |
| 819 | } |
| 820 | if (!empty($rows)) { |
| 821 | $form['results'][$i] = array( |
| 822 | '#type' => 'fieldset', |
| 823 | '#title' => t('Result') .': '. theme_placeholder($sql), |
| 824 | ); |
| 825 | $form['results'][$i]['result'] = array( |
| 826 | '#value' => theme('table', $header, $rows), |
| 827 | ); |
| 828 | unset($rows); |
| 829 | } |
| 830 | $i++; |
| 831 | } |
| 832 | $form['results'] = form_builder('dba_query_form', $form['results']); |
| 833 | } |
| 834 | } |
| 835 | |
| 836 | function dba_execute_query($sql) { |
| 837 | if (user_access('dba administer database')) { |
| 838 | return _db_query($sql); |
| 839 | } |
| 840 | } |
| 841 | |
| 842 | function dba_run_script() { |
| 843 | if (user_access('dba administer database')) { |
| 844 | $form['script'] = array('#type' => 'fieldset', '#title' => 'Script'); |
| 845 | $form['script']['script_filename'] = array( |
| 846 | '#type' => 'file', '#title' => t('Select a script'), |
| 847 | '#description' => t('Click the "browse" button to select a database script from your local computer.') |
| 848 | ); |
| 849 | $form['script']['verbose'] = array( |
| 850 | '#type' => 'checkbox', |
| 851 | '#title' => t('Verbose'), |
| 852 | '#return_value' => 1, |
| 853 | '#default_value' => 0, |
| 854 | '#description' => t('Check this box if you wish to see all queries that are run.'), |
| 855 | ); |
| 856 | $form['script']['submit'] = array( |
| 857 | '#type' => 'submit', |
| 858 | '#value' => t('Run script'), |
| 859 | ); |
| 860 | $form['#attributes'] = array('enctype' => 'multipart/form-data'); |
| 861 | } |
| 862 | return $form; |
| 863 | } |
| 864 | |
| 865 | function dba_run_script_submit($form_id, $form_values) { |
| 866 | if ($file = file_save_upload('script_filename')) { |
| 867 | // File is now in temporary directory. |
| 868 | if (file_exists($file->filepath)) { |
| 869 | if ($fp = fopen($file->filepath, 'r')) { |
| 870 | $query = NULL; |
| 871 | $count = 0; |
| 872 | while (!feof($fp)) { |
| 873 | $line = fgets($fp, 8192); |
| 874 | if ($line && strncmp($line, '--', 2) && strncmp($line, '#', 1)) { |
| 875 | $query .= $line; |
| 876 | if (strpos($line, ';')) { |
| 877 | if (db_query($query, FALSE)) { |
| 878 | if ($form_values['verbose']) { |
| 879 | drupal_set_message(check_plain($query)); |
| 880 | } |
| 881 | $count++; |
| 882 | } |
| 883 | else { |
| 884 | drupal_set_message(t('Query failed: %query', array('%query' => $query)), 'error'); |
| 885 | } |
| 886 | $query = NULL; |
| 887 | } |
| 888 | } |
| 889 | } |
| 890 | fclose ($fp); |
| 891 | drupal_set_message(t('Succesfully ran !query from script %filename.', array('!query' => format_plural($count, '1 query', '@count queries'), '%filename' => $file->filename))); |
| 892 | } |
| 893 | else { |
| 894 | drupal_set_message(t('Unable to open script %filename.', array('%filename' => $file->filename)), 'error'); |
| 895 | } |
| 896 | file_delete($file->filepath); |
| 897 | } |
| 898 | else { |
| 899 | drupal_set_message(t('Script %filename does not exist.', array('%filename' => $file->filename)), 'error'); |
| 900 | } |
| 901 | // Cleanup session. |
| 902 | unset($_SESSION['file_uploads'][$file->source]); |
| 903 | } |
| 904 | } |
| 905 | |
| 906 | function dba_check_tables_form() { |
| 907 | |
| 908 | // Setup a form value to remember what table(s) we're operating on. |
| 909 | $form['check_tables']['tables']['#type'] = 'hidden'; |
| 910 | // First, see if we what the active table is, based solely on |
| 911 | // $_SESSION and the URL. |
| 912 | $tables = dba_get_active_tables(0); |
| 913 | unset($_SESSION['dba_tables']); |
| 914 | if (!empty($tables)) { |
| 915 | // We already know, so this is easy... |
| 916 | $form['check_tables']['tables']['#default_value'] = implode(',', $tables); |
| 917 | } |
| 918 | else { |
| 919 | // It must be in the form values, then. In this case, we need to |
| 920 | // call form_builder() to safely grab the data out of $_POST. |
| 921 | $form['check_tables'] = form_builder('dba_check_tables', $form['check_tables']); |
| 922 | if (!empty($form['check_tables']['tables']['#value'])) { |
| 923 | $form_tables = explode(',', $form['check_tables']['tables']['#value']); |
| 924 | $tables = dba_get_active_tables(0, $form_tables); |
| 925 | } |
| 926 | } |
| 927 | // Make sure we have something to do. |
| 928 | if (empty($tables)) { |
| 929 | drupal_set_message(t('You must select the tables to check.'), 'error'); |
| 930 | drupal_goto('admin/build/database'); |
| 931 | } |
| 932 | |
| 933 | $form['check_options'] = array( |
| 934 | '#type' => 'fieldset', |
| 935 | '#title' => t('Actions'), |
| 936 | ); |
| 937 | $form['check_options']['check_type'] = array( |
| 938 | '#type' => 'radios', |
| 939 | '#title' => t('Check type'), |
| 940 | '#default_value' => variable_get('dba_default_check_type', 'MEDIUM'), |
| 941 | '#options' => array( |
| 942 | 'QUICK' => t('Quick'), |
| 943 | 'FAST' => t('Fast'), |
| 944 | 'CHANGED' => t('Changed'), |
| 945 | 'MEDIUM' => t('Medium'), |
| 946 | 'EXTENDED' => t('Extended') |
| 947 | ), |
| 948 | ); |
| 949 | $form['check_options']['check'] = array( |
| 950 | '#type' => 'submit', |
| 951 | '#value' => t('Check again') |
| 952 | ); |
| 953 | |
| 954 | // Most of the interesting stuff in this form has to be added via |
| 955 | // #pre_render, so that we can safely use validated form values to |
| 956 | // dynamically generate other form elements. In particular, we add |
| 957 | // a fieldset with the results of whatever operation we perform, and |
| 958 | // depending on the admin settings and the state of the tables, we |
| 959 | // might need to add a 'Repair' button, too. |
| 960 | $form['#pre_render'][] = 'dba_check_table_form_pre_render'; |
| 961 | |
| 962 | // We don't want to get redirected, which would run the queries twice. |
| 963 | $form['#redirect'] = false; |
| 964 | |
| 965 | return $form; |
| 966 | } |
| 967 | |
| 968 | function dba_check_table_form_pre_render($form_id, &$form) { |
| 969 | if (form_get_errors()) { |
| 970 | // If there's a validation error (e.g. #token is wrong), return |
| 971 | // immediately since we can't trust $form. |
| 972 | return; |
| 973 | } |
| 974 | |
| 975 | $action = isset($_POST['op']) ? $_POST['op'] : 'check'; |
| 976 | $type = $form['check_options']['check_type']['#value']; |
| 977 | $tables = explode(',', $form['check_tables']['tables']['#value']); |
| 978 | |
| 979 | if ($action == t('Repair')) { |
| 980 | drupal_set_title(t('Performing table repair.')); |
| 981 | $result = dba_repair_tables($tables); |
| 982 | } |
| 983 | else { |
| 984 | drupal_set_title(t('Performing %type table check', array('%type' => check_plain($type)))); |
| 985 | $result = dba_check_tables($tables, $type); |
| 986 | } |
| 987 | |
| 988 | // Construct the output of the operation as a table, and see if any |
| 989 | // tables need to be repaired. |
| 990 | $repair = array(); |
| 991 | $header = array( |
| 992 | t('Table'), |
| 993 | t('Operation'), |
| 994 | t('Message type'), |
| 995 | t('Message text'), |
| 996 | ); |
| 997 | while ($row = db_fetch_object($result)) { |
| 998 | $rows[] = (array)($row); |
| 999 | if ($row->Msg_type == 'status') { |
| 1000 | $status = $row->Msg_text; |
| 1001 | if ($status != 'OK' && $status != 'Table is already up to date') { |
| 1002 | // An error message will result if we use the database name when trying |
| 1003 | // to repair a table and the database has '-' in the name, so to be |
| 1004 | // safe we strip off the database name. |
| 1005 | $repair_table = explode('.', $row->Table); |
| 1006 | $repair[] = $repair_table[1]; |
| 1007 | } |
| 1008 | } |
| 1009 | } |
| 1010 | $output .= theme('table', $header, $rows); |
| 1011 | |
| 1012 | if ($repair) { |
| 1013 | $output .= '<h3>'. t('One or more tables need repairs.') .'</h3>'; |
| 1014 | $to_repair = 1; |
| 1015 | } |
| 1016 | else { |
| 1017 | $output .= '<h3>'. t('No repairs are required.') .'</h3>'; |
| 1018 | $to_repair = 0; |
| 1019 | } |
| 1020 | |
| 1021 | $form['check_results'] = array( |
| 1022 | '#type' => 'fieldset', |
| 1023 | '#title' => t('Result'), |
| 1024 | '#weight' => -5, |
| 1025 | ); |
| 1026 | $form['check_results']['result'] = array( |
| 1027 | '#type' => 'markup', |
| 1028 | '#value' => $output, |
| 1029 | ); |
| 1030 | // Since we just added these form elements, but we're already at the |
| 1031 | // pre_render stage, we need to manually invoke form_builder() so that |
| 1032 | // these elements are rendered in the final form show to the user. |
| 1033 | $form['check_results'] = form_builder('dba_check_tables', $form['check_results']); |
| 1034 | |
| 1035 | if (user_access('dba administer database')) { |
| 1036 | $repair_option = variable_get('dba_repair', 0); |
| 1037 | if (($repair_option == 0 && $to_repair) || $repair_option == 1) { |
| 1038 | $form['check_options']['repair'] = array( |
| 1039 | '#type' => 'submit', |
| 1040 | '#value' => t('Repair'), |
| 1041 | '#weight' => 20, |
| 1042 | ); |
| 1043 | if (!$repair_option) { |
| 1044 | $form['check_options']['repair_tables'] = array( |
| 1045 | '#type' => 'hidden', |
| 1046 | '#value' => implode(',', $repair_tables), |
| 1047 | ); |
| 1048 | } |
| 1049 | } |
| 1050 |