t('Clear')),
array('data' => t('Import')),
array('data' => t('Content Set')),
array('data' => t('Total rows')),
array('data' => t('Imported')),
array('data' => t('Unimported')),
array('data' => t('Last imported')),
);
$form['header'] = array('#type' => 'value', '#value' => $header);
$sql = "SELECT *
FROM {migrate_content_sets}
ORDER BY weight, contenttype, view_name, view_args";
$result = db_query($sql);
$clearing = array();
$importing = array();
$rownum = 0;
while ($row = db_fetch_object($result)) {
$status = '';
if ($row->mcsid) {
$view = views_get_view($row->view_name);
if (!$view) {
drupal_set_message(t('View !view does not exist - either (re)create this view, or
remove the content set using it.', array('!view' => $row->view_name)));
continue;
}
$clearing[$row->mcsid] = '';
$importing[$row->mcsid] = '';
$status = t('N/A');
$maptable = migrate_map_table_name($row->mcsid);
$sourcekey = $row->sourcekey;
$imported = db_result(db_query('SELECT COUNT(*) FROM {' . $maptable . '}'));
// If not caching counts, override the saved count with a fresh count
if (!variable_get('migrate_cache_counts', 0)) {
$row->rowcount = _migrate_get_view_count($view, $row->view_args);
}
$unimported = $row->rowcount - $imported;
$msgtablename = migrate_message_table_name($row->mcsid);
if ($unimported > 0) {
$messages = '';
$numerrors = db_result(db_query("SELECT COUNT(DISTINCT sourceid)
FROM {" . $msgtablename . "}
WHERE level=%d",
MIGRATE_MESSAGE_ERROR));
if ($numerrors > 0) {
$messages .= l(format_plural($numerrors, '1 error', '@count errors'),
"admin/content/tw/view/$msgtablename/" . MIGRATE_MESSAGE_ERROR,
array('html' => TRUE))
. '
';
}
$numwarnings = db_result(db_query("SELECT COUNT(DISTINCT sourceid)
FROM {" . $msgtablename . "}
WHERE level=%d",
MIGRATE_MESSAGE_WARNING));
if ($numwarnings > 0) {
$messages .= l(format_plural($numwarnings, '1 warning', '@count warnings'),
"admin/content/tw/view/$msgtablename/" . MIGRATE_MESSAGE_WARNING,
array('html' => TRUE))
. '
';
}
$numnotices = db_result(db_query("SELECT COUNT(DISTINCT sourceid)
FROM {" . $msgtablename . "}
WHERE level=%d",
MIGRATE_MESSAGE_NOTICE));
if ($numnotices > 0) {
$messages .= l(format_plural($numnotices, '1 notice', '@count notices'),
"admin/content/tw/view/$msgtablename/" . MIGRATE_MESSAGE_NOTICE,
array('html' => TRUE))
. '
';
}
if ($messages) {
$unimported = $messages . " $unimported total";
}
}
if ($imported > 0) {
$numinformational = db_result(db_query("SELECT COUNT(DISTINCT sourceid)
FROM {" . $msgtablename . "}
WHERE level=%d",
MIGRATE_MESSAGE_INFORMATIONAL));
if ($numinformational > 0) {
$imported .= '
' .
l(format_plural($numinformational, '1 informational message', '@count informational messages'),
"admin/content/tw/view/$msgtablename/" . MIGRATE_MESSAGE_INFORMATIONAL,
array('html' => TRUE))
. '
';
}
}
}
else {
$imported = '';
$unimported = '';
}
$form['data'][$rownum]['clearing'] = array('#value' => 0);
$form['data'][$rownum]['importing'] = array('#value' => 0);
$form['data'][$rownum]['description'] = array('#value' =>
l($row->description, 'admin/content/migrate/' . $row->mcsid));
$form['data'][$rownum]['importrows'] = array('#value' => check_plain($row->rowcount));
$form['data'][$rownum]['imported'] = array('#value' => $imported);
$form['data'][$rownum]['unimported'] = array('#value' => $unimported);
$form['data'][$rownum]['lastimported'] = array('#value' => $row->lastimported);
$form['data'][$rownum]['mcsid'] = array('#value' => check_plain($row->mcsid));
$form['data'][$rownum]['status'] = array('#value' => $row->status);
$rownum++;
}
$form['clearing'] = array(
'#type' => 'checkboxes',
'#options' => $clearing,
);
$form['importing'] = array(
'#type' => 'checkboxes',
'#options' => $importing,
);
if (user_access(MIGRATE_ACCESS_ADVANCED)) {
// Open the fieldset if we're coming back from a run
// TODO: Or from a Stop
$collapsed = strpos(referer_uri(), 'batch') === FALSE;
$form['interactive'] = array(
'#type' => 'fieldset',
'#title' => t('Execute'),
'#collapsible' => TRUE,
'#collapsed' => $collapsed,
'#description' => t('
While large migration tasks are best run via drush, you may choose here to execute tasks directly. Check any tasks you want to run, and click the Run button. Note that the settings below will be applied to each task you run.
Running tasks may be cleanly stopped by clicking Stop all running tasks.'), ); $form['interactive']['update'] = array( '#type' => 'checkbox', '#title' => t('Update previously-imported content'), '#description' => t('If unchecked, import operations will only process source data which has not already been imported. If checked, they will also replace previously-imported destination objects with the current source information.'), '#default_value' => variable_get('migrate_update', 0), ); $form['interactive']['limit'] = array( '#type' => 'textfield', '#title' => t('Sample size'), '#size' => 4, '#description' => t('Number of records to process. Leave blank to process all records in the content set.'), '#default_value' => variable_get('migrate_limit', ''), ); $form['interactive']['idlist'] = array( '#type' => 'textfield', '#title' => t('Source IDs'), '#size' => 30, '#description' => t('Enter a comma-separated list of IDs from the incoming content set, to process only those records.'), ); $form['interactive']['submit'] = array( '#type' => 'submit', '#value' => t('Run'), '#submit' => array('_migrate_dashboard_form_run'), ); $form['interactive']['stop'] = array( '#type' => 'submit', '#value' => t('Stop all running tasks'), '#submit' => array('_migrate_dashboard_form_stop'), ); } // Fetch information on available destinations $desttypes = migrate_invoke_all('types'); $form['addset'] = array( '#type' => 'fieldset', '#title' => t('Add a content set'), '#collapsible' => TRUE, '#collapsed' => $rownum == 0 ? FALSE: TRUE, ); $form['addset']['description'] = array( '#type' => 'textfield', '#title' => t('Description of the content set'), '#description' => t('A friendly phrase only used for display.'), ); $form['addset']['contenttype'] = array( '#type' => 'select', '#title' => t('Destination'), '#options' => $desttypes, '#description' => t('The type of Drupal content which will store the incoming records.'), ); $views = views_get_all_views(); foreach ($views as $name => $view) { if ($view->tag) { $options[$name] = $view->tag . ': ' . $name; } else { $options[$name] = $name; } if ($view->description) { if (drupal_strlen($view->description) > 60) { $view->description = drupal_substr($view->description, 0, 57) . '...'; } $options[$name] .= " ($view->description)"; } } asort($options); $form['addset']['view_name'] = array( '#type' => 'select', '#title' => t('Source view from which to import content'), '#options' => $options, '#description' => t('This View defines the records which are to be migrated.'), ); $form['addset']['view_args'] = array( '#type' => 'textfield', '#title' => t('View arguments'), '#description' => t('Arguments to apply to the view when processing, separated with a / as though they were a URL path.'), '#maxlength' => 255, '#size' => 30, ); $form['addset']['weight'] = array( '#type' => 'textfield', '#title' => t('Weight'), '#required' => TRUE, '#default_value' => 0, '#description' => t('The order in which content sets will be processed and displayed.'), ); $form['addset']['add'] = array( '#type' => 'submit', '#value' => t('Add'), '#submit' => array('_migrate_content_set_form_submit'), '#validate' => array('_migrate_content_set_form_validate'), ); return $form; } /** * Theme function for dashboard page */ function theme_migrate_dashboard($form) { $output = drupal_render($form['description']); if (isset($form['data']) && is_array($form['data'])) { foreach (element_children($form['data']) as $rownum) { $row = array(); foreach (element_children($form['data'][$rownum]) as $colname) { if ($colname == 'clearing' || $colname == 'importing') { $row[] = drupal_render($form[$colname][$form['data'][$rownum]['mcsid']['#value']]); // Throw out the column contents drupal_render($form['data'][$rownum][$colname]); drupal_render($form['data'][$rownum]['mcsid']); } elseif ($colname == 'status' || $colname == 'mcsid') { drupal_render($form['data'][$rownum][$colname]); } else { $row[] = drupal_render($form['data'][$rownum][$colname]); } } // Highlight any process currently running if ($form['data'][$rownum]['status']['#value']) { $rows[] = array('data' => $row, 'class' => 'migrate-running'); } else { $rows[] = $row; } } } $header = $form['header']['#value']; if (empty($rows)) { $rows[] = array(array('data' => t('No data in the table.'), 'colspan' => count($header))); } $output .= theme('table', $header, $rows, array('class' => 'migrate-dashboard')); $output .= drupal_render($form); return $output; } /* * Implementation of hook_submit(). */ function _migrate_dashboard_form_run($form, &$form_state) { $started = time(); $values = $form_state['values']; $clearing = array(); $importing = array(); foreach ($values['importing'] as $mcsid => $value) { if ($value) { $importing[$mcsid] = $mcsid; } if ($values['clearing'][$mcsid]) { $clearing[$mcsid] = $mcsid; } } variable_set('migrate_limit', $values['limit']); variable_set('migrate_update', $values['update']); $batch = array( 'operations' => array( array('migrate_content_process_batch', array($clearing, $importing, $values['limit'], trim($values['idlist'])))), 'title' => t('Migration processing'), 'file' => drupal_get_path('module', 'migrate') . '/migrate_pages.inc', 'init_message' => t('Starting migration process'), 'progress_message' => t(''), 'error_message' => t('An error occurred. Some or all of the migrate processing has failed.'), 'finished' => '_migrate_content_process_finish', ); batch_set($batch); } /* * Implementation of hook_submit(). */ function _migrate_dashboard_form_stop($form, &$form_state) { db_query("UPDATE {migrate_content_sets} SET status=%d", MIGRATE_STATUS_IDLE); drupal_set_message(t('All migration tasks have been stopped.')); } /** * Batch API finished callback - report results * * @param $success * Ignored * @param $results * List of results from batch processing * @param $operations * Ignored */ function _migrate_content_process_finish($success, $results, $operations) { foreach ($results as $result) { drupal_set_message($result); } } /** * Common validation function for content sets */ function _migrate_content_set_validate($form_state) { $description = trim($form_state['values']['description']); if (!$description) { form_set_error('description', t('Content set description is required')); } $weight = trim($form_state['values']['weight']); if (!is_numeric($weight) || (((int)$weight) != $weight)) { form_set_error('weight', t('Weight must be an integer value (positive or negative)')); } $view_name = $form_state['values']['view_name']; $view_args = trim($form_state['values']['view_args']); if (isset($form_state['values']['mcsid'])) { $sql = "SELECT mcsid FROM {migrate_content_sets} WHERE view_name='%s' AND view_args='%s' AND mcsid<>%d"; $mcsid = db_result(db_query($sql, $view_name, $view_args, $form_state['values']['mcsid'])); } else { $sql = "SELECT mcsid FROM {migrate_content_sets} WHERE view_name='%s' AND view_args='%s'"; $mcsid = db_result(db_query($sql, $view_name, $view_args)); } if ($mcsid) { if ($view_args) { form_set_error('view_name', t('There is already a content set with this combination of source view and view arguments.')); } else { form_set_error('view_name', t('There is already a content set with this source view and no view arguments.')); } } } /** * Implementation of hook_validate(). */ function _migrate_content_set_form_validate($form, $form_state) { _migrate_content_set_validate($form_state); } /** * Implementation of hook_submit(). */ function _migrate_content_set_form_submit($form, &$form_state) { $content_set['view_name'] = $form_state['values']['view_name']; $content_set['view_args'] = trim($form_state['values']['view_args']); $content_set['description'] = $form_state['values']['description']; $destination = explode('/', $form_state['values']['contenttype']); $content_set['contenttype'] = $destination[0]; if (isset($destination[1])) { $content_set['desttype'] = $destination[1]; } $content_set['weight'] = $form_state['values']['weight']; $mcsid = migrate_save_content_set($content_set); // Go straight to the mapping form $form_state['redirect'] = "admin/content/migrate/$mcsid"; } /** * Menu callback function for content set edit page. */ function migrate_content_set_mappings($form_state, $mcsid) { $row = db_fetch_object(db_query("SELECT * FROM {migrate_content_sets} WHERE mcsid=%d", $mcsid)); $desttype = $row->desttype; $view_name = $row->view_name; $view_args = $row->view_args; $sourcekey = $row->sourcekey; $description = $row->description; $contenttype = $row->contenttype; $desttype = $row->desttype; $weight = $row->weight; $multiple_separator = $row->multiple_separator; // Fetch information on available destinations $desttypes = migrate_invoke_all('types'); $destfields = migrate_invoke_all("fields_$contenttype", $desttype); $form['mcsid'] = array( '#type' => 'value', '#value' => $mcsid, ); $form['description'] = array( '#type' => 'textfield', '#title' => t('Description of the content set'), '#default_value' => $description, ); $form['show_view_name'] = array( '#prefix' => '
Each batch of a migration performed interactively will last a few seconds less than the less of max_execution_time and max_input_time. It is recommended that you set these to a higher value (say, 240) in .htaccess.
' ); } if ($memory_limit < 128*1024*1024) { $description .= t( 'Large migration operations can take substantial memory, particularly if there is cached information growing with each iteration. It is recommended that you set memory_limit higher (at least 256M if you can).
' ); } $description .= t('Current PHP configuration options:
max_execution_time | !max_execution_time |
max_input_time | !max_input_time |
memory_limit | !memory_limit |