Index: imagefield.install
===================================================================
RCS file: /cvs/drupal/contributions/modules/imagefield/imagefield.install,v
retrieving revision 1.2
diff -u -r1.2 imagefield.install
--- imagefield.install	1 Sep 2006 20:19:56 -0000	1.2
+++ imagefield.install	31 May 2007 16:51:04 -0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: imagefield.install,v 1.2 2006/09/01 20:19:56 dopry Exp $
+// $Id: imagefield.install,v 1.2.2.1 2007/04/18 20:59:08 quicksketch Exp $
 
 /**
  * Implementation of hook_install().
@@ -49,7 +49,41 @@
   include_once(drupal_get_path('module', 'content') .'/content.module');
   include_once(drupal_get_path('module', 'content') .'/content_admin.inc');
 
-  $fields = _content_fields();
+  $fields = content_fields();
+
+  foreach ($fields as $field) {
+    switch ($field['type']) {
+      case 'image':
+        $oldcolumns = array(
+          'fid' => array('type' => 'int', 'not null' => TRUE, 'default' => '0'),
+        );
+        $newcolumns = array(
+          'fid' => array('type' => 'int', 'not null' => TRUE, 'default' => '0'),
+          'title' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
+          'alt' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
+        );
+        content_alter_db_field($field, $oldcolumns, $field, $newcolumns);
+        break;
+    }
+    drupal_set_message('altered: <br /><pre>'. print_r($field, true) .'</pre>');
+  }
+
+
+  db_query('DELETE FROM {cache}');
+  return $ret;
+}
+
+/**
+ * Schema change to enable link option.
+ */
+
+function imagefield_update_3() {
+  $ret = array();
+
+  include_once(drupal_get_path('module', 'content') .'/content.module');
+  include_once(drupal_get_path('module', 'content') .'/content_admin.inc');
+
+  $fields = content_fields();
 
   foreach ($fields as $field) {
     switch ($field['type']) {
@@ -61,6 +95,8 @@
           'fid' => array('type' => 'int', 'not null' => TRUE, 'default' => '0'),
           'title' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
           'alt' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
+          'url' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
+          'target' => array('type' => 'varchar', 'length' => 20, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
         );
         content_alter_db_field($field, $oldcolumns, $field, $newcolumns);
         break;
Index: imagefield.module
===================================================================
RCS file: /cvs/drupal/contributions/modules/imagefield/imagefield.module,v
retrieving revision 1.31
diff -u -r1.31 imagefield.module
--- imagefield.module	19 Apr 2007 23:50:05 -0000	1.31
+++ imagefield.module	31 May 2007 16:51:07 -0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: imagefield.module,v 1.31 2007/04/19 23:50:05 quicksketch Exp $
+// $Id: imagefield.module,v 1.30.2.17 2007/04/21 21:41:15 quicksketch Exp $
 
 /**
  * @file
@@ -75,6 +75,8 @@
         'fid' => array('type' => 'int', 'not null' => TRUE, 'default' => '0'),
         'title' => array('type' => 'varchar', length => 255, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
         'alt' => array('type' => 'varchar', length => 255, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
+        'url' => array('type' => 'varchar', length => 255, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
+        'target' => array('type' => 'int', 'not null' => TRUE, 'default' => '0', 'sortable' => TRUE),
       );
       return $columns;
   }
@@ -92,7 +94,7 @@
   $fieldname = $field['field_name'];
   $filepath = file_create_path($field['widget']['image_path']) . '/' . $file['filename'];
 
-  if ($file = file_save_upload((object)$file, $filepath)) {
+  if (imagefield_check_directory($field['widget']['image_path']) && $file = file_save_upload((object)$file, $filepath)) {
     $file = (array)$file;
     $file['fid'] = db_next_id('{files}_fid');
     db_query("INSERT into {files} (fid, nid, filename, filepath, filemime, filesize)
@@ -145,24 +147,9 @@
         foreach ($node_field as $delta => $file) {
           $node_field[$delta]  = array_merge((array)$node_field[$delta], _imagefield_file_load($file['fid']));
         }
-        $output = array($fieldname => $node_field);
+        return array($fieldname => $node_field);
       };
-      break; 
-
-    case 'view':
-      $formatter = 'default';
-      if (module_exists('imagecache')) {
-        $formatter = $field['widget']['body_preset'];
-        if ($teaser) {
-          $formatter = $field['widget']['teaser_preset'];
-        }
-      }
-      foreach ($node_field as $delta => $item) {
-        $node_field[$delta]['view'] = content_format($field, $item, $formatter); 
-      }
-      $output = theme('field', $node, $field, $node_field, $teaser, $page); 
       break;
-
     // called before content.module defaults.
     case 'insert':
       foreach ($node_field as  $delta => $item) {
@@ -175,7 +162,13 @@
     case 'update':
       foreach ($node_field as $delta => $item) {
         $node_field[$delta] = imagefield_file_update($node, $item, $field); 
+        // Remove non-existant files from node_field
+        if (empty($node_field[$delta])) {
+          unset($node_field[$delta]);
+        }
       }
+      // Compact deltas.
+      $node_field = array_values($node_field);
       imagefield_clear_field_session($fieldname);
       break;
 
@@ -185,7 +178,6 @@
       }
       break;
   }
-  return $output;
 }
 
 /**
@@ -205,6 +197,9 @@
  */
 function imagefield_widget_settings($op, $widget) {
   switch ($op) {
+    case 'callbacks':
+      return array('default value' => CONTENT_CALLBACK_CUSTOM);
+
     case 'form':
       $form = array();
       $form['max_resolution'] = array (
@@ -221,7 +216,7 @@
         '#title' => t('Image path'), 
         '#default_value' => $widget['image_path'] ? $widget['image_path'] : '', 
         '#description' => t('Optional subdirectory within the "%dir" directory where images will be stored. Do not include trailing slash.', array('%dir' => variable_get('file_directory_path', 'files'))), 
-        '#after_build' => array('imagefield_check_directory'),
+        '#after_build' => array('imagefield_form_check_directory'),
       );
       $form['custom_alt'] = array(
         '#type' => 'checkbox',
@@ -235,60 +230,55 @@
         '#default_value' =>  $widget['custom_title'] ? $widget['custom_title'] : 0,
         '#description' => t('Enable custom title text for images. Filename will be used if not checked.'),
       );
-      if (module_exists('imagecache')) {
-        $options = array();
-        $options['default'] = 'Default';
-        $presets =  _imagecache_get_presets();
-        foreach($presets as $id => $name) {
-          $options[$name] = $name;
-        }
-        $form['imagecache'] = array(
-          '#type' => 'fieldset',
-          '#title' => 'Imagecache Options',
-        );
-        $form['imagecache']['teaser_preset'] = array(
-          '#title' => t('Teaser preset'),
-          '#description' => t('Select the imagecache preset you want to handle thumbnails in the teaser.'),
-          '#type' => 'select',
-          '#options' =>  $options,
-          '#default_value' => $widget['teaser_preset'] ? $widget['teaser_preset'] : 'default' ,
-        );
-        $form['imagecache']['body_preset'] = array(
-          '#title' => t('Body preset'),
-          '#description' => t('Select the imagecache preset you want to handle thumbnails in the teaser.'),
-          '#type' => 'select',
-          '#options' =>  $options,
-          '#default_value' => $widget['body_preset'] ? $widget['body_preset'] : 'default',
-        );
-      }
+      $form['wrap_in_link'] = array(
+        '#type' => 'checkbox',
+        '#title' => t('Wrap image in link'),
+        '#default_value' =>  $widget['wrap_in_link'] ? $widget['wrap_in_link'] : 0,
+        '#description' => t('Enable wrapping images in a link.  The link URL may be specified per image.'),
+      );
       return $form;
 
     case 'validate':
       break;
 
     case 'save':
-      return array('max_resolution', 'image_path', 'custom_alt', 'custom_title', 'teaser_preset', 'body_preset');
+      return array('max_resolution', 'image_path', 'custom_alt', 'custom_title', 'wrap_in_link', 'teaser_preset', 'body_preset');
   }
 }
 
 /**
- * Create the image directory relative to the 'files' dir - if user specified one
- * Won't allow form submit unless the directory exists & is writable
+ * Wrapper function for imagefield_check_directory that accepts a form element
+ * to validate - if user specified one. Won't allow form submit unless the
+ * directory exists & is writable
  * 
  * @param $form_element
  *   The form element containing the name of the directory to check.
- */ 
-function imagefield_check_directory($form_element) {
+ */
+function imagefield_form_check_directory($form_element) {
   if(!empty($form_element['#value'])) {
-    // create each directory necessary if it doesn't exist
-    foreach(explode('/', $form_element['#value']) as $dir) {
-      $dirs[] = $dir;
-      file_check_directory(file_create_path(implode($dirs,'/')), FILE_CREATE_DIRECTORY, $form_element['#parents'][0]);
-    }
+    imagefield_check_directory($form_element['#value'], $form_element);
   }
   return $form_element;
 }
 
+/**
+ * Create the image directory relative to the 'files' dir recursively for every
+ * directory in the path.
+ * 
+ * @param $directory
+ *   The directory path under files to check, such as 'photo/path/here'
+ * @param $form_element
+ *   A form element to throw an error on if the directory is not writable
+ */ 
+function imagefield_check_directory($directory, $form_element = array()) {
+  foreach(explode('/', $directory) as $dir) {
+    $dirs[] = $dir;
+    $path = file_create_path(implode($dirs,'/'));
+    file_check_directory($path, FILE_CREATE_DIRECTORY, $form_element['#parents'][0]);
+  }
+  return true;
+}
+
 function _imagefield_scale_image($file, $resolution = 0) {
   $info = image_get_info($file['filepath']);
   if ($info) {
@@ -317,10 +307,8 @@
 function imagefield_clear_field_session($fieldname) {
   if (is_array($_SESSION['imagefield'][$fieldname]) && count($_SESSION['imagefield'][$fieldname])) {
     foreach ($_SESSION['imagefield'][$fieldname] as $files) {
-      foreach ($files as $delta => $file) {
-        if (is_file($file['filepath'])) {
-          file_delete($file['filepath']);
-        }
+      if (is_file($file['filepath'])) {
+        file_delete($file['filepath']);
       }
     }
     unset($_SESSION['imagefield'][$fieldname]);
@@ -344,64 +332,68 @@
   $fieldname = $field['field_name'];
   $content_type = $field['type_name'];
   switch ($op) {
+    case 'default value':
+      return array();
+
     case 'prepare form values':
-      // clean up the session if we weren't posted.
-      if (!count($_POST)) {
-        imagefield_clear_session();
-      }
-
-      // Attach new files 
-      if ($file = file_check_upload($fieldname . '_upload')) {
-        $file = (array)$file;
-        if (strpos($file['filemime'],'image') !== FALSE) { 
-          $file = _imagefield_scale_image($file, $field['widget']['max_resolution']);
-          
-          // Create the filepath for the image preview
-          $filepath = file_create_filename($file['filename'], file_create_path($field['widget']['image_path']));
-          if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) ==  FILE_DOWNLOADS_PRIVATE) {
-            if (strpos($filepath, file_directory_path()) !== FALSE) {
-              $filepath = trim(substr($filepath, strlen(file_directory_path())), '\\/');
-            }
-            $filepath = 'system/files/' . $filepath;
-          }
-          
-          $file['fid'] = 'upload';
-          $file['preview'] = $filepath;
-          
-          // If a single field, mark any other images for deletion and delete files in session
-          if (!$field['multiple']) {
-            if (is_array($node_field)) {
-              foreach ($node_field as $delta => $session_file) {
-                $node_field[$delta]['flags']['delete'] = TRUE;
-              }
-            }
-            imagefield_clear_field_session($fieldname);
-          }
-          // Add the file to the session
-          $file_id = count($node_field) + count($_SESSION['imagefield'][$fieldname]);
-          $_SESSION['imagefield'][$fieldname][$file_id] = $file;
-        }
-      }
-      
-      // Load files from preview state. before committing actions.
-      if (is_array($_SESSION['imagefield'][$fieldname]) && count($_SESSION['imagefield'][$fieldname])) {
-        foreach($_SESSION['imagefield'][$fieldname] as $delta => $file) {
-          $node_field[] = $file;
-        }
-      }
-      break;
+      _imagefield_widget_prepare_form_values($node, $field, $node_field);
+      return;
 
     case 'form':
       $form = _imagefield_widget_form($node, $field, $node_field);
       return $form;
 
     case 'validate':
-      if ($field['required']) {
-        if (!count($node_field)) {
-          form_set_error($fieldname, $field['widget']['label'] .' is required.');
+      _imagefield_widget_form_validate($node, $field, $node_field);
+      return;
+  }
+}
+
+function _imagefield_widget_prepare_form_values($node, $field, &$node_field) {
+  $fieldname = $field['field_name'];
+  // clean up the session if we weren't posted.
+  if (!count($_POST)) {
+    imagefield_clear_session();
+  }
+
+  // Attach new files 
+  if ($file = file_check_upload($fieldname . '_upload')) {
+    $file = (array)$file;
+    if (strpos($file['filemime'],'image') !== FALSE) { 
+      $file = _imagefield_scale_image($file, $field['widget']['max_resolution']);
+      
+      // Create the filepath for the image preview
+      $filepath = file_create_filename($file['filename'], file_create_path($field['widget']['image_path']));
+      if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) ==  FILE_DOWNLOADS_PRIVATE) {
+        if (strpos($filepath, file_directory_path()) !== FALSE) {
+          $filepath = trim(substr($filepath, strlen(file_directory_path())), '\\/');
         }
+        $filepath = 'system/files/' . $filepath;
       }
-      return;
+      
+      $file['fid'] = 'upload';
+      $file['preview'] = $filepath;
+      
+      // If a single field, mark any other images for deletion and delete files in session
+      if (!$field['multiple']) {
+        if (is_array($node_field)) {
+          foreach ($node_field as $delta => $session_file) {
+            $node_field[$delta]['flags']['delete'] = TRUE;
+          }
+        }
+        imagefield_clear_field_session($fieldname);
+      }
+      // Add the file to the session
+      $file_id = count($node_field) + count($_SESSION['imagefield'][$fieldname]);
+      $_SESSION['imagefield'][$fieldname][$file_id] = $file;
+    }
+  }
+  
+  // Load files from preview state. before committing actions.
+  if (is_array($_SESSION['imagefield'][$fieldname]) && count($_SESSION['imagefield'][$fieldname])) {
+    foreach($_SESSION['imagefield'][$fieldname] as $delta => $file) {
+      $node_field[] = $file;
+    }
   }
 }
 
@@ -496,12 +488,34 @@
           );
         }
         
-        $form[$fieldname][$delta]['filename'] = array('#type' => 'value',  '#value' => $file['filename']);
-        $form[$fieldname][$delta]['filepath'] = array('#type' => 'value',  '#value' => $file['filepath']);
-        $form[$fieldname][$delta]['filemime'] = array('#type' => 'value',  '#value' => $file['filemime']);
-        $form[$fieldname][$delta]['filesize'] = array('#type' => 'value',  '#value' => $file['filesize']);
-        $form[$fieldname][$delta]['fid'] = array('#type' => 'value',  '#value' => $file['fid']);
-      
+        $form[$fieldname][$delta]['url'] = array(
+          '#type' => 'hidden',
+          '#value' => '',
+        );
+        $form[$fieldname][$delta]['target'] = array(
+          '#type' => 'hidden',
+          '#value' => '',
+        );
+        // overwrite with an input field if wrap_in_link is flagged;
+        if ($field['widget']['wrap_in_link']) {
+          $form[$fieldname][$delta]['url'] = array(
+            '#type' => 'textfield',
+            '#title' =>  t('Link URL'),
+            '#default_value' =>  $file['url'],
+            '#description' => t('Optional URL for image link.'),
+            '#maxlength' => 255,
+            '#size' => 10,
+          );
+
+          $form[$fieldname][$delta]['target'] = array(
+            '#type' => 'select',
+            '#title' =>  t('Link Target'),
+            '#options' => _imagefield_link_targets(),
+            '#default_value' =>  $file['target'],
+            '#description' => t('Optional link target for image link.'),
+          );
+        }
+        
         // Special handling for single value fields
         if (!$field['multiple']) {
           $form[$fieldname][$delta]['replace'] = array(
@@ -511,16 +525,34 @@
         }
       }
       elseif ($file['filepath'] && $file['flags']['delete']) {
-        $form[$fieldname][$delta]['flags']['delete'] = array(
-          '#type' => 'hidden', // A value type will not persist here, must be hidden
-          '#value' => $file['flags']['delete'],
-        );
+        // Hide all the form values if this item is marked for deletion
+        $form[$fieldname][$delta]['flags']['delete'] = array('#type' => 'value', '#value' => $file['flags']['delete']);
+        $form[$fieldname][$delta]['title'] = array('#type' => 'value', '#value' => $file['title']);
+        $form[$fieldname][$delta]['alt'] = array('#type' => 'value', '#value' => $file['alt']);
+        $form[$fieldname][$delta]['url'] = array('#type' => 'value', '#value' => $file['url']);
+        $form[$fieldname][$delta]['target'] = array('#type' => 'value', '#value' => $file['target']);
       }
+
+      $form[$fieldname][$delta]['filename'] = array('#type' => 'value',  '#value' => $file['filename']);
+      $form[$fieldname][$delta]['filepath'] = array('#type' => 'value',  '#value' => $file['filepath']);
+      $form[$fieldname][$delta]['filemime'] = array('#type' => 'value',  '#value' => $file['filemime']);
+      $form[$fieldname][$delta]['filesize'] = array('#type' => 'value',  '#value' => $file['filesize']);
+      $form[$fieldname][$delta]['fid'] = array('#type' => 'value',  '#value' => $file['fid']);
+
     }
   }
   return $form;
 }
 
+function _imagefield_widget_form_validate($node, $field, $node_field) {
+  $fieldname = $field['field_name'];
+  if ($field['required']) {
+    if (!count($node_field)) {
+      form_set_error($fieldname, $field['widget']['label'] .' is required.');
+    }
+  }
+}
+
 /**
  * Implementation of hook_field_formatter_info().
  */
@@ -531,15 +563,6 @@
       'field types' => array('image'),
     ),
   );
-  if (module_exists('imagecache')) {
-    $rules = _imagecache_get_presets();
-    foreach ($rules as $ruleid => $rulename) {
-       $formatters[$rulename] = array(
-         'label' => $rulename,
-         'field types' => array('image'),
-         );
-    }
-  }
   return $formatters;
 }
 
@@ -548,40 +571,39 @@
  *
  */
 function imagefield_field_formatter($field, $item, $formatter) {
-  if (!isset($item['fid'])) {
+  if (empty($item['fid'])) {
     return '';
   }
   $file = _imagefield_file_load($item['fid']);
-  if (module_exists('imagecache')) {
-    $rules = _imagecache_get_presets();
-    if (in_array($formatter, (array) $rules)) {
-      return theme('imagecache', $formatter, $file['filepath'], $item['alt'], $item['title']);
-    }
+
+  // If this image has a URL specified, display it as a link
+  if ($item['url']) {
+    $link_attributes = array();
+    if ($item['target'] > 0) {
+      $targets = _imagefield_link_targets();
+      $link_attributes['target'] = $targets[$item['target']];
+    }
+    return theme('imagefield_linked_image', $file, $item['alt'], $item['title'], $item['url'], $link_attributes);
+  } else {
+    // Otherwise display it without a link
+    return theme('imagefield_image', $file, $item['alt'], $item['title']);
   }
-  return theme('imagefield_image', $file, $item['alt'], $item['title']);
 }
 
 
 function _imagefield_file_load($fid = NULL) {
   // Don't bother if we weren't passed and fid.
-  if (isset($fid)) { 
-    // Test to catch fid, eventuall plan to have node_load syntax
-    // once file_attributes table is complete
-    if (is_numeric($fid)) {
-      $result = db_query('SELECT * FROM {files} WHERE fid = %d', $fid);
-      $file = db_fetch_array($result);
-      return ($file) ? $file : array();
-    }
+  if (!empty($fid) && is_numeric($fid)) { 
+    $result = db_query('SELECT * FROM {files} WHERE fid = %d', $fid);
+    $file = db_fetch_array($result);
   }
-  return array();
+  return is_array($file) ? $file : array();
 }
 
 function theme_imagefield_view_image($file, $alt = '', $title = '', $attributes = NULL, $getsize = TRUE) {
   return theme('imagefield_image', $file, $alt, $title, $attributes , $getsize);
 }
 
-
-
 function theme_imagefield_edit_image_row($element) {
   $output = '<div class="imagefield-edit-preview">'. drupal_render($element['preview']) .'</div>';
   $output .= '<div class="imagefield-edit-image-detail">';
@@ -590,6 +612,8 @@
   $output .= '</div>';
   $output .= drupal_render($element['alt']);
   $output .= drupal_render($element['title']);
+  $output .= drupal_render($element['url']);
+  $output .= drupal_render($element['target']);
   $output .= '</div>';
   //$output .= '<div class="imagefield-edit-image-fid">'. $element['fid']['#value'] .'</div>';
   $output = '<div class="imagefield-edit-image-row clear-block">'. $output .'</div>';
@@ -599,8 +623,23 @@
   return $output;  
 }
 
+/**
+ * formats an image.
+ * @param file
+ *    array containing image fields
+ * @param alt
+ *    string image alt attribute
+ * @param alt
+ *    string image title attribute
+ * @param attributes
+ *    array of additional attributes for img tag
+ * @param getsize
+ *    boolean getsize
+ * @return 
+ *    html string
+ */
+
 function theme_imagefield_image($file, $alt = '', $title = '', $attributes = NULL, $getsize = TRUE) {
-  
   $file = (array)$file;
   if (!$getsize || (is_file($file['filepath']) && (list($width, $height, $type, $image_attributes) = @getimagesize($file['filepath'])))) {
     $attributes = drupal_attributes($attributes);
@@ -616,6 +655,43 @@
 }
 
 /**
+ * formats an image wrapped in a link.
+ * @param file
+ *    array containing image fields
+ * @param alt
+ *    string image alt attribute
+ * @param alt
+ *    string image title attribute
+ * @param link_url
+ *    string href for image a tag
+ * @param link_attributes
+ *    array of attributes for image a tag
+ * @param attributes
+ *    array of additional attributes for img tag
+ * @param getsize
+ *    boolean getsize
+ * @return 
+ *    html string
+ */
+function theme_imagefield_linked_image($file, $alt = '', $title = '', $link_url = '', $link_attributes = array(), $attributes = NULL, $getsize = TRUE) {
+
+  $file = (array)$file;
+  if (!$getsize || (is_file($file['filepath']) && (list($width, $height, $type, $image_attributes) = @getimagesize($file['filepath'])))) {
+    $attributes = drupal_attributes($attributes);
+    
+    $path = $file['fid'] == 'upload' ? $file['preview'] : $file['filepath'];
+    $alt = empty($alt) ? $file['alt'] : $alt;
+    $title = empty($title) ? $file['title'] : $title;
+    
+    $url = file_create_url($path);
+    $img_tag = '<img src="'. check_url($url) .'" alt="'.
+        check_plain($alt) .'" title="'. check_plain($title) .'" '. $image_attributes . $attributes .' />';
+        
+    return l($img_tag, $link_url, $link_attributes, NULL, NULL, FALSE, TRUE);
+  }
+}
+
+/**
  * formats an array of images.
  * @param images
  *    array of individually themed images
@@ -663,3 +739,13 @@
     }
   }
 }
+
+/**
+ * returns an array of possible link targets.
+ * @return 
+ *    targets array
+ */
+function _imagefield_link_targets()
+{
+  return array("<unspecified>", "_self", "_parent", "_top", "_blank");
+}
\ No newline at end of file
