You are here

function _content_migrate_batch_process_migrate_data in Content Construction Kit (CCK) 7.3

Batch operation callback to migrate data. Copy old table data to new field table.

2 string references to '_content_migrate_batch_process_migrate_data'
drush_content_migrate_field_data in modules/content_migrate/includes/content_migrate.drush.inc
_content_migrate_batch in modules/content_migrate/includes/content_migrate.admin.inc
Helper function to create a batch.

File

modules/content_migrate/includes/content_migrate.admin.inc, line 298
content_migrate.admin.inc Code to process field data migration, moved into a separate file for efficiency.

Code

function _content_migrate_batch_process_migrate_data($field_name, &$context) {

  // The first time through, find all the nodes that have this field.
  if (!isset($context['sandbox']['progress'])) {
    $field_value = content_migrate_get_field_values($field_name);
    if (isset($field_value['messages'])) {
      unset($field_value['messages']);
    }
    $instance_values = content_migrate_get_instance_values(NULL, $field_name);
    if (isset($instance_values['messages'])) {
      unset($instance_values['messages']);
    }
    $types = array();
    foreach ($instance_values as $bundle => $instance_value) {
      $types[] = $bundle;
    }
    $field = field_info_field($field_name);
    $old_table = content_migrate_old_table($field_value, $instance_value);
    $old_cols = content_migrate_old_columns($field_value, $instance_value);
    $new_table = content_migrate_new_table($field);
    $new_revision_table = content_migrate_new_revision($field);
    $new_columns = content_migrate_new_columns($field);

    // Shared, non-multiple fields do not have a delta but are still in per-field tables.
    $add_delta = $field_value['cardinality'] != 1 && content_migrate_storage_type($field_value, $instance_value) == CONTENT_DB_STORAGE_PER_FIELD;
    $query = db_select($old_table, 'old_table', array(
      'fetch' => PDO::FETCH_ASSOC,
    ));
    $node_alias = $query
      ->join('node', 'n', 'old_table.nid=n.nid');
    $result = $query
      ->fields($node_alias, array(
      'title',
      'type',
      'vid',
      'language',
    ))
      ->fields('old_table', array(
      'nid',
    ))
      ->orderBy('nid', 'ASC')
      ->distinct()
      ->execute();
    $nodes = array();
    foreach ($result as $row) {
      $nodes[] = array(
        'nid' => $row['nid'],
        'title' => $row['title'],
        'type' => $row['type'],
        'vid' => $row['vid'],
        'language' => $row['language'],
      );
    }
    $context['sandbox']['progress'] = 0;
    $context['sandbox']['max'] = count($nodes);
    $context['sandbox']['nodes'] = $nodes;
    $context['sandbox']['old_table'] = $old_table;
    $context['sandbox']['new_table'] = $new_table;
    $context['sandbox']['new_revision_table'] = $new_revision_table;
    $context['sandbox']['old_cols'] = $old_cols;
    $context['sandbox']['new_cols'] = $new_columns;
    $context['sandbox']['types'] = $types;
    $context['sandbox']['field'] = $field;
    $context['sandbox']['add_delta'] = $add_delta;
  }

  // Process 100 nodes in each batch.
  $field = field_info_field($field_name);

  // Construct an record to insert into the new field table
  // from the data in the old table.
  $query = db_select($context['sandbox']['old_table'], 'old_table', array(
    'fetch' => PDO::FETCH_ASSOC,
  ));

  // We need new columns for bundle name, entity type, and language.
  // See the debate going on at http://drupal.org/node/1164852.
  // Reverting back to setting all nodes as untranslated.
  $language = LANGUAGE_NONE;
  if ($field['translatable']) {

    //$language = $node['language'];
  }
  $query
    ->addExpression("'node'", 'entity_type');
  $query
    ->addExpression("'" . $language . "'", 'language');

  // There are new names for what were the nid and vid columns.
  $query
    ->addField('old_table', 'nid', 'entity_id');
  $query
    ->addField('old_table', 'vid', 'revision_id');

  // Add the field columns to the select query.
  // Use the new column names as aliases in case the
  // name changed, hopefully none did.
  foreach ($context['sandbox']['old_cols'] as $column_name => $db_column_name) {
    $query
      ->addField('old_table', $db_column_name, $context['sandbox']['new_cols'][$column_name]);
  }

  // Add delta, or construct it if missing.
  if ($context['sandbox']['add_delta']) {
    $query
      ->addField('old_table', 'delta', 'delta');
  }
  else {
    $query
      ->addExpression(0, 'delta');
  }
  $base_query = $query;
  for ($i = 0; $i <= 100; $i++) {
    $query = clone $base_query;
    $node = array_shift($context['sandbox']['nodes']);
    if (!$node) {

      // Rollback the field if there was a data migration error.
      if ($context['sandbox']['rollback'] == TRUE) {
        content_migrate_rollback(array(
          $field_name,
        ));
      }
      return;
    }
    $instance = field_info_instance('node', $field_name, $node['type']);
    $query
      ->addExpression("'" . $node['type'] . "'", 'bundle');
    $query
      ->condition('nid', $node['nid']);
    $result = $query
      ->execute();
    foreach ($result as $record) {
      module_load_include('inc', 'content_migrate', 'modules/content_migrate.' . $field['module']);
      try {

        // Let modules alter this before the insert.
        drupal_alter('content_migrate_data_record', $record, $field, $instance);

        // Don't save empty values.
        if (!empty($record)) {
          $function = $field['module'] . '_field_is_empty';
          if (function_exists($function)) {

            // The $record array has the database columns as keys, which drupal_write_record() will need,
            // but the _field_is_empty() function will be looking for the short, normalized column name.
            $item = array();
            foreach ($context['sandbox']['new_cols'] as $column_name => $db_column_name) {
              if (array_key_exists($db_column_name, $record)) {
                $item[$column_name] = $record[$db_column_name];
              }
            }
            if ($function($item, $field)) {
              $record = NULL;
            }
          }
        }
        if (!empty($record)) {
          if ($record['revision_id'] == $node['vid']) {
            drupal_write_record($context['sandbox']['new_table'], $record);
          }
          drupal_write_record($context['sandbox']['new_revision_table'], $record);
        }
      } catch (Exception $e) {

        // An error has occurred trying to migrate a record of this field.
        // Set this field to be rolledback and display a detailed error message.
        $context['sandbox']['rollback'] = TRUE;
        $exception = t('<p>Requesting rollback of field "@field" due to failure to convert record:</p>' . '<p>@record</p>  <p>Cause:</p> <p>@cause</p>', array(
          '@field' => $field_name,
          '@record' => var_export($record, TRUE),
          '@cause' => $e,
        ));
        drupal_set_message($exception, 'error');
      }
    }

    // Update our progress information.
    $context['sandbox']['progress']++;
  }
  $context['message'] = t('Processing through nid %nid', array(
    '%nid' => $node['nid'],
  ));

  // Inform the batch engine that we are not finished,
  // and provide an estimation of the completion level we reached.
  if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
    $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
  }
}