WordPress Version: 6.2
/**
* Downloads an image from the specified URL, saves it as an attachment, and optionally attaches it to a post.
*
* @since 2.6.0
* @since 4.2.0 Introduced the `$return_type` parameter.
* @since 4.8.0 Introduced the 'id' option for the `$return_type` parameter.
* @since 5.3.0 The `$post_id` parameter was made optional.
* @since 5.4.0 The original URL of the attachment is stored in the `_source_url`
* post meta value.
* @since 5.8.0 Added 'webp' to the default list of allowed file extensions.
*
* @param string $file The URL of the image to download.
* @param int $post_id Optional. The post ID the media is to be associated with.
* @param string $desc Optional. Description of the image.
* @param string $return_type Optional. Accepts 'html' (image tag html) or 'src' (URL),
* or 'id' (attachment ID). Default 'html'.
* @return string|int|WP_Error Populated HTML img tag, attachment ID, or attachment source
* on success, WP_Error object otherwise.
*/
function media_sideload_image($file, $post_id = 0, $desc = null, $return_type = 'html')
{
if (!empty($file)) {
$allowed_extensions = array('jpg', 'jpeg', 'jpe', 'png', 'gif', 'webp');
/**
* Filters the list of allowed file extensions when sideloading an image from a URL.
*
* The default allowed extensions are:
*
* - `jpg`
* - `jpeg`
* - `jpe`
* - `png`
* - `gif`
* - `webp`
*
* @since 5.6.0
* @since 5.8.0 Added 'webp' to the default list of allowed file extensions.
*
* @param string[] $allowed_extensions Array of allowed file extensions.
* @param string $file The URL of the image to download.
*/
$allowed_extensions = apply_filters('image_sideload_extensions', $allowed_extensions, $file);
$allowed_extensions = array_map('preg_quote', $allowed_extensions);
// Set variables for storage, fix file filename for query strings.
preg_match('/[^\?]+\.(' . implode('|', $allowed_extensions) . ')\b/i', $file, $matches);
if (!$matches) {
return new WP_Error('image_sideload_failed', __('Invalid image URL.'));
}
$file_array = array();
$file_array['name'] = wp_basename($matches[0]);
// Download file to temp location.
$file_array['tmp_name'] = download_url($file);
// If error storing temporarily, return the error.
if (is_wp_error($file_array['tmp_name'])) {
return $file_array['tmp_name'];
}
// Do the validation and storage stuff.
$id = media_handle_sideload($file_array, $post_id, $desc);
// If error storing permanently, unlink.
if (is_wp_error($id)) {
@unlink($file_array['tmp_name']);
return $id;
}
// Store the original attachment source in meta.
add_post_meta($id, '_source_url', $file);
// If attachment ID was requested, return it.
if ('id' === $return_type) {
return $id;
}
$src = wp_get_attachment_url($id);
}
// Finally, check to make sure the file has been saved, then return the HTML.
if (!empty($src)) {
if ('src' === $return_type) {
return $src;
}
$alt = isset($desc) ? esc_attr($desc) : '';
$html = "<img src='{$src}' alt='{$alt}' />";
return $html;
} else {
return new WP_Error('image_sideload_failed');
}
}