function flickr_photos_exif_read(&$photo) { $map = flickr_photos_media_map(); if ($map[$photo['media']] == 'video') { return not_okay("video does not contain EXIF data"); } $fname = "{$photo['id']}_{$photo['originalsecret']}_o.{$photo['originalformat']}"; $froot = $GLOBALS['cfg']['flickr_static_path'] . flickr_photos_id_to_path($photo['id']); $path = "{$froot}/{$fname}"; if (!preg_match("/\\.jpe?g\$/i", $path)) { return not_okay("not a JPEG photo"); } if (!file_exists($path)) { return not_okay("original photo not found"); } if (!filesize($path)) { return not_okay("original photo is empty"); } # TO DO: cache me? $exif = exif_read_data($path); if (!$exif) { return not_okay("failed to read EXIF data"); } # TO DO: expand EXIF tag values $to_simplejoin = array('SubjectLocation', 'GPSLatitude', 'GPSLongitude', 'GPSTimeStamp'); foreach ($to_simplejoin as $tag) { if (is_array($exif[$tag])) { $exif[$tag] = implode(",", $exif[$tag]); } } # TO DO: work out how/where individual EXIF tags get # "prettified" ... ksort($exif); return okay(array("rows" => $exif)); }
function flickr_photos_metadata_path(&$photo) { $root = $GLOBALS['cfg']['flickr_static_path']; $path = flickr_photos_id_to_path($photo['id']) . "/"; $fname = "{$photo['id']}_{$photo['originalsecret']}_i.json"; $meta = $root . $path . $fname; return $meta; }
function flickr_urls_photo_original(&$photo) { if ($GLOBALS['cfg']['enable_feature_storage_s3']) { loadlib('storage_s3'); return storage_s3_url_photo($photo, 'o'); } $secret = $photo['originalsecret']; $sz = "o"; $ext = $photo['originalformat']; $root = $GLOBALS['cfg']['flickr_static_url']; $path = flickr_photos_id_to_path($photo['id']); $fname = "{$photo['id']}_{$secret}_{$sz}.{$ext}"; return $root . $path . "/" . $fname; }
function flickr_photos_import_photo_files(&$photo, $more = array()) { if ($GLOBALS['cfg']['enable_feature_storage_s3']) { return flickr_photos_import_photo_files_s3($photo, $more); } $root = "http://farm{$photo['farm']}.static.flickr.com/{$photo['server']}/{$photo['id']}"; $small = "{$root}_{$photo['secret']}_z.jpg"; $ext = $photo["originalsecret"] ? $photo["originalformat"] : "jpg"; if ($photo['originalsecret']) { # This is probably really only necessary for # Cal's account (20111208/straup) $orig = $ext ? "{$root}_{$photo['originalsecret']}_o.{$ext}" : null; } else { $orig = "{$root}_{$photo['secret']}_b.{$ext}"; } if ($photo['media'] == 1) { # http://www.flickr.com/photos/straup/2378794972/play/site/3bfc8d2bb9/ # http://www.flickr.com/photos/straup/2378794972/play/orig/5771b28b4b/ $video = $photo['originalsecret'] ? "orig/{$photo['originalsecret']}" : "site/{$photo['secret']}"; $orig = "http://www.flickr.com/photos/{$nsid}/{$photo['id']}/play/{$video}"; } # $path = $GLOBALS['cfg']['flickr_static_path'] . flickr_photos_id_to_path($photo['id']); if (!file_exists($path)) { mkdir($path, 0755, true); } # $local_small = "{$path}/" . basename($small); $local_orig = "{$path}/" . basename($orig); $local_info = str_replace("_o.{$photo['originalformat']}", "_i.json", $local_orig); $local_comments = str_replace("_o.{$photo['originalformat']}", "_c.json", $local_orig); # god how I wished we had implemented a system to records and pass back # to the API *what* had actually changed when a photo was updated; for # now we'll just assume that the photo hasn't been rotated or replaced... # (2011115/straup) $req = array(); if ($more['force'] || !file_exists($local_small)) { $req[] = array($small, $local_small); } if ($more['force'] || !file_exists($local_orig)) { # see above if ($orig) { $req[] = array($orig, $local_orig); } } # for now, just always fetch meta files because who knows # whether anything has changed; note the "json:foo:path" # syntax which are hints to tell the code to handle http_multi # responses (below) whether to inspect the contents of the # data returned by the flickr API if (!isset($more['skip_meta'])) { # basic photo info # viewer id and not photo owner? $flickr_user = flickr_users_get_by_user_id($photo['user_id']); $method = 'flickr.photos.getInfo'; $args = array('auth_token' => $flickr_user['auth_token'], 'photo_id' => $photo['id']); list($url, $args) = flickr_api_call_build($method, $args); $api_call = $url . "?" . http_build_query($args); $req[] = array($api_call, "json:info:{$local_info}"); # fetch comments, which is to say check to see if there # are any new photos worth storing $fetch_comments = 1; if ($more['min_date']) { $method = 'flickr.photos.comments.getList'; $args = array('photo_id' => $photo['id'], 'min_comment_date' => $more['min_date']); $rsp = flickr_api_call($method, $args); if ($rsp['ok'] && !isset($rsp['rsp']['comments']['comment'])) { $fetch_comments = 0; } } if ($fetch_comments) { $method = 'flickr.photos.comments.getList'; $args = array('photo_id' => $photo['id']); list($url, $args) = flickr_api_call_build($method, $args); $api_call = $url . "?" . http_build_query($args); $req[] = array($api_call, "json:comments:{$local_comments}"); } } # now go! # fetch all the bits using http_multi() if ($count = count($req)) { _flickr_photos_import_fetch_multi($req); } }