/** * Download an image from the specified URL and attach it to a post. * * Modified version of core function media_sideload_image() in /wp-admin/includes/media.php * (which returns an html img tag instead of attachment ID). * Additional functionality: ability override actual filename, * and to pass $post_data to override values in wp_insert_attachment (original only allowed $desc). * * Uses image cache to avoid re-downloading images. Keeps cache intact by * creating a copy of the cache file, which will eventually be moved. * * Credits to somatic * http://wordpress.stackexchange.com/questions/30284/media-sideload-image-file-name/44115#44115 * * @since 2.7.4 * * @param string $url (required) The URL of the image to download * @param int $post_id (required) The post ID the media is to be associated with * @param bool $thumb (optional) Whether to make this attachment the Featured Image for the post (post_thumbnail) * @param string $filename (optional) Replacement filename for the URL filename (do not include extension) * @param array $post_data (optional) Array of key => values for wp_posts table (ex: 'post_title' => 'foobar', 'post_status' => 'draft') * @return int|object The ID of the attachment or a WP_Error on failure */ function wprss_ftp_media_sideload_image( $url = null, $post_id = null, $thumb = null, $filename = null, $post_data = array() ) { if ( !$url || !$post_id ) { return new WP_Error('missing', "Need a valid URL and post ID..."); } // Get the local image file $cache = WPRSS_FTP_Images::get_instance()->get_cache(); try { $img = $cache->get_images( $url ); /* @var $img WPRSS_Image_Cache_Image */ } catch ( Exception $e ) { return new WP_Error( 'could_not_load_image', $e->getMessage(), $url ); } wprss_log_obj('Image from cache', $img->get_url() . ' -> ' . $img->get_local_path(), __METHOD__, WPRSS_LOG_LEVEL_SYSTEM); // Get the path $tmp = $img->get_local_path(); copy( $tmp, $tmp = wp_tempnam() ); // media_handle_sideload() will move the file, but we need the cache to remain wprss_log( "Copied cached image to $tmp", NULL, WPRSS_LOG_LEVEL_SYSTEM ); $url_filename = $img->get_unique_name(); wprss_log( "Unique name $url_filename"); // override filename if given, reconstruct server path if ( !empty( $filename ) ) { $filename = sanitize_file_name($filename); // extract path parts $tmppath = pathinfo( $tmp ); // build new path $new = $tmppath['dirname'] . "/". $filename . "." . $tmppath['extension']; // renames temp file on server rename($tmp, $new); // push new filename (in path) to be used in file array later $tmp = $new; } // determine file type (ext and mime/type) $url_type = wp_check_filetype($url_filename); // assemble file data (should be built like $_FILES since wp_handle_sideload() will be using) $file_array = array( ); // full server path to temp file $file_array['tmp_name'] = $tmp; if ( !empty( $filename ) ) { // user given filename for title, add original URL extension $file_array['name'] = $filename . "." . $url_type['ext']; } else { // just use original URL filename $file_array['name'] = $url_filename; } // set additional wp_posts columns if ( empty( $post_data['post_title'] ) ) { // just use the original filename (no extension) $post_data['post_title'] = basename($url_filename, "." . $url_type['ext']); } // make sure gets tied to parent if ( empty( $post_data['post_parent'] ) ) { $post_data['post_parent'] = $post_id; } // required libraries for media_handle_sideload require_once(ABSPATH . 'wp-admin/includes/file.php'); require_once(ABSPATH . 'wp-admin/includes/media.php'); require_once(ABSPATH . 'wp-admin/includes/image.php'); // NO FILENAME FIX // WordPress does not allow file images that are not in the form of a filename // ex: http://domain.com/thoufiqadsjucpqwuamoshfjnax8mtrh/iorqhewufjasj if ( apply_filters( 'wprss_ftp_override_upload_security', TRUE ) === TRUE ) { // If we successfully retrieved the MIME type if ( $url_type !== FALSE && isset( $url_type['type'] ) && !empty( $url_type['type'] ) ) { // Prepare the MIME and file type global $wprss_ftp_ext_override; global $wprss_ftp_type_override; $wprss_ftp_type_override = $url_type['type']; // Get MIME to extension mappings ( from WordPress wp_check_filetype_and_ext() function ) $mime_to_ext = apply_filters( 'getimagesize_mimes_to_exts', array( 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif', ) ); // Get the ext if ( isset( $mime_to_ext[$wprss_ftp_type_override] ) ) { $wprss_ftp_ext_override = $mime_to_ext[ $wprss_ftp_type_override ]; } else { $wprss_ftp_ext_override = 'png'; // Default to png (most common web image extension) } // Add a filter to ensure that the image ext and mime type get passed through add_filter( 'wp_check_filetype_and_ext', 'wprss_ftp_mime_override', 10, 4 ); } } // do the validation and storage stuff clearstatcache( false, $file_array['tmp_name'] ); // For some reason, deep down filesize() returned 0 for the temporary file without this $att_id = media_handle_sideload( $file_array, $post_id, '', $post_data ); // $post_data can override the items saved to wp_posts table, like post_mime_type, guid, post_parent, post_title, post_content, post_status // If error storing permanently, unlink if ( is_wp_error( $att_id ) ) { wprss_log( sprintf( 'Error downloading image "%1$s" for post #%2$s: ', $url, $post_id ) . $att_id->get_error_message() ); $img->delete(); @unlink( $tmp ); // Delete the cache copy needed for media_handle_sideload() return $att_id; // output wp_error } // set as post thumbnail if desired if ( $thumb ) WPRSS_FTP_Images::set_featured_image( $post_id, $att_id ); return $att_id; }