TRUE)); return $filepath; } } function _media_flickr_store_local($photo_code, $size) { static $count; // Obviously, only go forward if we have a photo_code. if ($photo_code) { // Get the URL to the original thumbnail. $thumbnail = media_flickr_photo_remote_url($photo_code, $size); // Go forward only if we have a URL to go by, and we haven't already // fetched our alloted remote images for this page load. if ($thumbnail && ((($max = variable_get('media_flickr_max_saves', 10)) && ($count < $max)) || !$max)) { // If we've attempted to save a thumbnail and failed, // let's not try again for awhile. if ($cached && $cache = cache_get('media_flickr:'. $photo_code .':'. $size, 'cache')) { return $cache->data; } // We should only attempt to save a few photos at a time, // to keep from initial slow page loads. $count++; // Attempt to fetch the thumbnail from the provided URL. $image = file_get_contents($thumbnail); // Only go forward if we actually have an image stream. if ($image) { // Add in our check of the the file name length. $validators['file_validate_name_length'] = array(); // Allow for transliteration, which will take unicode data and convert // it to US-ASCII for better file storage. if (module_exists('transliteration')) { // Transliterate our original URL. $thumbnail = transliteration_get($thumbnail); } // Our new filepath will be in the form of media-flickr-7351895427047-5.jpg. $basename = 'media-flickr-'. $photo_code .'-'. $size .'.'. pathinfo($thumbnail, PATHINFO_EXTENSION); // Get the base Drupal files path. $directory = file_directory_path(); $dir = variable_get('media_flickr_image_path', ''); if ($dir) { // Add the field's image path here. $directory .= '/'. $dir; } // Create a new filepath from our desired filename. $filepath = file_create_filename($basename, $directory); // Begin building file object. $file = new stdClass(); // The new file will be associated with the global user. global $user; $file->uid = $user->uid; // Strip out the query if provided. $file->filename = parse_url($basename, PHP_URL_PATH); $file->filepath = parse_url($filepath, PHP_URL_PATH); // If we have mimedetect, then do so. Otherwise we make a best guess // based on the filename. $file->filemime = module_exists('mimedetect') ? mimedetect_mime($file) : file_get_mimetype($file->filename); // Rename potentially executable files, to help prevent exploits. if (preg_match('/\.(php|pl|py|cgi|asp|js)$/i', $file->filename) && (substr($file->filename, -4) != '.txt')) { $file->filemime = 'text/plain'; $file->filepath .= '.txt'; $file->filename .= '.txt'; } $file->source = 'media_flickr_fetch_remote_thumbnail'; $file->destination = file_destination($file->filepath, $replace); $file->filesize = strlen($image); // Call the validation functions. $errors = array(); foreach ($validators as $function => $args) { array_unshift($args, $file); $errors = array_merge($errors, call_user_func_array($function, $args)); } // Check for validation errors. if (!empty($errors)) { $message = 'The remote Flickr image %name could not be saved.'; $arguments = array('%name' => $file->filename); if (count($errors) > 1) { $message .= ''; } else { $message .= ' '. array_pop($errors); } watchdog('media_flickr', $message, $arguments, WATCHDOG_ERROR); // Let's also cache it for awhile, as this can take a long time. cache_set('media_flickr:'. $photo_code .':'. $size, url($thumbnail), 'cache', time() + variable_get('emfield_cache_duration', 3600)); return $thumbnail; } if (!file_save_data($image, $file->filepath, FILE_EXISTS_RENAME)) { watchdog('file', 'Upload error. Could not move file %file to destination %destination.', array('%file' => $file->filename, '%destination' => $file->destination)); // Let's also cache it for awhile, as this can take a long time. cache_set('media_flickr:'. $photo_code .':'. $size, url($thumbnail), 'cache', time() + variable_get('emfield_cache_duration', 3600)); return $thumbnail; } // If we made it this far it's safe to record this file in the database. $file->status = FILE_STATUS_PERMANENT; $file->timestamp = time(); drupal_write_record('files', $file); $flickr = new stdClass(); $flickr->fid = $file->fid; $flickr->size = $size; $flickr->code = $photo_code; drupal_write_record('media_flickr_sizes', $flickr); // Let modules add additional properties to the yet barebone file object. // This uses the future hook_file from d7's API. Not sure if anything // actually uses this right now, but they might in the future. foreach (module_implements('file_insert') as $module) { $function = $module .'_file_insert'; $function($file); } return $file->filepath; } // Let's also cache it for awhile, as this can take a long time. cache_set('media_flickr:'. $photo_code .':'. $size, url($thumbnail), 'cache', time() + variable_get('emfield_cache_duration', 3600)); } // As a failsafe, let's return the remote URL. return $thumbnail; } } /** * Returns an array of all URLs for photos associated with a photoset, * associated by photo code. These will be of the Flickr specified size (1-5), * and may be local or remote, based on settings and availability. * * @param $photoset * The Flickr photoset id. * @param $size * Optional. A number from 1-5 (small to large). */ function _media_flickr_photoset_load_photos($photoset, $size = 5) { static $photosets; if (is_null($photosets)) { $photosets = array(); } $id = $photoset['photoset']['id']; // We cache our results in a static variable. if (is_null($photosets[$id])) { // Reset the array of photos. $photosets[$id] = array(); // If we're allowed to store images locally, then grab the latest list // of local URL's. if ($store_local = variable_get('media_flickr_store_local', FALSE)) { $results = db_query("SELECT z.code, f.filepath FROM {media_flickr_sets} s INNER JOIN {media_flickr_sizes} z ON z.code = s.code AND z.size = %d INNER JOIN {files} f ON f.fid = z.fid WHERE s.photoset = '%s'", $size, $photoset['photoset']['id']); while ($result = db_fetch_object($results)) { $photosets[$id][$result->code] = $result->filepath; } } // @TODO: remove 'dead' photos from photoset... // Ensure we have a URL for each photo in the photoset. // This can be local or remote. foreach ($photoset['photoset']['photo'] as $photo_code => $photo) { // If we don't have a URL yet, grab one. if (!isset($photosets[$id][$photo_code])) { // If we're allowed to store local photos, then attempt to do so now. if ($store_local) { // First ensure we have the photo associated with this photoset. if (!db_result(db_query("SELECT COUNT(*) FROM {media_flickr_sets} WHERE photoset = '%s' AND code = '%s'", $id, $photo_code))) { // The photo is newly associated to this photoset. Put it in place. $record = array( 'photoset' => $id, 'code' => $photo_code, ); drupal_write_record('media_flickr_sets', $record); // Now record the metadata associated with a photo. media_flickr_record_photo($photo_code); // Now we'll try to grab the URL manually, as it may have already // been stored locally through another photoset. If not, this will // attempt to fetch a photo and store it, or return the remote URL. $photosets[$id][$photo_code] = media_flickr_photo_url_from_size($photo_code, $size); } else { // We have the proper association; we just need this size photo. // Hopefully we'll grab a local photo. If not, we'll get the remote. $photosets[$id][$photo_code] = media_flickr_store_local($photo_code, $size); } } else { // Let's be happy with the remote URL. $photosets[$id][$photo_code] = media_flickr_photo_remote_url($photo_code, $size); } } } } return $photosets[$id]; }