Index: image.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/image/image.install,v
retrieving revision 1.7
diff -u -r1.7 image.install
--- image.install	6 Jul 2007 15:27:34 -0000	1.7
+++ image.install	6 Jul 2007 15:44:48 -0000
@@ -4,9 +4,31 @@
 /**
  * Installing and updating image.module.
  */
-
 function image_install() {
-  //Nothing to do.
+  switch ($GLOBALS['db_type']) {
+    case 'mysql':
+    case 'mysqli':
+      db_query("CREATE TABLE {image} (
+          `nid` INTEGER UNSIGNED NOT NULL,
+          `size` VARCHAR(255) NOT NULL,
+          `fid` INTEGER UNSIGNED NOT NULL,
+          PRIMARY KEY (`nid`, `size`),
+          INDEX image_fid(`fid`)
+        ) /*!40100 DEFAULT CHARACTER SET utf8 */;");
+      break;
+  }
+}
+
+/**
+ * Implementation of hook_uninstall().
+ */
+function image_uninstall() {
+  db_query('DROP TABLE {image}');
+
+  variable_del('image_default_path');
+  variable_del('image_max_upload_size');
+  variable_del('image_updated');
+  variable_del('image_sizes');
 }
 
 /**
@@ -107,3 +129,34 @@
 
   return $ret;
 }
+
+/**
+ * Move image files into their own table.
+ */
+function image_update_5() {
+  $ret = array();
+
+  switch ($GLOBALS['db_type']) {
+    case 'mysql':
+    case 'mysqli':
+      $ret[] = update_sql("CREATE TABLE {image} (
+          `nid` INTEGER UNSIGNED NOT NULL,
+          `size` VARCHAR(255) NOT NULL,
+          `fid` INTEGER UNSIGNED NOT NULL,
+          PRIMARY KEY (`nid`, `size`),
+          INDEX image_fid(`fid`)
+        ) /*!40100 DEFAULT CHARACTER SET utf8 */;");
+      
+      // Copy image files records into the new table.
+      $args = array_keys(_image_get_sizes());
+      $cond = " IN ('". implode("', '", $args) ."')";
+      $ret[] = update_sql("INSERT INTO {image} SELECT DISTINCT f.nid, f.filename, f.fid FROM {files} f INNER JOIN {node} n ON f.nid = n.nid WHERE n.type='image' AND f.filename". $cond);
+
+      // Remove old file_revision records.
+      $ret[] = update_sql("DELETE FROM {file_revisions} WHERE EXISTS (SELECT * FROM {image} WHERE {image}.fid = {file_revisions}.fid)");
+
+      break;
+  }
+
+  return $ret;
+}
Index: image.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/image/image.module,v
retrieving revision 1.245
diff -u -r1.245 image.module
--- image.module	6 Jul 2007 15:21:35 -0000	1.245
+++ image.module	6 Jul 2007 15:38:21 -0000
@@ -278,9 +278,7 @@
   foreach ($nids as $nid) {
     if ($node = node_load($nid)) {
       if ($node->type == 'image') {
-        drupal_set_message(t("Rebuilding %node-title's resized images.", array('%node-title' => $node->title)));
-        _image_remove_derivatives($node);
-        _image_build_derivatives($node, FALSE);
+        $node->rebuild_images = TRUE;
         node_save($node);
       }
     }
@@ -290,10 +288,23 @@
 /**
  * Implementation of hook_prepare().
  */
-function image_prepare(&$node, $field_name) {
+function image_prepare(&$node, $field_name = NULL) {
+  // We need to be aware that a user may try to edit multiple image nodes at
+  // once. By using the $nid variable each node's files can be stored separately
+  // in the session.
+  $nid = ($node->nid) ? $node->nid : 'new_node';
+  // When you enter the edit view the first time we need to clear our files in
+  // session for this node. This is so if you upload a file, then decide you
+  // don't want it and reload the form (without posting), the files will be
+  // discarded.
+  if(count($_POST) == 0) {
+    unset($_SESSION['image_new_files'][$nid]);
+  }
+
   if (is_null($field_name)) {
     $field_name = 'image';
   }
+
   if ($file = file_check_upload($field_name)) {
     // Ensure the file is an image.
     $image_info = image_get_info($file->filepath);
@@ -329,11 +340,19 @@
 
     // We're good to go.
     $node->images[IMAGE_ORIGINAL] = $file->filepath;
+    $node->rebuild_images = FALSE;
     $node->new_file = TRUE;
 
     // Call hook to allow other modules to modify the original image.
     module_invoke_all('image_alter', $node, $file->filepath, IMAGE_ORIGINAL);
     _image_build_derivatives($node, TRUE);
+
+    // Store the new file into the session.
+    $_SESSION['image_new_files'][$nid] = $node->images;
+  }
+  // Reload new files uploaded in a previous preview.
+  else if (isset($_SESSION['image_new_files'][$nid])) {
+    $node->images = $_SESSION['image_new_files'][$nid];
   }
 }
 
@@ -418,15 +437,10 @@
   }
 }
 
-function image_form_add_thumbnail($form_id, $edit) {
-  if ($edit['images']['thumbnail']) {
-    $node = (object)($edit);
-    $form = array(
-      '#type' => 'item',
-      '#title' => t('Thumbnail'),
-      '#value' => image_display($node, IMAGE_THUMBNAIL),
-      '#weight' => -10,
-    );
+function image_form_add_thumbnail($form, $form_values) {
+  if ($form_values['images']['thumbnail']) {
+    $node = (object)($form_values);
+    $form['#value'] = image_display($node, IMAGE_THUMBNAIL);
   }
   return $form;
 }
@@ -448,27 +462,28 @@
     '#default_value' => $node->title
   );
 
-  if ($node->new_file) {
-    $form['new_file'] = array('#type' => 'value', '#value' => TRUE);
-  }
-
   $form['images']['#tree'] = TRUE;
   foreach (_image_get_sizes() as $key => $size) {
-    if ($node->new_file) {
-      $form['images'][$key] = array(
-        '#type' => 'hidden',
-        '#value' => $node->images[$key]
-      );
-    }
-    else {
-      $form['images'][$key] = array(
-        '#type' => 'hidden',
-        '#default_value' => $node->images[$key]
-      );
-    }
+    $form['images'][$key] = array(
+      '#type' => 'value',
+      '#value' => $node->images[$key]
+    );
   }
 
-  $form['thumbnail']['#after_build'][] = 'image_form_add_thumbnail';
+  $form['thumbnail'] = array(
+    '#type' => 'item',
+    '#title' => t('Thumbnail'),
+    '#value' => image_display($node, IMAGE_THUMBNAIL),
+    '#weight' => -10,
+    '#after_build' => array('image_form_add_thumbnail'),
+  );
+
+  $form['rebuild_images'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Rebuild derivative images.'),
+    '#default_value' => FALSE,
+    '#description' => t('Check this to rebuild the derivative images for this node.'),
+  );
 
   $form['#attributes'] = array("enctype" => "multipart/form-data");
   $form['image'] = array(
@@ -492,15 +507,19 @@
 }
 
 function image_validate($node) {
-  if (empty($node->images[IMAGE_ORIGINAL])) {
+  $nid = ($node->nid) ? $node->nid : 'new_node';
+  if (!isset($node->images[IMAGE_ORIGINAL]) && !isset($_SESSION['image_new_files'][$nid])) {
     form_set_error('image', t('You must upload an image.'));
   }
 }
 
-function image_submit(&$node) {
-  if ($node->new_file) {
-    _image_remove_derivatives($node);
-    _image_build_derivatives($node, FALSE);
+function image_submit($node) {
+  $nid = ($node->nid) ? $node->nid : 'new_node';
+  if (isset($_SESSION['image_new_files'][$nid])) {
+    $node->new_file = TRUE;
+    $node->rebuild_images = FALSE;
+    $node->images = $_SESSION['image_new_files'][$nid];
+    unset($_SESSION['image_new_files'][$nid]);
   }
 }
 
@@ -534,10 +553,10 @@
  * Implementation of hook_load
  */
 function image_load(&$node) {
-  $result = db_query("SELECT filename, filepath FROM {files} WHERE nid=%d", $node->nid);
   $node->images = array();
+  $result = db_query("SELECT i.size, f.filepath FROM {image} i INNER JOIN {files} f ON i.fid = f.fid WHERE i.nid = %d", $node->nid);
   while ($file = db_fetch_object($result)) {
-    $node->images[$file->filename] = $file->filepath;
+    $node->images[$file->size] = $file->filepath;
   }
   // If the image is smaller than the thumbnail and prevew images, we just use
   // original image rather than creating new deriviatives.
@@ -553,25 +572,31 @@
  * Implementation of hook_insert
  */
 function image_insert($node) {
-  foreach (_image_get_sizes() as $key => $size_info) {
-    _image_insert($node, $key, $node->images[$key]);
-  }
+  _image_save($node);
 }
 
 /**
  * Implementation of hook_update
  */
 function image_update($node) {
-  foreach (_image_get_sizes() as $key => $size) {
-    $old_file = db_fetch_object(db_query("SELECT fid, filepath FROM {files} WHERE filename='%s' AND nid=%d", $key, $node->nid));
+  if ($node->new_file || $node->rebuild_images) {
+    _image_remove_derivatives($node);
 
-    // This is a new image.
-    if (!isset($node->images[$key]) || $old_file->filepath != $node->images[$key]) {
-      file_delete(file_create_path($old_file->filepath));
-      db_query("DELETE FROM {files} WHERE fid = %d", $old_file->fid);
-      db_query("DELETE FROM {file_revisions} WHERE fid = %d", $old_file->fid);
-      _image_insert($node, $key, $node->images[$key]);
+    if ($node->rebuild_images) {
+      _image_build_derivatives($node);
+      drupal_set_message(t('The derivative images for <a href="!link">%title</a> have been regenerated.', array('!link' => url('node/'. $node->nid), '%title' => $node->title)));
     }
+    else {
+      // Remove the original.
+      $file = db_fetch_object(db_query("SELECT i.fid, i.size, f.filepath FROM {image} i INNER JOIN {files} f ON i.fid = f.fid WHERE i.nid = %d AND size = '%s'", $node->nid, IMAGE_ORIGINAL));
+      if ($file) {
+        file_delete(file_create_path($file->filepath));
+        db_query("DELETE FROM {files} WHERE fid = %d", $file->fid);
+        db_query("DELETE FROM {image} WHERE fid = %d", $file->fid);
+      }
+   }
+
+    _image_save($node);
   }
 }
 
@@ -579,12 +604,12 @@
  * Implementation of hook_delete.
  */
 function image_delete($node) {
-  $result = db_query('SELECT fid, filepath FROM {files} WHERE nid = %d', $node->nid);
+  $result = db_query('SELECT i.fid, f.filepath FROM {image} i INNER JOIN {files} f ON i.fid = f.fid WHERE i.nid = %d', $node->nid);
   while ($file = db_fetch_object($result)) {
     file_delete(file_create_path($file->filepath));
-    db_query("DELETE FROM {file_revisions} WHERE fid = %d", $file->fid);
+    db_query('DELETE FROM {files} WHERE fid = %d', $file->fid);
   }
-  db_query('DELETE FROM {files} WHERE nid = %d', $node->nid);
+  db_query("DELETE FROM {image} WHERE nid = %d", $node->nid);
 }
 
 /**
@@ -621,10 +646,8 @@
       (!file_exists(file_create_path($node->images[$label])) ||
        filemtime(file_create_path($node->images[$label])) < variable_get('image_updated', 0)))
   {
-    _image_remove_derivatives($node);
-    _image_build_derivatives($node);
+    $node->rebuild_images = TRUE;
     node_save($node);
-    drupal_set_message(t('The image %title had missing derivative image which has been regenerated.', array('%title' => $node->title)));
   }
 
   if (empty($node->images[$label])) {
@@ -814,16 +837,15 @@
 }
 
 function _image_remove_derivatives($node) {
-  $original_file = db_fetch_object(db_query("SELECT * FROM {files} WHERE nid=%d AND filename = '%s'", $node->nid, IMAGE_ORIGINAL));
-  $result = db_query("SELECT * FROM {files} WHERE nid=%d AND fid <> %d", $node->nid, $original_file->fid);
+  $result = db_query("SELECT i.fid, i.size, f.filepath FROM {image} i INNER JOIN {files} f ON i.fid = f.fid WHERE i.nid = %d AND size <> '%s'", $node->nid, IMAGE_ORIGINAL);
   while ($file = db_fetch_object($result)) {
     // Never delete the original!
     if ($file->filepath != $original_file->filepath) {
       file_delete(file_create_path($file->filepath));
     }
+    db_query("DELETE FROM {files} WHERE fid = %d", $file->fid);
   }
-  db_query("DELETE FROM {files} WHERE nid = %d AND fid <> %d", $node->nid, $original_file->fid);
-  db_query("DELETE FROM {file_revisions} WHERE vid = %d AND fid <> %d", $node->vid, $original_file->fid);
+  db_query("DELETE FROM {image} WHERE nid = %d AND size <> '%s'", $node->nid, IMAGE_ORIGINAL);
 }
 
 /**
@@ -912,33 +934,35 @@
 }
 
 /**
- * Moves temporary (working) images to the final directory and stores
- * relevant information in the files table
+ * Moves temporary images to the final directory and stores relevant 
+ * information in the image and files tables.
  */
-function _image_insert(&$node, $size, $image_path) {
-  // Make sure there's an image.
-  if (empty($image_path)) {
-    return;
-  }
-
+function _image_save(&$node) {
   $original_path = $node->images[IMAGE_ORIGINAL];
 
-  // Don't duplicate images when a derivative == _original
-  if (($size != IMAGE_ORIGINAL) && (realpath($image_path) == realpath($original_path))) {
-    return;
-  }
+  foreach (array_keys(_image_get_sizes()) as $size) {
+    // Make sure there's an image.
+    if (empty($node->images[$size])) {
+      continue;
+    }
+    $image_path = $node->images[$size];
+    // Don't duplicate images when a derivative == _original
+    if ($size != IMAGE_ORIGINAL && $image_path == $original_path) {
+      continue;
+    }
 
-  if (file_move($image_path, _image_filename($original_path, $size))) {
-    // Update the node to reflect the actual filename, it may have been changed
-    // if a file of the same name already existed.
-    $node->images[$size] = $image_path;
-
-    $image_info = image_get_info($image_path);
-    $fid = db_next_id('{files}_fid');
-    db_query("INSERT INTO {files} (fid, nid, filename, filepath, filemime, filesize) VALUES (%d, %d, '%s', '%s', '%s', '%s')",
+    if (file_move($image_path, _image_filename($original_path, $size))) {
+      // Update the node to reflect the actual filename, it may have been changed
+      // if a file of the same name already existed.
+      $node->images[$size] = $image_path;
+
+      $image_info = image_get_info($image_path);
+      $fid = db_next_id('{files}_fid');
+      db_query("INSERT INTO {files} (fid, nid, filename, filepath, filemime, filesize) VALUES (%d, %d, '%s', '%s', '%s', '%s')",
              $fid, $node->nid, $size, $image_path, $image_info['mime_type'], $image_info['file_size']);
-    db_query("INSERT INTO {file_revisions} (fid, vid, description, list) VALUES (%d, %d, '%s', %d)",
-             $fid, $node->vid, '', 0);
+      db_query("INSERT INTO {image} (nid, size, fid) VALUES (%d, '%s', %d)",
+             $node->nid, $size, $fid);
+    }
   }
 }
 
