Migrated to D7; displaying images

After some deliberation I decided that it was finally time to move to Drupal 7. Most of the modules I use have been ported, and I figured I could hack my way around the rest. While there's substantially more hacking to be done, I have a fairly good handle on it so far. There were more complications than I expected, however.

I started using Drupal with 4.7 and have worked my way up from there. That upgrade went pretty smoothly. From 5 to 6 also worked okay, although I did lose my amazon nodes. That data is presumably still rattling around somewhere in the back of the database, and lessons learned recently may help me extract it.

A notable hole in the migration process is how images are dealt with. While it was possible to create your own image node types previously by adding imagefields to them, this is the only type of image node which exists in Drupal 7. By default, there is not an "image" content type. For those of us who have been managing images as nodes all along, this presents a bit of difficulty. In addition, the Image filter does not work, at all, and there is no img_attach for D7, at all. When converting from D6 to D7, then, someone who has used both of these means of inserting images is left with a lot of image nodes with no nodetype and no imagefield, and a lot of unprocessed image and img_assist tags in their content.

There is an official process for converting your image content to modern nodes, and it involves fetching the image_legacy module from a source repository. Along with the field_convert module this provides a means for getting your image nodes back, pretty much how you remember them. But actually displaying them is another matter, because there's no filters which do this. I made some myself with the Custom Filter module, which lets you match a regular expression and replace it with another one, or with some PHP code's output. I've attached image_legacy below, but you can't count on it being the latest version. It is possible that some kind soul will improve it.

After browsing through a number of resources including the custom filter examples I came up with this solution for image tags:

Pattern: /\[image:([\d]+) (.+?)]/

Replacement PHP code:

$nid = $matches[1];
$elements = explode(' ', $matches[2]);

$result = '(filter error or malformed image tag)';

foreach ($elements as $element) {
  $parts = explode('=', $element);
  if ( $parts[1] != '' ) {
    $values[$parts[0]] = $parts[1];
  }
}

if ( $nid ) {
  $mynode = node_load($nid);
  if (!$mynode) {
    $result = "(cannot load image node)";
  } else {
    $path = $mynode->node_image[$mynode->language][0]['uri'];
    if ( $values[height] && $values[width] ) {
      $result = theme('image_style', array('style_name' => 'large', 'path' => $path, 'getsize' => FALSE, 'alt' => $mynode->title, 'attributes' => array('class' => 'img_assist', 'width' => $values[width], 'height' => $values[height])));
    } else {
      $result = theme('image_style', array('style_name' => 'large', 'path' => $path, 'getsize' => TRUE, 'alt' => $mynode->title, 'attributes' => array('class' => 'img_assist')));
    }
  }
}

return $result;

And a similar piece of code for img_attach tags. To wit:

Pattern: /\[img_assist\|(.+?)]/

$elements = explode('|', $matches[1]);

$result = '(filter error or malformed img_assist tag)';

foreach ($elements as $element) {
  $parts = explode('=', $element);
  if ( $parts[1] != '' ) {
    $values[$parts[0]] = $parts[1];
  }
}

if ( $values[nid] ) {
  $mynode = node_load($values[nid]);
  if (!$mynode) {
    $result = "(cannot load image node)";
  } else {
    $path = $mynode->node_image[$mynode->language][0]['uri'];
    if ( $values[height] && $values[width] ) {
      $result = theme('image_style', array('style_name' => 'large', 'path' => $path, 'getsize' => FALSE, 'alt' => $mynode->title, 'attributes' => array('class' => 'img_assist', 'width' => $values[width], 'height' => $values[height])));
    } else {
      $result = theme('image_style', array('style_name' => 'large', 'path' => $path, 'getsize' => TRUE, 'alt' => $mynode->title, 'attributes' => array('class' => 'img_assist')));
    }
  }
}

return $result;

You can see how essentially similar these two filters are. You can also see just how little functionality I've implemented. Because these examples are so simple, though, it should be easy to understand how to extend them to support more or less the full range of functionality.

Before I even supported images, I actually used this approach for weblinks.

Pattern: /\[weblink:([\d]+)]/

$node = node_load($matches[1]);
if (!$node) {
    $result = '<span class="custom_filter_warning">-Node not found, check the node id you entered-</span>';
    }
else {
    $result = t($node->title);
    }
return $result;

Which you can see is pretty directly ripped off from one of the provided examples. It doesn't actually provide a link; the links are stored in another database table. I do intend to add that functionality though, probably before I mess with images any more. All this filter does is place the title of the weblink node (which is actually an untyped node) into the text in place of the weblink tag. This is enough to clean up the output, at least.

Another trick I played was converting my drinking games to a new node format. At some point they had both a body field and a game text field which held the actual node body, but eventually I deleted the body field because I never used it. The game text field was retained during the migration, but not displayed. I decided to use the Node Convert module to remedy this problem. I renamed the old node format to "drinking games old" and created a new type with the appropriate vocabulary fields selected from existing fields for the game type and boot factor, then created a node convert template which mapped the vocabulary fields across directly and mapped the game text to the body. After running this I only had to update my views to reflect the change in node type and all was well. Actually, those views had also decided they didn't know how to find my taxonomy fields since the migration, so I deleted those fields from the views and re-added them.

After this I discovered that the content type for my nodes had been reset to default, so various filters weren't being applied any more. I managed to find a page with a relevant php snippet that led me in the right direction. I thrashed around for a while trying to create an action which could be applied to nodes that would permit changing body text format for a whole bunch of nodes at once, but finally wound up using the Views Bulk Operations module and its content management view page (admin/content2) to execute PHP against nodes selected in the view. It also lets you select even non-visible nodes in the list (a sort of "select all") with a checkbox if you select all the visible results, which is a lovely feature. Here's what the code looked like in my case:

$entity->body[$entity->language][0]['format'] = '3'; // full html
node_save($entity);

The node object is already loaded into $entity, because you're doing a bulk operation on nodes. You can visit admin/config/content/formats and mouse over the formats to find out the value of format, or you can dig through the database. This worked neatly and sent me into the world of custom filters for images.

I also whipped up a new theme based on Zen, using an image I used for a D6 theme briefly before, apparently, accidentally deleting every copy of it that I had. It seems I've managed to bring back my old favicon as well. Perhaps I should work on animating one of those in between all my architectural projects.

File attachments: 

Comments

Hello from Hamburg/Germany; I'm just upgrading a webiste with thousands of images - uploaded in Drupal 6 with the node-type image; I've searched for days for a good instruction; but there is no good one on drupal.org or drupal.de; your instruction saved my soul ;-) especially the download-file of image_legacy wich I found on Drupal only as a code-site.... but - your download-file has a "_" behind the "tar" - I renamed it for unpacking and then it works !! thank you very much for this instruction and the download-file :-))) best regards Peter