From ebbcd617393c83364699592dfeca8c6e7c3a578a Mon Sep 17 00:00:00 2001 From: Silvio Date: Fri, 8 Oct 2010 15:34:02 -0300 Subject: CVS update --- exif.module | 569 +++++++++++++++++++++++++++++------------------------------- 1 file changed, 277 insertions(+), 292 deletions(-) (limited to 'exif.module') diff --git a/exif.module b/exif.module index 3853eb4..ecbbd6e 100755 --- a/exif.module +++ b/exif.module @@ -1,362 +1,347 @@ 'admin/settings/exif', - 'title' => t('Exif'), - 'callback' => 'drupal_get_form', - 'callback arguments' => array('exif_admin_settings_form'), - 'access' => user_access('administer site configuration'), - 'description' => t('Configure what Exif tags to display.'), - ); - } +function exif_menu() { + $items['admin/settings/exif'] = array( + 'title' => 'Exif', + 'page callback' => 'exif_admin_settings', + 'access arguments' => array('administer site configuration'), + 'description' => t('Display available fields'), + 'access callback' => 'user_access', + 'file' => 'exif.admin.inc', + 'type' => MENU_NORMAL_ITEM, + ); + $items['admin/settings/exif/general'] = array( + 'title' => 'Exif', + 'page callback' => 'exif_admin_settings', + 'access arguments' => array('administer site configuration'), + 'description' => t('Display available fields'), + 'access callback' => 'user_access', + 'file' => 'exif.admin.inc', + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + $items['admin/settings/exif/config'] = array( + 'title' => 'Config', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('exif_admin_settings_form'), + 'access arguments' => array('administer site configuration'), + 'description' => t('Some Settings'), + 'access callback' => 'user_access', + 'file' => 'exif.admin.inc', + 'type' => MENU_LOCAL_TASK, + ); return $items; } /** - * Implementation of hook_nodeapi(). + * implementation of hook_nodeapi */ -function exif_nodeapi(&$node, $op, $teaser) { - if ($teaser || $node->type != 'image') { +function exif_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) { + + if ($teaser) { return; } switch ($op) { - case 'insert': + case 'update': - $fid = db_result(db_query("SELECT fid FROM {files} WHERE filepath = '%s'", $node->images[IMAGE_ORIGINAL])); - $file = file_create_path($node->images[IMAGE_ORIGINAL]); - $data = _exif_read_exif($file); - db_query('DELETE FROM {exif} WHERE fid = %d', $fid); - - // Cache data in db. - foreach ($data as $ifd => $tags) { - foreach ($tags as $tag => $value) { - db_query("INSERT INTO {exif} (fid, ifd, tag, value) VALUES (%d, %d, %d, '%s')", - $fid, $ifd, $tag, $value); - } + //we are only going to update if we have said so + if (!variable_get('exif_update', TRUE)) { + break; } - break; + case 'insert': + if (! _exif_check_for_exif_data($node->type)) { + return; + } + $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); + + //get the path to the image + $image_path = _exif_get_image_path($fields, $node); - case 'load': - $fid = db_result(db_query("SELECT fid FROM {files} WHERE filepath = '%s'", $node->images[IMAGE_ORIGINAL])); - return array('exif_data' => _exif_get_exif($fid)); - case 'view': - $node->content['exif'] = array( - '#value' => theme('exif_table', $node), - '#weight' => 10, - ); + $fid = db_result(db_query("SELECT fid FROM {files} WHERE filepath = '%s'", $image_path)); + $file = file_create_path($image_path); + + $data1 = _exif_reformat($exif->readExifTags($file, $ar_exif_fields)); + $data2 = $exif->readIPTCTags($file, $ar_exif_fields); + + if (class_exists('SXMPFiles')) { + $data3 = $exif->readXMPTags($file, $ar_exif_fields); + $data = array_merge($data1, $data2, $data3); + } + else { + $data = array_merge($data1, $data2); + } + + // 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) { + if (variable_get('exif_empty_values', TRUE)) { + $node->{$field_name}[0]['value'] = NULL; + } + continue; + } + $field = $fields[$field_name]; + + // 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; } } /** - * Administration page callback. + * 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_admin_settings_form() { - _exif_bootstrap(); - $tags = exif_load_settings(); - foreach ($tags as $tag) { - $form['tags']["{$tag->ifd}_{$tag->tag}"]['type'] = array( - '#type' => 'markup', - '#value' => PelIfd::getTypeName($tag->ifd), - ); - $form['tags']["{$tag->ifd}_{$tag->tag}"]['ifd'] = array( - '#type' => 'hidden', - '#value' => $tag->ifd, - ); - $form['tags']["{$tag->ifd}_{$tag->tag}"]['tag'] = array( - '#type' => 'hidden', - '#value' => $tag->tag, - ); - $form['tags']["{$tag->ifd}_{$tag->tag}"]['status'] = array( - '#type' => 'checkbox', - '#title' => utf8_encode(PelTag::getTitle($tag->ifd, $tag->tag)), - '#default_value' => $tag->status, - ); - $form['tags']["{$tag->ifd}_{$tag->tag}"]['weight'] = array( - '#type' => 'weight', - '#delta' => 10, - '#default_value' => $tag->weight, - ); - $form['tags']["{$tag->ifd}_{$tag->tag}"]['#tree'] = TRUE; - $form['tags']["{$tag->ifd}_{$tag->tag}"]['#weight'] = $tag->weight; - } - $form['buttons']['submit'] = array( - '#type' => 'submit', - '#value' => t('Save configuration') - ); - $form['buttons']['reset'] = array( - '#type' => 'submit', - '#value' => t('Reset to defaults') - ); - - return $form; +function exif_date_format_types() { + return array('exif' => 'EXIF'); } -function exif_admin_settings_form_submit($form_id, $values) { - $op = isset($_POST['op']) ? $_POST['op'] : ''; +/** + * 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', + ), + ); +} - if ($op == t('Reset to defaults')) { - exif_reset_settings(); - drupal_set_message(t('The configuration options have been reset to their default values.')); +/** + * 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); } - elseif ($op == t('Save configuration')) { - exif_save_settings($values); - drupal_set_message(t('The configuration options have been saved.')); + + 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, + ); } /** - * Fetch exif data. + * Let's check if this node type contains an image field. + * + * @param $fields fields from this content type + * @return boolean */ -function _exif_get_exif($fid) { - $data = array(); - if ($result = db_query('SELECT * FROM {exif} WHERE fid = %d', $fid)) { - while ($row = db_fetch_object($result)) { - $data[$row->ifd][$row->tag] = $row->value; +function _exif_check_for_exif_data($node_type) { + + $new_types = array(); + //fill up array with checked nodetypes + foreach (variable_get('exif_nodetypes', array()) as $type) { + if ($type != "0" ) { + $new_types[] = $type; } } - - return $data; + if (in_array($node_type, $new_types)) { + return TRUE; + } + return FALSE; } /** - * Reads exif data from a file. + * From a given node we are going to get the imagepath of the image. if it's an image node + * it's just going to be images[IMAGE_ORIGINAL]. If it's an imagefield node, we have to go + * through the fields and look if there is an imagefield and then return the path + * + * @param $fields + * @param $node + * @return unknown_type */ -function _exif_read_exif($file) { - _exif_bootstrap(); - $data = array(); - if (!file_exists($file)) { - watchdog('exif', t('Image %file not found.', array('%file' => $file)), WATCHDOG_WARNING); - return $exif; - } - if (exif_imagetype($file) != IMAGETYPE_JPEG) { - return $data; +function _exif_get_image_path($fields, &$node) { + if ($node->type == 'image') { + return $node->images[IMAGE_ORIGINAL]; } - $jpeg = new PelJpeg($file); - $exif = $jpeg->getExif(); - if (!$exif) { - return $data; - } - $tiff = $exif->getTiff(); - if (!$tiff) { - return $data; - } - $ifd0 = $tiff->getIfd(); - if (!$ifd0) { - return $data; - } - $ifds[PelIfd::IFD0] = $ifd0; - if ($exif = $ifd0->getSubIfd(PelIfd::EXIF)) { - $ifds[PelIfd::EXIF] = $exif; - } - if ($gps = $ifd0->getSubIfd(PelIfd::GPS)) { - $ifds[PelIfd::GPS] = $gps; - } - $tags = exif_get_enabled_tags(); - $data = array(); - foreach ($tags as $tag) { - $entry = $ifds[$tag->ifd]->getEntry($tag->tag); - if ($entry) { - $row = array(); - switch($tag->tag) { - case PelTag::DATE_TIME: - case PelTag::DATE_TIME_ORIGINAL: - case PelTag::DATE_TIME_DIGITIZED: - // Return a unixtimestamp. Theme will handle date formating. - $data[$tag->ifd][$tag->tag] = $entry->getValue(); - break; - - default: - $data[$tag->ifd][$tag->tag] = utf8_encode($entry->getText()); - } + + foreach ($fields as $field) { + if ($field['type'] == 'filefield') { + $tmp = $node->$field['field_name']; + return $tmp[0]['filepath']; } } - return $data; + return NULL; } + /** - * Return an array containing only the tags that were enabled. + * Helper function to reformat fields where required. + * + * Some values (lat/lon) break down into structures, not strings. */ -function exif_get_enabled_tags() { - static $tags = array(); +function _exif_reformat($data) { + $date_array = array('datetimeoriginal', 'datetime', 'datetimedigitized'); + + // Make the key lowercase as CCK field names must be + $data = array_change_key_case($data, CASE_LOWER); - if (!count($tags)) { - $result = db_query('SELECT * FROM {exif_tags} WHERE status = 1'); - while ($tag = db_fetch_object($result)) { - $tags[] = $tag; + foreach ($data as $key => &$value) { + if (is_array($value)) { + $value = array_change_key_case($value, CASE_LOWER); } - if (!count($tags)) { - // Table is empty, get some defaults - $tags = exif_get_default_settings(); - foreach ($tags as $key => $tag) { - if (!$tag->status) { - unset($tags[$key]); - } - } + + // Check for individual keys + switch ($key) { + case 'gpslatitude': + $value = _exif_DMS2D($value, $data['gpslatituderef']); + break; + + case 'gpslongitude': + $value = _exif_DMS2D($value, $data['gpslongituderef']); + break; + + case 'gps_gpslatitude': + $value = _exif_DMS2D($value, $data['gps_gpslatituderef']); + break; + + case 'gps_gpslongitude': + $value = _exif_DMS2D($value, $data['gps_gpslongituderef']); + break; + } - usort($tags, '_exif_compare_tags'); } - - return $tags; + return $data; } /** - * Return an array with all the valid tags and their settings. + * Helper function to change GPS co-ords into decimals. */ -function exif_load_settings() { - $tags = exif_get_default_settings(); +function _exif_DMS2D($value, $ref) { + $parts = split('/', $value[0]); + $dec = (float) ((float) $parts[0] / (float) $parts[1]); - $result = db_query('SELECT * FROM {exif_tags}'); - while ($tag = db_fetch_object($result)) { - $tags["{$tag->ifd}_{$tag->tag}"] = $tag; - } - usort($tags, '_exif_compare_tags'); + $parts = split('/', $value[1]); + $dec += (float) (((float) $parts[0] / (float) $parts[1]) / 60); - return $tags; -} + $parts = split('/', $value[2]); + $dec += (float) (((float) $parts[0] / (float) $parts[1]) / 3600); -function exif_save_settings($values) { - db_lock_table('exif_tags'); - foreach ($values as $tag) { - if (!is_array($tag) || !isset($tag['ifd'])) { - continue; // Save only appropriate form values - } - db_query('DELETE FROM {exif_tags} WHERE ifd = %d AND tag = %d', $tag['ifd'], $tag['tag']); - db_query('INSERT INTO {exif_tags} (ifd, tag, status, weight) VALUES (%d, %d, %d, %d)', $tag['ifd'], $tag['tag'], $tag['status'], $tag['weight']); - } - db_unlock_tables(); -} - -function exif_reset_settings() { - db_query('DELETE FROM {exif_tags}'); + if ($ref == 'S' || $ref == 'W') $dec *= -1; + return $dec; } /** - * Return an array with all the valid tags, with some useful default settings. + * Helper function to get the exif class + * @return Exif */ -function exif_get_default_settings() { - $tags = exif_get_valid_tags(); - $tags[PelIfd::EXIF .'_'. PelTag::DATE_TIME_ORIGINAL]->status = 1; - $tags[PelIfd::EXIF .'_'. PelTag::DATE_TIME_ORIGINAL]->weight = -10; - $tags[PelIfd::IFD0 .'_'. PelTag::MODEL]->status = 1; - $tags[PelIfd::IFD0 .'_'. PelTag::MODEL]->weight = -8; - $tags[PelIfd::EXIF .'_'. PelTag::FOCAL_LENGTH]->status = 1; - $tags[PelIfd::EXIF .'_'. PelTag::FOCAL_LENGTH]->weight = -6; - $tags[PelIfd::EXIF .'_'. PelTag::APERTURE_VALUE]->status = 1; - $tags[PelIfd::EXIF .'_'. PelTag::APERTURE_VALUE]->weight = -4; - $tags[PelIfd::EXIF .'_'. PelTag::EXPOSURE_TIME]->status = 1; - $tags[PelIfd::EXIF .'_'. PelTag::EXPOSURE_TIME]->weight = -2; - $tags[PelIfd::EXIF .'_'. PelTag::ISO_SPEED_RATINGS]->status = 1; - $tags[PelIfd::EXIF .'_'. PelTag::ISO_SPEED_RATINGS]->weight = 0; - return $tags; +function _exif_get_class() { + include_once drupal_get_path('module', 'exif') .'/exif.class.php'; + $exif = Exif::getInstance(); + return $exif; } /** - * Helper function to return all the valid tags (well, at least those this module cares about). - * - * For convenience, each tag has a key in the form: "ifd_tag", where ifd and tag - * are standard Exif ids. Those ids can be found in PelIfd.php and PelTag.php. + * Implementation of hook_hoken_list + * @param array $type */ -function exif_get_valid_tags() { - $valid_tags = array(); - $valid_tags = array_merge($valid_tags, _exif_get_valid_ifd_tags(PelIfd::IFD0, new PelIfd(PelIfd::IFD0))); - $valid_tags = array_merge($valid_tags, _exif_get_valid_ifd_tags(PelIfd::EXIF, new PelIfd(PelIfd::EXIF))); - $valid_tags = array_merge($valid_tags, _exif_get_valid_ifd_tags(PelIfd::GPS, new PelIfd(PelIfd::GPS))); - return $valid_tags; -} - -function _exif_get_valid_ifd_tags($ifd_id, $ifd) { - $tags = array(); - $pel_tags = $ifd->getValidTags(); - foreach ($pel_tags as $pel_tag) { - $tag = new StdClass(); - $tag->ifd = $ifd_id; - $tag->tag = $pel_tag; - $tags["{$tag->ifd}_{$tag->tag}"] = $tag; - } - return $tags; -} - -function _exif_compare_tags($a, $b) { - $status = $b->status - $a->status; - // Separate enabled from disabled. - if ($status) { - return $status; - } - // Enabled tags - if ($a->status) { - $weight = $a->weight - $b->weight; - if ($weight) { - return $weight; +function fast_gallery_token_list($type = 'node') { + if ($type == 'node') { + $exif = _exif_get_class(); + $ar_iptc = $exif->getHumanReadableIPTCkey(); + foreach ($ar_iptc as $iptc) { + $tokens['iptc']['iptc_' . $iptc] = 'IPTC Field: ' . $iptc; } - return $a->ifd - $b->ifd; - } - // Disabled tags - else { - return $a->ifd - $b->ifd; + return $tokens; } } -function theme_exif_table($node) { - _exif_bootstrap(); - // Retrieve the desired tag values from the file - $tags = exif_get_enabled_tags(); - $rows = array(); - $data = $node->exif_data; - - foreach ($tags as $tag) { - if (!empty($data[$tag->ifd][$tag->tag])) { - $row = array(); - $row[] = array('data' => check_plain(utf8_encode(PelTag::getTitle($tag->ifd, $tag->tag))), 'class' => 'exif-title'); - $val = $data[$tag->ifd][$tag->tag]; - switch($tag->tag) { - case PelTag::DATE_TIME: - case PelTag::DATE_TIME_ORIGINAL: - case PelTag::DATE_TIME_DIGITIZED: - // Use Drupal's date formatting instead of Pel's - $row[] = array('data' => format_date($val, 'medium', '', 0), 'class' => 'exif-value'); - break; - - default: - $row[] = array('data' => check_plain($val), 'class' => 'exif-value'); - } - $rows[] = $row; +/** + * implementation of hook_token_values + * @param unknown_type $type + * @param unknown_type $object + * @param unknown_type $options + */ +function fast_gallery_token_values($type, $object = NULL, $options = array()) { + if ($type == 'node') { + $node = $object; + $exif = _exif_get_class(); + $ar_iptc = $exif->getHumanReadableIPTCkey(); + + $info = content_types($node->type); + $fields = $info['fields']; + //get the path to the image + $image_path = _exif_get_image_path($fields, $node); + + //dsm("start reading"); + $iptc_values = $exif->readIPTCTags($image_path, array(), array('style' => 'fullSmall')); + //dsm($iptc_values); + + // TODO: needs to be finished + foreach ($iptc_values as $key => $iptc) { + $tokens['iptc_' . $key] = 'IPTC Field: ' . utf8_encode($iptc); } + //dsm($tokens); + return $tokens; } - - if (empty($rows)) { - return ''; - } - $header = array(array('data' => t('Image information'), 'colspan' => 2)); - return theme('table', $header, $rows, array('class' => 'exif')); -} - -function theme_exif_admin_settings_form($form) { - $header = array(t('Tag'), t('Weight'), t('Type')); - $rows = array(); - foreach (element_children($form['tags']) as $key) { - $row = array(); - $row[] = drupal_render($form['tags'][$key]['status']); - $row[] = drupal_render($form['tags'][$key]['weight']); - $row[] = drupal_render($form['tags'][$key]['type']); - $rows[] = $row; - } - $output .= theme('table', $header, $rows, array('class' => 'admin-settings-exif')); - $output .= drupal_render($form); - return $output; -} - -function _exif_bootstrap() { - include_once drupal_get_path('module', 'exif') .'/pel/PelJpeg.php'; -} - +} \ No newline at end of file -- cgit v1.2.3