Migrating data from Drupal 6 to Drupal 7

Massaging Drupal 6 data into Drupal 7

One of our clients is redeveloping the front-end of their site and wanted to take the opportunity to upgrade from Drupal 6 in the process. As the basic data structure was to remain the same, it made sense to go for a straight upgrade, following the instructions in the UPGRADE.txt file from Drupal 7.

After checking that all the modules on the original site were up to date, I did a quick site audit. All of the Drupal 6 modules used had a Drupal 7 version except for the attribute module. The attribute module lets you create a CCK field that contains an attribute:value pair, such as color:blue or size:large. This kind of functionality can be created in Drupal 7 using the field collection module, but would require a bit of work to migrate the data over.

The original site used features extensively. The built in Drupal upgrade path is designed around migrating data contained in the database, not in code. A quick look through the features issue queue provided this patch which adds an extra drush command to features – drush features-import-all.  Running this moved all of the features into the database.  I could then disable each of the custom features without losing any configuration data.

Continuing with the instructions in UPGRADE.txt, I quickly had Drupal core updated to version 7 together with all the contributed modules that had a Drupal 7 release.  All the content types were still there, but missing lots of fields, which brings us to the next step – moving Drupal 6 CCK data to Drupal 7 fields.  This is well covered in the Drupal handbook page, Migrating D6 Content Construction Kit (CCK) to D7 Fields.

By this point, all the old content was showing up in Drupal 7 apart from the attribute fields. The old CCK attribute field was called field_item_for_sale_glance and all the data was in the content_field_item_for_sale_glance table in the database.

I created a new field_collection, which I also called field_item_for_sale_glance, containing two text fields; field_sale_attribute_key and field_sale_attribute_value.  After that, a quick bit of custom code was required to copy the data across.

function sale_attribute_to_field_collection() {
  // Get all item_for_sale nodes.
  $result = db_select('node', 'n')
    ->condition('n.type', 'item_for_sale')

  foreach ($result as $node_data) {
    // Check to see if the old CCK attribute field has any data for this node.
    $old_field = db_select('content_field_item_for_sale_glance', 'old')
      ->condition('old.nid', $node_data->nid)
      ->condition('old.vid', $node_data->vid)
      ->orderBy('old.delta', 'ASC')

    foreach ($old_field as $old_data) {
      if ($node = node_load($node_data->nid)) {
        // Create a new field collection item.
        $field_collection_item = entity_create('field_collection_item', array('field_name' => 'field_item_for_sale_glance'));
        // Attach it to the node.
        $field_collection_item->setHostEntity('node', $node);
        // Insert the attribute field values.
        $field_collection_item->field_sale_attribute_key[LANGUAGE_NONE][0]['value'] = $old_data->field_item_for_sale_glance_attribute;
        $field_collection_item->field_sale_attribute_value[LANGUAGE_NONE][0]['value'] = $old_data->field_item_for_sale_glance_value;
        // Save the field collection.

That successfully moved the last of the data over, ready for the front-end work to begin.

Once Drupal 8 is released, I imagine we'll see a flurry of Drupal 6 sites wanting to move to Drupal 7.  It's good to see that the upgrade process is relatively painless.