What it does
----------------
So you've finally upgraded your d5 site to d7, and the old image module galleries are gone, where to go next?

This drush command consolidates the old multiple images nodes into one node per gallery, based on the taxonomy terms that were assigned.

It loads each image node, and if the node has an entry in the taxonomy specified, it grabs the full taxonomy tree and makes that the title of the node, then any further images for the same taxonomy tree it attaches to the same node by directly updating the field_data_node_image & field_revision_node_image tables.

It will output some details as it goes about some images that don't have entries in the taxonomy etc, then it will DELETE the images that it has REMOVED the files from, and no longer needs.

* BACKUP YOUR CODE AND DATABASE FIRST, and run this on a test/local copy of your site.

Directions
-------------
* Copy the script below into your .drush folder
* BACKUP YOUR CODE AND DATABASE
* This drush command assumes your image field is in the "field_data_node_image" & "field_revision_node_image" tables, which should be standard if you upgraded from d5 image module. If you have different field names, you will need to modify the code.
* Ensure that the Image node type has "Unlimited" entries for the Image field.
* Change to the sites/default directory of your site
* Run drush image_d7_convert
* Choose the Image vocabulary
* Wait
* Visit the site once its complete, you may need to 'drush cc all'

After running this process, you probably want to use the EVA module - http://drupal.org/project/eva or http://drupal.org/node/1578774 to make your newly consolidated images show nicely in a per node gallery style

The script:

<?php

/**
 * Implements hook_drush_command();
 */
function image_d7_convert_drush_command() {
  $items = array();

  $items['image_d7_convert'] = array(
    'description' => "Convert d5 image module style nodes classified by taxonomy to single nodes with multiple images",
    'callback' => 'drush_image_d7_convert',
    'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL
  );

  return $items;
}

/**
 * Command callback for above
 */
function drush_image_d7_convert() {
  $galleries = array();
  $nids_to_delete = array();
  $no_gallery = 0;
  $count = 0;

  $vocabularies = taxonomy_vocabulary_get_names();
  foreach ($vocabularies as $vocab) {
    $vocabs[$vocab->vid] = $vocab->name;
  }

  $image_taxonomy = drush_choice($vocabs, "Choose image vocabulary");
  if ($image_taxonomy == "0") {
    return "No vocabulary chosen, aborting\n\n";
  }
  $full_vocab_name = 'taxonomy_vocabulary_'. $image_taxonomy;

  $query = db_select('node', 'n')
    ->condition('type', 'image');

  $nodes = $query->fields('n', array('nid'))
    ->execute()
    ->fetchAll();

  foreach ($nodes as $node) {
    $update = FALSE;

    // Load the full node
    $full_node = node_load($node->nid);
    if (!$full_node) {
      print dt("Node !node doesn't exist", array("!node" => $node->nid));
      continue;
    }
    
    // Firstly, check if we already have a node for this category
    if (isset($full_node->{$full_vocab_name}['und'])) {
      foreach ($full_node->{$full_vocab_name}['und'] as $tid) {
        $gallery_name = drush_image_d7_term_to_title($tid['tid']);
        if ($gallery_name && !isset($galleries[$gallery_name])) {
          print dt("New gallery !gallery\n", array("!gallery" => $gallery_name));
          $galleries[$gallery_name] = $full_node->nid;

          // Update the title to be the same as the gallery
          $full_node->title = $gallery_name;
          node_save($full_node);
        }
        else {
          $master_node = $galleries[$gallery_name];
          $update = TRUE;
          // Mark this node to be deleted, its images will be taken
          $nids_to_delete[] = $full_node->nid;
        }
      }
    }
    else {
      print dt("No gallery associated with !node, edit manually\n",
               array('!node' => url('node/'. $full_node->nid, array('absolute' => TRUE))));
      $no_gallery++;
    }

    if ($update) {
      foreach ($full_node->node_image['und'] as $image) {
        //print dt("Updating image from !node to !master_node for !fid\n", array('!node' => $full_node->nid, '!master_node' => $master_node, '!fid' => $image['fid']));

        // Update the file usage table
        db_update('file_usage')
          ->fields(array('id' => $master_node))
          ->condition('fid', $image['fid'])
          ->execute();

        // Now update the entity tables
        // Find next delta
        $delta = db_query("SELECT max(delta) as delta FROM {field_data_node_image} WHERE entity_id = :entity", array(':entity' => $master_node))->fetch();
        
        $new_delta = $delta->delta + 1;
        
        db_update('field_data_node_image')
          ->fields(
            array('entity_id' => $master_node, 
                  'revision_id' => $master_node,
                  'delta' => $new_delta))
          ->condition('entity_id', $full_node->nid)
          ->execute();

        db_update('field_revision_node_image')
          ->fields(
            array('entity_id' => $master_node, 
                  'revision_id' => $master_node,
                  'delta' => $new_delta))
          ->condition('entity_id', $full_node->nid)
          ->execute();
      }
    }

    $count++;
  }

  print dt("\n!count nodes had no gallery associated\n", array('!count' => $no_gallery));

  print "\nList of Galleries and their new master nodes\n";
  foreach ($galleries as $name => $nid) {
    print url('node/'. $nid, array('absolute' => TRUE)) ."\n";
  }

  print dt("\nConsolidated !count image nodes to !newcount\n", array("!count" => $count, "!newcount" => count($galleries)));

  print dt("Deleting !count no longer needed nodes, this can take some minutes\n", array("!count" => count($nids_to_delete)));
  node_delete_multiple($nids_to_delete);

  cache_clear_all();
  
  print "\nProcess completed\n";
}

function drush_image_d7_term_to_title($tid) {
  $term = taxonomy_term_load($tid);

  $parents = taxonomy_get_parents_all($tid);

  if ($parents) {
    foreach ($parents as $object) {
      $names[] = $object->name;
    }

    $tree_names = array_reverse($names);
    
    $tree_name = implode(" - ", $tree_names);

    return $tree_name;
  }
}

Comments

singularo’s picture

Just had to work through this again over the weekend and found that there are a few changes/corrections to the notes.

Directions
-------------
* Copy the script below into your .drush folder and name it image_d7_convert.drush.inc
* BACKUP YOUR CODE AND DATABASE
* drush -y en field_convert
* /admin/content/field_convert - select image and run the conversion - This is the part that creates the image field tables - "field_data_node_image" & "field_revision_node_image", which should standard if you upgraded from d5/d6 image module. If you have different field names, you will need to modify the drush code.
* Clear cache so Image type shows up
* Edit Image content type, node_image field so that it has "Unlimited" entries
* Run drush image_d7_convert
* Choose the Image vocabulary
* Wait
* Visit the site once its complete, you may need to 'drush cc all'

Once thats done, I'd recommend the eva module - drupal.org/project/eva - to display the list of images associated with a note.