'
', '#value' => t('Tables managed by the Table Wizard module are listed here, each with the name of the database table used to store the data, and statistics on the amount of data. Click the Analyze link to view and edit information on the fields available in the table. Click on the table name to view the data in the table and mark specific rows for exclusion.'), '#suffix' => '
', ); $tableheader = array('data' => t('Table name'), 'field' => 'twt.tablename', 'sort' => 'asc'); $form['header'] = array( '#type' => 'value', '#value' => array( array('data' => t('Delete')), array('data' => ''), $tableheader, ), ); $sql = "SELECT * FROM {tw_tables} twt"; $tablesort = tablesort_sql(array($tableheader)); $result = db_query($sql . $tablesort); $checks = array(); while ($row = db_fetch_object($result)) { $checks[$row->twtid] = ''; $form['twtid'][$row->twtid] = array('#value' => $row->twtid); $form['analyze'][$row->twtid] = array('#value' => l(t('Analyze'), 'admin/content/tw/analyze/'. $row->tablename, array('html' => TRUE))); $form['tablename'][$row->twtid] = array('#value' => l($row->tablename, 'admin/content/tw/view/'. $row->tablename, array('html' => TRUE))); } $form['checks'] = array('#type' => 'checkboxes', '#options' => $checks); $form['#theme'] = 'tw_sources'; $form['delete'] = array( '#type' => 'submit', '#value' => t('Remove selected tables'), ); // Keep each type's fields apart $form['#tree'] = TRUE; // Note that fieldset names ('existing', 'delimited', ...) are the source type names $sourcefieldsets = module_invoke_all('tw_form'); $form = array_merge($form, $sourcefieldsets); // Support file uploads $form['#attributes'] = array('enctype' => 'multipart/form-data'); return $form; } function theme_tw_sources($form) { $output = drupal_render($form['description']); if (isset($form['twtid']) && is_array($form['twtid'])) { foreach (element_children($form['twtid']) as $twtid) { $row = array(); // Don't show the table id $null = drupal_render($form['twtid']); $row[] = drupal_render($form['checks'][$twtid]); $row[] = drupal_render($form['analyze'][$twtid]); $row[] = drupal_render($form['tablename'][$twtid]); $rows[] = $row; } } $header = $form['header']['#value']; if (!isset($rows)) { $rows[] = array(array('data' => t('No tables have been added..'), 'colspan' => count($header))); } $output .= theme('table', $header, $rows); $output .= drupal_render($form['delete']); $output .= drupal_render($form); return $output; } /** * Enter description here... * * @param unknown_type $form * @param unknown_type $form_state */ function _tw_sources_form_submit($form, &$form_state) { $type = $form_state['clicked_button']['#parents'][0]; if ($type == 'delete') { foreach ($form_state['values']['checks'] as $twtid => $value) { if ($value) { $sql = "SELECT tablename FROM {tw_tables} WHERE twtid=%d"; $tablename = db_result(db_query($sql, $twtid)); tw_remove_tables($tablename); drupal_set_message(t('Removed table %tablename', array('%tablename' => $tablename))); } } } else { // Submit hooks return arrays of tablenames they're bringing in $values = $form_state['values'][$type]; $tableset = module_invoke_all("tw_form_submit_$type", $values); tw_add_tables($tableset); } } /** * Add a fieldset into the import form, for identifying where to obtain source data. * * @return unknown */ function tw_tw_form() { //////////////////////////////////////////////////////////// // Add existing tables // Build list of tables we already manage $excludes = array(); $sql = "SELECT * FROM {tw_tables}"; $tblresult = db_query($sql); while ($tblrow = db_fetch_object($tblresult)) { $tblname = $tblrow->tablename; // Exclude the table itself... $excludes[$tblname] = $tblname; } $sql = 'SHOW TABLES'; $result = db_query($sql); $options = array(); while ($row = db_fetch_array($result)) { foreach ($row as $tablename) { if (!$excludes[$tablename]) { // Remove the prefix if any - views knows tables by their logical name, not the DB name $rawtablename = schema_unprefix_table($tablename); $prefixtablename = db_prefix_tables('{'.$rawtablename.'}'); // See if this table already has a views definition - skip it if it does $views_data = views_fetch_data($rawtablename); if (!$views_data && ($tablename == $prefixtablename)) { $options[$tablename] = $tablename; } } } } // Add tables from any other available databases // TODO: Allow selecting a DB and updating the options list dynamically global $db_url; if (is_array($db_url)) { foreach ($db_url as $dbname => $url) { if ($dbname != 'default') { db_set_active($dbname); $sql = 'SHOW TABLES'; $result = db_query($sql); while ($row = db_fetch_array($result)) { foreach ($row as $tablename) { $tablename = $dbname . '.' . $tablename; $options[$tablename] = $tablename; } } } } db_set_active('default'); } $fieldsets['existing'] = array( '#type' => 'fieldset', '#title' => t('Add existing tables'), '#collapsible' => TRUE, '#collapsed' => TRUE, 'uploadhelp' => array( '#prefix' => '
', '#value' => t('Add tables to the Table Wizard.'), '#suffix' => '
', ), 'tablelist' => array( '#type' => 'select', '#title' => t('Available tables'), '#options' => $options, '#description' => t('Tables which are not currently managed by the Table Wizard or otherwise already made available to Views'), ), 'existingsubmit' => array( '#type' => 'submit', '#value' => t('Add tables'), ), ); return $fieldsets; } /** * Enter description here... * * @param unknown_type $values * @return unknown */ function tw_tw_form_submit_existing($values) { $tableset = array(); $tablename = $values['tablelist']; return array($tablename); } /** * Menu callback function * TODO: Flag any available FKs that are not indexed * * @param unknown_type $form_state * @param unknown_type $table * @param unknown_type $flag * @return unknown */ function tw_analysis($form_state, $table, $flag=TW_COLS_NONEMPTY) { $row = db_fetch_object(db_query("SELECT twtid,tabledb FROM {tw_tables} WHERE tablename='%s'", $table)); $twtid = $row->twtid; $tabledb = $row->tabledb; if (isset($_GET['reanalyze'])) { tw_perform_analysis($table, $tabledb); drupal_set_message(t('!tablename analyzed', array('!tablename' => $table))); } $form['twtid'] = array('#type' => 'value', '#value' => $twtid); $form['table'] = array('#type' => 'value', '#value' => $table); switch ($flag) { case TW_COLS_ALL: $flaglabel = t('All fields'); break; case TW_COLS_EMPTY: $flaglabel = t('Empty fields only'); break; case TW_COLS_NONEMPTY: $flaglabel = t('Non-empty fields only'); break; } $form['help'] = array( '#type' => 'fieldset', '#title' => t('Help'), '#collapsible' => TRUE, '#collapsed' => TRUE, ); $form['help']['help1'] = array( '#prefix' => '
', '#value' => t('Fields in the table are listed below, with some information on the range and type of values each field contains. Comments may be entered to document each field individually, and any fields deemed unnecessary can be marked Ignore to omit them from views based on this table.'), '#suffix' => '
', ); $form['help']['help2'] = array( '#prefix' => '
', '#value' => t('The first time this page is visited for a file that has been uploaded (including the first time after a new copy has been imported), the entire contents are read and analyzed - this can take quite a while. The results of the analysis are saved so later visits to the analysis page are quicker. Sometimes, if changes have been made to the table behind the scenes, it\'s useful to force the full analysis by clicking Reanalyze.'), '#suffix' => '
', ); $form['help']['help3'] = array( '#prefix' => '
', '#value' => t('View contents goes to the Table View page for this table. You may find it helpful to open this link in a new window, to browse the data in context while figuring out its meaning for the comments here.'), '#suffix' => '
', ); $form['help']['columns'] = array( '#prefix' => '
', '#value' => t('These are the columns in the table below:'), '#suffix' => '
', ); $form['help']['fieldname'] = array( '#prefix' => '
', '#value' => t('Field name - The name of the field as imported into the database table. This is not necessarily the same as the name in the original file - any non-alphanumeric characters are replaced by underscores (_), and duplicate column names have sequence numbers appended.'), '#suffix' => '
', ); $form['help']['ignore'] = array( '#prefix' => '
', '#value' => t('Ignore - Checking this box for a field will omit that field from the table view.'), '#suffix' => '
', ); $form['help']['pk'] = array( '#prefix' => '
', '#value' => t('Potential PK/PK - Any field which could be used as a primary key for the table (that is, each value is unique and there are no NULL values) is flagged with a 1. The PK checkbox is used to define a field as the primary key for the table.'), '#suffix' => '
', ); $form['help']['fk'] = array( '#prefix' => '
', '#value' => t('Available FK - Check this box to make the field available for use in table relationships.'), '#suffix' => '
', ); $form['help']['strlength'] = array( '#prefix' => '
', '#value' => t('String length - The ranges of string lengths in this field, which helps determine whether the data will fit into the corresponding Drupal field when migrated.'), '#suffix' => '
', ); $form['help']['numrange'] = array( '#prefix' => '
', '#value' => t('Numeric value range - For potential numeric fields, the range of numeric values they contain (determined numerically - e.g., 10 is greater than 9).'), '#suffix' => '
', ); $form['help']['strrange'] = array( '#prefix' => '
', '#value' => t('String value range - For all fields, the range of string values they contained (determined by character order - e.g., 9 is greater than 10). It\'s important to note that at this time all fields except the PK are being stored as strings, so sorting on "numeric" fields in the Table View won\'t necessarily have the expected effect.'), '#suffix' => '
', ); $form['help']['comments'] = array( '#prefix' => '
', '#value' => t('Comments - Description of the field - what it means, and what we will do with it in the migration (ignore it, map it to a given user field or node field, etc.).'), '#suffix' => '
', ); $form['title'] = array('#value' => "Analysis of $table"); $form['header'] = array( '#type' => 'value', '#value' => array( array('data' => t('Field name')), array('data' => t('Ignore')), array('data' => t('PK')), array('data' => t('Available FK')), array('data' => t('Current type')), array('data' => t('String length')), array('data' => t('Range')), array('data' => t('Comments')), ), ); $colcount = 0; $emptycount = 0; $result = db_query("SELECT * FROM {tw_columns} WHERE twtid=%d ORDER BY weight", $twtid); $availablefks = array(); $availablefkenable = array(); $ignoredcols = array(); $ignoreenable = array(); $cols = array(); $pks = array(); while ($row = db_fetch_object($result)) { $colname = $row->colname; $colcount++; if ($row->isempty) { $emptycount++; } if (($flag == TW_COLS_ALL) || (($flag == TW_COLS_EMPTY) && $row->isempty) || (($flag == TW_COLS_NONEMPTY) && !$row->isempty)) { $cols[] = $colname; $form['colname'][$colname] = array('#value' => $colname); $ignoredcols[$colname] = ''; if ($row->ignorecol) { $ignoreenable[] = $colname; } $form['primarykey'][$colname] = array('#value' => $row->primarykey); if ($row->primarykey) { $pks[] = $colname; } $availablefks[$colname] = ''; if ($row->availablefk) { $availablefkenable[] = $colname; } $form['currtype'][$colname] = array('#value' => $row->coltype); if (tw_column_type($row->coltype) == 'text') { $form['lengths'][$colname] = array('#value' => $row->maxlength ? $row->minlength.'-'.$row->maxlength : '' ); $form['values'][$colname] = array( '#attributes' => array('style' => 'white-space: normal'), '#prefix' => '
', '#value' => $row->maxlength ? substr(check_plain($row->minstring),0,40).'
'. substr(check_plain($row->maxstring),0,40) : '', '#suffix' => '
', ); } else { $form['lengths'][$colname] = array('#value' => ''); $form['values'][$colname] = array('#value' => $row->maxvalue ? $row->minvalue.'-'.$row->maxvalue : '' ); } $form['comments'][$colname] = array( '#type' => 'textarea', '#default_value' => $row->comments, '#cols' => 45, '#rows' => 3, '#resizable' => FALSE, ); } } $form['availablefk'] = array( '#type' => 'checkboxes', '#options' => $availablefks, '#default_value' => $availablefkenable, ); $form['ignorecol'] = array( '#type' => 'checkboxes', '#options' => $ignoredcols, '#default_value' => $ignoreenable, ); $form['cols'] = array( '#type' => 'value', '#value' => $cols, ); $form['colcounts'] = array('#value' => "$emptycount of $colcount fields have no data for any row."); $form['submit'] = array( '#type' => 'submit', '#value' => t('Submit changes'), ); if (count($pks) == 0) { drupal_set_message(t('!tablename has no primary key defined. A single-column primary key is necessary to use this table as the base table for a view.', array('!tablename' => $table))); } elseif (count($pks) > 1) { drupal_set_message(t('!tablename has a multiple-column primary key. A single-column primary key is necessary to use this table as the base table for a view.', array('!tablename' => $table))); } return $form; } /** * Enter description here... * * @param unknown_type $form * @return unknown */ function theme_tw_analysis($form) { $title = drupal_render($form['title']); $table = $form['table']['#value']; drupal_set_title($title); $output = ''; $output .= ''; $output .= '
'.drupal_render($form['colcounts']).'
'; $output .= drupal_render($form['help']); if (isset($form['colname']) && is_array($form['colname'])) { foreach(element_children($form['colname']) as $colname) { $row = array(); $row[] = drupal_render($form['colname'][$colname]); $row[] = drupal_render($form['ignorecol'][$colname]); $row[] = drupal_render($form['primarykey'][$colname]); $row[] = drupal_render($form['availablefk'][$colname]); $row[] = drupal_render($form['currtype'][$colname]); $row[] = drupal_render($form['lengths'][$colname]); $row[] = drupal_render($form['values'][$colname]); $row[] = drupal_render($form['comments'][$colname]); $rows[] = $row; } } $header = $form['header']['#value']; if (!isset($rows)) { $rows[] = array(array('data' => t('There are no non-empty columns in the table.'), 'colspan' => count($header))); } $output .= theme('table', $header, $rows); $output .= drupal_render($form); return $output; } /** * Implementation of hook_submit() * * @param unknown_type $form * @param unknown_type $form_state */ function tw_analysis_submit($form, &$form_state) { $twtid = $form_state['values']['twtid']; foreach($form_state['values']['cols'] as $key => $colname) { $newignore = $form_state['values']['ignorecol'][$colname] ? 1 : 0; $newavailablefk = $form_state['values']['availablefk'][$colname] ? 1 : 0; $newcomment = $form_state['values'][$colname]; $newfk = $form_state['values'][$colname.'_fk']; db_query("UPDATE {tw_columns} SET ignorecol=%d, availablefk=%d, comments='%s' WHERE twtid=%d AND colname='%s'", $newignore, $newavailablefk, $newcomment, $twtid, $colname); } drupal_flush_all_caches(); drupal_set_message(t('Your changes have been saved')); } /** * Enter description here... * * @return unknown */ function tw_relationships() { return(drupal_get_form('_tw_relationships_form')); } /** * Enter description here... * * @param unknown_type $form_state * @return unknown */ function _tw_relationships_form($form_state) { $form['description'] = array( '#prefix' => '
', '#value' => t('Define relationships between tables, enabling the creation of views joining those tables.'), '#suffix' => '
', ); $form['header'] = array( '#type' => 'value', '#value' => array( array('data' => t('Delete')), array('data' => t('Left column')), array('data' => t('Right column')), ), ); $sql = "SELECT twr.twrid,CONCAT(twtleft.tablename, '.', twcleft.colname) leftcol, CONCAT(twtright.tablename, '.', twcright.colname) rightcol, twtleft.tabledb leftdb, twtright.tabledb rightdb FROM {tw_relationships} twr INNER JOIN {tw_columns} twcleft ON twr.leftcol=twcleft.twcid INNER JOIN {tw_tables} twtleft ON twcleft.twtid=twtleft.twtid INNER JOIN {tw_columns} twcright ON twr.rightcol=twcright.twcid INNER JOIN {tw_tables} twtright ON twcright.twtid=twtright.twtid ORDER BY leftdb, leftcol, rightcol"; $result = db_query($sql); $checks = array(); while ($row = db_fetch_object($result)) { $checks[$row->twrid] = ''; $form['twrid'][$row->twrid] = array('#value' => $row->twrid); if ($row->leftdb != 'default') { $row->leftcol = $row->leftdb . '.' . $row->leftcol; } $form['leftcol'][$row->twrid] = array('#value' => $row->leftcol); if ($row->rightdb != 'default') { $row->rightcol = $row->rightdb . '.' . $row->rightcol; } $form['rightcol'][$row->twrid] = array('#value' => $row->rightcol); } $form['checks'] = array('#type' => 'checkboxes', '#options' => $checks); $form['#theme'] = 'tw_relationships'; $form['delete'] = array( '#type' => 'submit', '#value' => t('Delete selected relationships'), ); $form['addrel'] = array( '#type' => 'fieldset', '#title' => t('Add a relationship'), '#collapsible' => TRUE, ); $sql = "SELECT twc.twcid, twc.colname, twt.tablename, twt.tabledb FROM {tw_columns} twc INNER JOIN {tw_tables} twt ON twc.twtid=twt.twtid WHERE twc.availablefk=1 ORDER BY tabledb, tablename, colname"; $result = db_query($sql); while ($row = db_fetch_array($result)) { if ($row['tabledb'] == 'default') { $options[$row['twcid']] = $row['tablename'] . '.' . $row['colname']; } else { $options[$row['twcid']] = $row['tabledb'] . '.' . $row['tablename'] . '.' . $row['colname']; } } $form['addrel']['newleftcol'] = array( '#type' => 'select', '#title' => t('Column to appear on the left side of the join'), '#options' => $options, ); $form['addrel']['newrightcol'] = array( '#type' => 'select', '#title' => t('Column to appear on the right side of the join'), '#options' => $options, ); $form['addrel']['add'] = array( '#type' => 'submit', '#value' => t('Add'), ); return $form; } /** * Enter description here... * * @param unknown_type $form */ function theme_tw_relationships($form) { $output = drupal_render($form['description']); if (isset($form['twrid']) && is_array($form['twrid'])) { foreach (element_children($form['twrid']) as $twrid) { $row = array(); // Don't show the row ID $null = drupal_render($form['twrid']); $row[] = drupal_render($form['checks'][$twrid]); $row[] = drupal_render($form['leftcol'][$twrid]); $row[] = drupal_render($form['rightcol'][$twrid]); $rows[] = $row; } } $header = $form['header']['#value']; if (!isset($rows)) { $rows[] = array(array('data' => t('No relationships have been defined.'), 'colspan' => count($header))); } $output .= theme('table', $header, $rows); $output .= drupal_render($form['delete']); $output .= drupal_render($form['addrel']); $output .= drupal_render($form); return $output; } /** * Enter description here... * * @param unknown_type $form * @param unknown_type $form_state */ function _tw_relationships_form_submit($form, &$form_state) { if ($form_state['clicked_button']['#parents'][0] == 'delete') { foreach ($form_state['values']['checks'] as $twrid => $value) { if ($value) { tw_delete_relationship($twrid); $count++; } } if ($count) { drupal_set_message(format_plural($count, '1 relationship deleted', '@count relationships deleted')); } } else { $leftcol = $form_state['values']['newleftcol']; $rightcol = $form_state['values']['newrightcol']; tw_add_relationship($leftcol, $rightcol); } return; }