/**
 * 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;
}