Index: exif.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/exif/exif.module,v
retrieving revision 1.9.2.11
diff -d -u -r1.9.2.11 exif.module
--- exif.module	1 Dec 2009 15:00:49 -0000	1.9.2.11
+++ exif.module	21 Jan 2010 08:50:36 -0000
@@ -90,53 +90,130 @@
         break;
       }
     case 'insert':
-      if (_exif_check_for_exif_data($node->type)) {
-        $info = content_types($node->type);
-        $fields = $info['fields'];
-        $exif = _exif_get_class();
-
-        //get all the fields that will be filled with exif data
-        $ar_exif_fields = $exif->getExifFields($fields);
+      if (! _exif_check_for_exif_data($node->type)) {
+        return;
+      }
+      $info = content_types($node->type);
+      $fields = $info['fields'];
+      $exif = _exif_get_class();
 
-        //get the path to the image
-        $image_path = _exif_get_image_path($fields, $node);
+      //get all the fields that will be filled with exif data
+      $ar_exif_fields = $exif->getExifFields($fields);
 
-        $fid = db_result(db_query("SELECT fid FROM {files} WHERE filepath = '%s'", $image_path));
-        $file = file_create_path($image_path);
+      //get the path to the image
+      $image_path = _exif_get_image_path($fields, $node);
 
-        $data1 = _exif_reformat($exif->readExifTags($file, $ar_exif_fields));
-        $data2 = $exif->readIPTCTags($file, $ar_exif_fields);
-        $data = array_merge($data1, $data2);
+      $fid = db_result(db_query("SELECT fid FROM {files} WHERE filepath = '%s'", $image_path));
+      $file = file_create_path($image_path);
 
-        // prepare data to be stored in CCK
-        $i = 0;
-        foreach ($data as $key => $value) {
-          $field_name = 'field_'. $key;
-          $tmp = $node->$field_name;
+      $data1 = _exif_reformat($exif->readExifTags($file, $ar_exif_fields));
+      $data2 = $exif->readIPTCTags($file, $ar_exif_fields);
+      $data = array_merge($data1, $data2);
 
-          $date_array = array('datetimeoriginal', 'datetime', 'datetimedigitized');
-          //incase we get a datefield, we need to reformat it to the ISO 8601 standard:
-          //which will look something like 2004-02-12T15:19:21
-          if (in_array($key, $date_array)) {
-            $date_time = explode(" ", $value);
-            $date_time[0] = str_replace(":", "-", $date_time[0]);
-            if (variable_get('exif_granularity', 0) == 1) {
-              $date_time[1] = "00:00:00";
-            }
-            $value = implode("T", $date_time);
-            //dsm($value,$key);
-          }
-          $tmp[0]['value'] = $value;
+      // Loop through every exif enabled field and set its value to the
+      // corresponding exif value. If no exif value was found, set the field
+      // value to NULL, to avoid strange behaviour in other field modules
+      // (date).
+      foreach ($ar_exif_fields as $ar_exif_field) {
+        $exif_name = $ar_exif_field['section'] .'_'. $ar_exif_field['tag'];
+        $exif_value = isset($data[$exif_name]) ? $data[$exif_name] : NULL;
+        $field_name = 'field_'. $exif_name;
+        if (! $exif_value) {
+          $node->{$field_name}[0]['value'] = NULL;
+          continue;
+        }
+        $field = $fields[$field_name];
 
-          $node->$field_name = $tmp;
-          $i++;
+        // Setup the field value array for delta = 0.
+        switch ($exif_name) {
+          case 'exif_datetimeoriginal':
+          case 'exif_datetimedigitized':
+          case 'ifd0_datetime':
+            $first_delta = _exif_date_handler($field, $exif_value);
+            break;
+          default:
+            $first_delta = array('value' => $data[$exif_name]);
+            break;
         }
+        $node->{$field_name}[0] = $first_delta;
       }
       break;
   }
 }
 
 /**
+ * Date API hook.
+ *
+ * Make exif a date format in Date API. This makes it possible to alter the
+ * format exif dates is parsed as.
+ */
+function exif_date_format_types() {
+  return array('exif' => 'EXIF');
+}
+
+/**
+ * Date API hook.
+ *
+ * Make the EXIF date format default for the 'exif' date type.
+ */
+function exif_date_formats() {
+  return array(
+    array(
+      'type' => 'exif',
+      'format' => 'Y:m:d H:i:s',
+    ),
+  );
+}
+
+/**
+ * Helper function to handle all date values from exif header. This is
+ * designed for the date_api and date modules, but is compatible if these
+ * aren't enabled.
+ *
+ * @param array $field
+ *   The field definition for the matcing exif date
+ * @param string $exif_date
+ *   The date extracted from exif header.
+ * @return array
+ *   The field value array for delta = 0
+ */
+function _exif_date_handler($field, $exif_date) {
+  if (! module_exists('date_api')) {
+    // Don't bother doing anything if the webmaster doesn't ...
+    return array('value' => $exif_date);
+  }
+
+  require_once drupal_get_path('module', 'date_api') .'/date_api_elements.inc';
+  $date_datetime = date_convert_from_custom($exif_date, variable_get('date_format_exif', 'Y:m:d H:i:s'));
+  if (! in_array($field['type'], array('date', 'datetime', 'datestamp'))) {
+    // Field is not a date field type, so we return a ISO-8601 representation
+    return array('value' => date_convert($date_datetime, DATE_DATETIME, DATE_ISO));
+  }
+
+  // Exif doesn't handles timezones, so we assume the exif date is in the
+  // timezone configured for this date field.  This means the exif date needs
+  // to be converted to UTC before it's stored.
+  $timezone = date_get_timezone($field['tz_handling']);
+  $date = date_make_date($date_datetime, $timezone, DATE_DATETIME, $field['granularity']);
+
+  // Store date offset before converting to UTC as this is lost when setting
+  // timezone to 'UTC'.
+  $offset = date_offset_get($date);
+  date_timezone_set($date, timezone_open('UTC'));
+
+  // Finally, convert the date object in UTC to a date according to the field
+  // type: DATE_ISO, DATE_DATETIME or DATE_UNIX.
+  $date_field = date_convert($date, DATE_OBJECT, $field['type']);
+  return array(
+    'value' => $date_field,
+    'value2' => $date_field,
+    'timezone' => $timezone,
+    'offset' => $offset,
+    'offset2' => $offset,
+  );
+}
+
+/**
  * Let's check if this node type contains an image field.
  *
  * @param $fields fields from this content type
@@ -240,7 +317,6 @@
  * Helper function to reformat fields where required.
  *
  * Some values (lat/lon) break down into structures, not strings.
- * Dates should be parsed nicely.
  */
 function _exif_reformat($data) {
   $date_array = array('datetimeoriginal', 'datetime', 'datetimedigitized');
@@ -258,16 +334,6 @@
     elseif ($key == 'gps_longitude') {
       $value = _exif_DMS2D($value, $data['gps_gpslongituderef']);
     }
-    elseif (in_array($key, $date_array)) {
-      // In case we get a datefield, we need to reformat it to the ISO 8601 standard:
-      // which will look something like 2004-02-12T15:19:21
-      $date_time = explode(" ", $value);
-      $date_time[0] = str_replace(":", "-", $date_time[0]);
-      if (variable_get('exif_granularity', 0) == 1) {
-        $date_time[1] = "00:00:00";
-      }
-      $value = implode("T", $date_time);
-    }
   }
   return $data;
 }
