Index: image_resize_filter.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/image_resize_filter/image_resize_filter.module,v
retrieving revision 1.45.2.6
diff -u -r1.45.2.6 image_resize_filter.module
--- image_resize_filter.module	2 Dec 2010 00:04:07 -0000	1.45.2.6
+++ image_resize_filter.module	5 Dec 2010 20:51:18 -0000
@@ -11,7 +11,6 @@
  * Image that have been created take on the ownership of the original file.
  * Making so when the primary node is deleted, the images it provided are
  * deleted also.
- *
  */
 
 
@@ -59,7 +58,7 @@
       $settings['rel'] = variable_get('image_resize_filter_link_rel_' . $format, '');
       $settings['image_locations'] = array_filter(variable_get('image_resize_filter_image_locations_' . $format, array('local')));
       $images = image_resize_filter_get_images($settings, $text);
-      return image_resize_filter_process_images($images, $text, $settings);
+      return $images ? image_resize_filter_process_images($images, $text, $settings) : $text;
 
     default:
       return $text;
@@ -96,6 +95,9 @@
  */
 function image_resize_filter_theme() {
   return array(
+    'image_resize_filter_image' => array(
+      'arguments' => array('image' => NULL, 'settings' => NULL),
+    ),
     'image_resize_filter_form' => array(
       'arguments' => array('form' => NULL),
     ),
@@ -263,14 +265,21 @@
     $src = $matches[4][$key];
 
     $resize = NULL;
-    $width = NULL;
-    $height = NULL;
-    $needs_width = TRUE;
-    $needs_height = TRUE;
     $image_size = NULL;
+    $attributes = array();
+
+    // Find attributes of this image tag.
+    $attribute_matches = array();
+    preg_match_all('/([a-z]+)[ ]*=[ ]*"([^"]+)"/i', $img_tag, $attribute_matches);
+    foreach ($attribute_matches[0] as $key => $match) {
+      $attribute = $attribute_matches[1][$key];
+      $attribute_value = $attribute_matches[2][$key];
+      $attributes[$attribute] = $attribute_value;
+    }
 
-    // Because we don't know the order of the attributes and images might not
-    // have both attributes, match individually for height and width.
+    // Height and width need to be matched specifically because they may come as
+    // either an HTML attribute or as part of a style attribute. FCKeditor
+    // specifically has a habit of using style tags instead of height and width.
     foreach (array('width', 'height') as $property) {
       $property_matches = array();
       preg_match_all('/[ \'";]' . $property . '[ ]*([=:])[ ]*"?([0-9]+)(%?)"?/i', $img_tag, $property_matches);
@@ -278,8 +287,6 @@
       // If this image uses percentage width or height, do not process it.
       if (in_array('%', $property_matches[3])) {
         $resize = FALSE;
-        $needs_width = FALSE;
-        $needs_height = FALSE;
         break;
       }
 
@@ -288,27 +295,10 @@
       // browser will display.
       $property_key = 0;
       $property_count = count($property_matches[1]);
-      $needs_property = TRUE;
       if ($property_count) {
         $property_key = array_search(':', $property_matches[1]);
-        $needs_property = FALSE;
       }
-      // Only a style property found, we'll need to add a real height/width tag
-      // to the HTML later. This specifically prevents problems with FCKeditor
-      // that only adds style tags when resizing images.
-      if ($property_count == 1 && strcmp($property_matches[1][$property_key], ':') == 0){
-        $needs_property = TRUE;
-      }
-      ${$property} = !empty($property_matches[2][$property_key]) ? $property_matches[2][$property_key] : FALSE;
-      ${'needs_' . $property} = $needs_property;
-    }
-
-    // Find the image title if any.
-    $title = NULL;
-    $title_matches = array();
-    preg_match('/title[ ]*=[ ]*"([^"]+)"/i', $img_tag, $title_matches);
-    if (isset($title_matches[1])) {
-      $title = $title_matches[1];
+      $attributes[$property] = !empty($property_matches[2][$property_key]) ? $property_matches[2][$property_key] : '';
     }
 
     // Determine if this is a local or remote file.
@@ -394,35 +384,30 @@
       continue;
     }
 
-    $actual_width = $image_size[0];
-    $actual_height = $image_size[1];
+    $actual_width = (int) $image_size[0];
+    $actual_height = (int) $image_size[1];
 
     // If either height or width is missing, calculate the other.
-    if (!$width && !$height) {
-      $width = $actual_width;
-      $height = $actual_height;
+    if (!$attributes['width'] && !$attributes['height']) {
+      $attributes['width'] = $actual_width;
+      $attributes['height'] = $actual_height;
     }
-    if (!$height) {
+    if (!$attributes['height'] && is_numeric($attributes['width'])) {
       $ratio = $actual_height/$actual_width;
-      $height = round($ratio * $width);
+      $attributes['height'] = (int) round($ratio * $attributes['width']);
     }
-    elseif (!$width) {
+    elseif (!$attributes['width'] && is_numeric($attributes['height'])) {
       $ratio = $actual_width/$actual_height;
-      $width = round($ratio * $height);
+      $attributes['width'] = (int) round($ratio * $attributes['height']);
     }
 
     // Determine if this image requires a resize.
     if (!isset($resize)) {
-      $resize = ($actual_width != $width || $actual_height != $height);
+      $resize = ($actual_width != $attributes['width'] || $actual_height != $attributes['height']);
     }
 
-    // Skip processing if these conditions are met:
-    // - The image already has both height and width attributes.
-    // - The image is local and is already the right size.
-    // - The image is remote and a 1x1 pixel tracking image.
-    if ((!$needs_width && !$needs_height) &&
-        (($location == 'local' && !$resize) ||
-         ($location == 'remote' && $actual_width == 1 && $actual_height == 1))) {
+    // Skip processing if the image is a remote tracking image.
+    if ($location == 'remote' && $actual_width == 1 && $actual_height == 1) {
       image_resize_filter_delete_temp_file($location, $local_path);
       continue;
     }
@@ -456,16 +441,15 @@
       continue;
     }
 
-    // If getting this far, the image exists and is not the right size or needs
-    // to be saved locally from a remote server.
+    // If getting this far, the image exists and is not the right size, needs
+    // to be saved locally from a remote server, or needs attributes added.
     // Add all information to a list of images that need resizing.
     $images[] = array(
-      'expected_size' => array('width' => $width, 'height' => $height),
+      'expected_size' => array('width' => $attributes['width'], 'height' => $attributes['height']),
       'actual_size' => array('width' => $image_size[0], 'height' => $image_size[1]),
-      'add_properties' => array('width' => $needs_width, 'height' => $needs_height),
+      'attributes' => $attributes,
       'resize' => $resize,
       'img_tag' => $img_tag,
-      'title' => $title,
       'has_link' => $has_link,
       'original' => $src,
       'location' => $location,
@@ -478,7 +462,6 @@
   return $images;
 }
 
-
 /**
  * Processing function for image resize filter. Replace img src properties
  * with a URL to a resized image.
@@ -492,7 +475,9 @@
  */
 function image_resize_filter_process_images($images, $text, $settings) {
   $file_directory_path = file_directory_path();
-  $local_file_path = '';
+  $search = array();
+  $replace = array();
+
   foreach ($images as $image) {
     // Copy remote images locally.
     if ($image['location'] == 'remote') {;
@@ -501,6 +486,7 @@
     }
     // Destination and local path are the same if we're just adding attributes.
     elseif (!$image['resize']) {
+      $local_file_path = '';
       $image['destination'] = $image['local_path'];
     }
     else {
@@ -511,19 +497,19 @@
       $image['destination'] = $file_directory_path . '/' . $local_file_path;
     }
 
-    // Ensure that the destination directories exist.
-    $folders = explode('/', dirname($local_file_path));
-    $current_directory = $file_directory_path . '/';
-    foreach ($folders as $folder) {
-      $current_directory .= $folder . '/';
-      $check_directory = $current_directory;
-      // Use the "quiet" version of file_check_directory() provided by FileField
-      // if it exists. This suppresses "Directory was created" messages.
-      $file_check_directory = function_exists('field_file_check_directory') ? 'field_file_check_directory' : 'file_check_directory';
-      $file_check_directory($check_directory, FILE_CREATE_DIRECTORY);
-    }
-
     if (!file_exists($image['destination'])) {
+      // Ensure that the destination directories exist.
+      $folders = explode('/', dirname($local_file_path));
+      $current_directory = $file_directory_path . '/';
+      foreach ($folders as $folder) {
+        $current_directory .= $folder . '/';
+        $check_directory = $current_directory;
+        // Use the "quiet" version of file_check_directory() provided by FileField
+        // if it exists. This suppresses "Directory was created" messages.
+        $file_check_directory = function_exists('field_file_check_directory') ? 'field_file_check_directory' : 'file_check_directory';
+        $file_check_directory($check_directory, FILE_CREATE_DIRECTORY);
+      }
+
       // Move remote images into place if they are already the right size.
       if ($image['location'] == 'remote' && !$image['resize']) {
         $handle = fopen($image['destination'], 'w');
@@ -549,37 +535,23 @@
 
     // Replace the existing image source with the resized image.
     // Set the image we're currently updating in the callback function.
-    image_resize_filter_update_tag(NULL, $image, $settings);
-    $text = preg_replace_callback('/(<img[^>]*?src[ ]*=[ ]*")' . preg_quote($image['original'] ,'/') . '("[^>]*?)(\/?>)/i', 'image_resize_filter_update_tag', $text);
+    $search[] = $image['img_tag'];
+    $replace[] = image_resize_filter_image_tag($image, $settings);
   }
-  return $text;
+
+  return str_replace($search, $replace, $text);
 }
 
 /**
- * Regular expression callback.
+ * Generate a themed image tag based on an image array.
  *
- * @param $matches
- *   The matches for a call to preg_replace_callback().
- * @param $new_image
- *   If passed in, this will set a static variable so that this image data is
- *   available when this function is called from a regular expression.
+ * @param $image
+ *   An array containing image information and properties.
+ * @param $settings
+ *   Settings for the input filter.
  */
-function image_resize_filter_update_tag($matches = NULL, $new_image = NULL, $new_settings = NULL) {
+function image_resize_filter_image_tag($image = NULL, $settings = NULL) {
   global $base_url;
-  static $image, $settings;
-
-  $image = isset($new_image) ? $new_image : $image;
-  $settings = isset($new_settings) ? $new_settings : $settings;
-
-  if (!isset($matches)) {
-    return;
-  }
-
-  // Do not do replacements if the image tag doesn't match exactly. This can
-  // happen if the same image is in the same post multiple times.
-  if ($matches[0] != $image['img_tag']) {
-    return $matches[0];
-  }
 
   $src = $image['destination'];
   // Make the new file private if the original was private.
@@ -597,24 +569,41 @@
   if (!preg_match('/^http[s]?:\/\/' . preg_quote($_SERVER['HTTP_HOST']) . '/', $image['original'])) {
     $src = preg_replace('/^http[s]?:\/\/' . preg_quote($_SERVER['HTTP_HOST']) . '/', '', $src);
   }
+  $image['attributes']['src'] = $src;
 
-  $output = '';
-  $output .= $matches[1]; // The start of the tag.
-  $output .= $src; // The new src.
-  $output .= $matches[2]; // The end of the tag, excluding the closing "/>".
-
-  // Add height and width properties if they are missing from the original tag.
-  $output .= $image['add_properties']['width'] ? ' width="' . $image['expected_size']['width'] . '"' : '';
-  $output .= $image['add_properties']['height'] ? ' height="' . $image['expected_size']['height'] . '"' : '';
-
-  $output .= $matches[3]; // The closing "/>".
+  // Set the link properties if necessary.
+  $image['link'] = FALSE;
   if ($image['resize'] && $settings['link'] && !$image['has_link']) {
-    $class = !empty($settings['class']) ? ' class="' . $settings['class'] . '"' : '';
-    $rel = !empty($settings['rel']) ? ' rel="' . $settings['rel'] . '"' : '';
-    $title = !empty($image['title']) ? ' title="' . $image['title'] . '"' : '';
-    $output = '<a href="' . $image['original'] . '"' . $title . $class . $rel . '>' . $output . '</a>';
+    $image['link'] = array();
+    $image['link']['attributes'] = array('href' => $image['original']);
+    if (!empty($settings['class'])) {
+      $image['link']['attributes']['class'] = $settings['class'];
+    }
+    if (!empty($settings['rel'])) {
+      $image['link']['attributes']['rel'] = $settings['rel'];
+    }
+    if (!empty($image['title'])) {
+      $image['link']['attributes']['title'] = $image['title'];
+    }
   }
 
+  // Theme the output and return.
+  return theme('image_resize_filter_image', $image, $settings);
+}
+
+/**
+ * Generate a themed image tag based on an image array.
+ *
+ * @param $image
+ *   An array containing image information and properties.
+ * @param $settings
+ *   Settings for the input filter.
+ */
+function theme_image_resize_filter_image($image, $settings) {
+  $output = '<img' . drupal_attributes($image['attributes']) . ' />';
+  if ($image['link']) {
+    $output = '<a'. drupal_attributes($image['link']['attributes']) . '>' . $output . '</a>';
+  }
   return $output;
 }
 
