? image/imagecache_integration.png Index: image/image.admin.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/image/image.admin.inc,v retrieving revision 1.9 diff -u -p -r1.9 image.admin.inc --- image/image.admin.inc 13 Oct 2009 08:38:52 -0000 1.9 +++ image/image.admin.inc 4 Jun 2010 07:45:30 -0000 @@ -60,6 +60,18 @@ function image_admin_settings() { ); } + // Allow for third-party modules (imagecache) to add to the + // available preset operations. + // This will include our own image.module built-in actions also. + $operations = module_invoke_all('image_operations', TRUE); + // Convert the operation info to a select list. + $operation_options = array(); + foreach($operations as $operation_id => $operation) { + $operation_options[$operation_id] = $operation['name']; + } + // Note that our own actions get special treatment - the height/width settings. + $our_operations = image_image_operations(); + foreach ($sizes as $key => $size) { $form['image_sizes'][$key]['label'] = array( '#type' => 'textfield', @@ -77,20 +89,33 @@ function image_admin_settings() { $form['image_sizes'][$key]['operation'] = array( '#type' => 'select', '#default_value' => $size['operation'], - '#options' => array('scale' => t('Scale image'), 'scale_crop' => t('Scale and crop image')), - ); - $form['image_sizes'][$key]['width'] = array( - '#type' => 'textfield', - '#default_value' => $size['width'], - '#size' => 5, - '#maxlength' => 5, - ); - $form['image_sizes'][$key]['height'] = array( - '#type' => 'textfield', - '#default_value' => $size['height'], - '#size' => 5, - '#maxlength' => 5, + '#options' => $operation_options, ); + // Only show size fields for our own operations. + if (empty($size['operation']) || in_array($size['operation'], array_keys($our_operations))) { + $form['image_sizes'][$key]['width'] = array( + '#type' => 'textfield', + '#default_value' => @$size['width'], + '#size' => 5, + '#maxlength' => 5, + ); + $form['image_sizes'][$key]['height'] = array( + '#type' => 'textfield', + '#default_value' => @$size['height'], + '#size' => 5, + '#maxlength' => 5, + ); + } + else { + // Allow the other module to put something informative here instead of the dimensions. + $operation = @$operations[$size['operation']]; + if (!empty($operation['extra'])) { + $form['image_sizes'][$key]['extra'] = array( + '#type' => 'markup', + '#value' => $operation['extra'], + ); + } + } $form['image_sizes'][$key]['link'] = array( '#type' => 'select', '#default_value' => $size['link'], @@ -107,14 +132,25 @@ function image_admin_settings() { /** * Form validation handler for image admin settings form. + * + * CHANGELOG - this was using $form[...]['#value'] where it should have been + * using $form_state['values']. Changed it to behave normally, but unsure if the + * previous method was intentional. - dman */ function image_admin_settings_validate($form, &$form_state) { // Check that the sizes provided have the required amount of information. + + $our_operation_ids = array_keys(image_image_operations()); + $image_sizes = $form_state['values']['image_sizes']; foreach (element_children($form['image_sizes']) as $key) { - // If there's a label they must provide at either a height or width. - if ($key != IMAGE_ORIGINAL && !empty($form['image_sizes'][$key]['label']['#value'])) { - if (empty($form['image_sizes'][$key]['width']['#value']) && empty($form['image_sizes'][$key]['height']['#value'])) { - form_set_error("image_sizes][$key][width", t('You must specify width, height or both dimensions.')); + // Only validate our own own known operations, + // allow for other operations to be available without defined dimensions + if (in_array($image_sizes[$key]['operation'], $our_operation_ids)) { + // If there's a label they must provide at either a height or width. + if ($key != IMAGE_ORIGINAL && !empty($image_sizes[$key]['label'])) { + if (empty($image_sizes[$key]['width']) && empty($image_sizes[$key]['height'])) { + form_set_error("image_sizes][$key][width", t('You must specify width, height or both dimensions.')); + } } } } @@ -171,7 +207,7 @@ function image_admin_settings_submit($fo else if (isset($form_state['values']['image_sizes'][$key]) && isset($old_sizes[$key])) { // Did the operation, height or width change? foreach (array('operation', 'height', 'width') as $field) { - $rebuild |= ($form_state['values']['image_sizes'][$key][$field] != $old_sizes[$key][$field]); + $rebuild |= (@$form_state['values']['image_sizes'][$key][$field] != @$old_sizes[$key][$field]); } } } @@ -186,12 +222,22 @@ function image_admin_settings_submit($fo function theme_image_settings_sizes_form($form) { $header = array(t('Label'), t('Operation'), t('Width'), t('Height'), t('Link')); + foreach (element_children($form) as $key) { $row = array(); $row[] = drupal_render($form[$key]['label']); $row[] = drupal_render($form[$key]['operation']); - $row[] = drupal_render($form[$key]['width']); - $row[] = drupal_render($form[$key]['height']); + // If it's a third-party action, don't show the dimensions, show its provided info instead. + if (!empty($form[$key]['extra'])) { + $row[] = array( + 'colspan' => 2, + 'data' => drupal_render($form[$key]['extra']), + ); + } + else { + $row[] = drupal_render($form[$key]['width']); + $row[] = drupal_render($form[$key]['height']); + } $row[] = drupal_render($form[$key]['link']); $rows[] = $row; } Index: image/image.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/image/Attic/image.module,v retrieving revision 1.322 diff -u -p -r1.322 image.module --- image/image.module 13 Sep 2009 20:21:04 -0000 1.322 +++ image/image.module 4 Jun 2010 07:45:31 -0000 @@ -784,6 +784,67 @@ function _image_check_settings() { } /** + * Implementation of (our own) hook_image_operations(). + * + * Declare the operations we make available for use as derivative sizes. + * Returns an array of operation definitions, keyed by operation id. + * + * The operation definition may contain the keys: + * 'name' => "Human-readable name for this action", + * 'module' => "Name of the module that provides the operation" + * 'callback' => "Name of the function that performs the operation" + * 'extra' => "If present, it may provide some additional information about + * the operation, such as a link to its configuration page" + * + * See _image_build_derivative() for the "callback" function signature. + * + * @return an array of image operation definitions. + * + * @see image_admin_settings() + */ +function image_image_operations() { + $operations = array( + 'scale' => array( + 'name' => t('Scale image'), + 'module' => 'image', + 'callback' => '_image_build_derivative', + ), + 'scale_crop' => array( + 'name' => t('Scale and crop image'), + 'module' => 'image', + 'callback' => '_image_build_derivative', + ), + ); + return $operations; +} + +/** + * Generate a single image derivative. Invoked as a callback from within + * _image_build_derivatives(). + * + * @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 + * + * @see _image_build_derivatives() + */ +function _image_build_derivative($original_path, $destination, $derivative_info = array()) { + switch ($derivative_info['operation']) { + case 'scale': + return image_scale($original_path, $destination, $derivative_info['width'], $derivative_info['height']); + case 'scale_crop': + return image_scale_and_crop($original_path, $destination, $derivative_info['width'], $derivative_info['height']); + } + return FALSE; +} + +/** * Determine which sizes of derivative images need to be built for this image. * * @param $image_path @@ -806,6 +867,11 @@ function image_get_derivative_sizes($ima if ($key == IMAGE_ORIGINAL) { continue; } + if ($size['operation'] != 'scale' && $size['operation'] != 'scale_crop') { + // Not one of our own processess, Always rebuild. + $sizes[$key] = $size; + continue; + } // If the original isn't bigger than the requested size then there's no // need to resize it. @@ -844,24 +910,34 @@ function _image_build_derivatives($node, // Resize for the necessary sizes. $image_info = image_get_info($original_path); + $operations = module_invoke_all('image_operations'); foreach ($needed_sizes as $key => $size) { $destination = _image_filename($original_path, $key, $temp); $status = FALSE; - switch ($size['operation']) { - // Depending on the operation, the image will be scaled or resized & cropped - case 'scale': - $status = image_scale($original_path, $destination, $size['width'], $size['height']); - break; - - case 'scale_crop': - $status = image_scale_and_crop($original_path, $destination, $size['width'], $size['height']); - break; + // Depending on the operation, different callbacks will be invoked. + // Normally, for scale or scale_crop, that will mean calling our own + // callbacks declared in hook_image_operations() and executed in + // _image_build_derivative(). + + $operation = $operations[$size['operation']]; + // Be very careful not to die if the needed module or setting has gone missing. + if (empty($operation)) { + // The module that provides this operation is now unavailable? + watchdog('image', 'When building image derivative %key, it appears that the image operation %operation is invalid. Perhaps it depends on an unavailable module. Not building this derivative image.', array('%operation_name' => $operation['name'], '%key' => $key), WATCHDOG_ERROR ); + $status = FALSE; + } + if (!empty($operation['callback']) && function_exists($operation['callback'])) { + $status = $operation['callback']($original_path, $destination, $size); + } + else { + watchdog('image', 'When building image derivative %key, it appears that the image operation %operation is invalid. Could not access the callback function [%operation_callback] to process the image. Not building this derivative image.', array('%key' => $key, '%operation_name' => $operation['name'], '%operation_callback' => $operation['callback']), WATCHDOG_ERROR); + $status = FALSE; } if (!$status) { drupal_set_message(t('Unable to create scaled %label image.', array('%label' => $size['label'])), 'error'); - return FALSE; + //return FALSE; // one failure may not mean that we should give up entirely. } // Set standard file permissions for webserver-generated files @chmod($destination, 0664);