Given a node, get's all files connected to that node. Selects image cck fields. Flushes all image derivatives & regenerates them. I've never done an action before so It might need some help? Seems to work though.

Using these 2 "external" functions; which I've included below.
http://drupal.org/node/373864
http://drupal.org/node/369560#comment-1255453

/**
 * Implementation of hook_action_info().
 * 
 */
function imagecache_action_info() {
  return array(
    'imagecache_node_refresh_action' => array(
       'type' => 'node',
       'description' => t('Regenerate nodes images (flush + generate)'),
       'configurable' => FALSE,
       'hooks' => array(
         'nodeapi' => array('presave', 'insert', 'update', 'view'),
       )
    )
  );
}

/**
 * Regenerate all pictures in a given node
 * @param &$node
 *   
 * 
 * Notes
 *   This is a slow function, since it waits for each derivative to be generated
 */
function imagecache_node_refresh_action(&$node, $context) {
  $paths = imagecache_get_filepaths_via_nid($node->nid);
  print_r($paths);
  foreach ($paths as $path) {
    if ($path['type'] == 'image') {
      imagecache_image_flush($path['path']);
      imagecache_generate_all_presets($path['path']);
      echo $path['path'] . "\n";
    }
  }
}


/**
 * Get all filefield files connected to a node id.
 * @param $nid
 *   The Node ID.
 * 
 * Returns array()
 *   ['fid'] = file id
 *   ['type'] = type of cck field
 *   ['path'] = path to file
 *
 * Notes
 *   Does not return imagecache child files, only the base file.
 */
function imagecache_get_filepaths_via_nid($nid)
{
  $fids = array();
  $filepaths = array();
  foreach (content_fields() as $field) {
    // If Field is an Image (imagefield.module) or filefield then
    if ($field['type'] == 'image' || $field['type'] == 'filefield') {
      $db_info = content_database_info($field);
      // Get Content Type DB name - FROM statement
      $tablename = $db_info['table'];
      //Get File ID DB Column Name - SELECT statement
      $fid_column = $db_info['columns']['fid']['column'];
      
      //get file id's
      $sql = "SELECT ".$fid_column." FROM ".$tablename." WHERE nid = '%s'";
      $result = db_query($sql, array($nid));
      while ($fileid_row = db_fetch_array($result)) {
        $fids[] = array('fid' => $fileid_row[$fid_column], 'type' => $field['type']);
      }
    }
  }
  foreach ($fids as $fid) {
    //get paths for file id
    $sql = "SELECT filepath FROM files WHERE fid = '%s'";
    $result = db_query($sql, array($fid['fid']));
    while ($filepath_row = db_fetch_array($result)) {
      $filepaths[] = array('fid' => $fid['fid'], 'type' => $fid['type'], 'path' => $filepath_row['filepath']);
    }
  }
  return $filepaths;
}

/**
 * Request URI, thus generating pic 
 * @param $path
 *   The path to the orginal file
 * 
 * Notes
 *   This is a slow function, since it waits for each derivative to be generated
 */
function imagecache_generate_all_presets($path) {
  foreach (imagecache_presets() as $preset) {
    file_get_contents(base_url.$base_path.imagecache_create_path($preset['presetname'], $path));
  }
}

I'm just adding these functions at the end of the imagecache.module file.

Comments

mikeytown2’s picture

forgot to get rid of the print_r & echo lines in this function: imagecache_node_refresh_action

drewish’s picture

the problem with the function as pasted is that it creates a dependency on cck. there's plenty of ways to use this module that dont' involve the cck. i think that this would actually a better contrib module.

also this isn't a proper patch. please see http://drupal.org/patch for info on how to create one.

mikeytown2’s picture

StatusFileSize
new3.08 KB

@drewish, thanks for looking at the code.

Ideally imagecache_get_filepaths_via_nid() gets integrated with FileField (as I hinted at with the link in the original post). That takes care of the cck dependency. The question is where should the action live? Does it belong in ImageCache or in FileField, or ...? The action involves both FileField & ImageCache. It uses FileField to find what files are attached to the node, the real "action" is done with ImageCache (flush & generate).

Here's the kinda pointless diff IMHO

2noame’s picture

I don't know how to go about implementing this code. Do I just copy and paste it into the imagecache.module file and that's it? Do I need to run update.php or anything?

Also, what does this do exactly? I'm hoping what it does is makes Image smart enough to generate previews and thumbs in the same directory as the main image they are attached to, instead of in whatever directory is currently set as the default image path. Does it?

drewish’s picture

Status: Needs review » Needs work

Okay so giving this some thought and I can see some cool usecases but before I'd commit it I want it to operate like the email presets. There needs to be a configuration form where you pick a file source (attached via upload.module or select from the filefields ) and checkboxes for presets that should be run.

drewish’s picture

marked #375631: Rules integration as a duplicate.

mikeytown2’s picture

Been busy with boost #326515: Roadmap For stable 6.x-1.0 trying to get a stable release out. Making this configurable is the best way to do this. I can probably tackle this in late may.

mikeytown2’s picture

Title: Action: flush & regenerate per node » Actions: flush all, generate, generate all presets per node
Status: Needs work » Needs review
StatusFileSize
new3.72 KB

Here's my first go around at it. Adds in 3 actions, the generate one is configurable.

mshepherd’s picture

I've applied this patch and assigned the action correctly (to run the 'create all imagecache presets' action when a node is created or updated). I have a problem!

I get the following messages when I update a node.

  • warning: file_get_contents(/sites/dev.wayc.org.uk/files/imagecache/ib_thumbnail/image_field_images/3fishes.jpeg) [function.file-get-contents]: failed to open stream: No such file or directory in /home/server/websites/drupal/illuminate/live/drupal-6.14/sites/dev.wayc.org.uk/modules/imagecache/imagecache.module on line 1237.
  • warning: file_get_contents(/sites/dev.wayc.org.uk/files/imagecache/Large/image_field_images/3fishes.jpeg) [function.file-get-contents]: failed to open stream: No such file or directory in /home/server/websites/drupal/illuminate/live/drupal-6.14/sites/dev.wayc.org.uk/modules/imagecache/imagecache.module on line 1237.
  • warning: file_get_contents(/sites/dev.wayc.org.uk/files/imagecache/Medium/image_field_images/3fishes.jpeg) [function.file-get-contents]: failed to open stream: No such file or directory in /home/server/websites/drupal/illuminate/live/drupal-6.14/sites/dev.wayc.org.uk/modules/imagecache/imagecache.module on line 1237.
  • warning: file_get_contents(/sites/dev.wayc.org.uk/files/imagecache/Small/image_field_images/3fishes.jpeg) [function.file-get-contents]: failed to open stream: No such file or directory in /home/server/websites/drupal/illuminate/live/drupal-6.14/sites/dev.wayc.org.uk/modules/imagecache/imagecache.module on line 1237.
  • warning: file_get_contents(/sites/dev.wayc.org.uk/files/imagecache/ib_thumbnail/image_field_images/theme.png) [function.file-get-contents]: failed to open stream: No such file or directory in /home/server/websites/drupal/illuminate/live/drupal-6.14/sites/dev.wayc.org.uk/modules/imagecache/imagecache.module on line 1237.
  • warning: file_get_contents(/sites/dev.wayc.org.uk/files/imagecache/Large/image_field_images/theme.png) [function.file-get-contents]: failed to open stream: No such file or directory in /home/server/websites/drupal/illuminate/live/drupal-6.14/sites/dev.wayc.org.uk/modules/imagecache/imagecache.module on line 1237.
  • warning: file_get_contents(/sites/dev.wayc.org.uk/files/imagecache/Medium/image_field_images/theme.png) [function.file-get-contents]: failed to open stream: No such file or directory in /home/server/websites/drupal/illuminate/live/drupal-6.14/sites/dev.wayc.org.uk/modules/imagecache/imagecache.module on line 1237.
  • warning: file_get_contents(/sites/dev.wayc.org.uk/files/imagecache/Small/image_field_images/theme.png) [function.file-get-contents]: failed to open stream: No such file or directory in /home/server/websites/drupal/illuminate/live/drupal-6.14/sites/dev.wayc.org.uk/modules/imagecache/imagecache.module on line 1237.

An error for each preset and each attached image. Line 1237 is the file_get_contents($base_url . '/' . imagecache_create_path($preset['presetname'], $path)); line at the end of the patch.

I feel like it nearly works, but if you had some insight into what I could do to get it working properly, that would be great.

As a related note, my use case is that I use IMCE to browse and add previously added (cck imagefield) images to nodes. I'd like people to be able to choose between the presets, but unless they've been displayed before, they're not already generated. This patch would be useful in fixing that. Thanks.

mikeytown2’s picture

StatusFileSize
new4.06 KB

Here's a re-roll of the above patch, with a fix that should make it work; forgot global $base_url; at the top of that function.

mshepherd’s picture

That works perfect! Many thanks,
Matthew

mikeytown2’s picture

Set this to RTBC if everything works as expected.

mshepherd’s picture

Status: Needs review » Reviewed & tested by the community
drewish’s picture

Status: Reviewed & tested by the community » Needs work

imagecache_action_info() has some indenting issues in the last action definition.

PHPDocs for imagecache_flush_action() and imagecache_generate_all_action() are incomplete.

imagecache_generate_action_form() is not really an implementation of hook form is it?

imagecache_generate_action_submit()'s PHPDocs are also incorrect.

Remove the extra new line between the docs and the function body:

+ */
+
+function imagecache_image_generate_preset($path, $preset_name) {

Why can't this just call imagecache_image_generate_preset()?

+  foreach (imagecache_presets() as $preset) {
+    file_get_contents($base_url . '/' . imagecache_create_path($preset['presetname'], $path));
+  }
justintime’s picture

Status: Needs work » Reviewed & tested by the community

I would love to see this patch make it mainline, so I'll bite. I'm still pretty green to Drupal and PHPDoc and I'll take any criticism constructively.

imagecache_action_info() has some indenting issues in the last action definition.

Fixed.

PHPDocs for imagecache_flush_action() and imagecache_generate_all_action() are incomplete.

Fixed.

imagecache_generate_action_form() is not really an implementation of hook form is it?

No, it isn't. It doesn't look to me like simple FAPI form functions have PHPDocs by looking at node.module, so I just removed them.

imagecache_generate_action_submit()'s PHPDocs are also incorrect.

I also removed PHPDocs from here, I couldn't find any FAPI submit handlers in imagecache or node.module that had PHPDocs.

Remove the extra new line between the docs and the function body:

Fixed.

Why can't this just call imagecache_image_generate_preset()?

It can, and it does now.

justintime’s picture

StatusFileSize
new4.06 KB

Actually attaching the patch would probably help it get accepted faster -- sorry!

shiva7663’s picture

subscribe

robin van emden’s picture

Just tested the imagecache-374202-1 patch, works. Now using it on a live site. Would be great if this patch can be added to the next release.

justintime’s picture

Just a note that using this patch with Views Bulk Operations makes for a very powerful way of generating all thumbnails for all images using batch API.

shiva7663’s picture

Did using it with VBO chew up a big bunch of memory?

justintime’s picture

Nope, that's the beauty of it. You can tell VBO to use Batch API with actions, so it calls the action once per node. If you can run the action on one node, you can run it on 100,000 nodes in this manner - memory footprint will not be any different. From VBO's homepage:

I need VBO to modify thousands of nodes at once! Help!

VBO is designed to handle large numbers of nodes, without causing memory errors or timeouts. When you select thousands of nodes, you can choose to execute the operations using Batch API, which provides visual feedback on VBO's progress. To select Batch API, edit your view, open the "Bulk Operation" style settings and in the section "To execute operations:", select "Use Batch API". You can also choose to execute the operations during cron runs via the Job queue module if you have it enabled.

This is a perfect marriage if you ask me - after a huge import of images, you can prime imagecache so that your users don't have to wait for it.

ocanzillon’s picture

I have an issue with generating imagecache presets (all or some) for a node. This is probably due to call to file_get_contents function, which should be deactivated on my hosting. Does it should not call imagecache internal function, such as imagecache_build_derivative instead?

mikeytown2’s picture

StatusFileSize
new3.66 KB

@ocanzillon
Try this

mikeytown2’s picture

StatusFileSize
new4.19 KB

Here's a better attempt

mikeytown2’s picture

StatusFileSize
new4.22 KB

this one works

mikeytown2’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new4.29 KB

The real deal.

mikeytown2’s picture

StatusFileSize
new4.34 KB

Fixes the Generate All action

mikeytown2’s picture

StatusFileSize
new4.36 KB

Sorry, wrong patch; this one fixes the generate all

mikeytown2’s picture

@drewish
What are the odds of this getting accepted? I'm tempted to create a module just for this. One of the main reasons is it does not work correctly with core's trigger module because the trigger is fired too soon; the files are not there. OTOH using it with rules/VBO & the results are quite remarkable.

ocanzillon’s picture

Status: Needs review » Reviewed & tested by the community

That's ok for me: imagecache_build_derivative works perfectly in my case, where file_get_contents did not work before.
Moreover code is clean and very understandable! Thanks a lot!

drewish’s picture

Status: Reviewed & tested by the community » Needs work

this looks really good. couple of small nits before we can commit it.

the action functions take $node by reference but don't make any changes to it. and since we require PHP 5 $node is an object and always passed by reference. so lets drop that.

I don't think the default value for checkboxes should be a string:

+  $form['presets'] = array(
+    '#type' => 'checkboxes',
+    '#options' => $options,
+    '#description' => t('Select which imagecache presets will be effected'),
+    '#required' => TRUE,
+    '#default_value' => isset($context['imagecache_presets']) ? $context['imagecache_presets'] : '',
+  );

The Forms API Reference makes me think it should be an array.

I think that imagecache_generate_action_submit() could be simplified by using array_filter().

Could we change $dst to $destination?

drewish’s picture

mikeytown2, this will go in. it's really close and i appreciate your persistance in spite of my inattention.

mikeytown2’s picture

Status: Needs work » Needs review
StatusFileSize
new4.22 KB

i got $dst from function imagecache_build_derivative($actions, $src, $dst)
Changes made, please review.

drewish’s picture

StatusFileSize
new5.51 KB

I added some documentation to make it clearer that there are two types of actions in the module now. Also added some @see tags to link things together a bit more.

The bigger change is that I realized we don't have a hard dependency on the filefield module so we need to conditionally check if it exists. We should probably change the action text to make it clearer that it only affects file and image fields.

I made some changes to imagecache_generate_image() to have it return a value indicating success and to validate the presetname. I'm not sure that we should be checking file_exists(), it might be best to just always regenerate the image...

drewish’s picture

mikeytown2, any thoughts on this?

mikeytown2’s picture

I'm not sure that we should be checking file_exists(), it might be best to just always regenerate the image.

What do you think about generate preset (check file_exists) & the regenerate preset (doesn't check file_exists)? This would bring us up to 5 actions. 2 generate, 2 regenerate & 1 delete.

We should probably change the action text to make it clearer that it only affects file and image fields.

Is there anyway to detect other things in the node using imagecache? If it does all, that would be ideal.

drewish’s picture

no, i'd rather not add more variations, they just tend to clutter up the list. we should pick sane defaults and just go with those. i suppose that file_exists() is the sane default since you could have a flush all action ahead of that if you really wanted to regenerate them.

yeah file/imagefields are all we could really hit... though we could add upload module... we should add some messaging to make it clear whatever we decide to operate on.

mikeytown2’s picture

I've never played with the upload module, always been a filefield man myself. So if you can/want to add integration with the upload module, I would be +1 for that. Rewording the action, to let the admin know what files this action will work on would be a good idea. Who's going to make the wording changes, me or you?

drewish’s picture

Well lets get the filefield stuff in and word it appropriately for that and if someone wants to add upload.module support we can change the messaging then. If you've got the time to reroll I'd appreciate it.

mikeytown2’s picture

StatusFileSize
new6.65 KB

Rewrote the 3 actions so they point to a new function imagecache_get_images_in_node. Right now this just gets the filefield images; but we can use this for things like the image module in the future. This reduced some code duplication between the 3 actions.

Made sure the $node object is passed by reference.

Renamed the actions so they all start with ImageCache: . Example: "ImageCache: Generate ALL presets for this nodes filefield images".

mikeytown2’s picture

StatusFileSize
new6.67 KB

forgot the return $files in the new function

drewish’s picture

Coule of small things:

+      'description' => t('ImageCache: Flush ALL presets for this nodes filefield images'),

+      'description' => t('ImageCache: Generate ALL presets for this nodes filefield images'),

+      'description' => t('ImageCache: Generate Configured preset(s) for this nodes filefield images'),

Should be "node's" right?

I think we can drop imagecache_generate_action_submit() and instead just add the following to imagecache_generate_action_form():

  // Filter out false checkboxes: http://drupal.org/node/61760#comment-402631
  $form['array_filter'] = array('#type' => 'value', '#value' => TRUE);

We should add a node in the comment for imagecache_get_images_in_node() that it, currently, only supports images stored in filefields.

drewish’s picture

+ 'description' => t('ImageCache: Generate Configured preset(s) for this nodes filefield images'),
Configured should probably be lower case.

mikeytown2’s picture

StatusFileSize
new6.46 KB

is $form['array_filter'] correct? anyway re-roll of the patch with the 2 changes.

mikeytown2’s picture

StatusFileSize
new6.49 KB

lowercase c

drewish’s picture

Status: Needs review » Fixed
StatusFileSize
new6.48 KB

Made a few comment changes and committed the attached. Thanks for your patience... I now realize I put a typo in the commit message... oh well.

Status: Fixed » Closed (fixed)

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

protoplasm’s picture

This is amazing. The only feature missing is the check all button. For instance, if I have a 1000 nodes that I want to prepopulate, one click and all the nodes are selected. Thanks for your good efforts on this dev version. Imagecache rocks.

Oh--I see. If you enter a large number and add a pager, the select all button appears! Fantastic! Thanks all.

protoplasm’s picture

The latest dev version isn't generating these images for me. I get messages that the presets have been generated when, in fact, they aren't being generated. I thought maybe it was a permissions problem, so I went to the permissions page and checked off the actions_permission for administrator for vbo flush and generate actions. The permissions page says it is an illegal choice and won't permit the check mark. I don't have this problem with any of my other vbo actions. Also, I've noticed that the permissions on the preset files is now automatically 775 instead of 755--I don't know if that is by design or what.

This module feature has great potential for me if I can get it to work. Hope someone has an idea why this isn't working for me.

--a quick addendum--I looked for perms for the action_permissions but didn't find them.

Coupon Code Swap’s picture

I'm getting an error with latest Imagecache dev after attempting to save a Rule with - ImageCache: Generate configured preset(s) for this node's filefield images

the bug is reported here:

http://drupal.org/node/813804

is there any way to get this working?