? imagecache.image_integration-20100714.patch
Index: imagecache.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/imagecache/imagecache.module,v
retrieving revision 1.112.2.9
diff -u -p -r1.112.2.9 imagecache.module
--- imagecache.module	26 May 2010 21:08:58 -0000	1.112.2.9
+++ imagecache.module	14 Jul 2010 00:25:50 -0000
@@ -960,6 +960,112 @@ function imagecache_presets($reset = FAL
 }
 
 /**
+ * Implementation of hook_image_operations. (image.module)
+ * 
+ * Declare the operations we make available for use as derivative sizes.
+ * 
+ * @return 
+ *   an array of operations, keyed by id, declaring the name and operations
+ * used to create derivatives.
+ * 
+ * @see image_admin_settings()
+ * 
+ * @ingroup image.module integration
+ */
+function imagecache_image_operations() {
+  $operations = array();
+  foreach (imagecache_presets() as $preset_id => $preset) {
+    $operations['imagecache-'. $preset_id] = array(
+      'name' => $preset['presetname'],
+      'callback' => 'imagecache_image_build_derivative',
+      'module' => 'imagecache',
+      'extra' => l(t('Settings'), 'admin/build/imagecache/' . $preset_id),
+    );
+  };
+  return $operations;
+}
+
+
+/**
+ * Wrapper to imagecache_build_derivative. Used so we can invoke this as a
+ * callback by name from image.module:_image_build_derivatives()
+ * 
+ * This function acts like the utilities image_scale() image_scale_and_crop()
+ * that image.module uses.
+ * 
+ * It is invoked by name when an image preset notes the function as a callback.
+ * 
+ * @param $original_path 
+ *   Source image
+ * @param $destination 
+ *   Save image as
+ * @param $derivative_info 
+ *   an array of data that image.module settings form may save. Normally this
+ * includes the derivative name, operation id, and width and height.
+ * $derivative_info['operation'] will be of the form 'imagecache-n' where n is a
+ * preset id that we will build
+ * @return bool 
+ *   success
+ * 
+ * @see _image_build_derivatives()
+ * @see _image_build_derivative()
+ * 
+ * @ingroup image.module integration
+ */
+function imagecache_image_build_derivative($original_path, $destination, $derivative_info = array()) {
+  $operation_id = $derivative_info['operation'];
+  if (preg_match('/^imagecache-(.*)$/', $operation_id, $matches)) {
+    $preset_id = $matches[1];
+    if (! $preset = imagecache_preset($preset_id)) {
+      trigger_error("Failed to build derivative with the imagecache ID $preset_id", E_USER_WARNING);
+      watchdog('imagecache', 'Failed to build derivative with the imagecache ID %preset_id is not really an imagecache preset operation. It may have been deleted.', array('%operation_id' => $operation_id), WATCHDOG_ERROR);
+      return FALSE;
+    }
+    // Note the reversal of the args. imag.module :src,dst,action imagecache.module: action,src,dst
+    return imagecache_build_derivative($preset['actions'], $original_path, $destination);
+  }
+}
+
+
+
+/**
+ * Additional action to fire when a change is made to presets. It's possible
+ * that image. module needs to regenerate its derivatives as a result of changes
+ * made here.
+ * 
+ * When a preset is modified, check to see if that preset was already being used
+ * as an image.module derivative operation. If so, we must freshen ALL images by
+ * touching the derivative timestamp.
+ * 
+ * @ingroup image.module integration
+ * @see imagecache_preset_flush()
+ */
+function imagecache_image_trigger_rebuild($preset) {
+  // imagecache_preset_flush(), which calls this, gets called multiple times when
+  // saving a preset (once for each action then again for the preset) so try not
+  // to repeat any work too much here.
+  static $rebuild_triggered;
+  if ($rebuild_triggered) return;
+
+  $presetid = $preset['presetid'];
+  // Check the current image.module derivative definitions.
+  $sizes = image_get_sizes() ;
+  foreach ($sizes as $sizename => $size_def) {
+    if (@$size_def['operation'] == 'imagecache-' . $presetid) {
+      // Yes, this preset is being used by an image operation.
+      drupal_set_message(t("Due do a change in the '%preset' preset, all derived image.module '%sizename' images need updating. This should happen over time as needed.", array('%preset' => $preset['presetname'], '%sizename' => $sizename)));
+      // Trigger expiry on (all!) image.module derivatives.
+      // This is inefficient, but image.module doesn't let us trigger just one 
+      // preset change.
+      variable_set('image_updated', time());
+      // Once is enough.
+      $rebuild_triggered = TRUE;
+      return;
+    }
+  }
+}
+
+/**
  * Load a preset by preset_id.
  *
  * @param preset_id
@@ -1056,6 +1162,7 @@ function imagecache_preset_flush($preset
       _imagecache_recursive_delete($presetdir);
     }
   }
+  imagecache_image_trigger_rebuild($preset);
 }
 
 /**
