Skip to content

Instantly share code, notes, and snippets.

@richaber
Created June 23, 2022 17:06
Show Gist options
  • Save richaber/644cb365cb4a39591eb48d486a7dfacb to your computer and use it in GitHub Desktop.
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
<?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