\n";
echo "\n";
// Find out if the auxiliary image table has anything in it.
$already_optimized = ewww_image_optimizer_aux_images_table_count();
if ( ! $already_optimized ) {
esc_html_e( 'Nothing has been optimized yet!', 'ewww-image-optimizer' );
echo "
\n";
return;
}
echo "" . sprintf( esc_html__( 'Current queue status: %s', 'ewww-image-optimizer' ), esc_html( $queue_status ) ) . "
\n";
if ( $queue_count ) {
/* translators: %d: number of images */
echo sprintf( esc_html__( 'There are %d images in the queue currently.', 'ewww-image-optimizer' ), (int) $queue_count ) . "
\n";
$nonce = wp_create_nonce( 'ewww_image_optimizer_clear_queue' );
echo "\n
";
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) ) {
/* translators: %s: 'cloud' or 'local', translated separately */
printf( esc_html__( 'Restore all your images from %s backups in case of image corruption or degraded quality.', 'ewww-image-optimizer' ), esc_html( $backup_mode ) );
if ( ! get_option( 'ewww_image_optimizer_bulk_restore_position' ) ) {
echo '
';
esc_html_e( '*As such things are quite rare, it is highly recommended to contact support first, as this may be due to a plugin conflict.', 'ewww-image-optimizer' );
}
} else {
esc_html_e( 'Backups are currently disabled in the Local settings.', 'ewww-image-optimizer' );
}
echo "
\n";
echo "
\n";
if ( get_option( 'ewww_image_optimizer_bulk_restore_position' ) ) {
?>
-
'>
\n";
echo "
";
echo "
";
echo "
";
echo '
';
echo "
\n
" .
esc_html__( 'When WordPress scales down large images, it keeps the original on disk for thumbnail generation. You may delete them to save disk space.', 'ewww-image-optimizer' ) . "
\n";
echo "
\n
\n";
echo "
";
echo "
";
echo '
';
echo "
\n
" .
esc_html__( 'If you have converted images (PNG to JPG and friends) without deleting the originals, you may remove them when ready.', 'ewww-image-optimizer' ) . "
\n" .
'' . esc_html__( 'Please perform a site backup before proceeding.', 'ewww-image-optimizer' ) . "
\n";
echo "
\n
\n";
echo "
";
echo "
";
echo '
';
echo "
\n
" .
esc_html__( 'You may remove all the WebP images from your site if you no longer need them. For example, sites that use Easy IO do not need local WebP images.', 'ewww-image-optimizer' ) . "
\n";
echo "
\n";
if ( get_option( 'ewww_image_optimizer_webp_clean_position' ) ) {
?>
-
'>
\n";
echo "
";
echo "
";
$as3cf_remove = false;
if ( class_exists( 'Amazon_S3_And_CloudFront' ) ) {
global $as3cf;
if ( $as3cf->get_setting( 'serve-from-s3' ) && $as3cf->get_setting( 'remove-local-file' ) ) {
$as3cf_remove = true;
}
}
if ( ! ewww_image_optimizer_s3_uploads_enabled() && ! function_exists( 'ud_get_stateless_media' ) && ! $as3cf_remove ) {
echo '
';
echo "
\n
" .
esc_html__( 'Older sites may have duplicate records or references to deleted files. Use the cleanup tool to remove such records.', 'ewww-image-optimizer' ) . '
' .
'' . esc_html__( 'If you offload your media to external storage like Amazon S3, and remove the local files, do not run this tool.', 'ewww-image-optimizer' ) . "
\n";
echo "
\n
\n";
echo "
";
echo "
";
}
global $wpdb;
echo '
';
echo "
\n
" .
/* translators: 1: postmeta table name 2: ewwwio_images table name */
esc_html( sprintf( __( 'Sites using EWWW IO for 3+ years may have optimization data that still needs to be migrated between the %1$s and %2$s tables.', 'ewww-image-optimizer' ), $wpdb->postmeta, $wpdb->ewwwio_images ) ) . "
\n";
echo "
\n
\n";
echo "
";
echo "
";
echo '
';
echo "
" . esc_html__( 'Some plugins have bugs that cause them to re-create thumbnails and trigger re-optimization when the images are modified. Turn on the Debugging option to record trace logs for further investigation.', 'ewww-image-optimizer' ) . "
\n";
echo "
\n";
echo "
\n";
}
/**
* Outputs the navigation controls for the optimized images table.
*/
function ewwwio_table_nav_controls() {
echo "
\n" .
'
' . "\n" .
'
' . "\n" .
'' . "\n" .
'' . "\n" .
'
' . "\n" .
'
' . "\n";
}
/**
* Prepares the javascript functions for the tools page.
*
* @param string $hook The Hook suffix of the calling page.
*/
function ewww_image_optimizer_tool_script( $hook ) {
ewwwio_debug_message( '
' . __FUNCTION__ . '()' );
// Make sure we are being called from the bulk optimization page.
if ( 'tools_page_ewww-image-optimizer-tools' !== $hook ) {
return;
}
add_filter( 'admin_footer_text', 'ewww_image_optimizer_footer_review_text' );
wp_enqueue_script( 'ewww-tool-script', plugins_url( '/includes/eio-tools.js', __FILE__ ), array( 'jquery', 'jquery-ui-progressbar' ), EWWW_IMAGE_OPTIMIZER_VERSION, true );
// Number of images in the ewwwio_table (previously optimized images).
$image_count = ewww_image_optimizer_aux_images_table_count();
// Submit a couple variables for our javascript to work with.
$loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
$erase_warning = esc_html__( 'Warning: this cannot be undone and will cause a bulk optimize to re-optimize all images.', 'ewww-image-optimizer' );
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
$erase_warning = esc_html__( 'Warning: this cannot be undone. Re-optimizing images will use additional API credits.', 'ewww-image-optimizer' );
}
global $wpdb;
$attachment_count = (int) $wpdb->get_var( "SELECT count(ID) FROM $wpdb->posts WHERE (post_type = 'attachment' OR post_type = 'ims_image') AND (post_mime_type LIKE '%%image%%' OR post_mime_type LIKE '%%pdf%%') ORDER BY ID DESC" );
$restore_position = (int) get_option( 'ewww_image_optimizer_bulk_restore_position' );
$restorable_images = (int) $wpdb->get_var( $wpdb->prepare( "SELECT count(id) FROM $wpdb->ewwwio_images WHERE id > %d AND pending = 0 AND image_size > 0 AND updates > 0", $restore_position ) );
$webp_clean_resume = get_option( 'ewww_image_optimizer_webp_clean_position' );
$webp_position = is_array( $webp_clean_resume ) && ! empty( $webp_clean_resume['stage2'] ) ? (int) $webp_clean_resume['stage2'] : 0;
$webp_cleanable = (int) $wpdb->get_var( $wpdb->prepare( "SELECT count(id) FROM $wpdb->ewwwio_images WHERE id > %d AND pending = 0 AND image_size > 0 AND updates > 0", $webp_position ) );
wp_localize_script(
'ewww-tool-script',
'ewww_vars',
array(
'_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-tools' ),
'image_count' => $image_count,
'attachment_count' => $attachment_count,
/* translators: %d: number of attachments from Media Library */
'attachment_string' => sprintf( esc_html__( '%d attachments', 'ewww-image-optimizer' ), $attachment_count ),
/* translators: %d: number of images */
'count_string' => sprintf( esc_html__( '%d total images', 'ewww-image-optimizer' ), $image_count ),
'remove_failed' => esc_html__( 'Could not remove image from table.', 'ewww-image-optimizer' ),
'invalid_response' => esc_html__( 'Received an invalid response from your website, please check for errors in the Developer Tools console of your browser.', 'ewww-image-optimizer' ),
'original_restored' => esc_html__( 'Original Restored', 'ewww-image-optimizer' ),
'restoring' => '
' . esc_html__( 'Restoring', 'ewww-image-optimizer' ) . " 
",
'finished' => '
' . esc_html__( 'Finished', 'ewww-image-optimizer' ) . '
',
'stage1' => esc_html__( 'Stage 1:', 'ewww-image-optimizer' ),
'stage2' => esc_html__( 'Stage 2:', 'ewww-image-optimizer' ),
/* translators: used for Table Cleanup progress bar, like so: batch 32/346 */
'batch' => esc_html__( 'batch', 'ewww-image-optimizer' ),
'erase_warning' => $erase_warning,
'tool_warning' => esc_html__( 'Please be sure to backup your site before proceeding. Do you wish to continue?', 'ewww-image-optimizer' ),
'too_far' => esc_html__( 'More images have been processed than expected. Unless you have added new images, you should refresh the page to stop the process and contact support.', 'ewww-image-optimizer' ),
'restorable_images' => $restorable_images,
'webp_cleanable' => $webp_cleanable,
)
);
// Load the stylesheet for the jquery progressbar.
wp_enqueue_style( 'jquery-ui-progressbar', plugins_url( '/includes/jquery-ui-1.10.1.custom.css', __FILE__ ) );
ewwwio_memory( __FUNCTION__ );
}
/**
* Presents the bulk optimize form.
*/
function ewww_image_optimizer_bulk_preview() {
ewwwio_debug_message( '
' . __FUNCTION__ . '()' );
ewwwio_debug_version_info();
// Retrieve the attachment IDs that were pre-loaded in the database.
echo '
' . esc_html__( 'Bulk Optimize', 'ewww-image-optimizer' ) . '
';
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_auto' ) ) {
echo '
';
esc_html_e( 'Please disable Scheduled optimization before continuing.', 'ewww-image-optimizer' );
echo '
';
return;
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
echo '
' . esc_html__( 'Image credits available:', 'ewww-image-optimizer' ) . ' ' . wp_kses_post( ewww_image_optimizer_cloud_quota() ) . '';
echo '';
}
if (
! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) &&
ewww_image_optimizer_easy_active()
) {
?>
';
if ( $fullsize_count < 1 ) {
echo '
' . esc_html__( 'You do not appear to have uploaded any images yet.', 'ewww-image-optimizer' ) . '
';
} else {
if ( 'true' === $resume ) {
echo '
' . esc_html__( 'Resume where you left off:', 'ewww-image-optimizer' ) . '
';
} else {
$resizes = ewww_image_optimizer_get_image_sizes();
if ( is_array( $resizes ) ) {
$resize_count = count( $resizes );
}
$resize_count = ( ! empty( $resize_count ) && $resize_count > 1 ? $resize_count : 6 );
if ( ! empty( $_REQUEST['ids'] ) && ( preg_match( '/^[\d,]+$/', sanitize_text_field( wp_unslash( $_REQUEST['ids'] ) ) ) || is_numeric( sanitize_text_field( wp_unslash( $_REQUEST['ids'] ) ) ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
echo '
' .
/* translators: 1: number of images 2: number of registered image sizes */
esc_html( sprintf( _n( '%1$s uploaded item in the Media Library has been selected with up to %2$d image files per upload.', '%1$s uploaded items in the Media Library have been selected with up to %2$d image files per upload.', $fullsize_count, 'ewww-image-optimizer' ), number_format_i18n( $fullsize_count ), $resize_count ) ) .
' ' . esc_html__( 'The total number of images found will be displayed before optimization begins.', 'ewww-image-optimizer' ) .
'
';
} else {
echo '
' .
/* translators: 1: number of images 2: number of registered image sizes */
esc_html( sprintf( _n( '%1$s uploaded item in the Media Library has been selected with up to %2$d image files per upload.', '%1$s uploaded items in the Media Library have been selected with up to %2$d image files per upload.', $fullsize_count, 'ewww-image-optimizer' ), number_format_i18n( $fullsize_count ), $resize_count ) ) .
' ' . esc_html__( 'The total number of images found will be displayed before optimization begins.', 'ewww-image-optimizer' ) .
'
' .
esc_html__( 'The active theme, BuddyPress, WP Symposium, and folders that you have configured will also be scanned for unoptimized images.', 'ewww-image-optimizer' ) .
'
';
}
}
ewww_image_optimizer_bulk_action_output( $button_text, $fullsize_count, $resume );
}
// If the 'bulk resume' option was not empty, offer to reset it so the user can start back from the beginning.
if ( 'true' === $resume ) {
ewww_image_optimizer_bulk_reset_form_output();
}
echo '
';
ewwwio_memory( __FUNCTION__ );
ewww_image_optimizer_aux_images();
}
/**
* Make sure folks know their images will be resized during bulk optimization.
*/
function ewww_image_optimizer_bulk_resize_warning_message() {
if (
ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) &&
( ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' ) )
) {
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_other_existing' ) ) {
printf(
/* translators: 1: width in pixels, 2: height in pixels */
esc_html__( 'All images will be scaled to %1$d x %2$d.', 'ewww-image-optimizer' ),
(int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ),
(int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' )
);
} else {
printf(
/* translators: 1: width in pixels, 2: height in pixels */
esc_html__( 'All images in the Media Library will be scaled to %1$d x %2$d.', 'ewww-image-optimizer' ),
(int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ),
(int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' )
);
}
}
}
/**
* Outputs the status area and delay/force controls for the Bulk optimize page.
*/
function ewww_image_optimizer_bulk_head_output() {
global $ewww_force;
$loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
$delay = ewww_image_optimizer_get_option( 'ewww_image_optimizer_delay' ) ? (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_delay' ) : 0;
?>
' . esc_html__( 'Restoring', 'ewww-image-optimizer' ) . " 
",
'bulk_fail_more' => '' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . " $file 
";
} else {
$output['results'] = '' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . " 
";
}
$output['start_time'] = time();
ewwwio_memory( __FUNCTION__ );
ewwwio_ob_clean();
die( wp_json_encode( $output ) );
}
/**
* Skips an un-optimizable image after all counter-measures have been attempted.
*
* @param object $image The EWWW_Image object representing the image to skip.
*/
function ewww_image_optimizer_bulk_skip_image( $image ) {
ewwwio_debug_message( '' . esc_html__( 'Could not find image', 'ewww-image-optimizer' ) . ' %s
', esc_html( $image->file ) );
}
}
}
$countermeasures = ewww_image_optimizer_bulk_counter_measures( $image );
if ( $countermeasures ) {
$batch_image_limit = 1;
}
set_transient( 'ewww_image_optimizer_bulk_current_image', $image->file, 600 );
global $ewww_image;
$ewww_image = $image;
if ( 'full' === $image->resize && ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) && ! function_exists( 'imsanity_get_max_width_height' ) ) {
if ( empty( $meta ) || ! is_array( $meta ) ) {
$meta = wp_get_attachment_metadata( $image->attachment_id );
}
$new_dimensions = ewww_image_optimizer_resize_upload( $image->file );
if ( ! empty( $new_dimensions ) && is_array( $new_dimensions ) ) {
$meta['width'] = $new_dimensions[0];
$meta['height'] = $new_dimensions[1];
}
} elseif ( empty( $image->resize ) && ewww_image_optimizer_should_resize_other_image( $image->file ) ) {
$new_dimensions = ewww_image_optimizer_resize_upload( $image->file );
}
list( $file, $msg, $converted, $original ) = ewww_image_optimizer( $image->file, 1, false, false, 'full' === $image->resize );
// Gotta make sure we don't delete a pending record if the license is exceeded, so the license check goes first.
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
if ( 'exceeded' === get_transient( 'ewww_image_optimizer_cloud_status' ) ) {
$output['error'] = '' . esc_html__( 'Optimized', 'ewww-image-optimizer' ) . ' %s
', esc_html( $image->file ) );
if ( ! empty( $ewwwio_resize_status ) ) {
$output['results'] .= esc_html( $ewwwio_resize_status ) . '
';
if ( defined( 'WP_CLI' ) && WP_CLI ) {
WP_CLI::line( $ewwwio_resize_status );
}
}
$output['results'] .= "$msg
";
// Do metadata update after full-size is processed, usually because of conversion or resizing.
if ( 'full' === $image->resize && $image->attachment_id ) {
if ( ! empty( $meta ) && is_array( $meta ) ) {
clearstatcache();
if ( ! empty( $image->file ) && is_file( $image->file ) ) {
$meta['filesize'] = filesize( $image->file );
}
$meta_saved = wp_update_attachment_metadata( $image->attachment_id, $meta );
if ( ! $meta_saved ) {
ewwwio_debug_message( 'failed to save meta' );
}
}
}
// Pull the next image.
$next_image = new EWWW_Image( $attachment, 'media' );
// When we finish all the sizes, we stop the loop so we can fire off any filters for plugins that might need to take action when an image is updated.
// The call to wp_get_attachment_metadata() will be done in a separate AJAX request for better reliability, giving it the full request time to complete.
if ( $attachment && (int) $attachment !== (int) $next_image->attachment_id ) {
if ( defined( 'WP_CLI' ) && WP_CLI ) {
ewwwio_debug_message( 'saving attachment meta' );
$meta = wp_get_attachment_metadata( $image->attachment_id );
if ( ewww_image_optimizer_s3_uploads_enabled() ) {
ewwwio_debug_message( 're-uploading to S3(_Uploads)' );
ewww_image_optimizer_remote_push( $meta, $image->attachment_id );
}
if ( class_exists( 'Windows_Azure_Helper' ) && function_exists( 'windows_azure_storage_wp_generate_attachment_metadata' ) ) {
$meta = windows_azure_storage_wp_generate_attachment_metadata( $meta, $image->attachment_id );
if ( Windows_Azure_Helper::delete_local_file() && function_exists( 'windows_azure_storage_delete_local_files' ) ) {
windows_azure_storage_delete_local_files( $meta, $image->attachment_id );
}
}
wp_update_attachment_metadata( $image->attachment_id, $meta );
do_action( 'ewww_image_optimizer_after_optimize_attachment', $image->attachment_id, $meta );
} else {
$batch_image_limit = 1;
$output['update_meta'] = (int) $attachment;
}
}
// When an image (attachment) is done, pull the next attachment ID off the stack.
if ( ( 'full' === $next_image->resize || empty( $next_image->resize ) ) && ! empty( $attachment ) && (int) $attachment !== (int) $next_image->attachment_id ) {
ewwwio_debug_message( 'grabbing next attachment id' );
ewww_image_optimizer_delete_queued_images( array( $attachment ) );
if ( 1 === count( $attachments ) && 1 === (int) $batch_image_limit ) {
$attachments = ewww_image_optimizer_get_queued_attachments( 'media', $batch_image_limit );
} else {
$attachment = (int) array_shift( $attachments ); // Pull the first image off the stack.
}
if ( ! empty( $attachments ) && is_array( $attachments ) ) {
$attachment = (int) $attachments[0]; // Then grab the next one (if any are left).
} else {
$attachment = 0;
}
ewwwio_debug_message( "next id is $attachment" );
$next_image = new EWWW_Image( $attachment, 'media' );
}
$image = $next_image;
$time_adjustment = $image->time_estimate();
} // End while().
ewwwio_debug_message( 'ending bulk loop for now' );
// Calculate how much time has elapsed since we started.
$elapsed = microtime( true ) - $started;
// Output how much time has elapsed since we started.
if ( defined( 'WP_CLI' ) && WP_CLI ) {
/* translators: %s: number of seconds */
WP_CLI::line( sprintf( _n( 'Elapsed: %s second', 'Elapsed: %s seconds', $elapsed, 'ewww-image-optimizer' ), number_format_i18n( $elapsed, 2 ) ) );
if ( ewww_image_optimizer_function_exists( 'sleep' ) ) {
sleep( $delay );
}
}
/* translators: %s: number of seconds */
$output['results'] .= sprintf( '' . esc_html( _n( 'Elapsed: %s second', 'Elapsed: %s seconds', $elapsed, 'ewww-image-optimizer' ) ) . '
', number_format_i18n( $elapsed, 1 ) );
// Store the updated list of attachment IDs back in the 'bulk_attachments' option.
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
global $eio_debug;
$debug_button = esc_html__( 'Show Debug Output', 'ewww-image-optimizer' );
$debug_id = uniqid();
$output['results'] .= "' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . " $next_file 
";
} else {
$output['next_file'] = '' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . " 
";
}
} else {
$output['done'] = 1;
if ( defined( 'WP_CLI' ) && WP_CLI ) {
delete_transient( 'ewww_image_optimizer_bulk_counter_measures' );
delete_transient( 'ewww_image_optimizer_bulk_current_image' );
return false;
}
}
ewww_image_optimizer_debug_log();
delete_transient( 'ewww_image_optimizer_bulk_counter_measures' );
delete_transient( 'ewww_image_optimizer_bulk_current_image' );
ewwwio_memory( __FUNCTION__ );
if ( defined( 'WP_CLI' ) && WP_CLI ) {
return true;
}
$output['current_time'] = time();
ewwwio_ob_clean();
die( wp_json_encode( $output ) );
}
/**
* Called via AJAX to trigger any actions by other plugins.
*/
function ewww_image_optimizer_bulk_update_meta() {
ewwwio_debug_message( '