get('title')), $table->get('name'), db_result(db_query('SELECT COUNT(*) FROM {'. db_escape_table($table->get('name')) .'}')), ); if (module_exists('views')) { $path = data_ui_get_default_path($table->get('name')); $row[] = $path ? l(t('View'), $path) : l(t('Edit schema'), 'admin/build/data/edit/' . $table->get('name')); } $rows[] = $row; } $header = array(t('Title'), t('Name'), t('Number of rows')); if (module_exists('views')) { $header[] = ' '; } return theme('table', $header, $rows); } /** * Main page for data table management. */ function data_ui_manage() { $tables = data_get_all_tables(); $rows = array(); foreach ($tables as $table) { // Build operations depending on configuration status. $operations = array(); if ($table->get('export_type') == EXPORT_IN_CODE) { $status = t('Default'); $operations[] = l(t('Override'), 'admin/build/data/edit/'. $table->get('name')); } else if ($table->get('export_type') == (EXPORT_IN_CODE | EXPORT_IN_DATABASE)) { $status = t('Overridden'); $operations[] = l(t('Edit'), 'admin/build/data/edit/'. $table->get('name')); $operations[] = l(t('Revert'), 'admin/build/data/revert/'. $table->get('name')); } else { $status = t('Normal'); $operations[] = l(t('Edit'), 'admin/build/data/edit/'. $table->get('name')); $operations[] = l(t('Drop'), 'admin/build/data/drop/'. $table->get('name')); } if (module_exists('ctools')) { $operations[] = l(t('Export'), 'admin/build/data/export/'. $table->get('name')); } $row = array(); $row[] = check_plain($table->get('title')); $row[] = check_plain($table->get('name')); $row[] = $status; $row[] = implode(' | ', $operations); $rows[] = $row; } $rows[] = array( l(t('Create new table'), 'admin/build/data/create'), ' ', ' ', ' ', ); $header = array(t('Title'), t('Name'), t('Status'), t('Operations')); return theme('table', $header, $rows); } /** * Comparison page. */ function data_ui_compare() { $rows = array(); $tables = data_get_all_tables(); foreach ($tables as $table) { $row = array(); $comp = $table->compareSchema(); $row[] = check_plain($table->get('name')); $status = $comp['status']; if ($status != 'same') { $status .= ' - '. l(t('adjust'), 'admin/build/data/compare/'. $table->get('name')); } $row[] = $status; $row[] = empty($comp['warning']) ? '-' : $comp['warning']; $rows[] = $row; } $header = array(t('Name'), t('Status'), t('Warnings')); return theme('table', $header, $rows); } /** * Adjust table schema form: Present the user with the difference between schema information and * the actual schema in the Database and offer three options: * * - Adjust schema info, * - adjust database or * - leave it. */ function data_ui_adjust_form(&$form_state, $table) { drupal_set_title(t('Adjust @table', array('@table' => $table->get('name')))); $comparison = $table->compareSchema(); $form = array(); $form['#redirect'] = 'admin/build/data/compare'; $form['#table'] = $table; $form['#comparison'] = $comparison; $form['comparison'] = array( '#type' => 'fieldset', '#title' => t('Comparison'), ); $form['comparison']['comparison']['#value'] = theme('data_ui_schema_compare_table', $comparison); if ($comparison['status'] == 'different') { $form['update_schema'] = array( '#type' => 'fieldset', '#title' => t('Option 1: Update schema information'), ); $form['update_schema']['description'] = array( '#value' => t('
This option will update the schema information about this table.
'), ); $form['update_schema']['submit'] = array( '#type' => 'submit', '#submit' => array('data_ui_adjust_form_submit_update_schema'), '#value' => t('Update schema information'), ); $form['alter_table'] = array( '#type' => 'fieldset', '#title' => t('Option 2: Alter table'), ); $form['alter_table']['description'] = array( '#value' => t('Review the changes above carefully! This option will alter the database table and can very easily cause data loss.
'), ); $form['alter_table']['submit'] = array( '#type' => 'submit', '#submit' => array('data_ui_adjust_form_submit_alter_table'), '#value' => t('Alter table'), ); } elseif ($comparison['status'] == 'missing') { $form['alter_table'] = array( '#type' => 'fieldset', '#title' => t('Create table'), ); $form['alter_table']['description'] = array( '#value' => t('Create a new table from schema information.
'), ); $form['alter_table']['submit'] = array( '#type' => 'submit', '#submit' => array('data_ui_adjust_form_submit_create_table'), '#value' => t('Create table'), ); } $form['cancel'] = array( '#type' => 'fieldset', '#title' => t('Don\'t change anything'), ); $form['cancel']['cancel'] = array( '#type' => 'submit', '#value' => t('Cancel'), ); return $form; } /** * Submit handler for data_ui_adjust_form(). */ function data_ui_adjust_form_submit_update_schema($form, &$form_state) { $table = $form['#table']; $schema = schema_invoke('inspect'); if (isset($schema[$table->get('name')])) { $table->update(array('table_schema' => $schema[$table->get('name')])); drupal_set_message(t('Updated schema for @table', array('@table' => $table->get('name')))); } else { drupal_set_message(t('Error updating schema'), 'error'); } } /** * Submit handler for data_ui_adjust_form(). */ function data_ui_adjust_form_submit_alter_table($form, &$form_state) { $resolved = $resolved = array(); if (isset($form['#comparison']['reasons'])) { foreach ($form['#comparison']['reasons'] as $field_reason) { try { data_alter_table($form['#table'], $field_reason); $resolved[] = $field_reason; } catch (Exception $e) { $unresolved[] = $field_reason; } } } if (count($resolved)) { drupal_set_message(t('Resolved') . theme('item_list', $resolved)); } if (count($unresolved)) { drupal_set_message(t('Could not resolve') . theme('item_list', $unresolved), 'error'); } } /** * Submit handler for data_ui_adjust_form(). */ function data_ui_adjust_form_submit_create_table($form, &$form_state) { $table = $form['#table']; $ret = array(); db_create_table($ret, $table->get('name'), $table->get('table_schema')); drupal_get_schema($table->get('name'), TRUE); if ($ret[0]['success']) { drupal_set_message(t('Created table @table', array('@table' => $table->get('name')))); } else { drupal_set_message(t('Error creating table'), 'error'); } } /** * Form callback for adopt table form. * * 'Orphaned' tables are database tables that don't have an active schema * definition. */ function data_ui_adopt_form($form_state) { $form = array(); // Compile a list of orphaned tables. $drupal_schema = drupal_get_schema(NULL, TRUE); $db_schema = schema_invoke('inspect'); $orphaned_tables = array(); foreach ($db_schema as $name => $table) { if (!isset($drupal_schema[$name])) { $orphaned_tables[$name] = $name; } } $form['orphaned_tables'] = array( '#type' => 'checkboxes', '#title' => t('Orphaned Tables'), '#options' => $orphaned_tables, ); if (count($orphaned_tables) < 1) { $form['no_orphaned_tables'] = array( '#type' => 'item', '#value' => t('There are no orphaned tables in your database.'), ); } $form['submit'] = array( '#type' => 'submit', '#value' => 'Adopt', ); return $form; } /** * Submit handler for adopt table form. */ function data_ui_adopt_form_submit($form, &$form_state) { data_include('DataTable'); $tables = array_keys(array_filter($form_state['values']['orphaned_tables'])); foreach ($tables as $table_name) { $table = DataTable::instance($table_name); $table->adopt(); unset($table); } DataTable::clearCaches(); $form_state['redirect'] = 'admin/build/data'; } /** * Form callback for create table form. */ function data_ui_create_form(&$form_state) { $form = array(); if (!$form_state['storage']['field_num']) { $form['name'] = array( '#type' => 'textfield', '#title' => t('Table name'), '#description' => t('Machine readable name of the table - e. g. "my_table". Must only contain lower case letters and _.'), '#required' => TRUE, ); $form['title'] = array( '#type' => 'textfield', '#title' => t('Table title'), '#description' => t('Natural name of the table - e. g. "My Table".'), '#required' => TRUE, ); $form['field_num'] = array( '#type' => 'textfield', '#title' => t('Number of fields'), '#description' => t('The number of fields this table should contain.'), '#default_value' => 1, '#required' => TRUE, ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Next'), ); } else { $form['help']['#value'] = t('Define the fields of the new table.'); $form['fields'] = array( '#tree' => TRUE, ); for ($i = 0; $i < $form_state['storage']['field_num']; $i++) { $form['fields']['field_'. $i] = _data_ui_field_form(TRUE); } $form['submit'] = array( '#type' => 'submit', '#value' => t('Create'), ); } return $form; } /** * Validate handler for create table form. */ function data_ui_create_form_validate($form, &$form_state) { if (data_get_table(trim($form_state['storage']['name']))) { form_set_error('name', t('Name is already taken.')); } if (isset($form_state['values']['field_num'])) { if (is_numeric($form_state['values']['field_num'])) { if ($form_state['values']['field_num'] < 1) { form_set_error('field_num', t('At least one field must be created.')); } } else { form_set_error('field_num', t('Enter a number greater than 0.')); } } // Check for dupes. if (isset($form_state['values']['fields'])) { $names = array(); foreach ($form_state['values']['fields'] as $field) { if (is_numeric($names[$field['name']])) { form_set_error('name', t('Names can\'t be numbers.')); } if (!isset($names[$field['name']])) { $names[$field['name']] = $field['name']; } else { form_set_error('name', t('Names must be unique.')); } } } } /** * Submit handler for create table form. */ function data_ui_create_form_submit($form, &$form_state) { if (isset($form_state['values']['field_num'])) { $form_state['storage'] = $form_state['values']; } elseif (isset($form_state['values']['fields'])) { // Create a schema from user input. $schema = $index = $primary = $meta = array(); foreach ($form_state['values']['fields'] as $field) { $field['name'] = db_escape_table($field['name']); $schema['fields'][$field['name']] = data_build_field_definition($field); $meta['fields'][$field['name']]['label'] = check_plain($field['label']); // Limit index if field type is text. if (!empty($field['index'])) { $index[$field['name']] = data_get_index_definition($field['name'], $field); } if (!empty($field['primary'])) { $primary[] = data_get_pk_definition($field['name'], $field); } } $schema['indexes'] = $index; $schema['primary key'] = $primary; // Create table. if ($table = data_create_table(trim($form_state['storage']['name']), $schema, trim($form_state['storage']['title']))) { $meta = $table->update(array('meta' => $meta)); drupal_set_message(t('Created table @table', array('@table' => $table->get('name')))); } else { drupal_set_message(t('Error creating table'), 'error'); } // Unset storage to enable redirect. unset($form_state['storage']); $form_state['redirect'] = 'admin/build/data'; } } /** * Form callback for revert table form. */ function data_ui_revert_form(&$form_state, $table) { $form = array(); $form['#redirect'] = 'admin/build/data'; $form['#table'] = $table; return confirm_form($form, t('Revert this table?'), 'admin/build/data', t('Are you sure you would like to revert table @table? This will reset all information about this table its definition in code. This action cannot be undone.', array('@table' => $table->get('name'))), t('Revert'), t('Cancel') ); } /** * Submit handler for data_ui_revert_form(). */ function data_ui_revert_form_submit($form, &$form_state) { $table = $form['#table']; $table->revert(); } /** * Form callback for drop table form. */ function data_ui_drop_form(&$form_state, $table) { $form = array(); $form['#redirect'] = 'admin/build/data'; $form['#table'] = $table; return confirm_form($form, t('Drop this table?'), 'admin/build/data', t('Are you sure you would like to drop table @table? This action cannot be undone.', array('@table' => $table->get('name'))), t('Drop'), t('Cancel') ); } /** * Submit handler for data_ui_drop_form(). */ function data_ui_drop_form_submit($form, &$form_state) { $table = $form['#table']; data_drop_table(db_escape_table($table->get('name'))); } /** * Form callback for editing a table. */ function data_ui_edit_form(&$form_state, $table) { drupal_set_title(check_plain($table->get('title'))); $schema = $table->get('table_schema'); $meta = $table->get('meta'); $form = array(); // Keep table. $form['table'] = array( '#type' => 'value', '#value' => $table, ); // Existing fields. $form['fields'] = array('#tree' => TRUE); if (isset($schema['fields'])) { foreach ($schema['fields'] as $field_name => $field) { $form['fields'][$field_name] = array(); $form['fields'][$field_name]['selected'] = array( '#type' => 'checkbox', ); $form['fields'][$field_name]['name'] = array('#value' => check_plain($field_name)); $form['fields'][$field_name]['label'] = array( '#type' => 'textfield', '#size' => 20, '#default_value' => $meta['fields'][$field_name]['label'], ); $form['fields'][$field_name]['type'] = array( '#type' => 'select', '#options' => data_get_field_types(), '#default_value' => $field['type'], ); $form['fields'][$field_name]['size'] = array( '#type' => 'select', '#options' => data_get_field_sizes(), '#default_value' => isset($field['size']) ? $field['size'] : 'normal', ); $form['fields'][$field_name]['unsigned'] = array( '#type' => 'checkbox', '#default_value' => isset($field['unsigned']) ? $field['unsigned'] : FALSE, ); $form['fields'][$field_name]['index'] = array( '#type' => 'checkbox', '#default_value' => isset($schema['indexes'][$field_name]), ); $form['fields'][$field_name]['primary'] = array( '#type' => 'checkbox', '#default_value' => isset($schema['primary key']) ? in_array($field_name, $schema['primary key']) : FALSE, ); if (isset($meta['join']) && $join = _data_ui_get_join($meta['join'], $field_name)) { $join = $join['left_table'] .'.'. $join['left_field']; } else { $join = t('' . t('Note that not every handler will make sense or function correctly with every type of field.') . '
', ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Save'), ); return $form; } /** * Submit handler for data_ui_views_form(). */ function data_ui_views_form_submit($form, &$form_state) { $table = $form['#table']; $meta = $table->get('meta'); if (isset($form_state['values']['fields'])) { foreach ($form_state['values']['fields'] as $field_name => $handlers) { foreach ($handlers as $handler_type => $handler) { $meta['fields'][$field_name][$handler_type] = $handler; } } } $table->update(array('meta' => $meta)); views_invalidate_cache(); } /** * Join form. */ function data_ui_join_form(&$form_state, $table, $field_name) { // drupal_set_title(t('Join field')); $schema = $table->get('table_schema'); $meta = $table->get('meta'); // Validate input. if (!isset($field_name) || !isset($schema['fields'][$field_name])) { drupal_set_message(t('Invalid field.'), 'error'); drupal_goto('admin/build/data/edit/'. check_url($table->get('name'))); } // List all tables that schema API knows about as optoins. // @todo: This is a looong list - needs some AHAH to scale better. $table_schemas = drupal_get_schema(); ksort($table_schemas); $options = array(); foreach ($table_schemas as $table_name => $schema) { if ($table->get('name') != $table_name) { foreach ($schema['fields'] as $name => $info) { $options[$table_name][$table_name .'.'. $name] = $table_name .'.'. $name; } } } // Build form. $form = array(); $form['#table'] = $table; $form['#field_name'] = $field_name; $form['#redirect'] = 'admin/build/data/edit/'. check_url($table->get('name')); $join = _data_ui_get_join($meta['join'], $field_name); $form['#original_join'] = $join; $form['left'] = array( '#type' => 'select', '#title' => t('Join @table_field to ', array('@table_field' => $table->get('name') .'.'. $field_name)), '#options' => $options, '#default_value' => $join['left_table'] .'.'. $join['left_field'], ); $form['inner_join'] = array( '#type' => 'radios', '#title' => t('Join type'), '#options' => array(t('Left join'), t('Inner join')), '#default_value' => $join['inner_join'] ? $join['inner_join'] : 0, ); // Use confirm form for its formatting. $form = confirm_form($form, t('Join field'), 'admin/build/data/edit/'. check_url($table->get('name')), '', t('Save'), t('Cancel') ); $form['actions']['delete'] = array( '#type' => 'submit', '#value' => t('Delete'), '#submit' => array('data_ui_join_form_submit_delete'), ); krsort($form['actions']); return $form; } /** * Submit handler for data_ui_join_form(). */ function data_ui_join_form_submit($form, &$form_state) { list($left_table, $left_field) = explode('.', $form_state['values']['left']); $form['#table']->link($left_table, $left_field, $form['#field_name'], $form_state['values']['inner_join']); drupal_set_message(t('Updated join information.')); } /** * Submit handler for data_ui_join_form() - handles deletion. */ function data_ui_join_form_submit_delete($form, &$form_state) { // Use the original join information. $form['#table']->unlink($form['#original_join']['left_table']); drupal_set_message(t('Removed join information.')); } /** * Export form. */ function data_ui_export_form(&$form_state, $table) { $code = data_export(db_escape_table($table->get('name'))); $form['export'] = array( '#title' => t('Export table definition'), '#type' => 'textarea', '#value' => $code, '#rows' => substr_count($code, "\n"), ); return $form; } /** * View table with krumo(). */ function data_ui_view_schema($table) { drupal_set_title(check_plain($table->get('title'))); $output = '