How To: Migrate from Image.module to ImageField Documentation Project

Psicomante - December 18, 2007 - 13:27
Project:ImageField
Version:6.x-3.0
Component:Documentation
Category:bug report
Priority:normal
Assigned:Unassigned
Status:needs review
Description

Is there any possibility to convert image.module/imageattacch images in imagefield? Is there any project in progress?

Thanks.

#1

Psicomante - December 18, 2007 - 13:28

#2

dopry - December 18, 2007 - 17:45
Title:Image.module to imagefield/imagecache data conversion» Image.module to imagedfield/imagecache data conversion

This is a quick and dangerous suggestion... You should back up your database and do this on a test site before even considering it for production...

Background:

Both Image.module and ImageField maintain relationships between the files table and the node table. Relating files.fid to node.vid or node.nid. This means you can theoretically migrate from Image to ImageField by properly configuring a new Content type to replace Image and executing a few database queries. This process is dependent on the machine readable content type and field names used in the CCK image content type.

Here is a completely untested example workflow.

  1. Create a content type cck_image.
  2. Add a single value, required ImageField to your CCK image content type named 'image'.
  3. INSERT into content_type_cck_image (nid, vid) (SELECT nid, vid FROM node WHERE type='image')
  4. UPDATE content_type_cck_image cck join image i on cck.nid = i.nid SET cck.field_image_fid = i.fid WHERE i.image_size = '_original';
  5. UPDATE node SET type='cck_image' WHERE type='image'

However be warned this will no longer work with any of the modules intended to work with image.module. You will have to setup imagecache to handle derivative images, and it is very likely your themes will be broken, and any custom code built around image.module will no longer work.

If anyone has luck or refinements to the process please post them here and we will build a handbook page out of it.

#3

dopry - December 18, 2007 - 17:48
Title:Image.module to imagedfield/imagecache data conversion» How To: Migrate from Image.module to ImageField Documentation Project
Category:support request» task
Status:active» needs review

#4

sime - February 11, 2008 - 16:46

In my experience updating to Imagefiled 2, I needed to update the filepath in the files table.

Say your main files directory is "sites/default/files"
Your image.module directory will be "images" (sites/default/files/images)
You might find in the files table the filepath will be "image/blah.jpg"

Now say your new imagefield is configured to put images in "cck_image". The path will be "sites/default/files/cck_image".
But when you add an image this way, looking in the files table, the filepath is "sites/default/files/cck_image/blah.jpg

In short, imagefield stores the full filepath, while image module stored the filepath relative to the files directory.

So the SQL for me was something like:

UPDATE files
SET filepath = CONCAT('sites/default/files/', filepath)
WHERE filepath LIKE 'images%'

I also wanted to update the filename from '_original' so I simple worked out the length of, in this example, 'sites/default/files/cck_image/'. Which is 30. So:

UPDATE files
SET filename = RIGHT(filepath, LENGTH(filepath) - 30)
WHERE filename = '_original'

All from memory, can't guarantee the sql.

#5

asb - April 26, 2008 - 23:56

Hi,

> In my experience updating to Imagefiled 2, I needed to update the filepath in the files table.

Has anyone tested this already? If the precedure is solid, I'd like to suggest to add migration as a sub-module to Imagefield. Would this be possible?

Thanks & greetings, -asb

#6

nvoyageur - June 10, 2008 - 19:38

I migrated from image.module to imagefield the following way on http://www.ridetowork.org/everydayrides

Get Set Up

  1. BACK UP YOUR FILES AND DATABASE
  2. No, seriously, backup your files and database
  3. You need to create a content type
  4. Add an image field to that content type. In my case it was called 'image_cache'
  5. My images were in "/files/images/"

I used PHPMyAdmin to run these queries.

Load your 'content_field_image_cache' with info from the 'node' table.

insert into content_field_image_cache (vid,delta,nid,field_image_cache_fid, field_image_cache_title, field_image_cache_alt) SELECT n.vid,0 as delta,n.nid,f.fid,n.title,n.title FROM node n, files f WHERE n.nid = f.nid AND n.type = 'image' and f.filename = '_original'

You're going to change the 'image_cache' parts to what ever you named your imagefield.

Alerter your 'files' table

update files set filepath = CONCAT('files/',filepath) where filename = '_original' and filepath not like 'files/%'

This prepends 'files/' to your filepath field in

update files set filename = SUBSTRING(filepath,14) where filename = '_original'

This is the tricky part. It extracts the file name from our filepath (e.g. files/images/123.jpg) you will chop it down to just the filename (e.g. 123.jpg). If you change where you have kept the original images then you'll need to change 14 to another number to accommodate.

Alert your 'node' table

update node set type = 'everydayride' where type = 'image'

You're going to change 'everydayrides' to the name of your content type.

Empty Your Cache!!!

Clean Up

  1. Some images didn't show up because they had a '&' or '+' in the file name. I needed to change the file name on the server and then edit the corresponding node id (nid) in the 'files' table.
  2. Some of my filepath entries were different after the migration, I had to clean them up by hand.
  3. You will want to delete all the preview and thumbnail entries in the 'files' and 'file_revisions' tables
    delete fr from files f, file_revisions fr WHERE f.fid = fr.fid AND f.filename = 'thumbnail'

    delete fr from files f, file_revisions fr WHERE f.fid = fr.fid AND f.filename = 'preview'

    delete from files WHERE filename = 'preview' OR filename = 'thumbnail'
  4. You will want to delete all the *.preview.* and *.thumbnail.* files from your files/imagesdirectory.

There are a bunch of variables to this conversion such as where you store your images and the imagefield name. YMMV. I thought I read somewhere that someone is going to write a migration module for this for D7.

#7

moshe weitzman - May 2, 2008 - 02:12

Very useful, Spydor. I will try this one of these days on groups.drupal.org for group nodes. I will report back afterwards. if anyone else tries this, please let us know how it goes.

#8

seaneffel - June 2, 2008 - 23:17

Subscribing so I can follow along at home.

#9

seaneffel - June 3, 2008 - 01:10

In my first attempt to migrate from image.module to imagefield +imagecache was pretty good. There were a few changes I had to make in the queries listed by Spydor, some tables and fields did not yet exist.

Now, how about image_attach? With your directions I noticed that the thumbnails that were previously attached to nodes via image_attach are now disassociated. A good migration path would resolve these as well.

Also something to consider as part of migration, I think that the Video Image module also depends on the Image module.

#10

moshe weitzman - June 3, 2008 - 00:44

imagefield users generally use imagecache for thumbnailing. the beatiful thing about imagecache is that it generates thumbnails when it needs to. so you don't need to even think about migrating thumbnails. just focus on the originals.

#11

seaneffel - June 3, 2008 - 19:22

Oh yeah, I get that.

But there is some step that I did incorrectly where old image_attach thumbnails have not been replaced by new imagecache thumbnails. AFAICT, I used to create a blog node and use the image_attach module to create both an image node and then a resulting reference to the thumbnail that gets attached to the original blog. Something in this migration process above is not properly sticking imagefield values to nodes that used image_attach.

About 50% of the image_attach-ed nodes are missing imagefield values. All of the thumbs that were image_attach-ed to video nodes are not inserted into their imagefields (video used the video_image module to use the image_attach module to post a thumb).

Is there an additional step or did I botch the process?

#12

dopry - June 3, 2008 - 18:56

I know very little about image attach... drewish would be the best person to talk to about that...

#13

moshe weitzman - June 12, 2008 - 23:16
Status:needs review» fixed

Here is a migration script based on the code offerred here. The script is pretty well documented. I added a link to this issue from the imagefield project page. There may be more/other places which should link here.

<?php
/**
* @file
* Migrate all image.module nodes to imagefields. Any image nodes that participate in image_attach will be
* properly attached the imagefield. The script does migrate video_image.module images.
*
* PREREQUISITES
* --------------
* - You must create a single imagefield field to which all your images will be migrated. You
* should create a new content type for that.
* - If you use image_attach, you should also add this imagefield field to each content type that
* is image_attach enabled.
* - The imagefield should be configured for 'multiple values'.
* - The imagefield's Image path should be identical to the image.module's configured path (i.e. 'images' by default)
*
* USAGE
* ----------
* - Backup your Drupal database. Really.
* - Edit the 'Configuration' section below.
* - Place this script in the root of your Drupal site.
* - Run this script by requesting <a href="http://<yoursite>/imagefield_migrate.php" title="http://<yoursite>/imagefield_migrate.php" rel="nofollow">http://<yoursite>/imagefield_migrate.php</a> in your browser.
* - Remove this script from your site to prevent accidental re-run.
* - Disable and uninstall image and image_attach modules.
*
* KNOWN ISSUES
* -------------
* - Rename files that have a '+' in them in the files table and also rename in filesystem
*
* AUTHORS
*  -----------
* spydor (see <a href="http://drupal.org/node/201983#comment-828698" title="http://drupal.org/node/201983#comment-828698" rel="nofollow">http://drupal.org/node/201983#comment-828698</a>)
* Moshe Weitzman (<a href="http://drupal.org/moshe" title="http://drupal.org/moshe" rel="nofollow">http://drupal.org/moshe</a>)
*/

// ***** CONFIGURATION *******

// The imagefield field that you have already created and configured as per Prerequisites.
$field_name = 'field_imagefield';

// The content type that you have already created as per Prerequisites.
$type_name = 'image2';

// ***** END CONFIGURATION *******

require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

// Populate the imagefield table for every image node.
$table = 'content_'. $field_name;
$fid = $field_name. '_fid';
$title = $field_name. '_title';
$alt = $field_name. '_alt';

$sql = "INSERT INTO $table (vid,delta,nid,$fid, $title, $alt) SELECT n.vid, 0 as delta, n.nid,f.fid,n.title,n.title FROM node n, files f WHERE n.nid = f.nid AND n.type = 'image' AND f.filename = '_original'";
if (
db_query($sql)) {
  echo
"- $table populated.<br />\n";
}

// Set the needed filename in the files table.
$image_path = file_create_path(variable_get('image_default_path', 'images'));
$length = strlen($image_path)+2;
$sql = "UPDATE files SET filename = SUBSTRING(filepath, $length) WHERE filename = '_original'";
if (
db_query($sql)) {
  echo
"- files table updated<br />\n";
}

// Change the content type from 'image' to the configured type.
$sql = "UPDATE node SET type = '%s' WHERE type = 'image'";
db_query($sql, $type_name);

// Loop over the image_attach records
if (module_exists('image_attach')) {
 
$sql = "SELECT n.nid, n.vid, ia.iid FROM {image_attach} ia INNER JOIN {node} n ON ia.nid=n.nid";
 
$result = db_query($sql);
  if (
$num = db_num_rows($result)) {
    while (
$row = db_fetch_object($result)) {
     
// UPDATE the imagefield to point to the attached node, not the standalone node
     
$sql = "UPDATE $table SET nid = $row->nid, vid = $row->vid WHERE nid = $row->iid";
      if (
db_query($sql)) {
       
// Successful update. Now unpublish the standalone node that we just made.
       
$sql = "UPDATE {node} SET status = 0 WHERE nid = $row->iid";
       
db_query($sql);
      }
      else {
        echo
"update $table failed for $row->iid<br />\n";
      }
    }
    echo
"- $num image_attach relationships were migrated.<br />\n";
  }
}

if (
module_exists('video_image')) {
 
// Loop over the video.module nodes. Migrate video_image thumbnails to imagefield.
 
$sql = "SELECT nid, vid FROM {node} WHERE type = 'video'";
 
$result = db_query($sql);
  if (
$num = db_num_rows($result)) {
    while (
$row = db_fetch_object($result)) {
     
$node = node_load($row->nid);
      if (
$iid = $node->iid) {
       
$sql = "UPDATE $table SET nid = $row->nid, vid = $row->vid WHERE nid = $iid";
        if (
db_query($sql)) {
         
// Successful update. Now unpublish the standalone node that we just made.
         
$sql = "UPDATE {node} SET status = 0 WHERE nid = $iid";
         
db_query($sql);
        }
        else {
          echo
"update $table failed for $iid<br />\n";
        }
      };
    }
    echo
"- $num video.module thumbnails were migrated.<br />\n";
  }
}

// Clear CCK cache.
$sql = "DELETE FROM cache_content";
db_query($sql);
?>

#14

dopry - June 12, 2008 - 23:20

/me hugs moshe.

#15

HorsePunchKid - June 21, 2008 - 19:39

Here's a patch that puts curly braces around the table names that were lacking them and also rearranges a couple of the prerequisites into the order that you'll encounter them in the content type admin page. Possibly a couple of other style-level changes, but only on lines that I was already changing. Also attached is the patched version. Tested, and it worked as advertised. Thank you so much!

AttachmentSize
imagefield_migrate.php_.txt 4.64 KB
imagefield_migrate_misc.patch 2.8 KB

#16

Anonymous (not verified) - July 5, 2008 - 19:43
Status:fixed» closed

Automatically closed -- issue fixed for two weeks with no activity.

#17

truelove-nl - August 3, 2008 - 14:24

Unfortunately both scripts #13 and #15 didn't work for me. Had to restore from backup.
Created a node-type 'tijdelijk' and a imagefield 'image_field' prior to the migration. I added this field to 'tijdelijk' and 3 other content-types.

Here's a summary from the log:

update content_field_image failed for 581
..
..
update content_field_image failed for 3692
update content_field_image failed for 3694
- 682 image_attach relationships were migrated.

As far as I could see target tables were empty.

Question: take the scripts table-name-prefixes in account?
Other question: I would like to execute the migration manually (#6), but what are the queries to be executed to migrate the image_attach links?

Thanks for all the work.

#18

alexanderpas - September 16, 2008 - 15:18
Status:closed» needs work

line 78 doesn't account for prefixes

#19

hobbes_VT - November 12, 2008 - 02:05

After finally figuring out how to get all my image nodes transfered to image fields (including the table prefix) I realized that Imagefield lacks a few things I had back with the Image module ...
Anyway, just for anyone who would like to make the transition, below is the script that worked for my database - here are the basic changes:
1) in the "configuration" lines you can now also define your table prefix
2) the imagefield table in my database was not content_field_fieldname as the original script above has it, but rather content_type_typename ... thus the changes ... (check your database what you have before running either script)
3) I added a few variables to the script for the table names to include their prefixes

There's still one issue that remains ...
If you created your image nodes with the drupal-image plugin in TinyMCE (as I did) - those nodes are not migrated correctly (missing) as this process does not write the term "_original" into the file table ... that's the point when I figured out that Imagefield will not work perfectly for me, thus I didn't resolve this last piece of migration any more ... but here you go:

<?php
/**
* @file
* Migrate all image.module nodes to imagefields. Any image nodes that participate in image_attach will be
* properly attached the imagefield. The script does migrate video_image.module images.
*
* PREREQUISITES
* --------------
* - You must create a single imagefield field to which all your images will be migrated. You
* should create a new content type for that.
* - The imagefield's Image path should be identical to the image.module's configured path (i.e. 'images' by default)
* - The imagefield should be configured for 'multiple values'.
* - If you use image_attach, you should also add this imagefield field to each content type that
* is image_attach enabled.
*
* USAGE
* ----------
* - Backup your Drupal database. Really.
* - Edit the 'Configuration' section below.
* - Place this script in the root of your Drupal site.
* - Run this script by requesting <a href="http://<yoursite>/imagefield_migrate.php" title="http://<yoursite>/imagefield_migrate.php" rel="nofollow">http://<yoursite>/imagefield_migrate.php</a> in your browser.
* - Remove this script from your site to prevent accidental re-run.
* - Disable and uninstall image and image_attach modules.
*
* KNOWN ISSUES
* -------------
* - Rename files that have a '+' in them in the files table and also rename in filesystem
*
* AUTHORS
*  -----------
* spydor (see <a href="http://drupal.org/node/201983#comment-828698" title="http://drupal.org/node/201983#comment-828698" rel="nofollow">http://drupal.org/node/201983#comment-828698</a>)
* Moshe Weitzman (<a href="http://drupal.org/moshe" title="http://drupal.org/moshe" rel="nofollow">http://drupal.org/moshe</a>)
* hobbes_vt
*/

// ***** CONFIGURATION *******

// Table prefix ... in case you use it - otherwise leave blank
$table_pfx = '';

// The imagefield field that you have already created and configured as per Prerequisites.
$field_name = 'field_imagefield';

// The content type that you have already created as per Prerequisites.
$type_name = 'imagepage';

// ***** END CONFIGURATION *******

require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

// Populate the imagefield table for every image node.
$table = $table_pfx. 'content_type_'. $type_name; // this changed from the original version
$fid = $field_name. '_fid';
$title = $field_name. '_title';
$alt = $field_name. '_alt';
$table_node = $table_pfx. 'node'; // add prefix
$table_files = $table_pfx. 'files'; // add prefix

$sql = "INSERT INTO {$table} (vid, nid, $fid, $title, $alt) SELECT n.vid, n.nid, f.fid, n.title, n.title FROM {$table_node} n INNER JOIN {$table_files} f ON n.nid = f.nid WHERE n.type = 'image' AND f.filename = '_original'";
if (
db_query($sql)) {
  echo
"- $table populated.<br />\n";
}

// Set the needed filename in the files table.
$image_path = file_create_path(variable_get('image_default_path', 'images'));
$length = strlen($image_path)+2;
$sql = "UPDATE {$table_files} SET filename = SUBSTRING(filepath, $length) WHERE filename = '_original'";
if (
db_query($sql)) {
  echo
"- files table updated<br />\n";
}

// Change the content type from 'image' to the configured type.
$sql = "UPDATE {$table_node} SET type = '%s' WHERE type = 'image'";
db_query($sql, $type_name);

// Loop over the image_attach records
if (module_exists('image_attach')) {
 
$table_image_attach = $table_pfx. 'image_attach'; // add prefix
 
$sql = "SELECT n.nid, n.vid, ia.iid FROM {$table_image_attach} ia INNER JOIN {$table_node} n ON ia.nid=n.nid";
 
$result = db_query($sql);
  if (
$num = db_num_rows($result)) {
    while (
$row = db_fetch_object($result)) {
     
// UPDATE the imagefield to point to the attached node, not the standalone node
     
$sql = "UPDATE $table SET nid = $row->nid, vid = $row->vid WHERE nid = $row->iid";
      if (
db_query($sql)) {
       
// Successful update. Now unpublish the standalone node that we just made.
       
$sql = "UPDATE {$table_node} SET status = 0 WHERE nid = $row->iid";
       
db_query($sql);
      }
      else {
        echo
"update $table failed for $row->iid<br />\n";
      }
    }
    echo
"- $num image_attach relationships were migrated.<br />\n";
  }
}

if (
module_exists('video_image')) {
 
// Loop over the video.module nodes. Migrate video_image thumbnails to imagefield.
 
$sql = "SELECT nid, vid FROM {$table_node} WHERE type = 'video'";
 
$result = db_query($sql);
  if (
$num = db_num_rows($result)) {
    while (
$row = db_fetch_object($result)) {
     
$node = node_load($row->nid);
      if (
$iid = $node->iid) {
       
$sql = "UPDATE {$table} SET nid = $row->nid, vid = $row->vid WHERE nid = $iid";
        if (
db_query($sql)) {
         
// Successful update. Now unpublish the standalone node that we just made.
         
$sql = "UPDATE {$table_node} SET status = 0 WHERE nid = $iid";
         
db_query($sql);
        }
        else {
          echo
"update $table failed for $iid<br />\n";
        }
      };
    }
    echo
"- $num video.module thumbnails were migrated.<br />\n";
  }
}

// Clear CCK cache.
$table_cache_content = $table_pfx. 'cache_content'; // add prefix
$sql = "DELETE FROM {$table_cache_content}";
db_query($sql);
?>

#20

fasdalf@fasdalf.ru - December 15, 2008 - 19:04

There are another database structure in drupal 6. I cfn't figure out what should i change to make it work with Drupal 6 Image/Imagefield.

#21

markosef - December 19, 2008 - 12:46

so it doesnt work with drupal 6?

#22

seaneffel - December 19, 2008 - 14:06

It would work for Drupal 6 with a few changes. Start by comparing the schema of D5 Image to the D6 Image modules, and the same for Filefield for D5 and D6.

#23

asb - January 4, 2009 - 22:51

Hi,

is someone already working on a migration script for Image Gallery to something similar for Imagefield?

Thanks & greetings, -asb

#24

seaneffel - January 5, 2009 - 17:41

Someone correct me if I am wrong, but I don't think migrating from Image to Imagefield would require database-level scripting to fix your Image Gallery setup.

Image Gallery simply adds taxonomy terms to image nodes uploaded with the Image module and then displays image files on various layouts. When you run the migration script above then the taxonomy terms assigned when each node was created are still the same.

Then you would build a few views with the Views module to recreate the sorting and filtering of your old galleries using the same taxonomy. Views actually gives you more flexibility in your new "galleries" for how you sort, filter, arrange, hide, etc, your images.

No code necessary, but still do a backup for safety's sake.

#25

asb - January 6, 2009 - 09:46

Hi Sean,

thanks for your reply; maybe I was a bit mislead by this thread's name (which suggested to me a complete migration path for the whole "Image" module package, including the missing pieces like attaching CCK-based "imagefield nodes" to other nodes as Image attach does, like bulk uploading/importing images as Image import and Image attach and Image Publishing do, etc. As it seems, this thread is much tighter focused)

Regarding imagefield galleries: Most tutorials for galleries with imagefield(s) I know are based on multi-value imagefields; IMHO this would require something like migrating one "Image Gallery" with multiple images in it (from the "Image" module) into a CCK "Gallery" content type with one multi-value imagefield (where a newly created "Gallery" node would contain all images from the taxonomy-based "Image Gallery"). However, if your suggestion from #24 can be made work - I tried this several times and never succeeded - there would be no need for database-level scripting, indeed (which would be even better ;). One of the great features of "Image Gallery" is, that it works quite automatically; opposed to this, the gallery howto requires you to manually create as many views as you have galleries (which wouldn't make sense in my case). Maybe this can be done more intelligently, but I at least haven't yet figured out how to accomplish this.

Sorry fo hijacking this thread if it is supposed to be limited to migrating "Image" module image nodes into CCK/Imagefield-based nodes.

Greetings, asb

#26

rkeppner - January 6, 2009 - 16:17

I managed to get hobbes_VT's, et al. script from comment #19 working for Drupal 6, at least in my case. I'm posting it here to save others the rework, since the new CCK schema isn't as straightforward as it used to be. In addition to the prerequisites mentioned in the code, if you started with image.module in Drupal 5 (like I did), you'll need to make sure that you've successfully upgraded image.module first. (See http://drupal.org/node/342269.)

<?php

/**
* @file
* Migrate all image.module nodes to imagefields in Drupal 6. Any image nodes
* that participate in image_attach will be properly attached the imagefield.
* The script does migrate video_image.module images.
*
* PREREQUISITES
* -------------
* - You must create a single imagefield field to which all your images will be migrated. You
*   should create a new content type for that.
* - The imagefield's Image path should be identical to the image.module's configured path (i.e. 'images' by default)
* - The imagefield should be configured for 'multiple values'.
* - If you use image_attach, you should also add this imagefield field to each content type that
*   is image_attach enabled.
*
* USAGE
* -----
* - Backup your Drupal database. Really.
* - Edit the 'Configuration' section below.
* - Place this script in the root of your Drupal site.
* - Run this script by requesting <a href="http://<yoursite>/imagefield_migrate.php" title="http://<yoursite>/imagefield_migrate.php" rel="nofollow">http://<yoursite>/imagefield_migrate.php</a> in your browser.
* - Remove this script from your site to prevent accidental re-run.
* - Disable and uninstall image and image_attach modules.
*
* KNOWN ISSUES
* ------------
* - Rename files that have a '+' in them in the files table and also rename in filesystem
*
* AUTHORS
* -------
* spydor (see <a href="http://drupal.org/node/201983#comment-828698" title="http://drupal.org/node/201983#comment-828698" rel="nofollow">http://drupal.org/node/201983#comment-828698</a>)
* Moshe Weitzman (<a href="http://drupal.org/moshe" title="http://drupal.org/moshe" rel="nofollow">http://drupal.org/moshe</a>)
* hobbes_vt
* rkeppner
*/

// ***** CONFIGURATION *******

// Table prefix ... in case you use it - otherwise leave blank
$table_pfx = '';

// The imagefield field that you have already created and configured as per Prerequisites.
$field_name = 'field_imagefield';

// The content type that you have already created as per Prerequisites.
$type_name = 'imagepage';

// ***** END CONFIGURATION *******

require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

// Populate the imagefield table for every image node.
$table_content_type = $table_pfx. 'content_type_'. $type_name; // this changed from the original version
$table_content_field = $table_pfx. 'content_'. $field_name;
$fid = $field_name. '_fid';
$list = $field_name. '_list';
$data = $field_name. '_data';
$table_node = $table_pfx. 'node'; // add prefix
$table_files = $table_pfx. 'files'; // add prefix
$table_upload = $table_pfx. 'upload'; // add prefix

$sql = "INSERT INTO {$table_content_type} (vid, nid)
  SELECT n.vid, n.nid FROM {$table_node} n
  INNER JOIN {$table_upload} u ON n.nid = u.nid
  INNER JOIN {$table_files} f ON u.fid = f.fid
  WHERE n.type = 'image' AND f.filename = '_original'"
;
if (
db_query($sql)) {
  echo
"- $table_content_type populated.<br />\n";
}
else {
  echo
"- $table_content_type NOT populated.<br />\n";
}
$sql = "INSERT INTO {$table_content_field} (vid, nid, delta, $fid, $list, $data)
  SELECT n.vid, n.nid, 0, f.fid, 1, CONCAT('a:1:{s:11:\"description\";s:', CHAR_LENGTH(n.title), ':\"', n.title, '\";}')
  FROM {$table_node} n
  INNER JOIN {$table_upload} u ON n.nid = u.nid
  INNER JOIN {$table_files} f ON u.fid = f.fid
  WHERE n.type = 'image' AND f.filename = '_original'"
;
if (
db_query($sql)) {
  echo
"- $table_content_field populated.<br />\n";
}
else {
  echo
"- $table_content_field NOT populated.<br />\n";
}

// Set the needed filename in the files table.
$image_path = file_create_path(variable_get('image_default_path', 'images'));
$length = strlen($image_path)+2;
$sql = "UPDATE {$table_files} SET filename = SUBSTRING(filepath, $length) WHERE filename = '_original'";
if (
db_query($sql)) {
  echo
"- files table updated<br />\n";
}
else {
  echo
"- files table NOT updated<br />\n";
}

// Change the content type from 'image' to the configured type.
$sql = "UPDATE {$table_node} SET type = '%s' WHERE type = 'image'";
db_query($sql, $type_name);

// Loop over the image_attach records
if (module_exists('image_attach')) {
 
$table_image_attach = $table_pfx. 'image_attach'; // add prefix
 
$sql = "SELECT n.nid, n.vid, ia.iid FROM {$table_image_attach} ia INNER JOIN {$table_node} n ON ia.nid=n.nid";
 
$result = db_query($sql);
 
$num = 0;
  while (
$row = db_fetch_object($result)) {
   
$num++;
   
// UPDATE the imagefield to point to the attached node, not the standalone node
   
$sql = "UPDATE $table_content_type SET nid = $row->nid, vid = $row->vid WHERE nid = $row->iid";
    if (!
db_query($sql)) {
      echo
"update $table_content_type failed for $row->iid<br />\n";
    }
   
$sql = "UPDATE $table_content_field SET nid = $row->nid, vid = $row->vid WHERE nid = $row->iid";
    if (
db_query($sql)) {
     
// Successful update. Now unpublish the standalone node that we just made.
     
$sql = "UPDATE {$table_node} SET status = 0 WHERE nid = $row->iid";
     
db_query($sql);
    }
    else {
      echo
"update $table_content_field failed for $row->iid<br />\n";
    }
  }
  echo
"- $num image_attach relationships were migrated.<br />\n";
}

if (
module_exists('video_image')) {
 
// Loop over the video.module nodes. Migrate video_image thumbnails to imagefield.
 
$sql = "SELECT nid, vid FROM {$table_node} WHERE type = 'video'";
 
$result = db_query($sql);
 
$num = 0;
  while (
$row = db_fetch_object($result)) {
   
$num++;
   
$node = node_load($row->nid);
    if (
$iid = $node->iid) {
     
$sql = "UPDATE {$table_content_type} SET nid = $row->nid, vid = $row->vid WHERE nid = $iid";
      if (
db_query($sql)) {
       
// Successful update. Now unpublish the standalone node that we just made.
       
$sql = "UPDATE {$table_node} SET status = 0 WHERE nid = $iid";
       
db_query($sql);
      }
      else {
        echo
"update $table failed for $iid<br />\n";
      }
    };
  }
  echo
"- $num video.module thumbnails were migrated.<br />\n";
}

// Clear CCK cache.
$table_cache_content = $table_pfx. 'cache_content'; // add prefix
$sql = "DELETE FROM {$table_cache_content}";
db_query($sql);

?>

#27

seaneffel - January 6, 2009 - 18:05

I'm pretty sure that Image Gallery doesn't create nodes, correct me if I'm wrong. I think that module has a bunch of hard coded "views" that do the work of displaying galleries. I know the layout that you mean to recreate, where the Image Gallery displays a gallery browser each with the most recent photo and number of photos included.

I think you could still get a single view to do most of your work. One example of a views/taxonomy driven image gallery is here. I've got one view with an exposed filter for the taxonomy which was once the gallery name, it's only one view with several filtering choices. http://www.squarefour.org/photos

Leveraging a good argument out of your view might also be very helpful in getting many different results from the same view based on the URL. Like mysite.com/myview/term1 and then mysite.com/myview/term2 and so on. I have a personal and unreasonably biased hatred for working with arguments, but don't let that stop you since it is quite a good method.

#28

nickurbits - February 3, 2009 - 02:42

i had alot of problems getting that script to work, so i quickly wrote up my own, my node type was called image_cache and field was field_image_cache

<?php
require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
$sql = "SELECT * FROM {files} WHERE `filename`='_original' ORDER BY `nid` DESC;";
$result = db_query($sql);
while (
$file = db_fetch_array($result)) {
  if (
file_exists($file['filepath'])) {
   
$node = node_load($file['nid']);
    if (
$node->type != 'image_cache') {
      unset(
$node->nid);
     
$node->type = 'image_cache';
     
$node->field_image_cache[0]['fid'] = $file['fid'];
     
$title = strrpos($file['filepath'], '/');
     
$title = substr($file['filepath'], ($title + 1));
     
$node->field_image_cache[0]['title'] = $title;
     
$node->field_image_cache[0]['alt'] = $title;
     
$node->field_image_cache[0]['nid'] = $file['nid'];
     
$node->field_image_cache[0]['filepath'] = $file['filepath'];
     
$node->field_image_cache[0]['filemime'] = $file['filemime'];
     
$node->field_image_cache[0]['filesize'] = $file['filesize'];
     
node_save($node);
      print
'updated '. $node->title .'<br />';
    }
  }
}
?>

#29

gausarts - February 11, 2009 - 09:19

subs thanks

#30

trogie - February 14, 2009 - 10:19

thanks for these scripts.

I'm currently trying to adopt these scripts to be less 'destructive' as I want just to move the images from _one_ specific contenttype from img_attach to imagefield.

@nickurbits: how did you get that $node->field_image_cache array structure? I'm trying to programmatically change a node (not creating a new one) but the node doesn't keep the changes after the node_save...

#31

nickurbits - February 16, 2009 - 00:40

This ended up being my full script, for our purposes we needed to copy all the files to sites/default and create new nodes (image_cache).

<?php
require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
?>

<h1>Copying files to sites/default/files/images</h1>
<table border="1">
<?php
$sql
= "SELECT * FROM {files} WHERE `filename`='_original' ORDER BY `nid`;";
$result = db_query($sql);
$l = 0;
while (
$file = db_fetch_array($result)) {
  if (
file_exists($file['filepath'])) {
   
$sql = "SELECT * FROM {node} WHERE `nid`='%s';";
   
$node = db_fetch_object(db_query($sql, $file['nid']));
    if (
$node->type != 'image_cache') {
     
$i = strrpos($file['filepath'], '/');
     
$prefix = substr($file['filepath'], 0, $i);
     
$name = substr($file['filepath'], ($i + 1));
     
$filepath = $_SERVER['DOCUMENT_ROOT'] .'/'. $prefix .'/'. $name;
      if (
file_exists($filepath)) {
       
$new['prefix'] = 'sites/default/files/images';
       
$naughty = array(' ', '-', '(', '&', '*', ')', ',', '/', '\\',);
       
$new['name'] = str_replace('_.', '.', str_replace('___', '_', str_replace('__', '_', strtolower(str_replace($naughty, '_', $name)))));
       
$new['filepath'] = $_SERVER['DOCUMENT_ROOT'] .'/'. $new['prefix'] .'/'. $new['name'];
       
copy($filepath, $new['filepath']);
        print
'<tr>';
        print
'<td>'. $filepath .'</td><td><strong>'. $new['filepath'] .'</strong></td>';
        print
"</tr>\n";
        if (
file_exists($new['filepath'])) {
         
$sql = "UPDATE {files} SET `filepath`='%s' WHERE `fid`='%s';";
         
db_query($sql, $new['prefix'] .'/'. $new['name'], $file['fid']);
         
$data[$l]['node'] = $node;
         
$data[$l]['file'] = $file;
         
$data[$l]['new'] = $new;
         
$l = $l + 1;
        }
      }
      else {
       
$sql = "DELETE FROM {files} WHERE `fid`='%s';";
       
db_query($sql, $file['fid']);
        print
'Deleted '. $file['title'];
      }
    }
  }
}
?>

</table>
<h1>Creating new nodes</h1>
<?php
foreach ($data as $key => $object) {
 
$node = $object['node'];
 
$file = $object['file'];
 
$new = $object['new'];
  unset(
$node->nid);
 
$node->type = 'image_cache';
 
$node->field_image_cache[0]['fid'] = $file['fid'];
 
$title = strrpos($file['filepath'], '/');
 
$title = substr($file['filepath'], ($title + 1));
 
$node->field_image_cache[0]['title'] = $title;
 
$node->field_image_cache[0]['alt'] = $title;
 
$node->field_image_cache[0]['nid'] = $file['nid'];
 
$node->field_image_cache[0]['filepath'] = $new['prefix'] .'/'. $new['name'];
 
$node->field_image_cache[0]['filemime'] = $file['filemime'];
 
$node->field_image_cache[0]['filesize'] = $file['filesize'];
 
node_save($node);
  print
'Saved '. $node->title .'<br />';
}
?>

@trogie: umm, not 100% sure, it was a few weeks ago... The code above definitely works though.

#32

giorgio79 - February 26, 2009 - 21:21

Thanks for this info guys.

I am a bit confused about the need for setting up a new content type.

I already have a content type where I used image attach to upload images previously.

Later on I enabled imagefield, and have been using that since, and I would like to migrate my older image attach files over to imagefield.

Do I still need a new content type if I already have one?

#33

quicksketch - April 14, 2009 - 00:45
Status:needs work» closed

I've made a handbook page for this topic, please update the handbook page as necessary to accommodate new changes in the code. I'm marking this issue as closed, since the issue queue isn't really the place for storing permanent documentation.

#34

seaneffel - April 14, 2009 - 00:52

Do you have linkage to the handbook page?

#35

seaneffel - April 14, 2009 - 00:53

Oh, nm. I found it in your tracker. Follow to the handbook page here:

http://drupal.org/node/432860

#36

twowheeler - July 16, 2009 - 00:20

Ok, I figured it would be better to post support type questions here than in the handbook. I have tried this script twice and it failed both times. The output looks fine:

- content_type_imagefieldtype populated.
- content_field_imagefield populated.
- files table updated
- 2 image_attach relationships were migrated.

... and the new tables content_type_imagefieldtype and content_field_imagefield exist but are empty. There should be approximately 1000 images converted, but none of them make it. Where do I begin to debug this?

Any help appreciated.

#37

twowheeler - July 16, 2009 - 12:33
Category:task» bug report
Status:closed» needs review

Follow up: This code seems to assume that all of the image module images have been uploaded individually so they will be in the upload table. I have used the Image Upload submodule exclusively so none of my images have been recorded in the upload table, so that is where this script fails. After some study, I executed the following queries (after this script above) and it successfully populated the new tables. I post it here in case anyone else encounters the same issue. Note that you will have to edit it for your imagefield field name and imagefield content type name.

INSERT INTO content_type_imagefieldtype (vid, nid)
  SELECT n.vid, n.nid FROM node n
  INNER JOIN image i ON n.nid = i.nid
  INNER JOIN files f ON i.fid = f.fid
  WHERE n.type = 'imagefieldtype' AND i.image_size = '_original'
 

INSERT INTO content_field_imagefield (vid, nid, delta, field_imagefield_fid, field_imagefield_list, field_imagefield_data)
  SELECT n.vid, n.nid, 0, f.fid, 1, CONCAT('a:1:{s:11:\"description\";s:', CHAR_LENGTH(n.title), ':\"', n.title, '\";}')
  FROM node n
  INNER JOIN image i ON n.nid = i.nid
  INNER JOIN files f ON i.fid = f.fid
  WHERE n.type = 'imagefieldtype' AND i.image_size = '_original'

#38

japanitrat - July 20, 2009 - 12:15
Version:5.x-1.1» 6.x-3.0

the mentioned script in the handbook didn't work for me. Though I got the cck-field tables populated (content-type, imagefield field), it won't display the images. I got i18n running, but neither for the old image type, nor the new imagefield type.

#39

japanitrat - July 20, 2009 - 15:09

detected following problems in the solution #26:

  • imagefield/filefield save paths relative to drupal-root, not files-root (so filepaths also need to get updated)
  • there is something wrong with the filename-update in the script (calculated length is too long in my case which results in crippled filenames or no ones at all)

#40

kwixson - July 25, 2009 - 22:08

I had this error while using this (#26) script:

user warning: Unknown column 'delta' in 'field list' query: INSERT INTO content_field_image (vid, nid, delta, field_image_fid, field_image_list, field_image_data) SELECT n.vid, n.nid, 0, f.fid, 1, CONCAT('a:1:s:11:"description";s:', CHAR_LENGTH(n.title), ':"', n.title, '";') FROM node n INNER JOIN upload u ON n.nid = u.nid INNER JOIN files f ON u.fid = f.fid WHERE n.type = 'image' AND f.filename = '_original' in /home/thirdcoastsurvey/public_html/migrate_image.php on line 82.

#41

dopry - July 26, 2009 - 21:16

regarding table names in the inline scripts.. Rather than hard coding table names for the imagefield table... Take a look at the content_database_info function.. You can use it to get a proper table name for your field instead of trying to hard code the field name... Use the API guys. :)

#42

seaneffel - July 27, 2009 - 14:00

Step two of the Road to Drupal Hell suggests that you should "never search api.drupal.org for a function [that already exists]."

 
 

Drupal is a registered trademark of Dries Buytaert.