Created
June 23, 2022 17:06
-
-
Save richaber/644cb365cb4a39591eb48d486a7dfacb to your computer and use it in GitHub Desktop.
WP-CLI Sideload media command class, should work for images that don't have a file extension via Symfony\Component\Mime\MimeTypes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* SideLoad command class file. | |
* | |
* @package VendorName\ProjectName\Commands | |
*/ | |
namespace VendorName\ProjectName\Commands; | |
use Symfony\Component\Mime\MimeTypes; | |
use Throwable; | |
use WP_CLI; | |
/** | |
* SideLoad command class. | |
*/ | |
class SideLoad { | |
/** | |
* Sideload a file to the media library from a URL. | |
* | |
* ## OPTIONS | |
* | |
* <url> | |
* : URL of the file to sideload. | |
* | |
* ## EXAMPLES | |
* | |
* wp sideload https://www.example.com/api/file/4j7bSv74Q1SvckZ5Xzqk | |
* | |
* @subcommand sideload | |
* @alias sideload-file | |
* | |
* @since 0.1.0-dev | |
* | |
* @param mixed[] $args Positional arguments. | |
* @param mixed[] $assoc_args Associative arguments. | |
* | |
* @return void | |
*/ | |
public function sideload( array $args, array $assoc_args ): void { | |
list( $url ) = $args; | |
$temp_dir = get_temp_dir(); | |
/** | |
* Downloads a URL to a local temporary file using the WordPress HTTP API. | |
* | |
* Example: $tmpfname = '/var/folders/t4/7dv85j4j0mq9v2t1bzvz9ptr0000gs/T/4j7bSv74Q1SvckZ5Xzqk-IYnY3P.tmp' | |
* | |
* @var string|WP_Error $tmpfname Filename on success, WP_Error on failure. | |
*/ | |
$tmpfname = download_url( $url ); | |
if ( is_wp_error( $tmpfname ) ) { | |
WP_CLI::error( $tmpfname ); | |
} | |
$mime_types = new MimeTypes(); | |
try { | |
/** | |
* Guesses the MIME type of the file with the given path. | |
* | |
* Example: $mime_type = 'image/png' | |
* | |
* @var ?string $mime_type The MIME type on success, else null. | |
*/ | |
$mime_type = $mime_types->guessMimeType( $tmpfname ); | |
} catch ( Throwable $exception ) { | |
unlink( $tmpfname ); | |
WP_CLI::error( | |
$exception | |
); | |
} | |
// @phpstan-ignore-next-line | |
if ( null === $mime_type ) { | |
unlink( $tmpfname ); | |
WP_CLI::error( | |
sprintf( | |
'Unable to determine file format for URL %1$s.', | |
$url | |
) | |
); | |
} | |
/** | |
* Get the extensions for the given MIME type in decreasing order of preference. | |
* | |
* Example: | |
* $extensions = [ | |
* 0 => 'png', | |
* ]; | |
* | |
* @var string[] $extensions An array of file extensions. | |
* @phpstan-ignore-next-line | |
*/ | |
$extensions = $mime_types->getExtensions( $mime_type ); | |
if ( empty( $extensions ) ) { | |
unlink( $tmpfname ); | |
WP_CLI::error( | |
sprintf( | |
'Unable to determine file format for URL %1$s.', | |
$url | |
) | |
); | |
} | |
$extension = $extensions[0]; | |
$extension = '.' . $extension; | |
$filename = basename( $url ); | |
if ( 0 !== substr_compare( $filename, $extension, - strlen( $extension ) ) ) { | |
$filename .= $extension; | |
} | |
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents | |
$bits = file_get_contents( $tmpfname ); | |
if ( false === $bits ) { | |
unlink( $tmpfname ); | |
WP_CLI::error( | |
sprintf( | |
'Unable to read file contents for URL %1$s.', | |
$url | |
) | |
); | |
} | |
/** | |
* Create a file in the upload folder with given content. | |
* | |
* @var array{'file': string, 'url': string, 'type': string, 'error': string|false} $upload Information about the newly-uploaded file. | |
*/ | |
$upload = wp_upload_bits( | |
$filename, | |
null, | |
$bits | |
); | |
unlink( $tmpfname ); | |
if ( ! empty( $upload['error'] ) ) { | |
WP_CLI::error( | |
sprintf( | |
'Unable to sideload image for URL %1$s. Error: %2$s.', | |
$url, | |
$upload['error'] | |
) | |
); | |
} | |
$filename = basename( $upload['file'] ); | |
/** | |
* Get the filetype information that WordPress thinks. | |
* | |
* @var array{'ext': string|false, 'type': string|false} $filetype Values for the extension and mime type. | |
*/ | |
$filetype = wp_check_filetype( $filename ); | |
$attachment = [ | |
'post_mime_type' => $filetype['type'], | |
'post_parent' => 0, | |
'post_title' => preg_replace( '/\.[^.]+$/', '', $filename ), | |
'post_content' => '', | |
'post_status' => 'inherit', | |
]; | |
$attachment_id = wp_insert_attachment( | |
$attachment, | |
$upload['file'], | |
0, | |
true | |
); | |
if ( is_wp_error( $attachment_id ) ) { | |
WP_CLI::error( | |
$attachment_id | |
); | |
} | |
require_once ABSPATH . 'wp-admin/includes/image.php'; | |
$attachment_data = wp_generate_attachment_metadata( | |
$attachment_id, | |
$upload['file'] | |
); | |
wp_update_attachment_metadata( $attachment_id, $attachment_data ); | |
WP_CLI::success( | |
sprintf( | |
'Imported URL %1$s as attachment ID %2$s.', | |
$url, | |
$attachment_id | |
) | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment