Skip to content

Instantly share code, notes, and snippets.

@erikyo
Last active October 26, 2022 23:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erikyo/ebd78f0d5d1735175e5ab9ad1d4d0590 to your computer and use it in GitHub Desktop.
Save erikyo/ebd78f0d5d1735175e5ab9ad1d4d0590 to your computer and use it in GitHub Desktop.
While uploading a media into WordPress media library this script automatically generate a webp copy of the uploaded media. Works with jpg, png and pdf previews, add the .webp extension after the original name
<?php
// README: you need GD installed
function myprefix_explode_filepath( $filepath, $attachment_id ) {
$uploads = wp_upload_dir();
if ( strpos( $filepath, "/" ) == false ) {
return array( $uploads['basedir'], "", $filepath );
} else {
list( $year, $month, $filename ) = explode( '/', $filepath );
return array( $uploads['basedir'], "$year/$month", $filename );
}
}
function myprefix_explode_filename( $filename ) {
$filename_parts = explode( '.', $filename );
$fext = $filename_parts[ count( $filename_parts ) - 1 ];
unset( $filename_parts[ count( $filename_parts ) - 1 ] );
$fname = implode( '.', $filename_parts );
return array( $fname, $fext );
}
function save_webp_copy( $metadata, $attachment_id ) {
// PHP GD is required
if ( ! extension_loaded( 'gd' ) ) return $metadata;
// if the attachment doesn't contain resizes it isn't an image or document with previews (like pdf)
if (empty($metadata['sizes'])) return $metadata;
list( $basedir, $path, $filename ) = myprefix_explode_filepath( $metadata['file'], $attachment_id );
list( $fname, $fext ) = myprefix_explode_filename( $filename );
if ( isset( $metadata['mime-type'] ) ) {
if ( $metadata['mime-type'] == 'pdf' ) {
$file_collection = array_column( $metadata['sizes'], 'file' );
} else {
return true;
}
} else {
$file_collection = array_merge( array( $fname . "." . $fext ), array_column( $metadata['sizes'], 'file' ) );
}
switch ( $fext ) {
case 'jpg':
foreach ( $file_collection as $value ) {
$image = imagecreatefromjpeg( $basedir . '/' . $path . '/' . $value );
imagewebp( $image, $basedir . '/' . $path . '/' . $value . '.webp', 95 );
imagedestroy( $image );
}
break;
case 'png':
foreach ( $file_collection as $value ) {
$image = imagecreatefrompng( $basedir . '/' . $path . '/' . $value );
imagepalettetotruecolor( $image );
imagealphablending( $image, true );
imagesavealpha( $image, true );
imagewebp( $image, $basedir . '/' . $path . '/' . $value . '.webp', 90 );
imagedestroy( $image );
}
break;
default:
return false;
}
return $metadata;
}
add_filter( 'wp_generate_attachment_metadata', 'save_webp_copy', 30, 2 );
function delete_webp_copy( $post_id ) {
// get the file path for the image being deleted
$metadata = wp_get_attachment_metadata( $post_id );
list( $basedir, $path, $filename ) = myprefix_explode_filepath( $metadata['file'], $post_id );
list( $fname, $fext ) = myprefix_explode_filename( $filename );
// create a fake metadata/size to add the main image to remove list
$metadata["sizes"]["full"]["file"] = $fname . "." . $fext;
// remove the webp copy from using the metadata sizes as iterator
foreach ( $metadata['sizes'] as $file ) {
if ( isset( $file['file'] ) && file_exists( $basedir . '/' . $path . '/' . $file['file'] . '.webp' ) ) {
wp_delete_file( $basedir . '/' . $path . '/' . $file['file'] . '.webp' );
}
}
return $post_id;
}
add_filter( 'delete_attachment', 'delete_webp_copy' );
@fredddie91
Copy link

Hello, I am not sure under which folder to upload this file? Thanks

@erikyo
Copy link
Author

erikyo commented Oct 26, 2022

You have to place it inside functions.php of your WordPress template. 😉

@fredddie91
Copy link

Ok, erikyo, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment