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

Thanks.

Members fund testing for the Drupal project. Drupal Association Learn more

Comments

psicomante’s picture

dopry’s picture

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.

dopry’s picture

Title: Image.module to imagedfield/imagecache data conversion » How To: Migrate from Image.module to ImageField Documentation Project
Category: support » task
Status: Active » Needs review
sime’s picture

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.

asb’s picture

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

nvoyageur’s picture

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.

moshe weitzman’s picture

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.

seaneffel’s picture

Subscribing so I can follow along at home.

seaneffel’s picture

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.

moshe weitzman’s picture

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.

seaneffel’s picture

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?

dopry’s picture

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

moshe weitzman’s picture

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.

/**
 * @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 http:///imagefield_migrate.php 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 http://drupal.org/node/201983#comment-828698)
 * Moshe Weitzman (http://drupal.org/moshe)
 */
 
// ***** 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.
\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
\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
\n"; } } echo "- $num image_attach relationships were migrated.
\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
\n"; } }; } echo "- $num video.module thumbnails were migrated.
\n"; } } // Clear CCK cache. $sql = "DELETE FROM cache_content"; db_query($sql);
dopry’s picture

/me hugs moshe.

HorsePunchKid’s picture

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!

Anonymous’s picture

Status: Fixed » Closed (fixed)

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

altparty’s picture

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.

alexanderpas’s picture

Status: Closed (fixed) » Needs work

line 78 doesn't account for prefixes

hobbes_VT’s picture

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:

/**
 * @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 /imagefield_migrate.php" title="http:///imagefield_migrate.php" rel="nofollow">http:///imagefield_migrate.php 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 http://drupal.org/node/201983#comment-828698)
 * Moshe Weitzman (http://drupal.org/moshe)
* 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.
\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
\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
\n"; } } echo "- $num image_attach relationships were migrated.
\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
\n"; } }; } echo "- $num video.module thumbnails were migrated.
\n"; } } // Clear CCK cache. $table_cache_content = $table_pfx. 'cache_content'; // add prefix $sql = "DELETE FROM {$table_cache_content}"; db_query($sql);
fasdalf@fasdalf.ru’s picture

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.

markosef’s picture

so it doesnt work with drupal 6?

seaneffel’s picture

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.

asb’s picture

Hi,

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

Thanks & greetings, -asb

seaneffel’s picture

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.

asb’s picture

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

rkeppner’s picture

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 http://<yoursite>/imagefield_migrate.php 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 http://drupal.org/node/201983#comment-828698)
* Moshe Weitzman (http://drupal.org/moshe)
* 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);

?>
seaneffel’s picture

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.

nicksanta’s picture

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 />';
    }
  }
} 
?>
gausarts’s picture

subs thanks

trogie’s picture

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...

nicksanta’s picture

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.

giorgio79’s picture

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?

quicksketch’s picture

Status: Needs work » Closed (fixed)

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.

seaneffel’s picture

Do you have linkage to the handbook page?

seaneffel’s picture

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

http://drupal.org/node/432860

twowheeler’s picture

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.

twowheeler’s picture

Category: task » bug
Status: Closed (fixed) » 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'
japanitrat’s picture

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.

japanitrat’s picture

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)
kwixson’s picture

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.

dopry’s picture

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. :)

seaneffel’s picture

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

rzelnik’s picture

It works well for me after applying the patch #37.
Thank you, Twowheeler.

minesh’s picture

hey just quick question

I have a node type story (like most people do) using image attach. I need to move to imagefield for imagecatch

Will the script http://drupal.org/node/432860 move my images to the imagefield in the same node

basicly just moving the image to another field?

Thanks

Scott J’s picture

The new nodes are created for me, but they have no images. It looks like the entries are in the files table, but content_field_imagefield is empty.

- content_type_photo populated.
- content_field_image populated.
- files table updated
- 0 image_attach relationships were migrated.

Perhaps I need #37, but I tried with phpMyAdmin and i get:

"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INSERT INTO content_field_imagefield (vid, nid, delta, field_imagefield_fid, fie' at line 8"

FiNeX’s picture

@Scott: did you changed the table names to match your settings? remember to separate the two query with a ";".

Scott J’s picture

@FiNeX

Yahoo! Success! Thanks for that tip. Yes I did change the table names, but just copied and pasted the queries from #37 without really knowing what I was doing. I don't understand why this isn't part of the original script, but hey, I'm not a programmer...

Scott J’s picture

And thanks to twowheeler for code in #37. Why does the original script even look for the upload table, when it isn't required for image.module?

Scott J’s picture

May I give one warning to anyone else trying this conversion script. The script actually maintains the taxonomy terms of your images, so that you can keep your images in galleries, but if you later remove image.module gallery, it will take your taxonomy with it!

My solution was to use phpMyAdmin to back-up the taxonomy tables, then remove the Gallery module, and then restore the taxonomy tables. The relevant tables are listed at http://drupal.org/node/70614 . Now I can rebuild my galleries. I'll post my View when i'm finished.

Another thing: you may want to go to /admin/build/views to clone image_gallery and image_gallery_terms view to re-use them for your new gallery.

FiNeX’s picture

@scott (#47): If you don't know well what you're doing, I suggest you to be very careful when copy-paste things :-)

Scott J’s picture

Ha haa,
True, but I am only experimenting on a local copy of my data, not the live site, so no harm done; I just restore from backup and try again. If I post my experience here, then someone who DOES know what they are doing may be able to improve the script, or at least add a semicolon!

The image.module maintainers want to move directly to Drupal 7 version, but there may be others who wish to stay with Drupal 6, but change to imagefield.

Encarte’s picture

subscribe

quicksketch’s picture

Category: bug » support
Status: Needs review » Closed (fixed)

Any modifications to the handbook pages, please just make them directly to the page (any Drupal.org user can edit a documentation page).

izmeez’s picture

I am trying to migrate image module using the script on the handbook page http://drupal.org/node/432860 and see the last modified date is April 14, 2009 and it is not working for me either.

As described in #45, the new nodes are created for me, but they have no images. It looks like the entries are in the files table, but content_field_imagefield is empty.

- content_type_photo populated.
- content_field_image populated.
- files table updated

The configuration in my script file is:

$table_pfx = '';
$field_name = 'field_imagefield';
$type_name = 'image_page';

I am trying to understand how to execute the two queries in #37.
Can they be added to the script?

Any help is appreciated. Thanks,

Izzy

izmeez’s picture

Why am I even doing this?

I have just spent a lot of time trying to wrap my head around the concepts related to migrating existing Image module data to ImageField.

After a bunch of experiments I have found myself realizing that if I do this and rely solely on ImageField and ImageCache some things like reusing the images looks like it will be more difficult. Leading me to wondering about continuing to use both the Image module and ImageField/ ImageCache.

And I came across this thread

The Future of Image in Drupal 7, http://drupal.org/node/513096
and these comments (#12 and #13):
http://drupal.org/node/513096#comment-1852522
http://drupal.org/node/513096#comment-1853072

So, I'm leaning to keeping the Image module enabled and not migrating the existing data, although I have gone to the extent of adding the Transliteration module and manually retrospectively renaming files and database references.

I will proceed with also using ImageField and ImageCache and see how this integrates with the Image module along with the Drupal 7 developments.

Any comments?

asb’s picture

@izmeez:

A few months ago, even before migrating to D6, I was stuck exactly at the same point where you are now. Lots of things seemed so bright and promising in the CCK world that I spent days with my sandboxes and tried to migrate data from several sites, ignoring the immense robustness and flexibility of 'image' module. The results of these migration attemps were not convincing; the switch to CCK-based content types openend a whole lot of new issues and solved only a few. So I stopped working on the attempt to migrate my images, and did what probably everyone else is doing: Using 'image module' for same sites, using Filefield/Imagefield for others, and scratching my head every time before setting up a new site. Both approaches have their strenghts and weaknesses, and both feel like incomplete workarounds for very basic tasks (e.g. building and maintaining flexible image galleries; re-using existing images; being able to add captions, copyright information and descriptions to images; allowing users to bulk upload dozens of images; being able to use presentation tools like Lightbox2; embedding image derivates into textual content, creating on-demand image derivates, managing and maintaining large collections of images, etc.). But that's simply what we have to live with, unless we're able to throw in significant resources to solve all the issues that are itching us: There is no perfect 'image' solution for everything and everyone, and D7 probably won't change this. However, waiting for a robust migration path for 'image' module might considerably shift your ability to upgrade to D7 in the far future.

WigglyKoala’s picture

I'm glad I'm not the only one trying to figure out which options are best! Keeping an eye on this.

paranormals’s picture

Agreed. I have been reading in circles for days trying to wrap my head around all of this.

Subscribing

pelicani’s picture

Once again, this script helped us upgrade another site from image to imagefield.

moshe's original post is 2 years old and no longer works for current dv6 installs.
rkeppner's updated script worked great with one change.
the script assumes you use the upload table for your images.
In our install we used the image table.
Changing upload to image was our only change to this script.
Aside from the configuration.
Note, you must fill in your new content type and field in the configuration to make this work.
Be sure to read and complete the other requirements as well.

Rob_Feature’s picture

Status: Closed (fixed) » Needs work

Ok, I'm not sure if I'm missing something but it appears that none of these scripts are valid anymore (including rkeppner's) because I'm not seeing that filefield is using a table called: 'content_'. $field_name; (as in line 57 of the script).

It seems that the filefield data has moved directly into the content_type_$type_name table.

Am I wrong? Pelicani, did you make this work with a recent version of filefield/imagefield?

quicksketch’s picture

I'm not seeing that filefield is using a table called: 'content_'. $field_name; (as in line 57 of the script).

It seems that the filefield data has moved directly into the content_type_$type_name table.

This is CCK making the tables here, FileField just tells CCK what the data is and it worries about putting it in the database and pulling it out. If you have a field that is multiple values or shared, then the data is stored in a 'content_' . $field_name table. However if you only have a single-value, not shared field, then the data is stored in the content type table, 'content_type_' . $node_type. So it depends on how you've set up the field where the data will be stored.

Rob_Feature’s picture

quicksketch:
Brilliant...thanks man.

Ok, so I got this to work (I think)...but it created about 2000 empty nodes in addition to my conversions. Not sure what's up with that, I'll just delete them, but just an FYI if anyone sees what might be causing it.

I'll leave this as 'needs work' since the documentation is sorta all over the place as of now.

EDIT://
Another question...if I need to enable 'multiple' for the imagefield...after the migration can I change back to a single field? (I'm assuming not?). I don't want users to be able to upload multiple here....thoughts?

quicksketch’s picture

Yes, you can always switch between multiple and single and vice-versa. However if you switch from multiple to single, data will be dropped from all multiple value fields except for the first one.

Rob_Feature’s picture

Good to know (never knew how the 'behind the scenes' of multiple fields worked). Switched back to a single allowed upload without issue. Learn somethin' new every day!

palik’s picture

I've tried to migrate and failed... several problems found:

1) first, the configuration variables was set to empty strings just after drupal bootstrap, so i've moved configuration below include bootstrap lines
2) table_upload variable was set to 'upload', but later version of image module keeps image data in 'image' table, so i've got to change this,
3) after running script with above changes i got strange behavior:
- some 'image' nodes succesfully converted to 'imagefield' nodes - images appear as standalone nodes but they does not appear at nodes that they previously was in image attach field,
- some 'image' nodes wont show on standalone nodes anymore, but they are now in coresponding 'story' or 'article' node, in cck field...

yngens’s picture

Trying to migrate from Image to Imagefield on a Drupal 6 installation. Combining #26 and #37 does the job, though for some reason the last two queries cause the following errors:

user warning: Duplicate entry '47' for key 'PRIMARY' query: INSERT INTO content_type_imagepage (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 = 'imagepage' AND i.image_size = '_original' in /home/d6/public_html/migrate.php on line 170.

user warning: Duplicate entry '47-0' for key 'PRIMARY' query: 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 = 'imagepage' AND i.image_size = '_original' in /home/d6/public_html/migrate.php on line 178.

which can be ignored. Because, nevertheless it gives the errors all the images are successfully converted to imagefields. So final code is:


/**
* @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 /imagefield_migrate.php" title="http:///imagefield_migrate.php" rel="nofollow">http:///imagefield_migrate.php 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 http://drupal.org/node/201983#comment-828698)
* Moshe Weitzman (http://drupal.org/moshe)
* 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.
\n"; } else { echo "- $table_content_type NOT populated.
\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.
\n"; } else { echo "- $table_content_field NOT populated.
\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
\n"; } else { echo "- files table NOT updated
\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
\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
\n"; } } echo "- $num image_attach relationships were migrated.
\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
\n"; } }; } echo "- $num video.module thumbnails were migrated.
\n"; } // Clear CCK cache. $table_cache_content = $table_pfx. 'cache_content'; // add prefix $sql = "DELETE FROM {$table_cache_content}"; db_query($sql); $sql = "INSERT INTO {$table_content_type} (vid, nid)\n" . " SELECT n.vid, n.nid FROM node n\n" . " INNER JOIN image i ON n.nid = i.nid\n" . " INNER JOIN files f ON i.fid = f.fid\n" . " WHERE n.type = '{$type_name}' AND i.image_size = '_original'"; db_query($sql); $sql = "INSERT INTO {$table_content_field} (vid, nid, delta, field_imagefield_fid, field_imagefield_list, field_imagefield_data)\n" . " SELECT n.vid, n.nid, 0, f.fid, 1, CONCAT('a:1:{s:11:\"description\";s:', CHAR_LENGTH(n.title), ':\"', n.title, '\";}')\n" . " FROM node n\n" . " INNER JOIN image i ON n.nid = i.nid\n" . " INNER JOIN files f ON i.fid = f.fid\n" . " WHERE n.type = '{$type_name}' AND i.image_size = '_original'"; db_query($sql);

If someone could track down why the last two queries causing errors, then we could update the Handbook page with this code.

yngens’s picture

Did not pay enough attention to pelicani's post in #59. We do not need additional queries in #37 if we change 'upload' table to 'image' table.

Dret’s picture

Hi to all,

I tried the script in the handbook ( http://drupal.org/node/432860 ) but doesn't works for me.

The procedure is completed without errors but images are not ported in the new image_field created.

Looking at database i found that the image_field table is populated but some fields remain with NULL value: 'field_namefield_fid' 'field_namefield_list' 'field_namefield_data' and 'delta' is 0 everywhere.

I'm a bit confused about the version of the script to use...

Any suggestions about?

Thanks!
Bye

Scott J’s picture

Dret,
The latest version of the script, is at #66 above. It has those two extra SQL queries added at the bottom 15 lines.
Did you try that one?

Dret’s picture

No, i tried the original script posted on Handbook (link in my previous post) and only after I discover this thread!

I'll try in the next days!
Thanks, and have a nice New Years day!

Bye!

Dret’s picture

...ok tried with the #66 script... same result...!

Messages all ok but images are disappeared and table not populated...

yngens’s picture

Dret, look at #67. Should work.

Dret’s picture

Ok, but...

I have only to change 'upload' to 'image' or I have also to delete two queries from the script?

yngens’s picture

Correct, change 'upload' to 'image' in $table_upload = $table_pfx. 'upload'; and remove two queries in the end of the script.

Dret’s picture

Thanks... but a strange thing happens!

I made yesterday a first trial with an old database... and all works good!

Today, after reading your post, I made the procedure again with an updated db.

The script works... but for a single content type the procedure fail for attached image.

So at the moment, on 7 content type... 6 are migrated well... 1 not!

I didn't change anything in content type definition (I repeated the same procedures)

Any suggestions?

PS this is the error message:

- drupal_content_type_simage populated.
- drupal_content_field_img populated.
- files table updated
update drupal_content_field_img failed for 102
... here a long list of image content-type nodes... (used for attachments)
looking at those nodes, all images are passed right into imagefield but not inside their original content type...

Dret’s picture

ok, solved... with old snapshot of database...all work fine!

Thanks!

palik’s picture

Hi there, I've just spent 3 hours trying to do the migration and finally done it right... I cannot edit http://drupal.org/node/432860 page but maybe someone can do this and change upload to image, change that is referenced in several places in this thread.

Funny thing is that i made only 2 changes to the script in handbook, moving config below bootstrap and changing upload to image and it went like a charm. I did this previously and it went with some strange problems - see #65

i attached my final version that did work properly

nikolajb’s picture

Thanks a lot for this. Using the input in #59, I managed to convert 500+ images from image.module to imagefield after a couple of tries :)

udvranto’s picture

Is there a way to include support for img_assist? I am sure lot of other people will be looking for it.

udvranto’s picture

I think the following code adapted from image attach conversion should do it. However, the custom img_assist filter needs to be converted as well!

WARNING: Untested code

// Loop over the img_assist records
if (module_exists('img_assist')) {
  $table_img_assist = $table_pfx. 'img_assist_map'; // add prefix
  $sql = "SELECT n.nid, n.vid, ia.iid FROM {$table_img_assist} 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 img_assist relationships were migrated.<br />\n";
}
asb’s picture

The modified script from #77 isn't working for me in a local sandbox. Messages when running the script:

INSERT INTO content_type_bild (vid, nid) SELECT n.vid, n.nid FROM node n INNER JOIN image u ON n.nid = u.nid INNER JOIN files f ON u.fid = f.fid WHERE n.type = 'image' AND f.filename = '_original'
- content_type_bild populated.
INSERT INTO content_field_abbildung (vid, nid, delta, field_abbildung_fid, field_abbildung_list, field_abbildung_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 u ON n.nid = u.nid INNER JOIN files f ON u.fid = f.fid WHERE n.type = 'image' AND f.filename = '_original'
- content_field_abbildung NOT populated.
UPDATE files SET filename = SUBSTRING(filepath, 28) WHERE filename = '_original'
- files table updated
UPDATE node SET type = '%s' WHERE type = 'image'
SELECT n.nid, n.vid, ia.iid FROM image_attach ia INNER JOIN node n ON ia.nid=n.nid
UPDATE the imagefield to point to the attached node, not the standalone nodeUPDATE content_type_bild SET nid = 54, vid = 54 WHERE nid = 10365
Successful update. Now unpublish the standalone node that we just made.UPDATE node SET status = 0 WHERE nid = 10365
UPDATE the imagefield to point to the attached node, not the standalone nodeUPDATE content_type_bild SET nid = 72, vid = 72 WHERE nid = 11764
...
Successful update. Now unpublish the standalone node that we just made.UPDATE node SET status = 0 WHERE nid = 15943
UPDATE the imagefield to point to the attached node, not the standalone nodeUPDATE content_type_bild SET nid = 15980, vid = 17316 WHERE nid = 15979
Successful update. Now unpublish the standalone node that we just made.UPDATE node SET status = 0 WHERE nid = 15979
- 1181 image_attach relationships were migrated.
DELETE FROM cache_content

As a result, I'm getting 1,098 unpublished imagefield-image nodes (total: 3,085 imagefield image nodes, according to the 'Systeminfo' module) with no visible images, zero old image.module nodes and no visible images on nodes which used to have image attachments. Before running the script I had 3,159 (published) image nodes and 9 imagefield image nodes (total # of nodes on this site: 16,220).

The table content_field_abbildung (the new imagefield) contains only vid and nid values for 9 imagefield image nodes I created when setting up the new content type. The table content_type_bild includes 4,183 rows.

I've been using a non-standard path for image.module images (./sites/default/files/bilder), and the imagefield originally was configured to store it's files at ./sites/default/files/images, so be carefull if you have a similar setup.

mdhooge’s picture

FileSize
8.96 KB

You'll find attached my adapted version of the tool. Its output is purposely much more verbose.
The main changes are:
- By default, only a simulation of the migration is done (see $simulate)
- Images are moved to new folders based on users names (see $filepath). Maybe not the wisest idea but it helped me sort out which files were referenced.
- image.module thumbnails are deleted (see $derivatives)
- Only explicitly listed image_attach nodes are migrated (see $ia_types)
- CCK image fields (for image & image_attach) can be embedded in the content type table or have their own tables (see $type_has_external_field_table and $ia_has_external_field_table)

Note also that I removed the video migration part because I was unable to test it.

My 2 cents to this migration story.
Michel

mcurry’s picture

subscribe

BWPanda’s picture

Version: 6.x-3.0 » 6.x-3.x-dev
Status: Needs work » Needs review

Based on the comments in #67 above, here's the updated code that worked for me and others. I can't edit the handbook page for some reason, so someone with permission should update the handbook with this working code:

/**
* @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 /imagefield_migrate.php" title="http:///imagefield_migrate.php" rel="nofollow">http:///imagefield_migrate.php 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 http://drupal.org/node/201983#comment-828698)
* Moshe Weitzman (http://drupal.org/moshe)
* 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. 'image'; // 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.
\n"; } else { echo "- $table_content_type NOT populated.
\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.
\n"; } else { echo "- $table_content_field NOT populated.
\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
\n"; } else { echo "- files table NOT updated
\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
\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
\n"; } } echo "- $num image_attach relationships were migrated.
\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
\n"; } }; } echo "- $num video.module thumbnails were migrated.
\n"; } // Clear CCK cache. $table_cache_content = $table_pfx. 'cache_content'; // add prefix $sql = "DELETE FROM {$table_cache_content}"; db_query($sql);
twowheeler’s picture

Comment removed by author.

luco’s picture

it worked for me! thank you so much.

twooten’s picture

I can also confirm that #84 works great. Drupal 6.22.

Thanks a ton!
Tim

luco’s picture

I wish I'd read the issue more thoroughly... I made the leap and my taxonomy terms are gone.

thankfully I still have my backups ;] plus there's not many images so I think I'm just going to recreate the terms anyway.

edit: @Scott J #49 really helped me. thanks!

naught101’s picture

@quicksketch: Any reason why you locked and disabled comments on the docs page?

I was going to ad this comment there:
Has anyone looked at migrate.module for this? You can quite easily set up a Migration class that does a simple join between the node_revision table and the file_revision/upload table (depending on drupal version), and then uses migrate module's file handling to copy the node with the file into a pre-defined content type with an imagefield or what ever.

asb’s picture

@#90: When I'm looking at the handbook page for the migration module, setting up a migration class looks everything else but "simple" for me. Hoewever, ymmv if you're a experienced software developer.

Also, such an approach wouldn't solve the showstopper issue for all 'image attach' users since 'imagefield' has no equivalent for 'image attach' (D7 images haven't, either, so migrating to D7 is impossible as well).

PMorris’s picture

#84 worked great with Drupal 6.26. I also have my taxonomy intact after uninstalling image module by using #49.

Anyone know how I can move all my nodes / taxonomy into the Node Gallery module? I don't suppose that would be an easy process for non developer like myself. I took a look at the Migrate module but it is way beyond my skills.

sime’s picture

@naught101 which page are you trying to edit? it might just be set to a format you don't have permission for.

batigolix’s picture

I changed the text format so that everyone can edit the docs page.

I removed the out-of-date script and linked back to #201983

JeniferTucker’s picture

FileSize
32.2 KB

Have been looking for a while for a solution to make the jump across to D7 but the image_attach has been a real big issue. Anyway, I've taken the leap having found this thread, so huge thanks to everyone here posting and notably #92, #84 and #49 :-)

Issues I had managed to resolve!

cparfon’s picture

Hi

Is there such a migration script available for D7? Did anyone tried running it on D7 install ? Does is work ? Basically after migrating my D6 to D7 the users pictures won't get displayed :(

Baart’s picture

Unfortunately, #84 is not working for me on 6.29...

First of all, there are some quotes that need to be escaped on line 68 (the CONCAT-part), right?

Let's start with the situation of my site. It has story-nodes with (usually) multiple images attached. For example, I have this story with nid 1942, which has images nid's 1943, 1944 and 1945 attached.

When running the script, both tables are being populated and the files table is updated. However, in the example above, only 1943 is converted succesfully. I keep getting messages like "update {table} failed for {nid}".

I adjusted the conversion script to print_r the failed queries, and this is what it shows:

[600] => UPDATE content_type_newimg SET nid = 1942, vid = 1942 WHERE nid = 1944
[601] => UPDATE content_field_afbeeldingen SET nid = 1942, vid = 1942 WHERE nid = 1944
[602] => UPDATE content_type_newimg SET nid = 1942, vid = 1942 WHERE nid = 1945
[603] => UPDATE content_field_afbeeldingen SET nid = 1942, vid = 1942 WHERE nid = 1945

When running these failed queries manually thru phpMyAdmin, I get these error messages: #1062 - Duplicate entry '136' for key 'PRIMARY'

Certainly I'm not the first one who used image_attach to attach multiple images to a single node, right? Why am I the first one to encounter primary key-errors? And more importantly: how do I get rid of them :) I've been at it for 3 days now, any help would be much appreciated!

asb’s picture

Issue summary: View changes

I haven't attempted Image.module to ImageField migrations for a while because image_attach was never properly handled. One of the key features of image_attach is image re-use (meaning: image node re-use, including the node's metadata; meaning not: image file re-use) and there was never a workable solution how to mimic this behaviour with Imagefields (including D7).

Suggestions I got were: Drop the duplicates in the database (meaning: lose all connections for re-used images); and for D7 migrations: Do not even attempt to migrate Image.module content, start from scratch and just re-upload everything. Considering that the site I attempted to migrate had ~66,000 image nodes, this became so frustrating that I stayed with Image.module on D6. As I remember correctly, d.o had been using Image.module as well; it was completely dropped, probably during the D7 upgrade preparation. See #513096: The Future of Image in Drupal 7 for details about migration paths.

If you are not trying to prepare for a D7 upgrade and if you are using image_attach, an Image.module to ImageField migration does not make much sense (imho).

er.pushpinderrana’s picture

I also faced issues during migration of image attach module content from drupal 6 to drupal 7. I spent too much time to find any module for this without any success. There is no simple module that do this task better is write own custom script and migrate this image attachment data. I also followed the given steps and write my own custom script:

1. Created one new field of image in my content type and set unlimited option for this, that would play the role as image attachment.
2. Fetch the data from image_attach table and added every fid with file_usage and file_managed table.

This script was not a good script but did the task at my end.

cassioalmeidas’s picture

when I run the script displays the following error:

Parse error: syntax error, unexpected 'description' (T_STRING) in /var/www/html/pressflow6/imagefield_migrate.php on line 68

someone help me?

Brn’s picture

Thanks BWPanda for your code #84
Warning : the escape of double quote near line 68 in SQL syntax is missing :

-- CONCAT('a:1:{s:11:"description";s:', CHAR_LENGTH(n.title), ':"', n.title, '";}')

++ CONCAT('a:1:{s:11:\"description\";s:', CHAR_LENGTH(n.title), ':\"', n.title, '\";}')