' . __FUNCTION__ . '()' );
return apply_filters( 'ewww_image_optimizer_filter_page_output', $buffer );
}
/**
* Skips optimization when a file is within EWWW IO's own folder.
*
* @param bool $skip Defaults to false.
* @param string $filename The name of the file about to be optimized.
* @return bool True if the file is within the EWWW IO folder, unaltered otherwise.
*/
function ewww_image_optimizer_ignore_self( $skip, $filename ) {
if ( 0 === strpos( $filename, EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH ) ) {
return true;
}
return $skip;
}
/**
* Gets the version number from a plugin file.
*
* @param string $plugin_file The path to the plugin's main file.
* @return array With a single index, 'Version'.
*/
function ewww_image_optimizer_get_plugin_version( $plugin_file ) {
$default_headers = array(
'Version' => 'Version',
);
$plugin_data = get_file_data( $plugin_file, $default_headers, 'plugin' );
return $plugin_data;
}
/**
* Checks to see if some other lazy loader is active.
*
* @return bool True if third-party lazy load detected, false otherwise.
*/
function ewwwio_other_lazy_detected() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( class_exists( 'RocketLazyLoadPlugin\Plugin' ) || defined( 'ROCKET_LL_VERSION' ) ) {
$rocketll_settings = get_option( 'rocket_lazyload_options' );
if ( is_array( $rocketll_settings ) && ! empty( $rocketll_settings['images'] ) ) {
ewwwio_debug_message( 'rocket lazy detected (standalone free plugin)' );
return true;
}
}
if ( class_exists( 'WP_Rocket\Plugin' ) || defined( 'WP_ROCKET_VERSION' ) ) {
$rocket_settings = get_option( 'wp_rocket_settings' );
if ( is_array( $rocket_settings ) && ! empty( $rocket_settings['lazyload'] ) ) {
ewwwio_debug_message( 'WP Rocket with lazy detected' );
return true;
}
}
if ( class_exists( 'autoptimizeExtra' ) || defined( 'AUTOPTIMIZE_PLUGIN_VERSION' ) ) {
$ao_extra = get_option( 'autoptimize_imgopt_settings' );
if ( ! empty( $ao_extra['autoptimize_imgopt_checkbox_field_3'] ) ) {
ewwwio_debug_message( 'Autoptimize lazy detected' );
return true;
}
}
if ( class_exists( 'SiteGround_Optimizer\Helper\Helper' ) && get_option( 'siteground_optimizer_lazyload_images' ) ) {
ewwwio_debug_message( 'SG Optimizer lazy detected' );
return true;
}
if ( class_exists( '\A3Rev\LazyLoad' ) || defined( 'A3_LAZY_VERSION' ) ) {
ewwwio_debug_message( 'A3 lazy detected' );
return true;
}
if ( class_exists( 'WpFastestCache' ) || defined( 'WPFC_WP_PLUGIN_DIR' ) ) {
if ( ! empty( $GLOBALS['wp_fastest_cache_options']->wpFastestCacheLazyLoad ) ) {
ewwwio_debug_message( 'WPFC lazy detected' );
return true;
}
}
if ( class_exists( '\W3TC\Dispatcher' ) || defined( 'W3TC_VERSION' ) ) {
if ( method_exists( '\W3TC\Dispatcher', 'config' ) ) {
$w3tc_config = \W3TC\Dispatcher::config();
if ( method_exists( $w3tc_config, 'get_boolean' ) && $w3tc_config->get_boolean( 'lazyload.enabled' ) ) {
ewwwio_debug_message( 'W3TC lazy detected' );
return true;
}
}
}
if ( class_exists( 'Jetpack' ) && method_exists( 'Jetpack', 'is_module_active' ) && Jetpack::is_module_active( 'lazy-images' ) ) {
ewwwio_debug_message( 'Jetpack lazy detected' );
return true;
}
if ( class_exists( '\Automattic\Jetpack_Boost\Jetpack_Boost' ) ) {
if ( \get_option( 'jetpack_boost_status_lazy-images' ) ) {
ewwwio_debug_message( 'Jetpack Boost lazy detected' );
return true;
}
}
return false;
}
/**
* Checks to see if the WebP option from the Cache Enabler plugin is enabled.
*
* @return bool True if the WebP option for CE is enabled.
*/
function ewww_image_optimizer_ce_webp_enabled() {
if ( class_exists( 'Cache_Enabler' ) ) {
$ce_options = get_option( 'cache_enabler', array() );
if ( ! empty( $ce_options['convert_image_urls_to_webp'] ) || ! empty( $ce_options['webp'] ) ) {
ewwwio_debug_message( 'Cache Enabler WebP option enabled' );
return true;
}
}
return false;
}
/**
* Checks to see if the WebP option from the SWIS Performance plugin is enabled.
*
* @return bool True if the WebP option for SWIS is enabled.
*/
function ewww_image_optimizer_swis_webp_enabled() {
if ( function_exists( 'swis' ) && class_exists( '\SWIS\Cache' ) ) {
$cache_settings = swis()->cache->get_settings();
if ( swis()->settings->get_option( 'cache' ) && ! empty( $cache_settings['webp'] ) ) {
ewwwio_debug_message( 'SWIS WebP option enabled' );
return true;
}
}
return false;
}
/**
* Checks to see if there is a method available for WebP conversion.
*
* @return bool True if a WebP Convertor is available.
*/
function ewww_image_optimizer_webp_available() {
return true; // Because API mode is the fallback and is free for everyone.
if (
! ewwwio()->local->exec_check() &&
! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) &&
! ewwwio()->imagick_supports_webp() &&
! ewwwio()->gd_supports_webp()
) {
return false;
}
return true;
}
/**
* Checks to see if the WebP rules from WPFC are enabled.
*
* @return bool True if the WebP rules from WPFC are found.
*/
function ewww_image_optimizer_wpfc_webp_enabled() {
if ( class_exists( 'WpFastestCache' ) ) {
$wpfc_abspath = get_home_path() . '.htaccess';
ewwwio_debug_message( "looking for WPFC rules in $wpfc_abspath" );
$wpfc_rules = ewwwio_extract_from_markers( $wpfc_abspath, 'WEBPWpFastestCache' );
if ( empty( $wpfc_rules ) ) {
$wpfc_abspath = ABSPATH . '.htaccess';
ewwwio_debug_message( "looking for WPFC rules in $wpfc_abspath" );
$wpfc_rules = ewwwio_extract_from_markers( $wpfc_abspath, 'WEBPWpFastestCache' );
}
if ( ! empty( $wpfc_rules ) ) {
ewwwio_debug_message( 'WPFC webp rules enabled' );
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
ewwwio_debug_message( 'removing htaccess webp to prevent ExactDN problems' );
insert_with_markers( $wpfc_abspath, 'WEBPWpFastestCache', '' );
return false;
}
return true;
}
}
return false;
}
/**
* Set default permissions for manual operations (single image optimize, convert, restore).
*
* @param string $permissions A valid WP capability level.
* @return string Either the original value, unchanged, or the default capability level.
*/
function ewww_image_optimizer_manual_permissions( $permissions ) {
if ( empty( $permissions ) ) {
return 'edit_others_posts';
}
return $permissions;
}
/**
* Set default permissions for admin (configuration) and bulk operations.
*
* @param string $permissions A valid WP capability level.
* @return string Either the original value, unchanged, or the default capability level.
*/
function ewww_image_optimizer_admin_permissions( $permissions ) {
if ( empty( $permissions ) ) {
return 'activate_plugins';
}
return $permissions;
}
/**
* Set default permissions for multisite/network admin (configuration) operations.
*
* @param string $permissions A valid WP capability level.
* @return string Either the original value, unchanged, or the default capability level.
*/
function ewww_image_optimizer_superadmin_permissions( $permissions ) {
if ( empty( $permissions ) ) {
return 'manage_network_options';
}
return $permissions;
}
if ( ! function_exists( 'wp_getimagesize' ) ) {
/**
* Stub for WP prior to 5.7.
*
* @param string $filename The file path.
* @return array|false Array of image information or false on failure.
*/
function wp_getimagesize( $filename ) {
// phpcs:ignore WordPress.PHP.NoSilencedErrors
return @getimagesize( $filename );
}
}
if ( ! function_exists( 'str_ends_with' ) ) {
/**
* Polyfill for `str_ends_with()` function added in WP 5.9 or PHP 8.0.
*
* Performs a case-sensitive check indicating if
* the haystack ends with needle.
*
* @since 6.8.1
*
* @param string $haystack The string to search in.
* @param string $needle The substring to search for in the `$haystack`.
* @return bool True if `$haystack` ends with `$needle`, otherwise false.
*/
function str_ends_with( $haystack, $needle ) {
if ( '' === $haystack && '' !== $needle ) {
return false;
}
$len = strlen( $needle );
return 0 === substr_compare( $haystack, $needle, -$len, $len );
}
}
/**
* Find out if set_time_limit() is allowed.
*/
function ewww_image_optimizer_stl_check() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( defined( 'EWWW_IMAGE_OPTIMIZER_DISABLE_STL' ) && EWWW_IMAGE_OPTIMIZER_DISABLE_STL ) {
ewwwio_debug_message( 'stl disabled by user' );
return false;
}
if ( function_exists( 'wp_is_ini_value_changeable' ) && ! wp_is_ini_value_changeable( 'max_execution_time' ) ) {
ewwwio_debug_message( 'max_execution_time not configurable' );
return false;
}
return ewwwio()->function_exists( '\set_time_limit' );
}
/**
* Save the multi-site settings, if this is the WP admin, and they've been POSTed.
*/
function ewww_image_optimizer_save_network_settings() {
if ( ! is_admin() ) {
return;
}
if ( ! function_exists( 'is_plugin_active_for_network' ) && is_multisite() ) {
// Need to include the plugin library for the is_plugin_active function.
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
ewwwio_debug_message( 'saving network settings' );
// Set the common network settings if they have been POSTed.
if (
! empty( $_REQUEST['_wpnonce'] ) &&
wp_verify_nonce( sanitize_key( $_REQUEST['_wpnonce'] ), 'ewww_image_optimizer_options-options' ) &&
isset( $_POST['option_page'] ) &&
false !== strpos( sanitize_text_field( wp_unslash( $_POST['option_page'] ) ), 'ewww_image_optimizer_options' ) &&
current_user_can( 'manage_network_options' ) &&
! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) &&
false === strpos( wp_get_referer(), 'options-general' )
) {
ewwwio_debug_message( 'network-wide settings, no override' );
$ewww_image_optimizer_debug = ( empty( $_POST['ewww_image_optimizer_debug'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_debug', $ewww_image_optimizer_debug );
$ewww_image_optimizer_metadata_remove = ( empty( $_POST['ewww_image_optimizer_metadata_remove'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_metadata_remove', $ewww_image_optimizer_metadata_remove );
$ewww_image_optimizer_jpg_level = empty( $_POST['ewww_image_optimizer_jpg_level'] ) ? '' : (int) $_POST['ewww_image_optimizer_jpg_level'];
update_site_option( 'ewww_image_optimizer_jpg_level', $ewww_image_optimizer_jpg_level );
$ewww_image_optimizer_png_level = empty( $_POST['ewww_image_optimizer_png_level'] ) ? '' : (int) $_POST['ewww_image_optimizer_png_level'];
update_site_option( 'ewww_image_optimizer_png_level', $ewww_image_optimizer_png_level );
$ewww_image_optimizer_gif_level = empty( $_POST['ewww_image_optimizer_gif_level'] ) ? '' : (int) $_POST['ewww_image_optimizer_gif_level'];
update_site_option( 'ewww_image_optimizer_gif_level', $ewww_image_optimizer_gif_level );
$ewww_image_optimizer_pdf_level = empty( $_POST['ewww_image_optimizer_pdf_level'] ) ? '' : (int) $_POST['ewww_image_optimizer_pdf_level'];
update_site_option( 'ewww_image_optimizer_pdf_level', $ewww_image_optimizer_pdf_level );
$ewww_image_optimizer_svg_level = empty( $_POST['ewww_image_optimizer_svg_level'] ) ? '' : (int) $_POST['ewww_image_optimizer_svg_level'];
update_site_option( 'ewww_image_optimizer_svg_level', $ewww_image_optimizer_svg_level );
$ewww_image_optimizer_delete_originals = ( empty( $_POST['ewww_image_optimizer_delete_originals'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_delete_originals', $ewww_image_optimizer_delete_originals );
$ewww_image_optimizer_jpg_to_png = ( empty( $_POST['ewww_image_optimizer_jpg_to_png'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_jpg_to_png', $ewww_image_optimizer_jpg_to_png );
$ewww_image_optimizer_png_to_jpg = ( empty( $_POST['ewww_image_optimizer_png_to_jpg'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_png_to_jpg', $ewww_image_optimizer_png_to_jpg );
$ewww_image_optimizer_gif_to_png = ( empty( $_POST['ewww_image_optimizer_gif_to_png'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_gif_to_png', $ewww_image_optimizer_gif_to_png );
$ewww_image_optimizer_webp = ( empty( $_POST['ewww_image_optimizer_webp'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_webp', $ewww_image_optimizer_webp );
$ewww_image_optimizer_jpg_background = empty( $_POST['ewww_image_optimizer_jpg_background'] ) ? '' : sanitize_text_field( wp_unslash( $_POST['ewww_image_optimizer_jpg_background'] ) );
update_site_option( 'ewww_image_optimizer_jpg_background', ewww_image_optimizer_jpg_background( $ewww_image_optimizer_jpg_background ) );
$ewww_image_optimizer_sharpen = empty( $_POST['ewww_image_optimizer_sharpen'] ) ? false : true;
update_site_option( 'ewww_image_optimizer_sharpen', $ewww_image_optimizer_sharpen );
$ewww_image_optimizer_jpg_quality = empty( $_POST['ewww_image_optimizer_jpg_quality'] ) ? '' : (int) $_POST['ewww_image_optimizer_jpg_quality'];
update_site_option( 'ewww_image_optimizer_jpg_quality', ewww_image_optimizer_jpg_quality( $ewww_image_optimizer_jpg_quality ) );
$ewww_image_optimizer_webp_quality = empty( $_POST['ewww_image_optimizer_webp_quality'] ) ? '' : (int) $_POST['ewww_image_optimizer_webp_quality'];
update_site_option( 'ewww_image_optimizer_webp_quality', ewww_image_optimizer_webp_quality( $ewww_image_optimizer_webp_quality ) );
$ewww_image_optimizer_avif_quality = empty( $_POST['ewww_image_optimizer_avif_quality'] ) ? '' : (int) $_POST['ewww_image_optimizer_avif_quality'];
update_site_option( 'ewww_image_optimizer_avif_quality', ewww_image_optimizer_avif_quality( $ewww_image_optimizer_avif_quality ) );
$ewww_image_optimizer_disable_convert_links = ( empty( $_POST['ewww_image_optimizer_disable_convert_links'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_disable_convert_links', $ewww_image_optimizer_disable_convert_links );
$ewww_image_optimizer_backup_files = ( empty( $_POST['ewww_image_optimizer_backup_files'] ) ? '' : sanitize_text_field( wp_unslash( $_POST['ewww_image_optimizer_backup_files'] ) ) );
update_site_option( 'ewww_image_optimizer_backup_files', $ewww_image_optimizer_backup_files );
$ewww_image_optimizer_auto = ( empty( $_POST['ewww_image_optimizer_auto'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_auto', $ewww_image_optimizer_auto );
$ewww_image_optimizer_aux_paths = empty( $_POST['ewww_image_optimizer_aux_paths'] ) ? '' : sanitize_textarea_field( wp_unslash( $_POST['ewww_image_optimizer_aux_paths'] ) );
update_site_option( 'ewww_image_optimizer_aux_paths', ewww_image_optimizer_aux_paths_sanitize( $ewww_image_optimizer_aux_paths ) );
$ewww_image_optimizer_exclude_paths = empty( $_POST['ewww_image_optimizer_exclude_paths'] ) ? '' : sanitize_textarea_field( wp_unslash( $_POST['ewww_image_optimizer_exclude_paths'] ) );
update_site_option( 'ewww_image_optimizer_exclude_paths', ewww_image_optimizer_exclude_paths_sanitize( $ewww_image_optimizer_exclude_paths ) );
$ewww_image_optimizer_enable_cloudinary = ( empty( $_POST['ewww_image_optimizer_enable_cloudinary'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_enable_cloudinary', $ewww_image_optimizer_enable_cloudinary );
$exactdn_all_the_things = ( empty( $_POST['exactdn_all_the_things'] ) ? false : true );
update_site_option( 'exactdn_all_the_things', $exactdn_all_the_things );
$exactdn_lossy = ( empty( $_POST['exactdn_lossy'] ) ? false : true );
update_site_option( 'exactdn_lossy', $exactdn_lossy );
$exactdn_exclude = empty( $_POST['exactdn_exclude'] ) ? '' : sanitize_textarea_field( wp_unslash( $_POST['exactdn_exclude'] ) );
update_site_option( 'exactdn_exclude', ewww_image_optimizer_exclude_paths_sanitize( $exactdn_exclude ) );
$ewww_image_optimizer_add_missing_dims = ( empty( $_POST['ewww_image_optimizer_add_missing_dims'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_add_missing_dims', $ewww_image_optimizer_add_missing_dims );
$ewww_image_optimizer_lazy_load = ( empty( $_POST['ewww_image_optimizer_lazy_load'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_lazy_load', $ewww_image_optimizer_lazy_load );
$ewww_image_optimizer_ll_autoscale = ( empty( $_POST['ewww_image_optimizer_ll_autoscale'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_ll_autoscale', $ewww_image_optimizer_ll_autoscale );
$ewww_image_optimizer_use_lqip = ( empty( $_POST['ewww_image_optimizer_use_lqip'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_use_lqip', $ewww_image_optimizer_use_lqip );
// Using sanitize_text_field instead of textarea on purpose.
$ewww_image_optimizer_ll_all_things = empty( $_POST['ewww_image_optimizer_ll_all_things'] ) ? '' : sanitize_text_field( wp_unslash( $_POST['ewww_image_optimizer_ll_all_things'] ) );
update_site_option( 'ewww_image_optimizer_ll_all_things', $ewww_image_optimizer_ll_all_things );
$ewww_image_optimizer_ll_exclude = empty( $_POST['ewww_image_optimizer_ll_exclude'] ) ? '' : sanitize_textarea_field( wp_unslash( $_POST['ewww_image_optimizer_ll_exclude'] ) );
update_site_option( 'ewww_image_optimizer_ll_exclude', ewww_image_optimizer_exclude_paths_sanitize( $ewww_image_optimizer_ll_exclude ) );
$ewww_image_optimizer_maxmediawidth = empty( $_POST['ewww_image_optimizer_maxmediawidth'] ) ? 0 : (int) $_POST['ewww_image_optimizer_maxmediawidth'];
update_site_option( 'ewww_image_optimizer_maxmediawidth', $ewww_image_optimizer_maxmediawidth );
$ewww_image_optimizer_maxmediaheight = empty( $_POST['ewww_image_optimizer_maxmediaheight'] ) ? 0 : (int) $_POST['ewww_image_optimizer_maxmediaheight'];
update_site_option( 'ewww_image_optimizer_maxmediaheight', $ewww_image_optimizer_maxmediaheight );
$ewww_image_optimizer_resize_detection = ( empty( $_POST['ewww_image_optimizer_resize_detection'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_resize_detection', $ewww_image_optimizer_resize_detection );
$ewww_image_optimizer_resize_existing = ( empty( $_POST['ewww_image_optimizer_resize_existing'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_resize_existing', $ewww_image_optimizer_resize_existing );
$ewww_image_optimizer_resize_other_existing = ( empty( $_POST['ewww_image_optimizer_resize_other_existing'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_resize_other_existing', $ewww_image_optimizer_resize_other_existing );
$ewww_image_optimizer_include_media_paths = ( empty( $_POST['ewww_image_optimizer_include_media_paths'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_include_media_paths', $ewww_image_optimizer_include_media_paths );
$ewww_image_optimizer_include_originals = ( empty( $_POST['ewww_image_optimizer_include_originals'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_include_originals', $ewww_image_optimizer_include_originals );
$ewww_image_optimizer_webp_for_cdn = ( empty( $_POST['ewww_image_optimizer_webp_for_cdn'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_webp_for_cdn', $ewww_image_optimizer_webp_for_cdn );
$ewww_image_optimizer_picture_webp = ( empty( $_POST['ewww_image_optimizer_picture_webp'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_picture_webp', $ewww_image_optimizer_picture_webp );
$ewww_image_optimizer_webp_rewrite_exclude = empty( $_POST['ewww_image_optimizer_webp_rewrite_exclude'] ) ? '' : sanitize_textarea_field( wp_unslash( $_POST['ewww_image_optimizer_webp_rewrite_exclude'] ) );
update_site_option( 'ewww_image_optimizer_webp_rewrite_exclude', ewww_image_optimizer_exclude_paths_sanitize( $ewww_image_optimizer_webp_rewrite_exclude ) );
$ewww_image_optimizer_webp_force = ( empty( $_POST['ewww_image_optimizer_webp_force'] ) ? false : true );
update_site_option( 'ewww_image_optimizer_webp_force', $ewww_image_optimizer_webp_force );
$ewww_image_optimizer_webp_paths = ( empty( $_POST['ewww_image_optimizer_webp_paths'] ) ? '' : sanitize_textarea_field( wp_unslash( $_POST['ewww_image_optimizer_webp_paths'] ) ) );
update_site_option( 'ewww_image_optimizer_webp_paths', ewww_image_optimizer_webp_paths_sanitize( $ewww_image_optimizer_webp_paths ) );
$ewww_image_optimizer_allow_multisite_override = empty( $_POST['ewww_image_optimizer_allow_multisite_override'] ) ? false : true;
update_site_option( 'ewww_image_optimizer_allow_multisite_override', $ewww_image_optimizer_allow_multisite_override );
$ewww_image_optimizer_enable_help = empty( $_POST['ewww_image_optimizer_enable_help'] ) ? false : true;
update_site_option( 'ewww_image_optimizer_enable_help', $ewww_image_optimizer_enable_help );
$ewww_image_optimizer_allow_tracking = empty( $_POST['ewww_image_optimizer_allow_tracking'] ) ? false : ewwwio()->tracking->check_for_settings_optin( (bool) $_POST['ewww_image_optimizer_allow_tracking'] );
update_site_option( 'ewww_image_optimizer_allow_tracking', $ewww_image_optimizer_allow_tracking );
add_action( 'network_admin_notices', 'ewww_image_optimizer_network_settings_saved' );
} elseif (
isset( $_POST['ewww_image_optimizer_allow_multisite_override_active'] ) &&
current_user_can( 'manage_network_options' ) &&
isset( $_REQUEST['_wpnonce'] ) &&
wp_verify_nonce( sanitize_key( $_REQUEST['_wpnonce'] ), 'ewww_image_optimizer_options-options' )
) {
ewwwio_debug_message( 'network-wide settings, single-site overriding' );
$ewww_image_optimizer_allow_multisite_override = empty( $_POST['ewww_image_optimizer_allow_multisite_override'] ) ? false : true;
update_site_option( 'ewww_image_optimizer_allow_multisite_override', $ewww_image_optimizer_allow_multisite_override );
$ewww_image_optimizer_allow_tracking = empty( $_POST['ewww_image_optimizer_allow_tracking'] ) ? false : ewwwio()->tracking->check_for_settings_optin( (bool) $_POST['ewww_image_optimizer_allow_tracking'] );
update_site_option( 'ewww_image_optimizer_allow_tracking', $ewww_image_optimizer_allow_tracking );
add_action( 'network_admin_notices', 'ewww_image_optimizer_network_settings_saved' );
} // End if().
} // End if().
if ( is_multisite() && get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) &&
! ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) &&
! ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) &&
! ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ) &&
! ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) &&
! ewww_image_optimizer_get_option( 'ewww_image_optimizer_svg_level' )
) {
ewwwio()->set_defaults();
update_option( 'ewww_image_optimizer_disable_pngout', true );
update_option( 'ewww_image_optimizer_disable_svgcleaner', true );
update_option( 'ewww_image_optimizer_optipng_level', 2 );
update_option( 'ewww_image_optimizer_pngout_level', 2 );
update_option( 'ewww_image_optimizer_metadata_remove', true );
update_option( 'ewww_image_optimizer_jpg_level', '10' );
update_option( 'ewww_image_optimizer_png_level', '10' );
update_option( 'ewww_image_optimizer_gif_level', '10' );
update_option( 'ewww_image_optimizer_svg_level', 0 );
}
}
/**
* Load plugin compat on the plugins_loaded hook, which is about as early as possible.
*/
function ewww_image_optimizer_load_plugin_compat() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( ewww_image_optimizer_s3_uploads_enabled() ) {
ewwwio_debug_message( 's3-uploads detected, deferring resize_upload' );
add_filter( 'ewww_image_optimizer_defer_resizing', '__return_true' );
}
$active_plugins = get_option( 'active_plugins' );
if ( is_multisite() && is_array( $active_plugins ) ) {
$sitewide_plugins = get_site_option( 'active_sitewide_plugins' );
if ( is_array( $sitewide_plugins ) ) {
$active_plugins = array_merge( $active_plugins, array_flip( $sitewide_plugins ) );
}
}
if ( ewww_image_optimizer_iterable( $active_plugins ) ) {
ewwwio_debug_message( 'checking active plugins' );
foreach ( $active_plugins as $active_plugin ) {
if ( strpos( $active_plugin, '/nggallery.php' ) || strpos( $active_plugin, '\nggallery.php' ) ) {
$ngg = ewww_image_optimizer_get_plugin_version( trailingslashit( WP_PLUGIN_DIR ) . $active_plugin );
// Include the file that loads the nextgen gallery optimization functions.
ewwwio_debug_message( 'Nextgen version: ' . $ngg['Version'] );
if ( 1 < intval( substr( $ngg['Version'], 0, 1 ) ) ) { // For Nextgen 2+ support.
$nextgen_major_version = substr( $ngg['Version'], 0, 1 );
ewwwio_debug_message( "loading nextgen $nextgen_major_version support for $active_plugin" );
require_once EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-ewww-nextgen.php';
} else {
preg_match( '/\d+\.\d+\.(\d+)/', $ngg['Version'], $nextgen_minor_version );
if ( ! empty( $nextgen_minor_version[1] ) && $nextgen_minor_version[1] < 14 ) {
ewwwio_debug_message( "NOT loading nextgen legacy support for $active_plugin" );
} elseif ( ! empty( $nextgen_minor_version[1] ) && $nextgen_minor_version[1] > 13 ) {
ewwwio_debug_message( "loading nextcellent support for $active_plugin" );
require_once EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-ewww-nextcellent.php';
}
}
}
if ( strpos( $active_plugin, '/flag.php' ) || strpos( $active_plugin, '\flag.php' ) ) {
ewwwio_debug_message( "loading flagallery support for $active_plugin" );
// Include the file that loads the grand flagallery optimization functions.
require_once EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-ewww-flag.php';
}
}
}
}
/**
* Runs early for checks that need to happen on init before anything else.
*/
function ewww_image_optimizer_init() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
// For the settings page, check for the enable-local param and take appropriate action.
if ( ! empty( $_GET['enable-local'] ) && ! empty( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( sanitize_key( $_REQUEST['_wpnonce'] ), 'ewww_image_optimizer_options-options' ) ) {
update_option( 'ewww_image_optimizer_ludicrous_mode', true );
update_site_option( 'ewww_image_optimizer_ludicrous_mode', true );
} elseif ( isset( $_GET['enable-local'] ) && ! (bool) $_GET['enable-local'] && ! empty( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( sanitize_key( $_REQUEST['_wpnonce'] ), 'ewww_image_optimizer_options-options' ) ) {
delete_option( 'ewww_image_optimizer_ludicrous_mode' );
delete_site_option( 'ewww_image_optimizer_ludicrous_mode' );
}
if ( ! empty( $_GET['complete_wizard'] ) && ! empty( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( sanitize_key( $_REQUEST['_wpnonce'] ), 'ewww_image_optimizer_options-options' ) ) {
update_option( 'ewww_image_optimizer_wizard_complete', true, false );
}
if ( ! empty( $_GET['uncomplete_wizard'] ) && ! empty( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( sanitize_key( $_REQUEST['_wpnonce'] ), 'ewww_image_optimizer_options-options' ) ) {
update_option( 'ewww_image_optimizer_wizard_complete', false, false );
}
if ( defined( 'DOING_WPLR_REQUEST' ) && DOING_WPLR_REQUEST ) {
// Unhook all automatic processing, and save an option that (does not autoload) tells the user LR Sync regenerated their images and they should run the bulk optimizer.
remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
remove_filter( 'wp_generate_attachment_metadata', 'ewww_image_optimizer_resize_from_meta_data', 15 );
add_action( 'wplr_add_media', 'ewww_image_optimizer_lr_sync_update' );
add_action( 'wplr_update_media', 'ewww_image_optimizer_lr_sync_update' );
add_filter( 'ewww_image_optimizer_allowed_reopt', '__return_true' );
}
}
/**
* Plugin upgrade function
*
* @global object $wpdb
*/
function ewww_image_optimizer_upgrade() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
global $ewwwio_upgrading;
$ewwwio_upgrading = false;
if ( get_option( 'ewww_image_optimizer_version' ) < EWWW_IMAGE_OPTIMIZER_VERSION ) {
if ( wp_doing_ajax() && ! empty( $_POST['ewwwio_test_verify'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
return;
}
$ewwwio_upgrading = true;
ewww_image_optimizer_install_table();
ewwwio()->set_defaults();
ewww_image_optimizer_enable_background_optimization();
// This will get re-enabled if things are too slow.
ewww_image_optimizer_set_option( 'exactdn_prevent_db_queries', false );
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn_verify_method' ) > 0 ) {
delete_option( 'ewww_image_optimizer_exactdn_verify_method' );
delete_site_option( 'ewww_image_optimizer_exactdn_verify_method' );
}
if ( get_option( 'ewww_image_optimizer_version' ) < 297.5 ) {
// Cleanup background test mess.
wp_clear_scheduled_hook( 'wp_ewwwio_test_optimize_cron' );
global $wpdb;
if ( is_multisite() ) {
$wpdb->query( "DELETE FROM $wpdb->sitemeta WHERE meta_key LIKE 'wp_ewwwio_test_optimize_batch_%'" );
}
$wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE 'wp_ewwwio_test_optimize_batch_%'" );
}
if ( ! get_option( 'ewww_image_optimizer_version' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
add_option( 'exactdn_never_been_active', true, '', false );
}
if ( get_option( 'ewww_image_optimizer_version' ) < 280 ) {
ewww_image_optimizer_migrate_settings_to_levels();
}
if ( get_option( 'ewww_image_optimizer_version' ) > 0 && get_option( 'ewww_image_optimizer_version' ) < 434 && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_metadata_remove', false );
}
if ( get_option( 'ewww_image_optimizer_version' ) < 454 ) {
update_option( 'ewww_image_optimizer_bulk_resume', '' );
update_option( 'ewww_image_optimizer_aux_resume', '' );
ewww_image_optimizer_delete_pending();
// Make sure some of our options are not autoloaded (since they can be huge).
$bulk_attachments = get_option( 'ewww_image_optimizer_flag_attachments', '' );
delete_option( 'ewww_image_optimizer_flag_attachments' );
add_option( 'ewww_image_optimizer_flag_attachments', $bulk_attachments, '', 'no' );
$bulk_attachments = get_option( 'ewww_image_optimizer_ngg_attachments', '' );
delete_option( 'ewww_image_optimizer_ngg_attachments' );
add_option( 'ewww_image_optimizer_ngg_attachments', $bulk_attachments, '', 'no' );
}
if ( get_option( 'ewww_image_optimizer_version' ) < 530 ) {
ewww_image_optimizer_migrate_option_queue_to_table();
}
if ( get_option( 'ewww_image_optimizer_version' ) < 550 && ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_force_gif2webp', false );
} elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_force_gif2webp' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_force_gif2webp', true );
}
if (
get_option( 'ewww_image_optimizer_version' ) <= 601.0 &&
PHP_OS !== 'WINNT' &&
ewwwio_is_file( EWWW_IMAGE_OPTIMIZER_TOOL_PATH . '/pngout-static' ) &&
is_writable( EWWW_IMAGE_OPTIMIZER_TOOL_PATH . '/pngout-static' )
) {
ewwwio_debug_message( 'removing old version of pngout' );
ewwwio_delete_file( EWWW_IMAGE_OPTIMIZER_TOOL_PATH . '/pngout-static' );
}
if (
get_option( 'ewww_image_optimizer_version' ) < 661 &&
get_option( 'ewww_image_optimizer_exactdn' ) &&
! ewww_image_optimizer_get_option( 'ewww_image_optimizer_ludicrous_mode' ) &&
! ewww_image_optimizer_get_option( 'exactdn_lossy' )
) {
ewww_image_optimizer_set_option( 'exactdn_lossy', true );
}
if (
get_option( 'ewww_image_optimizer_version' ) <= 670 &&
ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' )
) {
$backup_mode = ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' );
if ( 'local' !== $backup_mode && 'cloud' !== $backup_mode ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_backup_files', 'cloud' );
}
}
if ( get_option( 'ewww_image_optimizer_local_mode' ) || get_site_option( 'ewww_image_optimizer_local_mode' ) ) {
update_option( 'ewww_image_optimizer_ludicrous_mode', true );
update_site_option( 'ewww_image_optimizer_ludicrous_mode', true );
delete_option( 'ewww_image_optimizer_local_mode' );
delete_site_option( 'ewww_image_optimizer_local_mode' );
}
if ( get_option( 'ewww_image_optimizer_version' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_review_time' ) ) {
$review_time = rand( time(), time() + 51 * DAY_IN_SECONDS );
add_option( 'ewww_image_optimizer_review_time', $review_time, '', false );
add_site_option( 'ewww_image_optimizer_review_time', $review_time );
} elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_review_time' ) ) {
$review_time = time() + 7 * DAY_IN_SECONDS;
add_option( 'ewww_image_optimizer_review_time', $review_time, '', false );
add_site_option( 'ewww_image_optimizer_review_time', $review_time );
}
if ( get_option( 'ewww_image_optimizer_version' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_wizard_complete' ) ) {
add_option( 'ewww_image_optimizer_wizard_complete', true, '', false );
add_site_option( 'ewww_image_optimizer_wizard_complete', true );
}
if ( is_file( EWWWIO_CONTENT_DIR . 'debug.log' ) && is_writable( EWWWIO_CONTENT_DIR . 'debug.log' ) ) {
unlink( EWWWIO_CONTENT_DIR . 'debug.log' );
}
ewww_image_optimizer_remove_obsolete_settings();
update_option( 'ewww_image_optimizer_version', EWWW_IMAGE_OPTIMIZER_VERSION );
}
ewwwio_memory( __FUNCTION__ );
}
/**
* Tests background optimization.
*
* Send a known packet to admin-ajax.php via the EWWW\Async_Test_Request class.
*/
function ewww_image_optimizer_enable_background_optimization() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( ewww_image_optimizer_detect_wpsf_location_lock() ) {
return;
}
ewww_image_optimizer_set_option( 'ewww_image_optimizer_background_optimization', false );
ewwwio_debug_message( 'running test async handler' );
ewwwio()->async_test_request->data( array( 'ewwwio_test_verify' => '949c34123cf2a4e4ce2f985135830df4a1b2adc24905f53d2fd3f5df5b162932' ) )->dispatch();
ewww_image_optimizer_debug_log();
}
/**
* Re-tests background optimization at a user's request.
*/
function ewww_image_optimizer_retest_background_optimization() {
if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', '' ) ) ) {
wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
}
ewww_image_optimizer_enable_background_optimization();
sleep( 10 );
$sendback = wp_get_referer();
wp_safe_redirect( $sendback );
exit;
}
/**
* Apply 6.2.0+ current_timestamp db upgrade.
*/
function ewww_image_optimizer_620_upgrade() {
if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', '' ) ) ) {
wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
}
delete_transient( 'ewww_image_optimizer_620_upgrade_needed' );
global $wpdb;
$suppress = $wpdb->suppress_errors();
$wpdb->query( "ALTER TABLE $wpdb->ewwwio_images MODIFY updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" );
$wpdb->suppress_errors( $suppress );
wp_safe_redirect( wp_get_referer() );
exit;
}
/**
* Setup wp_cron tasks for scheduled optimization.
*
* @global object $wpdb
*
* @param string $event Name of cron hook to schedule.
*/
function ewww_image_optimizer_cron_setup( $event ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
// Setup scheduled optimization if the user has enabled it, and it isn't already scheduled.
if ( ewww_image_optimizer_get_option( $event ) && ! wp_next_scheduled( $event ) ) {
ewwwio_debug_message( "scheduling $event" );
wp_schedule_event( time(), apply_filters( 'ewww_image_optimizer_schedule', 'hourly', $event ), $event );
} elseif ( ewww_image_optimizer_get_option( $event ) ) {
ewwwio_debug_message( "$event already scheduled: " . wp_next_scheduled( $event ) );
} elseif ( wp_next_scheduled( $event ) ) {
ewwwio_debug_message( "un-scheduling $event" );
wp_clear_scheduled_hook( $event );
if ( ! function_exists( 'is_plugin_active_for_network' ) && is_multisite() ) {
// Need to include the plugin library for the is_plugin_active function.
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
global $wpdb;
$blogs = $wpdb->get_results( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs WHERE site_id = %d", $wpdb->siteid ), ARRAY_A );
if ( ewww_image_optimizer_iterable( $blogs ) ) {
foreach ( $blogs as $blog ) {
switch_to_blog( $blog['blog_id'] );
wp_clear_scheduled_hook( $event );
restore_current_blog();
}
}
}
}
}
/**
* Checks to see if this is an AJAX request, and whether the WP_Image_Editor hooks should be undone.
*
* @since 3.3.0
*/
function ewww_image_optimizer_ajax_compat_check() {
if ( ! wp_doing_ajax() ) {
return;
}
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
$action = ! empty( $_REQUEST['action'] ) ? sanitize_key( $_REQUEST['action'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
if ( $action ) {
ewwwio_debug_message( "doing $action" );
}
// Check for (Force) Regenerate Thumbnails action (includes MLP regenerate).
if (
'regeneratethumbnail' === $action ||
'rta_regenerate_thumbnails' === $action ||
'meauh_save_image' === $action ||
'hotspot_save' === $action
) {
ewwwio_debug_message( 'doing regeneratethumbnail' );
ewww_image_optimizer_image_sizes( false );
add_filter( 'ewww_image_optimizer_allowed_reopt', '__return_true' );
return;
}
if ( 'mic_crop_image' === $action ) {
ewwwio_debug_message( 'doing Manual Image Crop' );
if ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) ) {
define( 'EWWWIO_EDITOR_OVERWRITE', true );
}
add_filter( 'ewww_image_optimizer_allowed_reopt', '__return_true' );
return;
}
if ( false !== strpos( $action, 'wc_regenerate_images' ) ) {
// Unhook all automatic processing, and save an option that (does not autoload) tells the user WC regenerated their images and they should run the bulk optimizer.
remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
remove_filter( 'wp_generate_attachment_metadata', 'ewww_image_optimizer_resize_from_meta_data', 15 );
update_option( 'ewww_image_optimizer_wc_regen', true, false );
return;
}
// Check for Image Watermark plugin.
$iwaction = ! empty( $_REQUEST['iw-action'] ) ? sanitize_key( $_REQUEST['iw-action'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
if ( $iwaction ) {
ewwwio_debug_message( "doing $iwaction" );
global $ewww_preempt_editor;
$ewww_preempt_editor = true;
if ( 'applywatermark' === $iwaction ) {
remove_filter( 'wp_generate_attachment_metadata', 'ewww_image_optimizer_resize_from_meta_data', 15 );
add_action( 'iw_after_apply_watermark', 'ewww_image_optimizer_single_size_optimize', 10, 2 );
}
add_filter( 'ewww_image_optimizer_allowed_reopt', '__return_true' );
return;
}
// Check for other MLP actions, including multi-regen.
if ( class_exists( 'MaxGalleriaMediaLib' ) && ( 'regen_mlp_thumbnails' === $action || 'move_media' === $action || 'copy_media' === $action || 'maxgalleria_rename_image' === $action ) ) {
ewwwio_debug_message( 'doing regen_mlp_thumbnails' );
ewww_image_optimizer_image_sizes( false );
add_filter( 'ewww_image_optimizer_allowed_reopt', '__return_true' );
return;
}
// Check for MLP upload.
if ( class_exists( 'MaxGalleriaMediaLib' ) && ! empty( $_REQUEST['nonce'] ) && 'upload_attachment' === $action ) { // phpcs:ignore WordPress.Security.NonceVerification
ewwwio_debug_message( 'doing maxgalleria upload' );
ewww_image_optimizer_image_sizes( false );
add_filter( 'ewww_image_optimizer_allowed_reopt', '__return_true' );
return;
}
// Check for Image Regenerate and Select Crop (better way).
if ( defined( 'DOING_SIRSC' ) && DOING_SIRSC ) {
ewwwio_debug_message( 'IRSC action/regen' );
ewww_image_optimizer_image_sizes( false );
add_filter( 'ewww_image_optimizer_allowed_reopt', '__return_true' );
return;
} elseif ( 0 === strpos( $action, 'sirsc' ) ) {
// Image Regenerate and Select Crop (old check).
ewwwio_debug_message( 'IRSC action/regen (old)' );
ewww_image_optimizer_image_sizes( false );
add_filter( 'ewww_image_optimizer_allowed_reopt', '__return_true' );
return;
}
// Check for Phoenix Media Rename action.
if ( class_exists( 'Phoenix_Media_Rename' ) && 'phoenix_media_rename' === $action ) {
ewwwio_debug_message( 'Phoenix Media Rename, verifying' );
if ( check_ajax_referer( 'phoenix_media_rename', '_wpnonce', false ) ) {
ewwwio_debug_message( 'PMR verified' );
remove_filter( 'wp_generate_attachment_metadata', 'ewww_image_optimizer_resize_from_meta_data', 15 );
ewww_image_optimizer_image_sizes( false );
add_filter( 'ewww_image_optimizer_allowed_reopt', '__return_true' );
return;
}
}
}
/**
* Adds suggested privacy policy content for site admins.
*
* Note that this is just a suggestion, it should be customized for your site.
*/
function ewww_image_optimizer_privacy_policy_content() {
if ( ! function_exists( 'wp_add_privacy_policy_content' ) || ! function_exists( 'wp_kses_post' ) ) {
return;
}
$content = '
';
$content .= wp_kses_post( __( 'By default, the EWWW Image Optimizer does not store any personal data nor share it with anyone.', 'ewww-image-optimizer' ) ) . '
';
$content .= wp_kses_post( __( 'If you accept user-submitted images and use the API or Easy IO, those images may be transmitted to third-party servers in foreign countries. If Backup Originals is enabled, images are stored for 30 days. Otherwise, no images are stored on the API for longer than 30 minutes.', 'ewww-image-optimizer' ) ) . '
';
$content .= '
' . wp_kses_post( __( 'Suggested API Text:' ) ) . '' . wp_kses_post( __( 'User-submitted images may be transmitted to image compression servers in the United States and stored there for up to 30 days.' ) ) . '
';
$content .= '
' . wp_kses_post( __( 'Suggested Easy IO Text:' ) ) . '' . wp_kses_post( __( 'User-submitted images that are displayed on this site will be transmitted and stored on a global network of third-party servers (a CDN).' ) ) . '
';
wp_add_privacy_policy_content( 'EWWW Image Optimizer', $content );
}
/**
* Check the current screen, currently used to temporarily enable debugging on settings page.
*
* @param object $screen Information about the page/screen currently being loaded.
*/
function ewww_image_optimizer_current_screen( $screen ) {
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
return;
}
if ( false !== strpos( $screen->id, 'settings_page_ewww-image-optimizer' ) ) {
return;
}
if ( false !== strpos( $screen->id, 'media_page_ewww-image-optimizer-bulk' ) ) {
return;
}
EWWW\Base::$debug_data = '';
EWWW\Base::$temp_debug = false;
}
/**
* Optimize a single image from an attachment, based on the size and ID.
*
* @param int $id The attachment ID number.
* @param string $size The slug/name of the image size.
*/
function ewww_image_optimizer_single_size_optimize( $id, $size ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
session_write_close();
$meta = wp_get_attachment_metadata( $id );
global $wpdb;
if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
ewww_image_optimizer_db_init();
global $ewwwdb;
} else {
$ewwwdb = $wpdb;
}
list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
ewwwio_debug_message( "retrieved file path: $file_path" );
$type = ewww_image_optimizer_mimetype( $file_path, 'i' );
$supported_types = array(
'image/jpeg',
'image/png',
'image/gif',
'application/pdf',
'image/svg+xml',
);
if ( ! in_array( $type, $supported_types, true ) ) {
ewwwio_debug_message( "mimetype not supported: $id" );
return;
}
if ( 'full' === $size ) {
$ewww_image = new EWWW_Image( $id, 'media', $file_path );
$ewww_image->resize = 'full';
// Run the optimization and store the results.
ewww_image_optimizer( $file_path, 4, false, false, true );
return;
}
// Resized version, continue.
if ( isset( $meta['sizes'] ) && is_array( $meta['sizes'][ $size ] ) ) {
$disabled_sizes = ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_resizes_opt', false, true );
ewwwio_debug_message( "processing size: $size" );
$base_dir = trailingslashit( dirname( $file_path ) );
$data = $meta['sizes'][ $size ];
if ( strpos( $size, 'webp' ) === 0 ) {
return;
}
if ( ! empty( $disabled_sizes[ $size ] ) ) {
return;
}
if ( ! empty( $disabled_sizes['pdf-full'] ) && 'full' === $size ) {
return;
}
if ( empty( $data['file'] ) ) {
return;
}
// If this is a unique size.
$resize_path = $base_dir . wp_basename( $data['file'] );
if ( 'application/pdf' === $type && 'full' === $size ) {
$size = 'pdf-full';
ewwwio_debug_message( 'processing full size pdf preview' );
}
$ewww_image = new EWWW_Image( $id, 'media', $resize_path );
$ewww_image->resize = $size;
// Run the optimization and store the results.
ewww_image_optimizer( $resize_path );
// Optimize retina images, if they exist.
if ( function_exists( 'wr2x_get_retina' ) ) {
$retina_path = wr2x_get_retina( $resize_path );
} else {
$retina_path = false;
}
if ( $retina_path && ewwwio_is_file( $retina_path ) ) {
$ewww_image = new EWWW_Image( $id, 'media', $retina_path );
$ewww_image->resize = $size . '-retina';
ewww_image_optimizer( $retina_path );
} else {
ewww_image_optimizer_hidpi_optimize( $resize_path );
}
} // End if().
}
/**
* Checks to see if this is a REST API request, and whether the WP_Image_Editor hooks should be undone.
*
* @since 4.0.6
*/
function ewww_image_optimizer_restapi_compat_check() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( ! empty( $GLOBALS['wp']->query_vars['rest_route'] ) && false !== strpos( $GLOBALS['wp']->query_vars['rest_route'], '/regenerate-thumbnails' ) ) {
ewwwio_debug_message( 'doing regenerate-thumbnails via REST' );
ewww_image_optimizer_image_sizes( false );
add_filter( 'ewww_image_optimizer_allowed_reopt', '__return_true' );
return;
}
if (
! empty( $GLOBALS['wp']->query_vars['rest_route'] ) &&
strpos( $GLOBALS['wp']->query_vars['rest_route'], '/media/' ) &&
preg_match( '/media\/\d+\/edit$/', $GLOBALS['wp']->query_vars['rest_route'] )
) {
ewwwio_debug_message( 'image edited via REST' );
global $ewww_preempt_editor;
$ewww_preempt_editor = true;
}
}
/**
* Generates css include for progressbars to match admin style.
*/
function ewww_image_optimizer_progressbar_style() {
wp_add_inline_style( 'jquery-ui-progressbar', '.ui-widget-header { background-color: ' . ewww_image_optimizer_admin_background() . '; }' );
ewwwio_memory( __FUNCTION__ );
}
/**
* Grabs the color scheme information from the current admin theme and saves it for later.
*
* @global $ewwwio_admin_color The color we want to use for theming.
* @global array $_wp_admin_css_colors An array of available admin color/theme objects.
*/
function ewww_image_optimizer_save_admin_colors() {
global $ewwwio_admin_color;
global $_wp_admin_css_colors;
if ( function_exists( 'wp_add_inline_style' ) ) {
$user_info = wp_get_current_user();
if (
is_array( $_wp_admin_css_colors ) &&
! empty( $user_info->admin_color ) &&
isset( $_wp_admin_css_colors[ $user_info->admin_color ] ) &&
is_object( $_wp_admin_css_colors[ $user_info->admin_color ] ) &&
is_array( $_wp_admin_css_colors[ $user_info->admin_color ]->colors ) &&
! empty( $_wp_admin_css_colors[ $user_info->admin_color ]->colors[2] ) &&
preg_match( '/^\#([0-9a-fA-F]){3,6}$/', $_wp_admin_css_colors[ $user_info->admin_color ]->colors[2] )
) {
$ewwwio_admin_color = $_wp_admin_css_colors[ $user_info->admin_color ]->colors[2];
}
}
if ( empty( $ewwwio_admin_color ) ) {
$ewwwio_admin_color = '#0073aa';
}
}
/**
* Determines the background color to use based on the selected admin theme.
*/
function ewww_image_optimizer_admin_background() {
global $ewwwio_admin_color;
if ( ! empty( $ewwwio_admin_color ) && preg_match( '/^\#([0-9a-fA-F]){3,6}$/', $ewwwio_admin_color ) ) {
return $ewwwio_admin_color;
}
if ( function_exists( 'wp_add_inline_style' ) ) {
$user_info = wp_get_current_user();
global $_wp_admin_css_colors;
if (
is_array( $_wp_admin_css_colors ) &&
! empty( $user_info->admin_color ) &&
isset( $_wp_admin_css_colors[ $user_info->admin_color ] ) &&
is_object( $_wp_admin_css_colors[ $user_info->admin_color ] ) &&
is_array( $_wp_admin_css_colors[ $user_info->admin_color ]->colors ) &&
! empty( $_wp_admin_css_colors[ $user_info->admin_color ]->colors[2] ) &&
preg_match( '/^\#([0-9a-fA-F]){3,6}$/', $_wp_admin_css_colors[ $user_info->admin_color ]->colors[2] )
) {
$ewwwio_admin_color = $_wp_admin_css_colors[ $user_info->admin_color ]->colors[2];
return $ewwwio_admin_color;
}
switch ( $user_info->admin_color ) {
case 'midnight':
return '#e14d43';
case 'blue':
return '#096484';
case 'light':
return '#04a4cc';
case 'ectoplasm':
return '#a3b745';
case 'coffee':
return '#c7a589';
case 'ocean':
return '#9ebaa0';
case 'sunrise':
return '#dd823b';
default:
return '#0073aa';
}
}
return '#0073aa';
}
/**
* If a multisite is over 1000 sites, tells WP this is a 'large network' when querying image stats.
*
* @param bool $large_network Normally only true with 10,000+ users or sites.
* @param string $criteria The criteria for determining a large network, 'sites' or 'users'.
* @param int $count The number of sites/users.
* @return bool True if this is a 'large network'.
*/
function ewww_image_optimizer_large_network( $large_network, $criteria, $count ) {
if ( 'sites' === $criteria && $count > 1000 ) {
return true;
}
return false;
}
/**
* Adds/upgrades table in db for storing status of all images that have been optimized.
*
* @global object $wpdb
*/
function ewww_image_optimizer_install_table() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
global $wpdb;
$wpdb->ewwwio_images = $wpdb->prefix . 'ewwwio_images';
$wpdb->ewwwio_queue = $wpdb->prefix . 'ewwwio_queue';
// Get the current wpdb charset and collation.
$db_collation = $wpdb->get_charset_collate();
ewwwio_debug_message( "current collation: $db_collation" );
$primary_key_definition = 'PRIMARY KEY (id),';
// See if the path column exists, and what collation it uses to determine the column index size.
if ( $wpdb->get_var( "SHOW TABLES LIKE '$wpdb->ewwwio_images'" ) === $wpdb->ewwwio_images ) {
ewwwio_debug_message( 'upgrading table and checking collation for path, table exists' );
$mysql_version = 'unknown';
if ( method_exists( $wpdb, 'db_server_info' ) ) {
$mysql_version = strtolower( $wpdb->db_server_info() );
}
ewwwio_debug_message( $mysql_version );
if ( false !== strpos( $mysql_version, 'maria' ) && false !== strpos( $mysql_version, '10.4.' ) ) {
$primary_key_definition = 'UNIQUE KEY id (id),';
}
if ( false && false === strpos( $mysql_version, 'maria' ) || false === strpos( $mysql_version, '10.4.' ) ) {
ewwwio_debug_message( 'checking primary/unique index' );
if ( ! $wpdb->get_results( "SHOW INDEX FROM $wpdb->ewwwio_images WHERE Key_name = 'PRIMARY'", ARRAY_A ) ) {
ewwwio_debug_message( 'adding primary index' );
$wpdb->query( "ALTER TABLE $wpdb->ewwwio_images ADD PRIMARY KEY(id)" );
}
if ( $wpdb->get_results( "SHOW INDEX FROM $wpdb->ewwwio_images WHERE Key_name = 'id'", ARRAY_A ) ) {
ewwwio_debug_message( 'dropping unique index' );
$wpdb->query( "ALTER TABLE $wpdb->ewwwio_images DROP INDEX id" );
}
}
// Check if the old path_image_size index exists, and drop it.
if ( $wpdb->get_results( "SHOW INDEX FROM $wpdb->ewwwio_images WHERE Key_name = 'path_image_size'", ARRAY_A ) ) {
ewwwio_debug_message( 'getting rid of path_image_size index' );
$wpdb->query( "ALTER TABLE $wpdb->ewwwio_images DROP INDEX path_image_size" );
}
// Make sure there are valid dates in updated column.
$wpdb->query( "UPDATE $wpdb->ewwwio_images SET updated = '1971-01-01 00:00:00' WHERE updated < '1001-01-01 00:00:01'" );
// Get the current table layout.
$suppress = $wpdb->suppress_errors();
$tablefields = $wpdb->get_results( "DESCRIBE {$wpdb->ewwwio_images};" );
$wpdb->suppress_errors( $suppress );
$timestamp_upgrade_needed = false;
if ( ewww_image_optimizer_iterable( $tablefields ) ) {
foreach ( $tablefields as $tablefield ) {
if (
'updated' === $tablefield->Field && // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
false === stripos( $tablefield->Default, 'current_timestamp' ) && // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
false === stripos( $tablefield->Default, 'now' ) // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
) {
$timestamp_upgrade_needed = true;
ewwwio_debug_message( 'updated timestamp upgrade needed' );
}
}
}
if (
(
false !== strpos( $mysql_version, '5.6.' ) ||
false !== strpos( $mysql_version, '5.7.' ) ||
false !== strpos( $mysql_version, '10.1.' )
) &&
$timestamp_upgrade_needed
) {
$count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->ewwwio_images" );
if ( is_multisite() || $count < 10000 ) {
// Do the upgrade in real-time for multi-site and sites with less than 10k image records.
$wpdb->query( "ALTER TABLE $wpdb->ewwwio_images MODIFY updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" );
} else {
// Do it later via user interaction.
set_transient( 'ewww_image_optimizer_620_upgrade_needed', true );
}
} elseif ( $timestamp_upgrade_needed ) {
$wpdb->query( "ALTER TABLE $wpdb->ewwwio_images ALTER updated SET DEFAULT (CURRENT_TIMESTAMP)" );
}
// Check the current collation and adjust it if necessary.
$column_collate = $wpdb->get_col_charset( $wpdb->ewwwio_images, 'path' );
if ( ! empty( $column_collate ) && ! is_wp_error( $column_collate ) && 'utf8mb4' !== $column_collate ) {
$path_index_size = 255;
ewwwio_debug_message( "current column collation: $column_collate" );
if ( strpos( $column_collate, 'utf8' ) === false ) {
ewwwio_debug_message( 'converting path column to utf8' );
$wpdb->query( "ALTER TABLE $wpdb->ewwwio_images CHANGE path path BLOB" );
if ( $wpdb->has_cap( 'utf8mb4_520' ) && strpos( $db_collation, 'utf8mb4' ) ) {
ewwwio_debug_message( 'using mb4 version 5.20' );
$wpdb->query( "ALTER TABLE $wpdb->ewwwio_images DROP INDEX path_image_size" );
$wpdb->query( "ALTER TABLE $wpdb->ewwwio_images CONVERT TO CHARACTER SET utf8mb4, CHANGE path path TEXT" );
unset( $path_index_size );
} elseif ( $wpdb->has_cap( 'utf8mb4' ) && strpos( $db_collation, 'utf8mb4' ) ) {
ewwwio_debug_message( 'using mb4 version 4' );
$wpdb->query( "ALTER TABLE $wpdb->ewwwio_images DROP INDEX path_image_size" );
$wpdb->query( "ALTER TABLE $wpdb->ewwwio_images CONVERT TO CHARACTER SET utf8mb4, CHANGE path path TEXT" );
unset( $path_index_size );
} else {
ewwwio_debug_message( 'using plain old utf8' );
$wpdb->query( "ALTER TABLE $wpdb->ewwwio_images CONVERT TO CHARACTER SET utf8, CHANGE path path TEXT" );
}
} elseif ( strpos( $column_collate, 'utf8mb4' ) === false && strpos( $db_collation, 'utf8mb4' ) ) {
if ( $wpdb->has_cap( 'utf8mb4_520' ) ) {
ewwwio_debug_message( 'using mb4 version 5.20' );
$wpdb->query( "ALTER TABLE $wpdb->ewwwio_images DROP INDEX path_image_size" );
$wpdb->query( "ALTER TABLE $wpdb->ewwwio_images CONVERT TO CHARACTER SET utf8mb4, CHANGE path path TEXT" );
unset( $path_index_size );
} elseif ( $wpdb->has_cap( 'utf8mb4' ) ) {
ewwwio_debug_message( 'using mb4 version 4' );
$wpdb->query( "ALTER TABLE $wpdb->ewwwio_images DROP INDEX path_image_size" );
$wpdb->query( "ALTER TABLE $wpdb->ewwwio_images CONVERT TO CHARACTER SET utf8mb4, CHANGE path path TEXT" );
unset( $path_index_size );
}
}
}
} // End if().
// If the path column doesn't yet exist, and the default collation is utf8mb4, then we need to lower the column index size.
if ( empty( $path_index_size ) && strpos( $db_collation, 'utf8mb4' ) ) {
$path_index_size = 191;
} else {
$path_index_size = 255;
}
ewwwio_debug_message( "path index size: $path_index_size" );
/*
* Create a table with 15 columns:
* id: unique for each record/image,
* attachment_id: the unique id within the media library, nextgen, or flag
* gallery: 'media', 'nextgen', 'nextcell', or 'flag',
* resize: size of the image,
* path: filename of the image, potentially replaced with ABSPATH or WP_CONTENT_DIR,
* converted: filename of the image before conversion,
* results: human-readable savings message,
* image_size: optimized size of the image,
* orig_size: original size of the image,
* backup: hash where the image is stored on the API servers,
* level: the optimization level used on the image,
* pending: 1 if the image is queued for optimization,
* updates: how many times an image has been optimized,
* updated: when the image was last optimized,
* trace: tracelog from the last optimization if debugging was enabled.
*/
$sql = "CREATE TABLE $wpdb->ewwwio_images (
id int unsigned NOT NULL AUTO_INCREMENT,
attachment_id bigint unsigned,
gallery varchar(10),
resize varchar(75),
path text NOT NULL,
converted text NOT NULL,
results varchar(75) NOT NULL,
image_size int unsigned,
orig_size int unsigned,
backup varchar(100),
level int unsigned,
pending tinyint NOT NULL DEFAULT 0,
updates int unsigned,
updated timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
trace blob,
$primary_key_definition
KEY path (path($path_index_size)),
KEY attachment_info (gallery(3),attachment_id)
) $db_collation;";
// Include the upgrade library to install/upgrade a table.
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
$updates = dbDelta( $sql );
ewwwio_debug_message( 'images db upgrade results: ' . implode( ' ', $updates ) );
/*
* Create a table with 5 columns:
* id: unique for each record/image,
* attachment_id: the unique id within the media library, nextgen, or flag
* gallery: 'media', 'nextgen', 'nextcell', 'flag', plus -async variants.
* scanned: 1 if the image is queued for optimization, 0 if it still needs scanning.
* new: 1 if the image is a 'new' upload queued for optimization, 0 otherwise.
*/
$sql = "CREATE TABLE $wpdb->ewwwio_queue (
id int unsigned NOT NULL AUTO_INCREMENT,
attachment_id bigint unsigned,
gallery varchar(20),
scanned tinyint NOT NULL DEFAULT 0,
new tinyint NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY attachment_info (gallery(3),attachment_id)
) COLLATE utf8_general_ci;";
// Include the upgrade library to install/upgrade a table.
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
$updates = dbDelta( $sql );
ewwwio_debug_message( 'queue db upgrade results: ' . implode( ' ', $updates ) );
}
/**
* Migrates old cloud/compression settings to compression levels.
*/
function ewww_image_optimizer_migrate_settings_to_levels() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_jpegtran' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_jpg_level', 0 );
}
if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_jpegtran' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_jpg_level', 10 );
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_jpg' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_lossy' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_jpg_level', 20 );
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_jpg' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_lossy' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_lossy_fast' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_jpg_level', 30 );
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_jpg' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_lossy' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_lossy_fast' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_jpg_level', 40 );
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_pngout' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_optipng' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_png_level', 0 );
}
if ( ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_pngout' ) || ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_optipng' ) ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_png_level', 10 );
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_png' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_lossy' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_png_compress' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_png_level', 20 );
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_png' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_lossy' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_png_compress' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_png_level', 30 );
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_png' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_lossy' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_lossy_fast' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_png_level', 40 );
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_png' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_lossy' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_lossy_fast' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_png_level', 50 );
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_gifsicle' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_gif_level', 0 );
}
if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_gifsicle' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_gif_level', 10 );
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_pdf' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_lossy' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_pdf_level', 10 );
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_pdf' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_lossy' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_pdf_level', 20 );
}
}
/**
* Removes settings which are no longer used.
*/
function ewww_image_optimizer_remove_obsolete_settings() {
delete_option( 'ewww_image_optimizer_disable_jpegtran' );
delete_option( 'ewww_image_optimizer_cloud_jpg' );
delete_option( 'ewww_image_optimizer_jpg_lossy' );
delete_option( 'ewww_image_optimizer_lossy_fast' );
delete_option( 'ewww_image_optimizer_cloud_png' );
delete_option( 'ewww_image_optimizer_png_lossy' );
delete_option( 'ewww_image_optimizer_cloud_png_compress' );
delete_option( 'ewww_image_optimizer_disable_gifsicle' );
delete_option( 'ewww_image_optimizer_cloud_gif' );
delete_option( 'ewww_image_optimizer_cloud_pdf' );
delete_option( 'ewww_image_optimizer_pdf_lossy' );
delete_option( 'ewww_image_optimizer_skip_check' );
delete_option( 'ewww_image_optimizer_disable_optipng' );
delete_option( 'ewww_image_optimizer_interval' );
delete_option( 'ewww_image_optimizer_jpegtran_path' );
delete_option( 'ewww_image_optimizer_optipng_path' );
delete_option( 'ewww_image_optimizer_gifsicle_path' );
delete_option( 'ewww_image_optimizer_import_status' );
delete_option( 'ewww_image_optimizer_bulk_image_count' );
delete_option( 'ewww_image_optimizer_maxwidth' );
delete_option( 'ewww_image_optimizer_maxheight' );
delete_option( 'ewww_image_optimizer_exactdn_failures' );
delete_option( 'ewww_image_optimizer_exactdn_suspended' );
delete_option( 'ewww_image_optimizer_bulk_attachments' );
delete_option( 'ewww_image_optimizer_aux_attachments' );
delete_option( 'ewww_image_optimizer_defer_attachments' );
}
/**
* Migrate any option-based queues to the queue table.
*/
function ewww_image_optimizer_migrate_option_queue_to_table() {
global $wpdb;
$key = 'wp_ewwwio_media_optimize_batch_%';
$queues = $wpdb->get_results(
$wpdb->prepare(
"SELECT *
FROM $wpdb->options
WHERE option_name LIKE %s",
$key
),
ARRAY_A
);
if ( ! empty( $queues ) ) {
foreach ( $queues as $queue ) {
$items = maybe_unserialize( $queue['option_value'] );
if ( ewww_image_optimizer_iterable( $items ) ) {
foreach ( $items as $item ) {
ewwwio()->background_media->push_to_queue(
array(
'id' => $item['id'],
'new' => 0,
)
);
}
}
ewwwio()->background_media->dispatch();
}
}
// Clear all queues.
$key = 'wp_ewwwio_%';
$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->options WHERE option_name LIKE %s", $key ) );
$key = '%ewwwio-background-in-progress-%';
$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->options WHERE option_name LIKE %s", $key ) );
}
/**
* Checks to see if the WebP conversion was just enabled.
*
* @param mixed $old_value The old value, also a boolean generally.
* @param mixed $new_value The new value, in this case it will be boolean usually.
*/
function ewww_image_optimizer_webp_maybe_enabled( $old_value, $new_value ) {
if ( ! empty( $new_value ) && (bool) $new_value !== (bool) $old_value ) {
update_option( 'ewww_image_optimizer_webp_enabled', true );
}
}
/**
* Checks to see if Scheduled Optimization was just disabled.
*
* @param mixed $old_value The old value, also a boolean generally.
* @param mixed $new_value The new value, in this case it will be boolean usually.
*/
function ewww_image_optimizer_scheduled_optimization_changed( $old_value, $new_value ) {
if ( empty( $new_value ) && (bool) $new_value !== (bool) $old_value ) {
ewwwio()->background_image->cancel_process();
update_option( 'ewwwio_stop_scheduled_scan', true, false );
}
}
/**
* Checks to see if Resize Images dimensions have been modified.
*
* If resize dimensions are modified, then we clear out the legacy settings,
* as it is highly likely the admin wants something different now.
*
* @param mixed $old_value The old value, also a boolean generally.
* @param mixed $new_value The new value, in this case it will be boolean usually.
*/
function ewww_image_optimizer_resize_dimensions_changed( $old_value, $new_value ) {
if ( (int) $new_value !== (int) $old_value ) {
update_option( 'ewww_image_optimizer_maxotherwidth', 0 );
update_option( 'ewww_image_optimizer_maxotherheight', 0 );
update_site_option( 'ewww_image_optimizer_maxotherwidth', 0 );
update_site_option( 'ewww_image_optimizer_maxotherheight', 0 );
}
}
/**
* Display a notice that the user should run the bulk optimizer after WebP activation.
*/
function ewww_image_optimizer_notice_webp_bulk() {
if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', '' ) ) ) {
return;
}
$already_done = ewww_image_optimizer_aux_images_table_count();
if ( $already_done > 50 ) {
echo "
' . sprintf(
/* translators: 1: An error message 2: The folder where svgcleaner should be installed */
esc_html__( 'Svgcleaner was not installed: %1$s. Make sure this folder is writable: %2$s', 'ewww-image-optimizer' ),
( ! empty( $_REQUEST['ewww_error'] ) ? esc_html( sanitize_text_field( wp_unslash( $_REQUEST['ewww_error'] ) ) ) : esc_html( 'unknown error', 'ewww-image-optimizer' ) ), // phpcs:ignore WordPress.Security.NonceVerification
esc_html( EWWW_IMAGE_OPTIMIZER_TOOL_PATH )
) . "
\n" .
"
\n";
}
}
/**
* Display a notice that we could not activate an ExactDN domain.
*/
function ewww_image_optimizer_notice_exactdn_activation_error() {
return;
global $exactdn_activate_error;
if ( empty( $exactdn_activate_error ) ) {
$exactdn_activate_error = 'error unknown';
}
echo '
' .
sprintf(
/* translators: %s: A link to the documentation */
esc_html__( 'Could not activate Easy IO, please try again in a few minutes. If this error continues, please see %s for troubleshooting steps.', 'ewww-image-optimizer' ),
'https://docs.ewww.io/article/66-exactdn-not-verified'
) .
' ' . esc_html( $exactdn_activate_error ) . '' .
'
';
}
/**
* Let the user know ExactDN setup was successful.
*/
function ewww_image_optimizer_notice_exactdn_activation_success() {
return;
?>
" . esc_html__( 'ShortPixel image optimization has been disabled to prevent conflicts with Easy IO (EWWW Image Optimizer).', 'ewww-image-optimizer' ) . '
';
}
/**
* Display a notice that PHP version 7.2 will be required in a future version.
*/
function ewww_image_optimizer_php72_warning() {
if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', '' ) ) ) {
return;
}
echo '
';
}
/**
* Warn the user that scheduled optimization will no longer work without background/async mode.
*/
function ewww_image_optimizer_notice_schedule_noasync() {
if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', '' ) ) ) {
return;
}
global $ewwwio_upgrading;
if ( $ewwwio_upgrading ) {
return;
}
echo "
" . esc_html__( 'Scheduled Optimization will not work without background/async ability. See the EWWW Image Optimizer Settings for further instructions.', 'ewww-image-optimizer' ) . '
';
}
/**
* Informs the user about optimization during thumbnail regeneration.
*/
function ewww_image_optimizer_thumbnail_regen_notice() {
echo "
" . esc_html__( 'New thumbnails will be optimized by the EWWW Image Optimizer as they are generated. You may wish to disable the plugin and run a bulk optimize later to speed up the process.', 'ewww-image-optimizer' ) . '';
echo ' ' . esc_html__( 'Learn more.', 'ewww-image-optimizer' ) . '
';
}
/**
* Lets the user know WooCommerce has regenerated thumbnails and that they need to take action.
*/
function ewww_image_optimizer_notice_wc_regen() {
if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', '' ) ) ) {
return;
}
echo "
" . esc_html__( 'EWWW Image Optimizer has detected a WooCommerce thumbnail regeneration. To optimize new thumbnails, you may run the Bulk Optimizer from the Media menu. This notice may be dismissed after the regeneration is complete.', 'ewww-image-optimizer' ) . '
';
}
/**
* Loads the inline script to dismiss the WC regen notice.
*/
function ewww_image_optimizer_wc_regen_script() {
echo "\n";
}
/**
* Lets the user know LR Sync has regenerated thumbnails and that they need to take action.
*/
function ewww_image_optimizer_notice_lr_sync() {
if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', '' ) ) ) {
return;
}
echo "
" . esc_html__( 'EWWW Image Optimizer has detected a WP/LR Sync process. To optimize new thumbnails, you may run the Bulk Optimizer from the Media menu. This notice may be dismissed after the Sync process is complete.', 'ewww-image-optimizer' ) . '
';
}
/**
* Loads the inline script to dismiss the LR sync notice.
*/
function ewww_image_optimizer_lr_sync_script() {
echo "\n";
}
/**
* Let the user know they can view more options and stats in the Media Library's list mode.
*/
function ewww_image_optimizer_notice_media_listmode() {
$current_screen = get_current_screen();
if ( 'upload' === $current_screen->id && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_dismiss_media_notice' ) ) {
$user_info = wp_get_current_user();
if ( ! empty( $user_info->wp_media_library_mode ) && 'list' === $user_info->wp_media_library_mode ) {
update_option( 'ewww_image_optimizer_dismiss_media_notice', true, false );
update_site_option( 'ewww_image_optimizer_dismiss_media_notice', true );
return;
}
?>
';
}
/**
* Ask the user to leave a review for the plugin on wp.org.
*/
function ewww_image_optimizer_notice_review() {
if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', '' ) ) ) {
return;
}
echo "
" .
esc_html__( "Hi, you've been using the EWWW Image Optimizer for a while, and we hope it has been a big help for you.", 'ewww-image-optimizer' ) . ' ' .
esc_html__( 'If you could take a few moments to rate it on WordPress.org, we would really appreciate your help making the plugin better. Thanks!', 'ewww-image-optimizer' ) .
' ' . esc_html__( 'Post Review', 'ewww-image-optimizer' ) . '' .
'
';
}
/**
* Add review link to the footer on our pages.
*
* @param string $footer_text The existing footer text.
* @return string The modified footer text.
*/
function ewww_image_optimizer_footer_review_text( $footer_text ) {
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_dismiss_review_notice' ) ) {
return $footer_text;
}
$review_text = esc_html( 'Thank you for using EWWW Image Optimizer!', 'ewww-image-optimizer' ) . ' ' . esc_html__( 'Please rate us on WordPress.org', 'ewww-image-optimizer' ) . '';
return str_replace( '', '', $footer_text ) . ' | ' . $review_text . '';
}
/**
* Loads the inline script to dismiss the review notice.
*/
function ewww_image_optimizer_notice_review_script() {
echo "\n";
}
/**
* Inform the user of our beacon function so that they can opt-in.
*/
function ewww_image_optimizer_notice_beacon() {
if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', '' ) ) ) {
return;
}
$optin_url = admin_url( 'admin.php?action=eio_opt_into_hs_beacon' );
$optout_url = admin_url( 'admin.php?action=eio_opt_out_of_hs_beacon' );
echo '
';
}
/**
* Alert the user when 5 images have been re-optimized more than 10 times.
*
* @global object $wpdb
*/
function ewww_image_optimizer_notice_reoptimization() {
return; // This is already disabled at the admin_notice hook registration above, but just to be sure.
if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', '' ) ) ) {
return;
}
// Allows the user to reset all images back to 1 optimization, which clears the alert.
if ( ! empty( $_GET['ewww_reset_reopt_nonce'] ) && wp_verify_nonce( sanitize_key( $_GET['ewww_reset_reopt_nonce'] ), 'reset_reoptimization_counters' ) ) {
global $wpdb;
$debug_images = $wpdb->query( "UPDATE $wpdb->ewwwio_images SET updates=1 WHERE updates > 1" );
delete_transient( 'ewww_image_optimizer_images_reoptimized' );
} else {
$reoptimized = get_transient( 'ewww_image_optimizer_images_reoptimized' );
if ( empty( $reoptimized ) ) {
global $wpdb;
$reoptimized = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->ewwwio_images WHERE updates > 5 AND path NOT LIKE '%wp-content/themes%' AND path NOT LIKE '%wp-content/plugins%' LIMIT 10" );
if ( empty( $reoptimized ) ) {
set_transient( 'ewww_image_optimizer_images_reoptimized', 'zero', 12 * HOUR_IN_SECONDS );
} else {
set_transient( 'ewww_image_optimizer_images_reoptimized', $reoptimized, 12 * HOUR_IN_SECONDS );
}
} elseif ( 'zero' === $reoptimized ) {
$reoptimized = 0;
}
// Do a check for 10+ optimizations on 5+ images.
if ( ! empty( $reoptimized ) && $reoptimized > 5 ) {
$debugging_page = admin_url( 'tools.php?page=ewww-image-optimizer-tools' );
$reset_page = wp_nonce_url( add_query_arg( '', '' ), 'reset_reoptimization_counters', 'ewww_reset_reopt_nonce' );
// Display an alert, and let the user reset the warning if they wish.
echo "
",
)
);
}
}
/**
* Gets the link to the main EWWW IO settings.
*
* @return string The link to the main settings (network vs. single-site).
*/
function ewww_image_optimizer_get_settings_link() {
if ( ! function_exists( 'is_plugin_active_for_network' ) && is_multisite() ) {
// Need to include the plugin library for the is_plugin_active function.
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
// Load the html for the settings link.
if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) && ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) {
return network_admin_url( 'settings.php?page=ewww-image-optimizer-options' );
} else {
return admin_url( 'options-general.php?page=ewww-image-optimizer-options' );
}
}
/**
* Adds a link on the Plugins page for the EWWW IO settings.
*
* @param array $links A list of links to display next to the plugin listing.
* @return array The new list of links to be displayed.
*/
function ewww_image_optimizer_settings_link( $links ) {
if ( ! is_array( $links ) ) {
$links = array();
}
$settings_link = '' . esc_html__( 'Settings', 'ewww-image-optimizer' ) . '';
// Load the settings link into the plugin links array.
array_unshift( $links, $settings_link );
// Send back the plugin links array.
return $links;
}
/**
* Check for GD support of both PNG and JPG.
*
* @param bool $cache Whether to use a cached result.
* @return string The version of GD if full support is detected.
*/
function ewww_image_optimizer_gd_support( $cache = true ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
return ewwwio()->gd_support();
}
/**
* Check for GD support of WebP format.
*
* @return bool True if proper WebP support is detected.
*/
function ewww_image_optimizer_gd_supports_webp() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
return ewwwio()->gd_supports_webp();
}
/**
* Use GD to convert an image to WebP.
*
* @param string $file The original source image path.
* @param string $type The mime-type of the original image.
* @param string $webpfile The location to store the new WebP image.
*/
function ewww_image_optimizer_gd_create_webp( $file, $type, $webpfile ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
$quality = (int) apply_filters( 'webp_quality', 75, 'image/webp' );
if ( $quality < 50 || $quality > 100 ) {
$quality = 75;
}
switch ( $type ) {
case 'image/jpeg':
$image = imagecreatefromjpeg( $file );
if ( false === $image ) {
return;
}
break;
case 'image/png':
$image = imagecreatefrompng( $file );
if ( false === $image ) {
return;
}
if ( ! imageistruecolor( $image ) ) {
ewwwio_debug_message( 'converting to true color' );
imagepalettetotruecolor( $image );
}
if ( ewww_image_optimizer_png_alpha( $file ) ) {
ewwwio_debug_message( 'saving alpha and disabling alpha blending' );
imagealphablending( $image, false );
imagesavealpha( $image, true );
}
if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_LOSSY_PNG2WEBP' ) || ! EWWW_IMAGE_OPTIMIZER_LOSSY_PNG2WEBP ) {
$quality = 100;
}
break;
default:
return;
}
ewwwio_debug_message( "creating $webpfile with quality $quality" );
$result = imagewebp( $image, $webpfile, $quality );
// Make sure to cleanup--if $webpfile is borked, that will be handled elsewhere.
imagedestroy( $image );
}
/**
* Check for IMagick support of both PNG and JPG.
*
* @return bool True if full Imagick support is detected.
*/
function ewww_image_optimizer_imagick_support() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
return ewwwio()->imagick_support();
}
/**
* Check for IMagick support of WebP.
*
* @return bool True if WebP support is detected.
*/
function ewww_image_optimizer_imagick_supports_webp() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
return ewwwio()->imagick_supports_webp();
}
/**
* Use IMagick to convert an image to WebP.
*
* @param string $file The original source image path.
* @param string $type The mime-type of the original image.
* @param string $webpfile The location to store the new WebP image.
*/
function ewww_image_optimizer_imagick_create_webp( $file, $type, $webpfile ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
$sharp_yuv = defined( 'EIO_WEBP_SHARP_YUV' ) && EIO_WEBP_SHARP_YUV ? true : false;
if ( empty( $sharp_yuv ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_sharpen' ) ) {
$sharp_yuv = true;
}
$quality = (int) apply_filters( 'webp_quality', 75, 'image/webp' );
if ( $quality < 50 || $quality > 100 ) {
$quality = 75;
}
$profiles = array();
switch ( $type ) {
case 'image/jpeg':
$image = new Imagick( $file );
if ( false === $image ) {
return;
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) ) {
// Getting possible color profiles.
$profiles = $image->getImageProfiles( 'icc', true );
}
$color = $image->getImageColorspace();
ewwwio_debug_message( "color space is $color" );
if ( Imagick::COLORSPACE_CMYK === $color ) {
ewwwio_debug_message( 'found CMYK image' );
if ( ewwwio_is_file( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'vendor/icc/sRGB2014.icc' ) ) {
ewwwio_debug_message( 'adding icc profile' );
$icc_profile = file_get_contents( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'vendor/icc/sRGB2014.icc' );
$image->profileImage( 'icc', $icc_profile );
}
ewwwio_debug_message( 'attempting SRGB transform' );
$image->transformImageColorspace( Imagick::COLORSPACE_SRGB );
ewwwio_debug_message( 'removing icc profile' );
$image->setImageProfile( '*', null );
$profiles = array();
}
$image->setImageFormat( 'WEBP' );
if ( $sharp_yuv ) {
ewwwio_debug_message( 'enabling sharp_yuv' );
$image->setOption( 'webp:use-sharp-yuv', 'true' );
}
ewwwio_debug_message( "setting quality to $quality" );
$image->setImageCompressionQuality( $quality );
break;
case 'image/png':
$image = new Imagick( $file );
if ( false === $image ) {
return;
}
$image->setImageFormat( 'WEBP' );
if ( defined( 'EWWW_IMAGE_OPTIMIZER_LOSSY_PNG2WEBP' ) && EWWW_IMAGE_OPTIMIZER_LOSSY_PNG2WEBP ) {
ewwwio_debug_message( 'doing lossy conversion' );
if ( $sharp_yuv ) {
ewwwio_debug_message( 'enabling sharp_yuv' );
$image->setOption( 'webp:use-sharp-yuv', 'true' );
}
ewwwio_debug_message( "setting quality to $quality" );
$image->setImageCompressionQuality( $quality );
} else {
ewwwio_debug_message( 'sticking to lossless' );
$image->setOption( 'webp:lossless', true );
$image->setOption( 'webp:alpha-quality', 100 );
}
break;
default:
return;
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) ) {
ewwwio_debug_message( 'removing meta' );
$image->stripImage();
if ( ! empty( $profiles ) ) {
ewwwio_debug_message( 'adding color profile to WebP' );
$image->profileImage( 'icc', $profiles['icc'] );
}
}
ewwwio_debug_message( 'getting blob' );
$image_blob = $image->getImageBlob();
ewwwio_debug_message( 'writing file' );
file_put_contents( $webpfile, $image_blob );
}
/**
* Check for GMagick support of both PNG and JPG.
*
* @return bool True if full Gmagick support is detected.
*/
function ewww_image_optimizer_gmagick_support() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
return ewwwio()->gmagick_support();
}
/**
* Filter the filename past any folders the user chose to ignore.
*
* @param bool $bypass True to skip optimization, defaults to false.
* @param string $filename The file about to be optimized.
* @return bool True if the file matches any folders to ignore.
*/
function ewww_image_optimizer_ignore_file( $bypass, $filename ) {
$ignore_folders = ewww_image_optimizer_get_option( 'ewww_image_optimizer_exclude_paths' );
if ( ! ewww_image_optimizer_iterable( $ignore_folders ) ) {
return $bypass;
}
foreach ( $ignore_folders as $ignore_folder ) {
if ( strpos( $filename, $ignore_folder ) !== false ) {
return true;
}
}
return $bypass;
}
/**
* Add a file to the exclusions list.
*
* @param string $file_path The path of the file to ignore.
*/
function ewww_image_optimizer_add_file_exclusion( $file_path ) {
if ( ! is_string( $file_path ) ) {
return;
}
// Add it to the files to ignore.
$ignore_folders = ewww_image_optimizer_get_option( 'ewww_image_optimizer_exclude_paths' );
if ( ! is_array( $ignore_folders ) ) {
$ignore_folders = array();
}
$file_path = str_replace( ABSPATH, '', $file_path );
$file_path = str_replace( WP_CONTENT_DIR, '', $file_path );
$ignore_folders[] = $file_path;
ewww_image_optimizer_set_option( 'ewww_image_optimizer_exclude_paths', $ignore_folders );
}
/**
* Sanitize the list of disabled resizes.
*
* @param array $disabled_resizes A list of sizes, like 'medium_large', 'thumb', etc.
* @return array|string The sanitized list of sizes, or an empty string.
*/
function ewww_image_optimizer_disable_resizes_sanitize( $disabled_resizes ) {
if ( is_array( $disabled_resizes ) ) {
return $disabled_resizes;
} else {
return '';
}
}
/**
* Sanitize the list of folders to optimize.
*
* @param string $input A list of filesystem paths, from a textarea.
* @return array The list of paths, validated, and converted to an array.
*/
function ewww_image_optimizer_aux_paths_sanitize( $input ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( empty( $input ) ) {
return '';
}
$path_array = array();
if ( is_array( $input ) ) {
$paths = $input;
} elseif ( is_string( $input ) ) {
$paths = explode( "\n", $input );
}
$abspath = false;
$permissions = apply_filters( 'ewww_image_optimizer_superadmin_permissions', '' );
if ( is_multisite() && current_user_can( $permissions ) ) {
$abspath = true;
} elseif ( ! is_multisite() ) {
$abspath = true;
}
$blog_one = false;
if ( 1 === get_current_blog_id() ) {
$blog_one = true;
}
if ( ewww_image_optimizer_iterable( $paths ) ) {
$i = 0;
foreach ( $paths as $path ) {
++$i;
$path = sanitize_text_field( $path );
ewwwio_debug_message( "validating auxiliary path: $path" );
// Retrieve the location of the WordPress upload folder.
$upload_dir = wp_get_upload_dir();
// Retrieve the path of the upload folder from the array.
$upload_path = trailingslashit( $upload_dir['basedir'] );
if ( ! $abspath && $blog_one && false !== strpos( $path, $upload_path . 'sites' ) ) {
add_settings_error(
'ewww_image_optimizer_aux_paths',
"ewwwio-aux-paths-$i",
sprintf(
/* translators: %s: A file system path */
esc_html__( 'Could not save Folder to Optimize: %s. Access denied.', 'ewww-image-optimizer' ),
esc_html( $path )
)
);
continue;
}
if ( ( ( $abspath && strpos( $path, ABSPATH ) === 0 ) || strpos( $path, $upload_path ) === 0 ) && ewwwio_is_dir( $path ) ) {
$path_array[] = $path;
continue;
}
// If they put in a relative path.
if ( $abspath && ewwwio_is_dir( ABSPATH . ltrim( $path, '/' ) ) ) {
$path_array[] = ABSPATH . ltrim( $path, '/' );
continue;
}
// Or a path relative to the upload dir?
if ( ewwwio_is_dir( $upload_path . ltrim( $path, '/' ) ) ) {
$path_array[] = $upload_path . ltrim( $path, '/' );
continue;
}
// What if they put in a url?
$pathabsurl = ABSPATH . ltrim( str_replace( get_site_url(), '', $path ), '/' );
if ( $abspath && ewwwio_is_dir( $pathabsurl ) ) {
$path_array[] = $pathabsurl;
continue;
}
// Or a url in the uploads folder?
$pathupurl = $upload_path . ltrim( str_replace( $upload_dir['baseurl'], '', $path ), '/' );
if ( ewwwio_is_dir( $pathupurl ) ) {
$path_array[] = $pathupurl;
continue;
}
if ( ! empty( $path ) ) {
add_settings_error(
'ewww_image_optimizer_aux_paths',
"ewwwio-aux-paths-$i",
sprintf(
/* translators: %s: A file system path */
esc_html__( 'Could not save Folder to Optimize: %s. Please ensure that it is a valid location on the server.', 'ewww-image-optimizer' ),
esc_html( $path )
)
);
}
} // End foreach().
} // End if().
ewwwio_memory( __FUNCTION__ );
return $path_array;
}
/**
* Sanitize the url patterns used for WebP rewriting.
*
* @param string $paths A list of urls/patterns, from a textarea.
* @return array The sanitize list of url patterns for WebP matching.
*/
function ewww_image_optimizer_webp_paths_sanitize( $paths ) {
if ( empty( $paths ) ) {
return '';
}
$paths_saved = array();
if ( is_array( $paths ) ) {
$paths_entered = $paths;
} elseif ( is_string( $paths ) ) {
$paths_entered = explode( "\n", $paths );
}
if ( ewww_image_optimizer_iterable( $paths_entered ) ) {
$i = 0;
foreach ( $paths_entered as $path ) {
++$i;
$original_path = esc_html( trim( $path, '*' ) );
$path = esc_url( $path, null, 'db' );
if ( ! empty( $path ) ) {
if ( ! substr_count( $path, '.' ) ) {
add_settings_error(
'ewww_image_optimizer_webp_paths',
"ewwwio-webp-paths-$i",
sprintf(
/* translators: %s: A url or domain name */
esc_html__( 'Could not save WebP URL: %s.', 'ewww-image-optimizer' ),
esc_html( $original_path )
) . ' ' . esc_html__( 'Please enter a valid URL including the domain name.', 'ewww-image-optimizer' )
);
continue;
}
$paths_saved[] = trailingslashit( str_replace( 'http://', '', $path ) );
}
}
}
return $paths_saved;
}
/**
* Retrieves/sanitizes jpg background fill setting or returns null for png2jpg conversions.
*
* @param string $background The hexadecimal value entered by the user.
* @return string The background color sanitized.
*/
function ewww_image_optimizer_jpg_background( $background = null ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( is_null( $background ) ) {
// Retrieve the user-supplied value for jpg background color.
$background = ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_background' );
}
// Verify that the supplied value is in hex notation.
if ( is_string( $background ) && preg_match( '/^\#*([0-9a-fA-F]){6}$/', $background ) ) {
// We remove a leading # symbol, since we take care of it later.
$background = ltrim( $background, '#' );
// Send back the verified, cleaned-up background color.
ewwwio_debug_message( "background: $background" );
ewwwio_memory( __FUNCTION__ );
return $background;
} else {
if ( ! empty( $background ) ) {
add_settings_error( 'ewww_image_optimizer_jpg_background', 'ewwwio-jpg-background', esc_html__( 'Could not save the JPG background color, please enter a six-character, hexadecimal value.', 'ewww-image-optimizer' ) );
}
// Send back a blank value.
ewwwio_memory( __FUNCTION__ );
return '';
}
}
/**
* Retrieves/sanitizes the jpg quality setting for png2jpg conversion or returns null.
*
* @param int $quality The JPG quality level as set by the user.
* @return int The sanitized JPG quality level.
*/
function ewww_image_optimizer_jpg_quality( $quality = null ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( is_null( $quality ) ) {
// Retrieve the user-supplied value for jpg quality.
$quality = ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_quality' );
}
// Verify that the quality level is an integer, 1-100.
if ( is_numeric( $quality ) && preg_match( '/^(100|[1-9][0-9]?)$/', $quality ) ) {
ewwwio_debug_message( "quality: $quality" );
// Send back the valid quality level.
ewwwio_memory( __FUNCTION__ );
return $quality;
} else {
if ( ! empty( $quality ) ) {
add_settings_error( 'ewww_image_optimizer_jpg_quality', 'ewwwio-jpg-quality', esc_html__( 'Could not save the JPG quality, please enter an integer between 1 and 100.', 'ewww-image-optimizer' ) );
}
// Send back nothing.
return '';
}
}
/**
* Overrides the default JPG quality for WordPress image editing operations.
*
* @param int $quality The default JPG quality level.
* @return int The default quality, or the user configured level.
*/
function ewww_image_optimizer_set_jpg_quality( $quality ) {
$new_quality = ewww_image_optimizer_jpg_quality();
if ( ! empty( $new_quality ) ) {
return min( 92, $new_quality );
}
return min( 92, $quality );
}
/**
* Retrieves/sanitizes the WebP quality setting or returns null.
*
* @param int $quality The WebP quality level as set by the user.
* @return int The sanitized WebP quality level.
*/
function ewww_image_optimizer_webp_quality( $quality = null ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( is_null( $quality ) ) {
// Retrieve the user-supplied value for WebP quality.
$quality = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_quality' );
}
// Verify that the quality level is an integer, 1-100.
if ( is_numeric( $quality ) && preg_match( '/^(100|[1-9][0-9]?)$/', $quality ) ) {
ewwwio_debug_message( "webp quality: $quality" );
// Send back the valid quality level.
return $quality;
} else {
if ( ! empty( $quality ) ) {
add_settings_error( 'ewww_image_optimizer_webp_quality', 'ewwwio-webp-quality', esc_html__( 'Could not save the WebP quality, please enter an integer between 50 and 100.', 'ewww-image-optimizer' ) );
}
// Send back nothing.
return '';
}
}
/**
* Overrides the default WebP quality (if a user-defined value is set).
*
* @param int $quality The default WebP quality level.
* @return int The default quality, or the user configured level.
*/
function ewww_image_optimizer_set_webp_quality( $quality ) {
$new_quality = ewww_image_optimizer_webp_quality();
if ( ! empty( $new_quality ) ) {
return min( 92, $new_quality );
}
return min( 92, $quality );
}
/**
* Retrieves/sanitizes the AVIF quality setting or returns null.
*
* @param int $quality The AVIF quality level as set by the user.
* @return int The sanitized AVIF quality level.
*/
function ewww_image_optimizer_avif_quality( $quality = null ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( is_null( $quality ) ) {
// Retrieve the user-supplied value for AVIF quality.
$quality = ewww_image_optimizer_get_option( 'ewww_image_optimizer_avif_quality' );
}
// Verify that the quality level is an integer, 1-100.
if ( is_numeric( $quality ) && preg_match( '/^(100|[1-9][0-9]?)$/', $quality ) ) {
ewwwio_debug_message( "avif quality: $quality" );
// Send back the valid quality level.
return $quality;
} else {
if ( ! empty( $quality ) ) {
add_settings_error( 'ewww_image_optimizer_avif_quality', 'ewwwio-avif-quality', esc_html__( 'Could not save the AVIF quality, please enter an integer between 50 and 100.', 'ewww-image-optimizer' ) );
}
// Send back nothing.
return '';
}
}
/**
* Overrides the default AVIF quality (if a user-defined value is set).
*
* @param int $quality The default AVIF quality level.
* @return int The default quality, or the user configured level.
*/
function ewww_image_optimizer_set_avif_quality( $quality ) {
$new_quality = ewww_image_optimizer_avif_quality();
if ( ! empty( $new_quality ) ) {
return min( 92, $new_quality );
}
return min( 92, $quality );
}
/**
* Check default WP threshold and adjust to comply with normal EWWW IO behavior.
*
* @param int $size The default WP scaling size, or whatever has been filtered by other plugins.
* @param array $imagesize {
* Indexed array of the image width and height in pixels.
*
* @type int $0 The image width.
* @type int $1 The image height.
* }
* @param string $file Full path to the uploaded image file.
* @return int The proper size to use for scaling originals.
*/
function ewww_image_optimizer_adjust_big_image_threshold( $size, $imagesize = array(), $file = '' ) {
if ( false !== strpos( $file, 'noresize' ) ) {
return false;
}
$max_size = max(
ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ),
ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' ),
(int) $size
);
return $max_size;
}
/**
* Setup the global filesystem class variable.
*/
function ewwwio_get_filesystem() {
require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php';
require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php';
global $eio_filesystem;
if ( ! defined( 'FS_CHMOD_DIR' ) ) {
define( 'FS_CHMOD_DIR', ( fileperms( ABSPATH ) & 0777 | 0755 ) );
}
if ( ! defined( 'FS_CHMOD_FILE' ) ) {
define( 'FS_CHMOD_FILE', ( fileperms( ABSPATH . 'index.php' ) & 0777 | 0644 ) );
}
if ( ! isset( $eio_filesystem ) || ! is_object( $eio_filesystem ) ) {
$eio_filesystem = new WP_Filesystem_Direct( '' );
}
}
/**
* Check filesize, and prevent errors by ensuring file exists, and that the cache has been cleared.
*
* @param string $file The name of the file.
* @return int The size of the file or zero.
*/
function ewww_image_optimizer_filesize( $file ) {
$file = realpath( $file );
if ( ewwwio_is_file( $file ) ) {
global $eio_filesystem;
ewwwio_get_filesystem();
// Flush the cache for filesize.
clearstatcache();
// Find out the size of the new PNG file.
return $eio_filesystem->size( $file );
} else {
return 0;
}
}
/**
* Check if open_basedir restriction is in effect, and that the path is allowed and exists.
*
* Note that when the EWWWIO_OPEN_BASEDIR constant is defined, is_file() will be skipped.
*
* @param string $file The path of the file to check.
* @return bool False if open_basedir setting cannot be retrieved, or the file is "out of bounds", true if the file exists.
*/
function ewwwio_system_binary_exists( $file ) {
if ( ! ewww_image_optimizer_function_exists( 'ini_get' ) && ! defined( 'EWWWIO_OPEN_BASEDIR' ) ) {
return false;
}
if ( defined( 'EWWWIO_OPEN_BASEDIR' ) ) {
$basedirs = EWWWIO_OPEN_BASEDIR;
} else {
$basedirs = ini_get( 'open_basedir' );
}
if ( empty( $basedirs ) ) {
return defined( 'EWWWIO_OPEN_BASEDIR' ) ? true : is_file( $file );
}
$basedirs = explode( PATH_SEPARATOR, $basedirs );
foreach ( $basedirs as $basedir ) {
$basedir = trim( $basedir );
if ( 0 === strpos( $file, $basedir ) ) {
return defined( 'EWWWIO_OPEN_BASEDIR' ) ? true : is_file( $file );
}
}
return false;
}
/**
* Check if a file/directory is readable.
*
* @param string $file The path to check.
* @return bool True if it is, false if it ain't.
*/
function ewwwio_is_readable( $file ) {
global $eio_filesystem;
ewwwio_get_filesystem();
return $eio_filesystem->is_readable( $file );
}
/**
* Check if directory exists, and that it is local rather than using a protocol like http:// or phar://
*
* @param string $dir The path of the directoy to check.
* @return bool True if the directory exists and is local, false otherwise.
*/
function ewwwio_is_dir( $dir ) {
if ( false !== strpos( $dir, '://' ) ) {
return false;
}
if ( false !== strpos( $dir, 'phar://' ) ) {
return false;
}
global $eio_filesystem;
ewwwio_get_filesystem();
$dir = realpath( $dir );
$wp_dir = realpath( ABSPATH );
$upload_dir = wp_get_upload_dir();
$upload_dir = realpath( $upload_dir['basedir'] );
$content_dir = realpath( WP_CONTENT_DIR );
if ( empty( $content_dir ) ) {
$content_dir = $wp_dir;
}
if ( empty( $upload_dir ) ) {
$upload_dir = $content_dir;
}
if ( defined( 'EWWW_IMAGE_OPTIMIZER_TOOL_PATH' ) ) {
$tool_dir = realpath( EWWW_IMAGE_OPTIMIZER_TOOL_PATH );
$tool_dir = dirname( $tool_dir );
}
if ( empty( $tool_dir ) ) {
$tool_dir = $content_dir;
}
if ( defined( 'EWWWIO_CONTENT_DIR' ) ) {
$eio_content_dir = realpath( EWWWIO_CONTENT_DIR );
}
if ( empty( $eio_content_dir ) ) {
$eio_content_dir = $content_dir;
}
$plugin_dir = realpath( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH );
if (
false === strpos( $dir, $upload_dir ) &&
false === strpos( $dir, $content_dir ) &&
false === strpos( $dir, $wp_dir ) &&
false === strpos( $dir, $plugin_dir ) &&
false === strpos( $file, $tool_dir ) &&
false === strpos( $file, $eio_content_dir )
) {
return false;
}
return $eio_filesystem->is_dir( $dir );
}
/**
* Check if file exists, and that it is local rather than using a protocol like http:// or phar://
*
* @param string $file The path of the file to check.
* @return bool True if the file exists and is local, false otherwise.
*/
function ewwwio_is_file( $file ) {
if ( false !== strpos( $file, '://' ) ) {
return false;
}
if ( false !== strpos( $file, 'phar://' ) ) {
return false;
}
global $eio_filesystem;
ewwwio_get_filesystem();
$file = realpath( $file );
$wp_dir = realpath( ABSPATH );
$upload_dir = wp_get_upload_dir();
$upload_dir = realpath( $upload_dir['basedir'] );
$content_dir = realpath( WP_CONTENT_DIR );
if ( empty( $content_dir ) ) {
$content_dir = $wp_dir;
}
if ( empty( $upload_dir ) ) {
$upload_dir = $content_dir;
}
$plugin_dir = realpath( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH );
if ( defined( 'EWWW_IMAGE_OPTIMIZER_TOOL_PATH' ) ) {
$tool_dir = realpath( EWWW_IMAGE_OPTIMIZER_TOOL_PATH );
$tool_dir = dirname( $tool_dir );
}
if ( empty( $tool_dir ) ) {
$tool_dir = $content_dir;
}
if ( defined( 'EWWWIO_CONTENT_DIR' ) ) {
$eio_content_dir = realpath( EWWWIO_CONTENT_DIR );
}
if ( empty( $eio_content_dir ) ) {
$eio_content_dir = $content_dir;
}
if (
false === strpos( $file, $upload_dir ) &&
false === strpos( $file, $content_dir ) &&
false === strpos( $file, $wp_dir ) &&
false === strpos( $file, $plugin_dir ) &&
false === strpos( $file, $tool_dir ) &&
false === strpos( $file, $eio_content_dir )
) {
return false;
}
return $eio_filesystem->is_file( $file );
}
/**
* Check if destination is in an approved location and rename the original.
*
* @param string $src The path of the original file.
* @param string $dst The destination file path.
* @return bool True if the file was removed, false otherwise.
*/
function ewwwio_rename( $src, $dst ) {
global $eio_filesystem;
ewwwio_get_filesystem();
$src = realpath( $src );
if ( false !== strpos( $dst, WP_CONTENT_DIR ) ) {
return $eio_filesystem->move( $src, $dst, true );
}
if ( false !== strpos( $dst, ABSPATH ) ) {
return $eio_filesystem->move( $src, $dst, true );
}
$upload_dir = wp_get_upload_dir();
if ( false !== strpos( $dst, $upload_dir['basedir'] ) ) {
return $eio_filesystem->move( $src, $dst, true );
}
return false;
}
/**
* Check if file is in an approved location and remove it.
*
* @param string $file The path of the file to check.
* @param string $dir The path of the folder constraint. Optional.
* @return bool True if the file was removed, false otherwise.
*/
function ewwwio_delete_file( $file, $dir = '' ) {
$file = realpath( $file );
if ( ! empty( $dir ) ) {
return wp_delete_file_from_directory( $file, $dir );
}
$wp_dir = realpath( ABSPATH );
$upload_dir = wp_get_upload_dir();
$upload_dir = realpath( $upload_dir['basedir'] );
$content_dir = realpath( WP_CONTENT_DIR );
if ( false !== strpos( $file, $upload_dir ) ) {
return wp_delete_file_from_directory( $file, $upload_dir );
}
if ( false !== strpos( $file, $content_dir ) ) {
return wp_delete_file_from_directory( $file, $content_dir );
}
if ( false !== strpos( $file, $wp_dir ) ) {
return wp_delete_file_from_directory( $file, $wp_dir );
}
return false;
}
/**
* Check if file is in an approved location and chmod it.
*
* @param string $file The path of the file to check.
* @param string $mode The mode to apply to the file.
*/
function ewwwio_chmod( $file, $mode ) {
global $eio_filesystem;
ewwwio_get_filesystem();
clearstatcache();
$file = realpath( $file );
$upload_dir = wp_get_upload_dir();
if ( false !== strpos( $file, $upload_dir['basedir'] ) && is_writable( $file ) ) {
return $eio_filesystem->chmod( $file, $mode );
}
if ( false !== strpos( $file, WP_CONTENT_DIR ) && is_writable( $file ) ) {
return $eio_filesystem->chmod( $file, $mode );
}
if ( false !== strpos( $file, ABSPATH ) && is_writable( $file ) ) {
return $eio_filesystem->chmod( $file, $mode );
}
return false;
}
/**
* Manually process an image from the Media Library
*
* @global bool $ewww_defer True if the image optimization should be deferred.
*/
function ewww_image_optimizer_manual() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
global $ewww_force;
global $ewww_convert;
global $ewww_defer;
$ewww_defer = false;
add_filter( 'ewww_image_optimizer_allowed_reopt', '__return_true' );
// Check permissions of current user.
$permissions = apply_filters( 'ewww_image_optimizer_manual_permissions', '' );
if ( ! current_user_can( $permissions ) ) {
// Display error message if insufficient permissions.
if ( ! wp_doing_ajax() ) {
wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
}
ewwwio_ob_clean();
wp_die( wp_json_encode( array( 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) ) ) );
}
// Make sure we didn't accidentally get to this page without an attachment to work on.
if ( empty( $_REQUEST['ewww_attachment_ID'] ) || empty( $_REQUEST['action'] ) ) {
// Display an error message since we don't have anything to work on.
if ( ! wp_doing_ajax() ) {
wp_die( esc_html__( 'Invalid request.', 'ewww-image-optimizer' ) );
}
ewwwio_ob_clean();
wp_die( wp_json_encode( array( 'error' => esc_html__( 'Invalid request.', 'ewww-image-optimizer' ) ) ) );
}
session_write_close();
if ( empty( $_REQUEST['ewww_manual_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_REQUEST['ewww_manual_nonce'] ), 'ewww-manual' ) ) {
if ( ! wp_doing_ajax() ) {
wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
}
ewwwio_ob_clean();
wp_die( wp_json_encode( array( 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ) ) ) );
}
// Store the attachment ID value.
$attachment_id = (int) $_REQUEST['ewww_attachment_ID'];
$ewww_force = ! empty( $_REQUEST['ewww_force'] ) ? true : false;
$ewww_convert = ! empty( $_REQUEST['ewww_convert'] ) ? true : false;
// Retrieve the existing attachment metadata.
$original_meta = wp_get_attachment_metadata( $attachment_id );
// If the call was to optimize...
if ( 'ewww_image_optimizer_manual_optimize' === $_REQUEST['action'] || 'ewww_manual_optimize' === $_REQUEST['action'] ) {
// Call the optimize from metadata function and store the resulting new metadata.
$new_meta = ewww_image_optimizer_resize_from_meta_data( $original_meta, $attachment_id );
} elseif ( 'ewww_image_optimizer_manual_restore' === $_REQUEST['action'] || 'ewww_manual_restore' === $_REQUEST['action'] ) {
$new_meta = ewww_image_optimizer_restore_from_meta_data( $original_meta, $attachment_id );
} elseif ( 'ewww_image_optimizer_manual_image_restore' === $_REQUEST['action'] || 'ewww_manual_image_restore' === $_REQUEST['action'] ) {
global $eio_backup;
$new_meta = $eio_backup->restore_backup_from_meta_data( $attachment_id, 'media', $original_meta );
} else {
if ( ! wp_doing_ajax() ) {
wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
}
ewwwio_ob_clean();
wp_die( wp_json_encode( array( 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ) ) ) );
}
$basename = '';
if ( is_array( $new_meta ) && ! empty( $new_meta['file'] ) ) {
$basename = wp_basename( $new_meta['file'] );
}
// Update the attachment metadata in the database.
$meta_saved = wp_update_attachment_metadata( $attachment_id, $new_meta );
if ( ! $meta_saved ) {
ewwwio_debug_message( 'failed to save meta, or no changes' );
}
if ( 'exceeded' === get_transient( 'ewww_image_optimizer_cloud_status' ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_exceeded' ) > time() ) {
if ( ! wp_doing_ajax() ) {
wp_die( '' . esc_html__( 'License exceeded', 'ewww-image-optimizer' ) . '' );
}
ewwwio_ob_clean();
wp_die(
wp_json_encode(
array(
'error' => '' . esc_html__( 'License exceeded', 'ewww-image-optimizer' ) . '',
)
)
);
} elseif ( 'exceeded quota' === get_transient( 'ewww_image_optimizer_cloud_status' ) ) {
if ( ! wp_doing_ajax() ) {
wp_die( '' . esc_html__( 'Soft quota reached, contact us for more', 'ewww-image-optimizer' ) . '' );
}
ewwwio_ob_clean();
wp_die(
wp_json_encode(
array(
'error' => '' . esc_html__( 'Soft quota reached, contact us for more', 'ewww-image-optimizer' ) . '',
)
)
);
}
$success = ewww_image_optimizer_custom_column_capture( 'ewww-image-optimizer', $attachment_id, $new_meta );
ewww_image_optimizer_debug_log();
// Do a redirect, if this was called via GET.
if ( ! wp_doing_ajax() ) {
// Store the referring webpage location.
$sendback = wp_get_referer();
// Send the user back where they came from.
wp_safe_redirect( $sendback );
die;
}
ewwwio_memory( __FUNCTION__ );
ewwwio_ob_clean();
wp_die(
wp_json_encode(
array(
'success' => $success,
'basename' => $basename,
)
)
);
}
/**
* Manually restore a converted image.
*
* @global object $wpdb
* @global object $ewwwdb A clone of $wpdb unless it is lacking utf8 connectivity.
*
* @param array $meta The attachment metadata.
* @param int $id The attachment id number.
* @return array The attachment metadata.
*/
function ewww_image_optimizer_restore_from_meta_data( $meta, $id ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
global $wpdb;
if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
ewww_image_optimizer_db_init();
global $ewwwdb;
} else {
$ewwwdb = $wpdb;
}
$db_image = $ewwwdb->get_results( "SELECT id,path,converted FROM $ewwwdb->ewwwio_images WHERE attachment_id = $id AND gallery = 'media' AND resize = 'full'", ARRAY_A );
if ( empty( $db_image ) || ! is_array( $db_image ) || empty( $db_image['path'] ) ) {
// Get the filepath based on the meta and id.
list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
$db_image = ewww_image_optimizer_find_already_optimized( $file_path );
if ( empty( $db_image ) || ! is_array( $db_image ) || empty( $db_image['path'] ) ) {
return $meta;
}
}
$ewww_image = new EWWW_Image( $id, 'media', ewww_image_optimizer_absolutize_path( $db_image['path'] ) );
remove_filter( 'wp_update_attachment_metadata', 'ewww_image_optimizer_update_filesize_metadata', 9 );
return ewww_image_optimizer_update_filesize_metadata( $ewww_image->restore_with_meta( $meta ), $id, $ewww_image->file );
}
/**
* Manually restore an attachment from the API
*
* @global object $wpdb
* @global object $ewwwdb A clone of $wpdb unless it is lacking utf8 connectivity.
*
* @param int $id The attachment id number.
* @param string $gallery Optional. The gallery from whence we came. Default 'media'.
* @param array $meta Optional. The image metadata from the postmeta table.
* @return array The altered meta (if size differs), or the original value passed along.
*/
function ewww_image_optimizer_cloud_restore_from_meta_data( $id, $gallery = 'media', $meta = array() ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
global $wpdb;
if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
ewww_image_optimizer_db_init();
global $ewwwdb;
} else {
$ewwwdb = $wpdb;
}
$images = $ewwwdb->get_results( "SELECT id,path,resize,backup FROM $ewwwdb->ewwwio_images WHERE attachment_id = $id AND gallery = '$gallery'", ARRAY_A );
foreach ( $images as $image ) {
if ( ! empty( $image['path'] ) ) {
$image['path'] = ewww_image_optimizer_absolutize_path( $image['path'] );
}
ewww_image_optimizer_cloud_restore_single_image( $image );
if ( 'media' === $gallery && 'full' === $image['resize'] && ! empty( $meta['width'] ) && ! empty( $meta['height'] ) ) {
list( $width, $height ) = wp_getimagesize( $image['path'] );
if ( (int) $width !== (int) $meta['width'] || (int) $height !== (int) $meta['height'] ) {
$meta['height'] = $height;
$meta['width'] = $width;
}
}
}
remove_filter( 'wp_update_attachment_metadata', 'ewww_image_optimizer_update_filesize_metadata', 9 );
$meta = ewww_image_optimizer_update_filesize_metadata( $meta, $id );
if ( ewww_image_optimizer_s3_uploads_enabled() ) {
ewww_image_optimizer_remote_push( $meta, $id );
ewwwio_debug_message( 're-uploading to S3(_Uploads)' );
}
return $meta;
}
/**
* Handle the AJAX call for a single image restore.
*/
function ewww_image_optimizer_cloud_restore_single_image_handler() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
// Check permissions of current user.
$permissions = apply_filters( 'ewww_image_optimizer_manual_permissions', '' );
if ( false === current_user_can( $permissions ) ) {
// Display error message if insufficient permissions.
ewwwio_ob_clean();
wp_die( wp_json_encode( array( 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) ) ) );
}
// Make sure we didn't accidentally get to this page without an attachment to work on.
if ( empty( $_REQUEST['ewww_image_id'] ) ) {
// Display an error message since we don't have anything to work on.
ewwwio_ob_clean();
wp_die( wp_json_encode( array( 'error' => esc_html__( 'No image ID was provided.', 'ewww-image-optimizer' ) ) ) );
}
if ( empty( $_REQUEST['ewww_wpnonce'] ) || ! wp_verify_nonce( sanitize_key( $_REQUEST['ewww_wpnonce'] ), 'ewww-image-optimizer-tools' ) ) {
ewwwio_ob_clean();
wp_die( wp_json_encode( array( 'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) ) ) );
}
session_write_close();
$image = (int) $_REQUEST['ewww_image_id'];
if ( ewww_image_optimizer_cloud_restore_single_image( $image ) ) {
ewwwio_ob_clean();
wp_die( wp_json_encode( array( 'success' => 1 ) ) );
}
ewwwio_ob_clean();
wp_die( wp_json_encode( array( 'error' => esc_html__( 'Unable to restore image.', 'ewww-image-optimizer' ) ) ) );
}
/**
* Restores a single image from the API.
*
* @global object $wpdb
* @global object $ewwwdb A clone of $wpdb unless it is lacking utf8 connectivity.
*
* @param int|array $image The db record/ID of the image to restore.
* @return bool True if the image was restored successfully.
*/
function ewww_image_optimizer_cloud_restore_single_image( $image ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
global $eio_backup;
global $wpdb;
if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
ewww_image_optimizer_db_init();
global $ewwwdb;
} else {
$ewwwdb = $wpdb;
}
if ( ! is_array( $image ) && ! empty( $image ) && is_numeric( $image ) ) {
$image = $ewwwdb->get_row( "SELECT id,path,backup FROM $ewwwdb->ewwwio_images WHERE id = $image", ARRAY_A );
}
if ( ! empty( $image['path'] ) ) {
$image['path'] = ewww_image_optimizer_absolutize_path( $image['path'] );
}
$api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
$domain = parse_url( get_site_url(), PHP_URL_HOST );
$url = 'http://optimize.exactlywww.com/backup/restore.php';
$ssl = wp_http_supports( array( 'ssl' ) );
if ( $ssl ) {
$url = set_url_scheme( $url, 'https' );
}
$result = wp_remote_post(
$url,
array(
'timeout' => 30,
'sslverify' => false,
'body' => array(
'api_key' => $api_key,
'domain' => $domain,
'hash' => $image['backup'],
),
)
);
if ( is_wp_error( $result ) ) {
$error_message = $result->get_error_message();
ewwwio_debug_message( "restore request failed: $error_message" );
ewwwio_memory( __FUNCTION__ );
/* translators: %s: An HTTP error message */
$eio_backup->throw_error( sprintf( __( 'Restore failed with HTTP error: %s', 'ewww-image-optimizer' ), $error_message ) );
return false;
} elseif ( ! empty( $result['body'] ) && strpos( $result['body'], 'missing' ) === false ) {
$enabled_types = array( 'image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'image/svg+xml' );
if ( ! is_dir( dirname( $image['path'] ) ) ) {
wp_mkdir_p( dirname( $image['path'] ) );
}
file_put_contents( $image['path'] . '.tmp', $result['body'] );
$new_type = ewww_image_optimizer_mimetype( $image['path'] . '.tmp', 'i' );
$old_type = '';
if ( ewwwio_is_file( $image['path'] ) ) {
$old_type = ewww_image_optimizer_mimetype( $image['path'], 'i' );
}
if ( ! in_array( $new_type, $enabled_types, true ) ) {
/* translators: %s: An image filename */
$eio_backup->throw_error( sprintf( __( 'Backup file for %s has the wrong mime type.', 'ewww-image-optimizer' ), $image['path'] ) );
return false;
}
if ( empty( $old_type ) || $old_type === $new_type ) {
if ( ewwwio_rename( $image['path'] . '.tmp', $image['path'] ) ) {
ewwwio_debug_message( "{$image['path']} was restored, removing .webp version and resetting db record" );
if ( ewwwio_is_file( $image['path'] . '.webp' ) && is_writable( $image['path'] . '.webp' ) ) {
unlink( $image['path'] . '.webp' );
}
// Set the results to nothing.
$ewwwdb->query( "UPDATE $ewwwdb->ewwwio_images SET results = '', image_size = 0, updates = 0, updated=updated, level = 0 WHERE id = {$image['id']}" );
return true;
}
}
}
/* translators: %s: An image filename */
$eio_backup->throw_error( sprintf( __( 'Backup could not be retrieved for %s.', 'ewww-image-optimizer' ), $image['path'] ) );
return false;
}
/**
* Cleans up when an attachment is being deleted.
*
* Removes any .webp images, backups from conversion, and removes related database records.
*
* @global object $wpdb
* @global object $ewwwdb A clone of $wpdb unless it is lacking utf8 connectivity.
*
* @param int $id The id number for the attachment being deleted.
*/
function ewww_image_optimizer_delete( $id ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
global $eio_backup;
global $wpdb;
if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
ewww_image_optimizer_db_init();
global $ewwwdb;
} else {
$ewwwdb = $wpdb;
}
$id = (int) $id;
// Finds non-meta images to remove from disk, and from db, as well as converted originals.
$optimized_images = $ewwwdb->get_results( "SELECT path,converted FROM $ewwwdb->ewwwio_images WHERE attachment_id = $id AND gallery = 'media'", ARRAY_A );
if ( $optimized_images ) {
if ( ewww_image_optimizer_iterable( $optimized_images ) ) {
foreach ( $optimized_images as $image ) {
if ( ! empty( $image['path'] ) ) {
$image['path'] = ewww_image_optimizer_absolutize_path( $image['path'] );
}
if ( ! empty( $image['path'] ) ) {
if ( ewwwio_is_file( $image['path'] ) ) {
ewwwio_debug_message( 'removing: ' . $image['path'] );
ewwwio_delete_file( $image['path'] );
}
if ( ewwwio_is_file( $image['path'] . '.webp' ) ) {
ewwwio_debug_message( 'removing: ' . $image['path'] . '.webp' );
ewwwio_delete_file( $image['path'] . '.webp' );
}
$webpfileold = preg_replace( '/\.\w+$/', '.webp', $image['path'] );
if ( ewwwio_is_file( $webpfileold ) ) {
ewwwio_debug_message( 'removing: ' . $webpfileold );
ewwwio_delete_file( $webpfileold );
}
$eio_backup->delete_local_backup( $image['path'] );
}
if ( ! empty( $image['converted'] ) ) {
$image['converted'] = ewww_image_optimizer_absolutize_path( $image['converted'] );
$eio_backup->delete_local_backup( $image['converted'] );
}
if ( ! empty( $image['converted'] ) && ewwwio_is_file( $image['converted'] ) ) {
ewwwio_debug_message( 'removing: ' . $image['converted'] );
ewwwio_delete_file( $image['converted'] );
if ( ewwwio_is_file( $image['converted'] . '.webp' ) ) {
ewwwio_debug_message( 'removing: ' . $image['converted'] . '.webp' );
ewwwio_delete_file( $image['converted'] . '.webp' );
}
}
}
}
ewwwio_debug_message( "removing all db records for attachment $id" );
$ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'attachment_id' => $id ) );
}
$s3_path = false;
$s3_dir = false;
if ( ewww_image_optimizer_s3_uploads_enabled() && ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) ) {
$s3_path = get_attached_file( $id );
if ( 0 === strpos( $s3_path, 's3://' ) ) {
ewwwio_debug_message( 'removing: ' . $s3_path . '.webp' );
unlink( $s3_path . '.webp' );
}
$s3_dir = trailingslashit( dirname( $s3_path ) );
}
// Retrieve the image metadata.
$meta = wp_get_attachment_metadata( $id );
// If the attachment has an original file set.
if ( ! empty( $meta['orig_file'] ) ) {
// Get the filepath from the metadata.
$file_path = $meta['orig_file'];
// Get the base filename.
$filename = wp_basename( $file_path );
// Delete any residual webp versions.
$webpfile = $file_path . '.webp';
$webpfileold = preg_replace( '/\.\w+$/', '.webp', $file_path );
if ( ewwwio_is_file( $webpfile ) ) {
ewwwio_debug_message( 'removing: ' . $webpfile );
ewwwio_delete_file( $webpfile );
}
if ( ewwwio_is_file( $webpfileold ) ) {
ewwwio_debug_message( 'removing: ' . $webpfileold );
ewwwio_delete_file( $webpfileold );
}
// Retrieve any posts that link the original image.
$esql = "SELECT ID, post_content FROM $ewwwdb->posts WHERE post_content LIKE '%$filename%' LIMIT 1";
$rows = $ewwwdb->get_row( $esql );
// If the original file still exists and no posts contain links to the image.
if ( ewwwio_is_file( $file_path ) && empty( $rows ) ) {
ewwwio_debug_message( 'removing: ' . $file_path );
ewwwio_delete_file( $file_path );
$eio_backup->delete_local_backup( $file_path );
ewwwio_debug_message( "removing all db records for $file_path" );
$ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $file_path ) ) );
}
}
$file_path = get_attached_file( $id );
// If the attachment has an original file set.
if ( ! empty( $meta['original_image'] ) ) {
// One way or another, $file_path is now set, and we can get the base folder name.
$base_dir = dirname( $file_path ) . '/';
// Get the original filename from the metadata.
$orig_path = $base_dir . wp_basename( $meta['original_image'] );
// Delete any residual webp versions.
$webpfile = $orig_path . '.webp';
if ( ewwwio_is_file( $webpfile ) ) {
ewwwio_debug_message( 'removing: ' . $webpfile );
ewwwio_delete_file( $webpfile );
}
if ( $s3_path && $s3_dir && wp_basename( $meta['original_image'] ) ) {
ewwwio_debug_message( 'removing: ' . $s3_dir . wp_basename( $meta['original_image'] ) . '.webp' );
unlink( $s3_dir . wp_basename( $meta['original_image'] ) . '.webp' );
}
$eio_backup->delete_local_backup( $orig_path );
ewwwio_debug_message( "removing all db records for $orig_path" );
$ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $orig_path ) ) );
}
// Remove the regular image from the ewwwio_images tables.
ewwwio_debug_message( "removing all db records for $file_path" );
$ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $file_path ) ) );
// Resized versions, so we can continue.
if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
// One way or another, $file_path is now set, and we can get the base folder name.
$base_dir = dirname( $file_path ) . '/';
foreach ( $meta['sizes'] as $size => $data ) {
// Delete any residual webp versions.
$webpfile = $base_dir . wp_basename( $data['file'] ) . '.webp';
$webpfileold = preg_replace( '/\.\w+$/', '.webp', $base_dir . wp_basename( $data['file'] ) );
if ( ewwwio_is_file( $webpfile ) ) {
ewwwio_debug_message( 'removing: ' . $webpfile );
ewwwio_delete_file( $webpfile );
}
if ( ewwwio_is_file( $webpfileold ) ) {
ewwwio_debug_message( 'removing: ' . $webpfileold );
ewwwio_delete_file( $webpfileold );
}
if ( $s3_path && $s3_dir && wp_basename( $data['file'] ) ) {
ewwwio_debug_message( 'removing: ' . $s3_dir . wp_basename( $data['file'] ) . '.webp' );
unlink( $s3_dir . wp_basename( $data['file'] ) . '.webp' );
}
$eio_backup->delete_local_backup( $base_dir . wp_basename( $data['file'] ) );
ewwwio_debug_message( "removing all db records for {$data['file']}" );
$ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $base_dir . $data['file'] ) ) );
// If the original resize is set, and still exists.
if ( ! empty( $data['orig_file'] ) && ewwwio_is_file( $base_dir . $data['orig_file'] ) ) {
unset( $srows );
// Retrieve the filename from the metadata.
$filename = $data['orig_file'];
// Retrieve any posts that link the image.
$esql = "SELECT ID, post_content FROM $ewwwdb->posts WHERE post_content LIKE '%$filename%' LIMIT 1";
$srows = $ewwwdb->get_row( $esql );
// If there are no posts containing links to the original, delete it.
if ( empty( $srows ) ) {
ewwwio_debug_message( 'removing: ' . $base_dir . $data['orig_file'] );
ewwwio_delete_file( $base_dir . $data['orig_file'] );
$eio_backup->delete_local_backup( $base_dir . $data['orig_file'] );
ewwwio_debug_message( "removing all db records for {$data['orig_file']}" );
$ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $base_dir . $data['orig_file'] ) ) );
}
}
}
}
if ( ewwwio_is_file( $file_path . '.webp' ) ) {
ewwwio_debug_message( 'removing: ' . $file_path . '.webp' );
ewwwio_delete_file( $file_path . '.webp' );
}
$webpfileold = preg_replace( '/\.\w+$/', '.webp', $file_path );
if ( ewwwio_is_file( $webpfileold ) ) {
ewwwio_debug_message( 'removing: ' . $webpfileold );
ewwwio_delete_file( $webpfileold );
}
$eio_backup->delete_local_backup( $file_path );
}
/**
* Cleans up when a file has been deleted.
*
* Removes any .webp images, backups from conversion, and removes related database records.
*
* @global object $wpdb
* @global object $ewwwdb A clone of $wpdb unless it is lacking utf8 connectivity.
*
* @param int $id The id number for the attachment being deleted.
* @param string $file The file being deleted.
*/
function ewww_image_optimizer_file_deleted( $id, $file ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
global $eio_backup;
global $wpdb;
if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
ewww_image_optimizer_db_init();
global $ewwwdb;
} else {
$ewwwdb = $wpdb;
}
$id = (int) $id;
// Finds non-meta images to remove from disk, and from db, as well as converted originals.
$maybe_relative_path = ewww_image_optimizer_relativize_path( $file );
$query = $ewwwdb->prepare( "SELECT * FROM $ewwwdb->ewwwio_images WHERE path = %s", $maybe_relative_path );
$optimized_images = $ewwwdb->get_results( $query, ARRAY_A );
if ( ewww_image_optimizer_iterable( $optimized_images ) ) {
foreach ( $optimized_images as $image ) {
if ( ! empty( $image['path'] ) ) {
$image['path'] = ewww_image_optimizer_absolutize_path( $image['path'] );
}
if ( strpos( $image['path'], WP_CONTENT_DIR ) === false ) {
continue;
}
if ( ! empty( $image['converted'] ) ) {
$image['converted'] = ewww_image_optimizer_absolutize_path( $image['converted'] );
}
if ( ! empty( $image['converted'] ) && ewwwio_is_file( $image['converted'] ) ) {
ewwwio_delete_file( $image['converted'] );
if ( ewwwio_is_file( $image['converted'] . '.webp' ) ) {
ewwwio_delete_file( $image['converted'] . '.webp' );
}
}
$eio_backup->delete_local_backup( $image['converted'] );
$ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'id' => $image['id'] ) );
}
}
if ( ewwwio_is_file( $file . '.webp' ) ) {
ewwwio_delete_file( $file . '.webp' );
}
$eio_backup->delete_local_backup( $file );
}
/**
* Cleans records from database when an image is about to be replaced.
*
* @param array $attachment An array with the attachment/image ID.
*/
function ewww_image_optimizer_media_replace( $attachment ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
global $wpdb;
if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
ewww_image_optimizer_db_init();
global $ewwwdb;
} else {
$ewwwdb = $wpdb;
}
$id = (int) $attachment['post_id'];
// Finds non-meta images to remove from disk, and from db, as well as converted originals.
$optimized_images = $ewwwdb->get_results( "SELECT path,converted FROM $ewwwdb->ewwwio_images WHERE attachment_id = $id AND gallery = 'media'", ARRAY_A );
if ( $optimized_images ) {
if ( ewww_image_optimizer_iterable( $optimized_images ) ) {
foreach ( $optimized_images as $image ) {
if ( ! empty( $image['path'] ) ) {
$image['path'] = ewww_image_optimizer_absolutize_path( $image['path'] );
}
if ( false === strpos( $image['path'], WP_CONTENT_DIR ) ) {
continue;
}
if ( ! empty( $image['path'] ) ) {
if ( ewwwio_is_file( $image['path'] . '.webp' ) ) {
ewwwio_delete_file( $image['path'] . '.webp' );
}
}
if ( ! empty( $image['converted'] ) ) {
$image['converted'] = ewww_image_optimizer_absolutize_path( $image['converted'] );
}
if ( ! empty( $image['converted'] ) && ewwwio_is_file( $image['converted'] ) ) {
ewwwio_delete_file( $image['converted'] );
if ( ewwwio_is_file( $image['converted'] . '.webp' ) ) {
ewwwio_delete_file( $image['converted'] . '.webp' );
}
}
}
}
ewwwio_debug_message( "removing all db records for attachment $id" );
$ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'attachment_id' => $id ) );
}
// Retrieve the image metadata.
$meta = wp_get_attachment_metadata( $id );
// If the attachment has an original file set.
if ( ! empty( $meta['orig_file'] ) ) {
// Get the filepath from the metadata.
$file_path = $meta['orig_file'];
$webpfile = $file_path . '.webp';
$webpfileold = preg_replace( '/\.\w+$/', '.webp', $file_path );
if ( ewwwio_is_file( $webpfile ) ) {
ewwwio_delete_file( $webpfile );
}
if ( ewwwio_is_file( $webpfileold ) ) {
ewwwio_delete_file( $webpfileold );
}
$ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $file_path ) ) );
}
list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
// If the attachment has an original file set.
if ( ! empty( $meta['original_image'] ) ) {
// One way or another, $file_path is now set, and we can get the base folder name.
$base_dir = dirname( $file_path ) . '/';
// Get the original filename from the metadata.
$orig_path = $base_dir . wp_basename( $meta['original_image'] );
// Delete any residual webp versions.
$webpfile = $orig_path . '.webp';
if ( ewwwio_is_file( $webpfile ) ) {
ewwwio_delete_file( $webpfile );
}
$ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $orig_path ) ) );
}
// Remove the regular image from the ewwwio_images tables.
$ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $file_path ) ) );
// Resized versions, so we can continue.
if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
// One way or another, $file_path is now set, and we can get the base folder name.
$base_dir = dirname( $file_path ) . '/';
foreach ( $meta['sizes'] as $size => $data ) {
// Delete any residual webp versions.
$webpfile = $base_dir . $data['file'] . '.webp';
$webpfileold = preg_replace( '/\.\w+$/', '.webp', $base_dir . $data['file'] );
if ( ewwwio_is_file( $webpfile ) ) {
ewwwio_delete_file( $webpfile );
}
if ( ewwwio_is_file( $webpfileold ) ) {
ewwwio_delete_file( $webpfileold );
}
$ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $base_dir . $data['file'] ) ) );
// If the original resize is set, and still exists.
if ( ! empty( $data['orig_file'] ) ) {
// Retrieve the filename from the metadata.
$filename = $data['orig_file'];
$ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $base_dir . $data['orig_file'] ) ) );
}
}
}
}
/**
* Cleans records from database after an image has been renamed.
*
* @param string $old_name The filename of the original/old image.
* @param string $new_name The filename of the new image.
*/
function ewww_image_optimizer_media_rename( $old_name, $new_name ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
global $wpdb;
if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
ewww_image_optimizer_db_init();
global $ewwwdb;
} else {
$ewwwdb = $wpdb;
}
if ( ! check_ajax_referer( 'phoenix_media_rename', '_wpnonce', false ) || empty( $_REQUEST['post_id'] ) ) {
return;
}
$id = (int) $_REQUEST['post_id'];
ewwwio_debug_message( "image renamed from $old_name to $new_name, looking for old records (id $id)" );
// Finds images to remove from disk, and from db, as well as converted originals.
$optimized_images = $ewwwdb->get_results( "SELECT id,path,resize,converted FROM $ewwwdb->ewwwio_images WHERE attachment_id = $id AND gallery = 'media'", ARRAY_A );
if ( ewww_image_optimizer_iterable( $optimized_images ) ) {
foreach ( $optimized_images as $image ) {
if ( ! empty( $image['path'] ) ) {
$image['path'] = ewww_image_optimizer_absolutize_path( $image['path'] );
}
ewwwio_debug_message( "checking to see if {$image['path']} is stale" );
if ( false === strpos( $image['path'], WP_CONTENT_DIR ) ) {
ewwwio_debug_message( 'not in ' . WP_CONTENT_DIR );
continue;
}
if ( ewwwio_is_file( $image['path'] ) ) {
ewwwio_debug_message( 'file still exists, skipping' );
continue;
}
if ( ! empty( $image['path'] ) && ewwwio_is_file( $image['path'] . '.webp' ) ) {
ewwwio_debug_message( 'removing WebP version' );
ewwwio_delete_file( $image['path'] . '.webp' );
}
if ( ! empty( $image['converted'] ) ) {
$image['converted'] = ewww_image_optimizer_absolutize_path( $image['converted'] );
}
if ( ! empty( $image['converted'] ) && ewwwio_is_file( $image['converted'] ) ) {
ewwwio_debug_message( 'removing "converted" file' );
ewwwio_delete_file( $image['converted'] );
if ( ewwwio_is_file( $image['converted'] . '.webp' ) ) {
ewwwio_debug_message( 'and WebP derivative' );
ewwwio_delete_file( $image['converted'] . '.webp' );
}
}
if ( 'full' === $image['resize'] ) {
ewwwio_debug_message( "updating path for $id (full)" );
$new_path = str_replace( wp_basename( $old_name ), wp_basename( $new_name ), $image['path'] );
if ( ewwwio_is_file( $new_path ) ) {
$new_path = ewww_image_optimizer_relativize_path( $new_path );
$ewwwdb->update(
$ewwwdb->ewwwio_images,
array(
'path' => $new_path,
),
array(
'id' => $image['id'],
)
);
continue;
}
}
$ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'id' => $image['id'] ) );
}
}
// Retrieve the image metadata.
$meta = wp_get_attachment_metadata( $id );
// If the attachment has an original file set.
if ( ! empty( $meta['orig_file'] ) && ! ewwwio_is_file( $meta['orig_file'] ) ) {
// Get the filepath from the metadata.
$file_path = $meta['orig_file'];
$webpfile = $file_path . '.webp';
$webpfileold = preg_replace( '/\.\w+$/', '.webp', $file_path );
if ( ewwwio_is_file( $webpfile ) ) {
ewwwio_delete_file( $webpfile );
}
if ( ewwwio_is_file( $webpfileold ) ) {
ewwwio_delete_file( $webpfileold );
}
$ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relativize_path( $file_path ) ) );
}
ewww_image_optimizer_resize_from_meta_data( $meta, $id );
}
/**
* Activates Easy IO via AJAX.
*/
function ewww_image_optimizer_exactdn_activate_ajax() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( false === current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', '' ) ) ) {
// Display error message if insufficient permissions.
ewwwio_ob_clean();
wp_die( wp_json_encode( array( 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ) ) ) );
}
// Make sure we didn't accidentally get to this page without an attachment to work on.
if ( empty( $_REQUEST['ewww_wpnonce'] ) || ! wp_verify_nonce( sanitize_key( $_REQUEST['ewww_wpnonce'] ), 'ewww-image-optimizer-settings' ) ) {
die( wp_json_encode( array( 'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) ) ) );
}
if ( is_multisite() && defined( 'EXACTDN_SUB_FOLDER' ) && EXACTDN_SUB_FOLDER ) {
update_site_option( 'ewww_image_optimizer_exactdn', true );
} elseif ( defined( 'EXACTDN_SUB_FOLDER' ) ) {
update_option( 'ewww_image_optimizer_exactdn', true );
} elseif ( is_multisite() && get_site_option( 'exactdn_sub_folder' ) ) {
update_site_option( 'ewww_image_optimizer_exactdn', true );
} else {
update_option( 'ewww_image_optimizer_exactdn', true );
}
if ( ! class_exists( 'EWWW\ExactDN' ) ) {
/**
* Page Parsing class for working with HTML content.
*/
require_once EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-page-parser.php';
/**
* ExactDN class for parsing image urls and rewriting them.
*/
require_once EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-exactdn.php';
}
global $exactdn;
if ( $exactdn->get_exactdn_domain() ) {
die( wp_json_encode( array( 'success' => esc_html__( 'Easy IO setup and verification is complete.', 'ewww-image-optimizer' ) ) ) );
}
global $exactdn_activate_error;
if ( empty( $exactdn_activate_error ) ) {
$exactdn_activate_error = 'error unknown';
}
$error_message = sprintf(
/* translators: 1: A link to the documentation 2: the error message/details */
esc_html__( 'Could not activate Easy IO, please try again in a few minutes. If this error continues, please see %1$s for troubleshooting steps: %2$s', 'ewww-image-optimizer' ),
'https://docs.ewww.io/article/66-exactdn-not-verified',
'' . esc_html( $exactdn_activate_error ) . ''
);
if ( 'as3cf_cname_active' === $exactdn_activate_error ) {
$error_message = esc_html__( 'Easy IO cannot optimize your images while using a custom domain (CNAME) in WP Offload Media. Please disable the custom domain in the WP Offload Media settings.', 'ewww-image-optimizer' );
}
die(
wp_json_encode(
array(
'error' => $error_message,
)
)
);
}
/**
* Activates Easy IO via AJAX for a given blog on a multi-site install.
*/
function ewww_image_optimizer_exactdn_activate_site_ajax() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( false === current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', '' ) ) ) {
// Display error message if insufficient permissions.
ewwwio_ob_clean();
wp_die( wp_json_encode( array( 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ) ) ) );
}
if ( empty( $_REQUEST['ewww_wpnonce'] ) || ! wp_verify_nonce( sanitize_key( $_REQUEST['ewww_wpnonce'] ), 'ewww-image-optimizer-settings' ) ) {
die( wp_json_encode( array( 'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) ) ) );
}
if ( empty( $_REQUEST['blog_id'] ) ) {
die( wp_json_encode( array( 'error' => esc_html__( 'Blog ID not provided.', 'ewww-image-optimizer' ) ) ) );
}
$blog_id = (int) $_REQUEST['blog_id'];
if ( get_current_blog_id() !== $blog_id ) {
switch_to_blog( $blog_id );
}
ewwwio_debug_message( "activating site $blog_id" );
if ( get_option( 'ewww_image_optimizer_exactdn' ) ) {
die( wp_json_encode( array( 'success' => esc_html__( 'Easy IO setup and verification is complete.', 'ewww-image-optimizer' ) ) ) );
}
update_option( 'ewww_image_optimizer_exactdn', true );
global $exactdn;
if ( ! class_exists( 'EWWW\ExactDN' ) ) {
/**
* Page Parsing class for working with HTML content.
*/
require_once EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-page-parser.php';
/**
* ExactDN class for parsing image urls and rewriting them.
*/
require_once EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-exactdn.php';
} elseif ( is_object( $exactdn ) ) {
unset( $GLOBALS['exactdn'] );
$exactdn = new EWWW\ExactDN();
}
if ( $exactdn->get_exactdn_domain() ) {
ewwwio_debug_message( 'activated site ' . $exactdn->content_url() . ' got domain ' . $exactdn->get_exactdn_domain() );
die( wp_json_encode( array( 'success' => esc_html__( 'Easy IO setup and verification is complete.', 'ewww-image-optimizer' ) ) ) );
}
restore_current_blog();
global $exactdn_activate_error;
if ( empty( $exactdn_activate_error ) ) {
$exactdn_activate_error = 'error unknown';
}
$error_message = sprintf(
/* translators: 1: The blog URL 2: the error message/details */
esc_html__( 'Could not activate Easy IO on %1$s: %2$s', 'ewww-image-optimizer' ),
esc_url( get_home_url( $blog_id ) ),
'' . esc_html( $exactdn_activate_error ) . ''
);
if ( 'as3cf_cname_active' === $exactdn_activate_error ) {
$error_message = esc_html__( 'Easy IO cannot optimize your images while using a custom domain (CNAME) in WP Offload Media. Please disable the custom domain in the WP Offload Media settings.', 'ewww-image-optimizer' );
}
die(
wp_json_encode(
array(
'error' => $error_message,
)
)
);
}
/**
* Registers Easy IO via AJAX for a given blog on a multi-site install.
*/
function ewww_image_optimizer_exactdn_register_site_ajax() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( false === current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', '' ) ) ) {
// Display error message if insufficient permissions.
ewwwio_ob_clean();
wp_die( wp_json_encode( array( 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ) ) ) );
}
if ( empty( $_REQUEST['ewww_wpnonce'] ) || ! wp_verify_nonce( sanitize_key( $_REQUEST['ewww_wpnonce'] ), 'ewww-image-optimizer-settings' ) ) {
die( wp_json_encode( array( 'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) ) ) );
}
if ( empty( $_REQUEST['blog_id'] ) ) {
die( wp_json_encode( array( 'error' => esc_html__( 'Blog ID not provided.', 'ewww-image-optimizer' ) ) ) );
}
$blog_id = (int) $_REQUEST['blog_id'];
if ( get_current_blog_id() !== $blog_id ) {
$switch = true;
switch_to_blog( $blog_id );
}
ewwwio_debug_message( "registering site $blog_id" );
if ( get_option( 'ewww_image_optimizer_exactdn' ) ) {
if ( ! empty( $switch ) ) {
restore_current_blog();
}
die( wp_json_encode( array( 'status' => 'active' ) ) );
}
$result = ewww_image_optimizer_register_site_post();
if ( ! empty( $switch ) ) {
restore_current_blog();
}
if ( is_wp_error( $result ) ) {
$error_message = $result->get_error_message();
$easyio_site_url = get_home_url( $blog_id );
ewwwio_debug_message( "registration failed for $easyio_site_url: $error_message" );
die(
wp_json_encode(
array(
'error' => sprintf(
/* translators: %s: an HTTP error message */
esc_html__( 'Could not register site, HTTP error: %s', 'ewww-image-optimizer' ),
$error_message
),
)
)
);
} elseif ( ! empty( $result['body'] ) ) {
$response = json_decode( $result['body'], true );
if ( ! empty( $response['error'] ) && false !== strpos( strtolower( $response['error'] ), 'duplicate site url' ) ) {
die( wp_json_encode( array( 'status' => 'registered' ) ) );
}
die( wp_json_encode( $response ) );
}
$error_message = sprintf(
/* translators: %s: The blog URL */
esc_html__( 'Could not register Easy IO for %s: error unknown.', 'ewww-image-optimizer' ),
esc_url( get_home_url( $blog_id ) )
);
die(
wp_json_encode(
array(
'error' => $error_message,
)
)
);
}
/**
* Registers Easy IO for a new blog on a multi-site install.
*
* @param object $new_site WP_Site instace for the new site.
*/
function ewww_image_optimizer_initialize_site( $new_site ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( empty( $new_site->id ) ) {
return;
}
if ( ! defined( 'EASYIO_NEW_SITE_AUTOREG' ) || ! EASYIO_NEW_SITE_AUTOREG ) {
return;
}
if ( get_current_blog_id() !== $new_site->id ) {
$switch = true;
switch_to_blog( $new_site->id );
}
$result = ewww_image_optimizer_register_site_post();
$easyio_site_url = get_home_url( $new_site->id );
if ( ! empty( $switch ) ) {
restore_current_blog();
}
if ( is_wp_error( $result ) ) {
$error_message = $result->get_error_message();
ewwwio_debug_message( "registration failed for $easyio_site_url: $error_message" );
} elseif ( ! empty( $result['body'] ) ) {
$response = json_decode( $result['body'], true );
if ( ! empty( $response['error'] ) ) {
ewwwio_debug_message( "registration failed for $easyio_site_url: {$response['error']}" );
}
}
}
/**
* POSTs the site URL to the API for Easy IO registration.
*
* @return array The results of the http POST request.
*/
function ewww_image_optimizer_register_site_post() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
// Get the site URL for a given blog.
$site_url = ewwwio()->content_url();
$key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
if ( empty( $key ) ) {
return new WP_Error( 'missing_key', __( 'No API key for Easy IO registration', 'ewww-image-optimizer' ) );
}
ewwwio_debug_message( "registering $site_url on Easy IO" );
$url = 'https://optimize.exactlywww.com/exactdn/create.php';
add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
$result = wp_remote_post(
$url,
array(
'timeout' => 60,
'sslverify' => false,
'body' => array(
'api_key' => $key,
'site_url' => $site_url,
),
)
);
return $result;
}
/**
* Removes site from Easy IO via AJAX for a given site ID.
*/
function ewww_image_optimizer_exactdn_deregister_site_ajax() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( false === current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', '' ) ) ) {
// Display error message if insufficient permissions.
ewwwio_ob_clean();
wp_die( wp_json_encode( array( 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ) ) ) );
}
if ( empty( $_REQUEST['ewww_wpnonce'] ) || ! wp_verify_nonce( sanitize_key( $_REQUEST['ewww_wpnonce'] ), 'ewww-image-optimizer-settings' ) ) {
die( wp_json_encode( array( 'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) ) ) );
}
if ( empty( $_REQUEST['site_id'] ) ) {
die( wp_json_encode( array( 'error' => esc_html__( 'Site ID unknown.', 'ewww-image-optimizer' ) ) ) );
}
$site_id = (int) $_REQUEST['site_id'];
ewwwio_debug_message( "deregistering site $site_id" );
$result = ewww_image_optimizer_deregister_site_post( $site_id );
if ( is_wp_error( $result ) ) {
$error_message = $result->get_error_message();
ewwwio_debug_message( "de-registration failed: $error_message" );
die(
wp_json_encode(
array(
'error' => sprintf(
/* translators: %s: an HTTP error message */
esc_html__( 'Could not de-register site, HTTP error: %s', 'ewww-image-optimizer' ),
$error_message
),
)
)
);
} elseif ( ! empty( $result['body'] ) ) {
$response = json_decode( $result['body'], true );
if ( ! empty( $response['success'] ) ) {
$response['success'] = esc_html__( 'Successfully removed site from Easy IO.', 'ewww-image-optimizer' );
}
die( wp_json_encode( $response ) );
}
die(
wp_json_encode(
array(
'error' => esc_html__( 'Could not remove site from Easy IO: error unknown.', 'ewww-image-optimizer' ),
)
)
);
}
/**
* POSTs the site URL to the API for Easy IO registration.
*
* @param int $site_id The site ID for the Easy IO zone.
* @return array The results of the http POST request.
*/
function ewww_image_optimizer_deregister_site_post( $site_id ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
$key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
if ( empty( $key ) ) {
return new WP_Error( 'missing_key', __( 'No API key for Easy IO removal', 'ewww-image-optimizer' ) );
}
ewwwio_debug_message( "removing site $site_id from Easy IO" );
$url = 'https://optimize.exactlywww.com/exactdn/remove.php';
add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
$result = wp_remote_post(
$url,
array(
'timeout' => 60,
'sslverify' => false,
'body' => array(
'api_key' => $key,
'site_id' => (int) $site_id,
),
)
);
return $result;
}
/**
* Checks to see if a site is registered with Easy IO.
*
* @param string $site_url The site URL to check for an Easy IO record.
* @return bool True if the site is already registered, false otherwise.
*/
function ewww_image_optimizer_easy_site_registered( $site_url ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
global $easyio_site_registered;
global $easyio_site_id;
if ( isset( $easyio_site_registered ) ) {
return $easyio_site_registered;
}
$easyio_site_registered = false;
$easyio_site_id = 0;
$cloud_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
if ( ! empty( $cloud_key ) ) {
ewwwio_debug_message( "checking $site_url with Easy IO" );
$url = 'https://optimize.exactlywww.com/exactdn/show.php';
add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
$result = wp_remote_post(
$url,
array(
'timeout' => 30,
'sslverify' => false,
'body' => array(
'api_key' => $cloud_key,
'site_url' => $site_url,
),
)
);
if ( is_wp_error( $result ) ) {
$error_message = $result->get_error_message();
ewwwio_debug_message( "register check via /show.php failed: $error_message" );
} else {
$easy_info = json_decode( $result['body'], true );
if (
is_array( $easy_info ) && ! empty( $easy_info['sites'][0]['site_url'] ) &&
trailingslashit( $site_url ) === $easy_info['sites'][0]['site_url']
) {
$easyio_site_registered = true;
$easyio_site_id = (int) $easy_info['sites'][0]['site_id'];
return true;
}
if ( is_array( $easy_info ) && ! empty( $easy_info['sites'][0]['site_url'] ) ) {
ewwwio_debug_message( 'found (maybe different) site 0: ' . $easy_info['sites'][0]['site_url'] );
}
}
}
return false;
}
/**
* Sanitizes an API key for the cloud service.
*
* @param string $key An API key entered by the user.
* @return string A sanitized API key.
*/
function ewww_image_optimizer_cloud_key_sanitize( $key ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
$key = trim( $key );
if ( ! empty( $key ) && strlen( $key ) < 200 && preg_match( '/^[a-zA-Z0-9]+$/', $key ) ) {
return $key;
}
return '';
}
/**
* Verifies an API key via AJAX.
*/
function ewww_image_optimizer_cloud_key_verify_ajax() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( false === current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', '' ) ) ) {
// Display error message if insufficient permissions.
ewwwio_ob_clean();
wp_die( wp_json_encode( array( 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ) ) ) );
}
if ( empty( $_REQUEST['ewww_wpnonce'] ) || ! wp_verify_nonce( sanitize_key( $_REQUEST['ewww_wpnonce'] ), 'ewww-image-optimizer-settings' ) ) {
die( wp_json_encode( array( 'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) ) ) );
}
if ( empty( $_POST['compress_api_key'] ) ) {
die( wp_json_encode( array( 'error' => esc_html__( 'Please enter your API key and try again.', 'ewww-image-optimizer' ) ) ) );
}
$api_key = trim( ewww_image_optimizer_cloud_key_sanitize( wp_unslash( $_POST['compress_api_key'] ) ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$url = 'http://optimize.exactlywww.com/verify/';
if ( wp_http_supports( array( 'ssl' ) ) ) {
$url = set_url_scheme( $url, 'https' );
}
$result = ewww_image_optimizer_cloud_post_key( $url, $api_key );
if ( is_wp_error( $result ) ) {
$url = set_url_scheme( $url, 'http' );
$error_message = $result->get_error_message();
ewwwio_debug_message( "verification failed: $error_message" );
$result = ewww_image_optimizer_cloud_post_key( $url, $api_key );
}
if ( is_wp_error( $result ) ) {
$error_message = $result->get_error_message();
ewwwio_debug_message( "verification failed via $url: $error_message" );
die(
wp_json_encode(
array(
'error' => sprintf(
/* translators: %s: an HTTP error message */
esc_html__( 'Could not validate API key, HTTP error: %s', 'ewww-image-optimizer' ),
$error_message
),
)
)
);
} elseif ( ! empty( $result['body'] ) && preg_match( '/(great|exceeded)/', $result['body'] ) ) {
$verified = $result['body'];
if ( preg_match( '/exceeded/', $verified ) ) {
die( wp_json_encode( array( 'error' => esc_html__( 'No credits remaining for API key.', 'ewww-image-optimizer' ) ) ) );
}
ewwwio_debug_message( "verification success via: $url" );
delete_option( 'ewww_image_optimizer_cloud_key_invalid' );
ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_key', $api_key );
set_transient( 'ewww_image_optimizer_cloud_status', $verified, HOUR_IN_SECONDS );
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) < 20 && ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) < 20 && ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ) < 20 && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) ) {
ewww_image_optimizer_cloud_enable();
}
ewwwio_debug_message( "verification body contents: {$result['body']}" );
die( wp_json_encode( array( 'success' => esc_html__( 'Successfully validated API key, happy optimizing!', 'ewww-image-optimizer' ) ) ) );
} else {
ewwwio_debug_message( "verification failed via: $url" );
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && ewww_image_optimizer_function_exists( 'print_r' ) ) {
ewwwio_debug_message( print_r( $result, true ) );
}
die( wp_json_encode( array( 'error' => esc_html__( 'Could not validate API key, please copy and paste your key to ensure it is correct.', 'ewww-image-optimizer' ) ) ) );
}
}
/**
* Checks to see if all images should be processed via the API.
*
* @return bool True if all 'cloud' options are enabled.
*/
function ewww_image_optimizer_full_cloud() {
return ewwwio()->cloud_mode;
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) > 10 && ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) > 10 ) {
return true;
}
return false;
}
/**
* Used to turn on the cloud settings when they are all disabled.
*/
function ewww_image_optimizer_cloud_enable() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
ewww_image_optimizer_set_option( 'ewww_image_optimizer_jpg_level', 30 );
ewww_image_optimizer_set_option( 'ewww_image_optimizer_png_level', 20 );
ewww_image_optimizer_set_option( 'ewww_image_optimizer_gif_level', 10 );
ewww_image_optimizer_set_option( 'ewww_image_optimizer_pdf_level', 10 );
ewww_image_optimizer_set_option( 'ewww_image_optimizer_svg_level', 10 );
if ( 'local' !== ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_backup_files', 'cloud' );
}
}
/**
* Adds the EWWW IO version to the useragent for http requests.
*
* @param string $useragent The current useragent used in http requests.
* @return string The useragent with the EWWW IO version appended.
*/
function ewww_image_optimizer_cloud_useragent( $useragent ) {
if ( strpos( $useragent, 'EWWW' ) === false ) {
$useragent .= ' EWWW/' . EWWW_IMAGE_OPTIMIZER_VERSION . ' ';
}
return $useragent;
}
/**
* Submits the api key for verification. Will retrieve the key option if parameter not provided.
*
* @param string $api_key The API key to verify. Default empty string.
* @param bool $cache Optional. True to return cached verification results. Default true.
* @return string|bool False if verification fails, status message otherwise: great/exceeded.
*/
function ewww_image_optimizer_cloud_verify( $api_key, $cache = true ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
$sanitize = false;
if ( empty( $api_key ) ) {
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) > 10 ) {
update_site_option( 'ewww_image_optimizer_jpg_level', 10 );
update_option( 'ewww_image_optimizer_jpg_level', 10 );
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) > 10 && 40 !== (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) ) {
update_site_option( 'ewww_image_optimizer_png_level', 10 );
update_option( 'ewww_image_optimizer_png_level', 10 );
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) > 0 ) {
update_site_option( 'ewww_image_optimizer_pdf_level', 0 );
update_option( 'ewww_image_optimizer_pdf_level', 0 );
}
if ( 'local' !== ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) ) {
update_site_option( 'ewww_image_optimizer_backup_files', '' );
update_option( 'ewww_image_optimizer_backup_files', '' );
}
return false;
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_exceeded' ) > time() ) {
set_transient( 'ewww_image_optimizer_cloud_status', 'exceeded', HOUR_IN_SECONDS );
ewwwio_debug_message( 'license exceeded notice has not expired' );
return 'exceeded';
}
$ewww_cloud_status = get_transient( 'ewww_image_optimizer_cloud_status' );
if ( ! ewww_image_optimizer_detect_wpsf_location_lock() && $cache && preg_match( '/great/', $ewww_cloud_status ) ) {
ewwwio_debug_message( 'using cached verification' );
ewwwio()->async_key_verify->dispatch();
return $ewww_cloud_status;
}
$url = 'http://optimize.exactlywww.com/verify/';
$ssl = wp_http_supports( array( 'ssl' ) );
if ( $ssl ) {
$url = set_url_scheme( $url, 'https' );
}
$result = ewww_image_optimizer_cloud_post_key( $url, $api_key );
if ( is_wp_error( $result ) ) {
$url = set_url_scheme( $url, 'http' );
$error_message = $result->get_error_message();
ewwwio_debug_message( "verification failed: $error_message" );
$result = ewww_image_optimizer_cloud_post_key( $url, $api_key );
}
if ( is_wp_error( $result ) ) {
$error_message = $result->get_error_message();
ewwwio_debug_message( "verification failed via $url: $error_message" );
} elseif ( ! empty( $result['body'] ) && preg_match( '/(great|exceeded)/', $result['body'] ) ) {
$verified = $result['body'];
if ( preg_match( '/exceeded/', $verified ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_exceeded', time() + 300 );
}
if ( false !== strpos( $result['body'], 'expired' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_key', '' );
}
ewwwio_debug_message( "verification success via: $url" );
delete_option( 'ewww_image_optimizer_cloud_key_invalid' );
} else {
update_option( 'ewww_image_optimizer_cloud_key_invalid', true, false );
if ( ! empty( $result['body'] ) && false !== strpos( $result['body'], 'invalid' ) ) {
ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_key', '' );
}
ewwwio_debug_message( "verification failed via: $url" );
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && ewww_image_optimizer_function_exists( 'print_r' ) ) {
ewwwio_debug_message( print_r( $result, true ) );
}
}
if ( empty( $verified ) ) {
ewwwio_memory( __FUNCTION__ );
return false;
} else {
set_transient( 'ewww_image_optimizer_cloud_status', $verified, HOUR_IN_SECONDS );
ewwwio_debug_message( "verification body contents: {$result['body']}" );
ewwwio_memory( __FUNCTION__ );
return $verified;
}
}
/**
* POSTs the API key to the API for verification.
*
* @param string $url The address of the server to use.
* @param string $key The API key to submit via POST.
* @return array The results of the http POST request.
*/
function ewww_image_optimizer_cloud_post_key( $url, $key ) {
add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
$result = wp_remote_post(
$url,
array(
'timeout' => 5,
'sslverify' => false,
'body' => array(
'api_key' => $key,
),
)
);
return $result;
}
/**
* Let the user know their key is invalid.
*/
function ewww_image_optimizer_notice_invalid_key() {
echo "
" . esc_html__( 'Could not validate EWWW Image Optimizer API key, please check your key to ensure it is correct.', 'ewww-image-optimizer' ) . '
';
}
/**
* Checks the configured API key for quota information.
*
* @param bool $raw True to return the usage array as-is.
* @return string A message with how many credits they have used/left and possibly a renwal date.
*/
function ewww_image_optimizer_cloud_quota( $raw = false ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
$api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
$url = 'http://optimize.exactlywww.com/quota/v2/';
$ssl = wp_http_supports( array( 'ssl' ) );
if ( $ssl ) {
$url = set_url_scheme( $url, 'https' );
}
add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
$result = wp_remote_post(
$url,
array(
'timeout' => 5,
'sslverify' => false,
'body' => array(
'api_key' => $api_key,
),
)
);
if ( is_wp_error( $result ) ) {
$error_message = $result->get_error_message();
ewwwio_debug_message( "quota request failed: $error_message" );
ewwwio_memory( __FUNCTION__ );
return '';
} elseif ( ! empty( $result['body'] ) ) {
ewwwio_debug_message( "quota data retrieved: {$result['body']}" );
$quota = json_decode( $result['body'], true );
if ( ! is_array( $quota ) ) {
return '';
}
if ( ! empty( $quota['status'] ) && 'expired' === $quota['status'] ) {
return '';
}
ewwwio_memory( __FUNCTION__ );
if ( $raw ) {
return $quota;
}
if ( ! empty( $quota['unlimited'] ) && $quota['consumed'] >= 0 && isset( $quota['soft_cap'] ) ) {
$consumed = (int) $quota['consumed'];
$soft_cap = '' . (int) $quota['soft_cap'] . '';
$soft_cap .= ewwwio_get_help_link( 'https://docs.ewww.io/article/101-soft-quotas-on-unlimited-plans', '608ddf128996210f18bd95d3' );
return sprintf(
/* translators: 1: Number of images optimized, 2: image quota */
__( 'optimized %1$d (of %2$s) images.', 'ewww-image-optimizer' ),
$consumed,
$soft_cap
);
} elseif ( ! $quota['licensed'] && $quota['consumed'] > 0 ) {
return sprintf(
/* translators: 1: Number of images 2: Number of days until renewal */
_n( 'optimized %1$d images, renewal is in %2$d day.', 'optimized %1$d images, renewal is in %2$d days.', $quota['days'], 'ewww-image-optimizer' ),
$quota['consumed'],
$quota['days']
);
} elseif ( ! $quota['licensed'] && $quota['consumed'] < 0 ) {
return sprintf(
/* translators: 1: Number of image credits for the compression API */
_n( '%1$d image credit remaining.', '%1$d image credits remaining.', abs( $quota['consumed'] ), 'ewww-image-optimizer' ),
abs( $quota['consumed'] )
);
} elseif ( $quota['licensed'] > 0 && $quota['consumed'] <= 0 ) {
$real_quota = (int) $quota['licensed'] - (int) $quota['consumed'];
return sprintf(
/* translators: 1: Number of image credits for the compression API */
_n( '%1$d image credit remaining.', '%1$d image credits remaining.', $real_quota, 'ewww-image-optimizer' ),
$real_quota
);
} elseif ( ! $quota['licensed'] && ! $quota['consumed'] && ! $quota['days'] && ! $quota['metered'] ) {
return __( 'no credits remaining, please purchase more.', 'ewww-image-optimizer' );
} else {
return sprintf(
/* translators: 1: Number of image credits used 2: Number of image credits available 3: days until subscription renewal */
_n( 'used %1$d of %2$d, usage will reset in %3$d day.', 'used %1$d of %2$d, usage will reset in %3$d days.', $quota['days'], 'ewww-image-optimizer' ),
$quota['consumed'],
$quota['licensed'],
$quota['days']
);
}
}
}
/**
* Submits an image to the cloud optimizer and saves the optimized image to disk.
*
* Returns an array of the $file, $converted, possibly a $msg, and the $new_size.
*
* @global object $ewww_image Contains more information about the image currently being processed.
*
* @param string $file Full absolute path to the image file.
* @param string $type Mimetype of $file.
* @param bool $convert Optional. True if we want to attempt conversion of $file. Default false.
* @param string $newfile Optional. Filename to be used if image is converted. Default null.
* @param string $newtype Optional. Mimetype expected if image is converted. Default null.
* @param bool $fullsize Optional. True if this is an original upload. Default false.
* @param array $jpg_fill Optional. Fill color for PNG to JPG conversion in hex format.
* @param int $jpg_quality Optional. JPG quality level. Default null. Accepts 1-100.
* @return array {
* Information about the cloud optimization.
*
* @type string Filename of the optimized version.
* @type bool True if the image was converted.
* @type string Set to 'exceeded' if the API key is out of credits. Or 'exceeded quota' if soft quota is reached.
* @type int File size of the (new) image.
* }
*/
function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $newfile = null, $newtype = null, $fullsize = false, $jpg_fill = '', $jpg_quality = 82 ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( ! ewwwio_is_file( $file ) || ! is_writable( $file ) || false !== strpos( $file, '../' ) ) {
return array( $file, false, 'invalid file', 0, '' );
}
if ( ! ewwwio_check_memory_available( filesize( $file ) * 2.2 ) ) { // 2.2 = upload buffer + download buffer (2) multiplied by a factor of 1.1 for extra wiggle room.
$memory_required = filesize( $file ) * 2.2;
ewwwio_debug_message( "possibly insufficient memory for cloud (optimize) operation: $memory_required" );
if ( function_exists( 'wp_raise_memory_limit' ) ) {
add_filter( 'image_memory_limit', 'ewww_image_optimizer_raise_memory_limit' );
wp_raise_memory_limit( 'image' );
}
}
$api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
if ( 'exceeded' === get_transient( 'ewww_image_optimizer_cloud_status' ) ) {
$started = microtime( true );
if ( ! ewww_image_optimizer_cloud_verify( $api_key ) ) {
return array( $file, false, 'key verification failed', 0, '' );
}
// Calculate how much time has elapsed since we started.
$elapsed = microtime( true ) - $started;
ewwwio_debug_message( "cloud verify took $elapsed seconds" );
}
if ( 'exceeded quota' === get_transient( 'ewww_image_optimizer_cloud_status' ) ) {
ewwwio_debug_message( 'soft quota reached, image not processed' );
return array( $file, false, 'exceeded quota', 0, '' );
}
if ( 'exceeded' === get_transient( 'ewww_image_optimizer_cloud_status' ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_exceeded' ) > time() ) {
ewwwio_debug_message( 'license exceeded, image not processed' );
return array( $file, false, 'exceeded', 0, '' );
}
global $ewww_force;
global $ewww_force_smart;
global $eio_filesystem;
ewwwio_get_filesystem();
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_skip_full' ) && $fullsize ) {
$metadata = 1;
} elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) ) {
// Don't copy metadata.
$metadata = 0;
} else {
// Copy all the metadata.
$metadata = 1;
}
if ( empty( $convert ) ) {
$convert = 0;
} else {
$convert = 1;
}
$lossy_fast = 0;
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_lossy_skip_full' ) && $fullsize ) {
$lossy = 0;
} elseif ( 'image/png' === $type && ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) >= 40 ) {
$lossy = 1;
if ( 40 === (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) ) {
$lossy_fast = 1;
}
} elseif ( 'image/jpeg' === $type && ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) >= 30 ) {
$lossy = 1;
if ( 30 === (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) ) {
$lossy_fast = 1;
}
} elseif ( 'application/pdf' === $type && 20 === (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) ) {
$lossy = 1;
} else {
$lossy = 0;
}
if ( strpos( $file, '/wp-admin/' ) || strpos( $file, '/wp-includes/' ) || strpos( $file, '/wp-content/themes/' ) || strpos( $file, '/wp-content/plugins/' ) ) {
$lossy = 0;
$lossy_fast = 0;
}
$sharp_yuv = defined( 'EIO_WEBP_SHARP_YUV' ) && EIO_WEBP_SHARP_YUV ? 1 : 0;
if ( empty( $sharp_yuv ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_sharpen' ) ) {
$sharp_yuv = 1;
}
if ( 'image/webp' === $newtype ) {
$webp = 1;
$jpg_quality = apply_filters( 'webp_quality', 75, 'image/webp' );
if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_LOSSY_PNG2WEBP' ) || ! EWWW_IMAGE_OPTIMIZER_LOSSY_PNG2WEBP ) {
$lossy = 0;
}
if ( defined( 'EWWW_IMAGE_OPTIMIZER_LOSSY_GIF2WEBP' ) && ! EWWW_IMAGE_OPTIMIZER_LOSSY_GIF2WEBP ) {
$lossy = 1;
}
} else {
$webp = 0;
}
if ( $jpg_quality < 50 ) {
$jpg_quality = 75;
}
$png_compress = 0;
if ( 'image/svg+xml' === $type && 10 === (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_svg_level' ) ) {
$png_compress = 1;
}
if ( 'image/png' === $type && 30 === (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) ) {
$png_compress = 1;
}
$backup_exclusions = array(
EWWWIO_CONTENT_DIR,
'/wp-admin/',
'/wp-includes/',
'/wp-content/themes/',
'/wp-content/plugins/',
'/cache/',
'/dynamic/', // Nextgen dynamic images.
);
$backup_exclusions = apply_filters( 'ewww_image_optimizer_backup_exclusions', $backup_exclusions );
$backup_excluded = false;
foreach ( $backup_exclusions as $backup_exclusion ) {
if ( false !== strpos( $file, $backup_exclusion ) ) {
$backup_excluded = true;
}
}
if ( ! $webp && 'cloud' === ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) && ! $backup_excluded ) {
global $ewww_image;
if ( is_object( $ewww_image ) && $ewww_image->file === $file && ! empty( $ewww_image->backup ) ) {
$hash = $ewww_image->backup;
}
if ( empty( $hash ) && ( ! empty( $ewww_force ) || ! empty( $ewww_force_smart ) ) ) {
$image = ewww_image_optimizer_find_already_optimized( $file );
if ( ! empty( $image ) && is_array( $image ) && ! empty( $image['backup'] ) ) {
$hash = $image['backup'];
}
}
if ( empty( $hash ) ) {
$hash = uniqid() . hash( 'sha256', $file );
}
$domain = parse_url( get_site_url(), PHP_URL_HOST );
} else {
$hash = '';
$domain = parse_url( get_site_url(), PHP_URL_HOST );
}
ewwwio_debug_message( "file: $file " );
ewwwio_debug_message( "type: $type" );
ewwwio_debug_message( "convert: $convert" );
ewwwio_debug_message( "newfile: $newfile" );
ewwwio_debug_message( "newtype: $newtype" );
ewwwio_debug_message( "webp: $webp" );
ewwwio_debug_message( "sharp_yuv: $sharp_yuv" );
ewwwio_debug_message( "jpg fill: $jpg_fill" );
ewwwio_debug_message( "jpg quality: $jpg_quality" );
$free_exec = ! ewwwio()->local->exec_check() && 'image/jpeg' === $type;
if (
! $free_exec &&
! ewwwio()->local->get_path( 'jpegtran' ) &&
'image/jpeg' === $type
) {
$free_exec = true;
}
if ( ! $free_exec && $webp ) {
$free_exec = true;
}
if ( empty( $api_key ) && ! $free_exec ) {
ewwwio_debug_message( 'no API key and free_exec mode inactive' );
return array( $file, false, 'key verification failed', 0, '' );
}
$url = 'http://optimize.exactlywww.com/v2/';
$ssl = wp_http_supports( array( 'ssl' ) );
if ( $ssl ) {
$url = set_url_scheme( $url, 'https' );
}
$boundary = wp_generate_password( 24, false );
$headers = array(
'content-type' => 'multipart/form-data; boundary=' . $boundary,
'timeout' => 300,
'httpversion' => '1.0',
'blocking' => true,
);
$post_fields = array(
'filename' => $file,
'convert' => $convert,
'metadata' => $metadata,
'api_key' => $api_key,
'jpg_fill' => $jpg_fill,
'quality' => $jpg_quality,
'compress' => $png_compress,
'lossy' => $lossy,
'lossy_fast' => $lossy_fast,
'webp' => $webp,
'sharp_yuv' => $sharp_yuv,
'backup' => $hash,
'domain' => $domain,
);
$payload = '';
foreach ( $post_fields as $name => $value ) {
$payload .= '--' . $boundary;
$payload .= "\r\n";
$payload .= 'Content-Disposition: form-data; name="' . $name . '"' . "\r\n\r\n";
$payload .= $value;
$payload .= "\r\n";
}
$payload .= '--' . $boundary;
$payload .= "\r\n";
$payload .= 'Content-Disposition: form-data; name="file"; filename="' . wp_basename( $file ) . '"' . "\r\n";
$payload .= 'Content-Type: ' . $type . "\r\n";
$payload .= "\r\n";
$payload .= $eio_filesystem->get_contents( $file );
$payload .= "\r\n";
$payload .= '--' . $boundary;
$payload .= 'Content-Disposition: form-data; name="submitHandler"' . "\r\n";
$payload .= "\r\n";
$payload .= "Upload\r\n";
$payload .= '--' . $boundary . '--';
add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
$response = wp_remote_post(
$url,
array(
'timeout' => 300,
'headers' => $headers,
'sslverify' => false,
'body' => $payload,
)
);
if ( is_wp_error( $response ) ) {
$error_message = $response->get_error_message();
ewwwio_debug_message( "optimize failed: $error_message" );
return array( $file, false, 'cloud optimize failed', 0, '' );
} elseif ( empty( $response['body'] ) ) {
ewwwio_debug_message( 'cloud results: no savings' );
return array( $file, false, '', filesize( $file ), $hash );
} else {
$tempfile = $file . '.tmp';
file_put_contents( $tempfile, $response['body'] );
$orig_size = filesize( $file );
$newsize = $orig_size;
$converted = false;
$msg = '';
if ( 100 > strlen( $response['body'] ) && strpos( $response['body'], 'invalid' ) ) {
ewwwio_debug_message( 'License Invalid' );
ewww_image_optimizer_remove_cloud_key( 'none' );
ewwwio_delete_file( $tempfile );
} elseif ( 100 > strlen( $response['body'] ) && strpos( $response['body'], 'exceeded quota' ) ) {
ewwwio_debug_message( 'Soft quota Exceeded' );
set_transient( 'ewww_image_optimizer_cloud_status', 'exceeded quota', HOUR_IN_SECONDS );
$msg = 'exceeded quota';
ewwwio_delete_file( $tempfile );
} elseif ( 100 > strlen( $response['body'] ) && strpos( $response['body'], 'exceeded' ) ) {
ewwwio_debug_message( 'License Exceeded' );
set_transient( 'ewww_image_optimizer_cloud_status', 'exceeded', HOUR_IN_SECONDS );
$msg = 'exceeded';
ewwwio_delete_file( $tempfile );
} elseif ( ewww_image_optimizer_mimetype( $tempfile, 'i' ) === $type ) {
$newsize = filesize( $tempfile );
ewwwio_debug_message( "cloud results: $newsize (new) vs. $orig_size (original)" );
ewwwio_rename( $tempfile, $file );
} elseif ( ewww_image_optimizer_mimetype( $tempfile, 'i' ) === 'image/webp' ) {
$newsize = filesize( $tempfile );
ewwwio_debug_message( "cloud results: $newsize (new) vs. $orig_size (original)" );
ewwwio_rename( $tempfile, $newfile );
} elseif ( ! is_null( $newtype ) && ! is_null( $newfile ) && ewww_image_optimizer_mimetype( $tempfile, 'i' ) === $newtype ) {
ewwwio_debug_message( "renaming file from $tempfile to $newfile" );
if ( ewwwio_rename( $tempfile, $newfile ) ) {
$converted = true;
$newsize = filesize( $newfile );
$file = $newfile;
ewwwio_debug_message( "cloud results: $newsize (new) vs. $orig_size (original)" );
}
}
clearstatcache();
if ( ewwwio_is_file( $tempfile ) ) {
ewwwio_delete_file( $tempfile );
}
ewwwio_memory( __FUNCTION__ );
return array( $file, $converted, $msg, $newsize, $hash );
} // End if().
}
/**
* Automatically corrects JPG rotation using API servers.
*
* @param string $file Name of the file to fix.
* @param string $type File type of the file.
*
* @return bool True if the rotation was successful.
*/
function ewww_image_optimizer_cloud_autorotate( $file, $type ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( ! ewwwio_check_memory_available( filesize( $file ) * 2.2 ) ) { // 2.2 = upload buffer + download buffer (2) multiplied by a factor of 1.1 for extra wiggle room.
$memory_required = filesize( $file ) * 2.2;
ewwwio_debug_message( "possibly insufficient memory for cloud (rotate) operation: $memory_required" );
if ( function_exists( 'wp_raise_memory_limit' ) ) {
add_filter( 'image_memory_limit', 'ewww_image_optimizer_raise_memory_limit' );
wp_raise_memory_limit( 'image' );
}
}
$api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
if ( empty( $api_key ) ) {
return false;
}
$started = microtime( true );
if ( 'exceeded' === get_transient( 'ewww_image_optimizer_cloud_status' ) ) {
if ( ! ewww_image_optimizer_cloud_verify( $api_key ) ) {
ewwwio_debug_message( 'cloud verify failed, image not rotated' );
return false;
}
}
// Calculate how much time has elapsed since we started.
$elapsed = microtime( true ) - $started;
ewwwio_debug_message( "cloud verify took $elapsed seconds" );
if ( 'exceeded' === get_transient( 'ewww_image_optimizer_cloud_status' ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_exceeded' ) > time() ) {
ewwwio_debug_message( 'license exceeded, image not rotated' );
return false;
}
global $eio_filesystem;
ewwwio_get_filesystem();
ewwwio_debug_message( "file: $file " );
ewwwio_debug_message( "type: $type" );
$url = 'http://optimize.exactlywww.com/rotate/';
$ssl = wp_http_supports( array( 'ssl' ) );
if ( $ssl ) {
$url = set_url_scheme( $url, 'https' );
}
$boundary = wp_generate_password( 24, false );
$headers = array(
'content-type' => 'multipart/form-data; boundary=' . $boundary,
'timeout' => 60,
'httpversion' => '1.0',
'blocking' => true,
);
$post_fields = array(
'filename' => $file,
'api_key' => $api_key,
);
$payload = '';
foreach ( $post_fields as $name => $value ) {
$payload .= '--' . $boundary;
$payload .= "\r\n";
$payload .= 'Content-Disposition: form-data; name="' . $name . '"' . "\r\n\r\n";
$payload .= $value;
$payload .= "\r\n";
}
$payload .= '--' . $boundary;
$payload .= "\r\n";
$payload .= 'Content-Disposition: form-data; name="file"; filename="' . wp_basename( $file ) . '"' . "\r\n";
$payload .= 'Content-Type: ' . $type . "\r\n";
$payload .= "\r\n";
$payload .= $eio_filesystem->get_contents( $file );
$payload .= "\r\n";
$payload .= '--' . $boundary;
$payload .= 'Content-Disposition: form-data; name="submitHandler"' . "\r\n";
$payload .= "\r\n";
$payload .= "Upload\r\n";
$payload .= '--' . $boundary . '--';
add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
$response = wp_remote_post(
$url,
array(
'timeout' => 60,
'headers' => $headers,
'sslverify' => false,
'body' => $payload,
)
);
if ( is_wp_error( $response ) ) {
$error_message = $response->get_error_message();
ewwwio_debug_message( "rotate failed: $error_message" );
return false;
} else {
$tempfile = $file . '.tmp';
file_put_contents( $tempfile, $response['body'] );
$orig_size = filesize( $file );
$newsize = $orig_size;
if ( preg_match( '/exceeded/', $response['body'] ) ) {
ewwwio_debug_message( 'License Exceeded' );
set_transient( 'ewww_image_optimizer_cloud_status', 'exceeded', HOUR_IN_SECONDS );
ewwwio_delete_file( $tempfile );
} elseif ( ewww_image_optimizer_mimetype( $tempfile, 'i' ) === $type ) {
$newsize = filesize( $tempfile );
ewwwio_debug_message( "cloud rotation success: $newsize (new) vs. $orig_size (original)" );
ewwwio_rename( $tempfile, $file );
return true;
} else {
ewwwio_delete_file( $tempfile );
}
ewwwio_memory( __FUNCTION__ );
return false;
}
}
/**
* Backup an image using API servers.
*
* @since 4.8.0
*
* @param string $file Name of the file to backup.
*/
function ewww_image_optimizer_cloud_backup( $file ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
$api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
if ( empty( $api_key ) ) {
return false;
}
if ( 'cloud' !== ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) ) {
return false;
}
if ( ! ewwwio_is_file( $file ) || ! ewwwio_is_readable( $file ) ) {
return false;
}
if ( ! ewwwio_check_memory_available( filesize( $file ) * 1.1 ) ) { // 1.1 = upload buffer (filesize) multiplied by a factor of 1.1 for extra wiggle room.
$memory_required = filesize( $file ) * 1.1;
ewwwio_debug_message( "possibly insufficient memory for cloud (backup) operation: $memory_required" );
if ( function_exists( 'wp_raise_memory_limit' ) ) {
add_filter( 'image_memory_limit', 'ewww_image_optimizer_raise_memory_limit' );
wp_raise_memory_limit( 'image' );
}
}
if ( ! ewww_image_optimizer_cloud_verify( $api_key ) ) {
ewwwio_debug_message( 'cloud verify failed, image not backed up' );
return false;
}
ewwwio_debug_message( "file: $file " );
$url = 'http://optimize.exactlywww.com/backup/store.php';
$ssl = wp_http_supports( array( 'ssl' ) );
if ( $ssl ) {
$url = set_url_scheme( $url, 'https' );
}
$boundary = wp_generate_password( 24, false );
$headers = array(
'content-type' => 'multipart/form-data; boundary=' . $boundary,
'timeout' => 20,
'httpversion' => '1.0',
'blocking' => true,
);
$post_fields = array(
'filename' => $file,
'api_key' => $api_key,
);
global $ewww_image;
global $eio_filesystem;
ewwwio_get_filesystem();
if ( is_object( $ewww_image ) && $ewww_image->file === $file && ! empty( $ewww_image->backup ) ) {
$post_fields['backup'] = $ewww_image->backup;
} elseif ( is_object( $ewww_image ) && $ewww_image->file === $file && empty( $ewww_image->backup ) ) {
$post_fields['backup'] = uniqid() . hash( 'sha256', $file );
$ewww_image->backup = $post_fields['backup'];
} else {
ewwwio_debug_message( 'probably a new upload, not backing up yet' );
return false;
}
$payload = '';
foreach ( $post_fields as $name => $value ) {
$payload .= '--' . $boundary;
$payload .= "\r\n";
$payload .= 'Content-Disposition: form-data; name="' . $name . '"' . "\r\n\r\n";
$payload .= $value;
$payload .= "\r\n";
}
$payload .= '--' . $boundary;
$payload .= "\r\n";
$payload .= 'Content-Disposition: form-data; name="file"; filename="' . wp_basename( $file ) . '"' . "\r\n";
$payload .= 'Content-Type: ' . ewww_image_optimizer_mimetype( $file, 'i' ) . "\r\n";
$payload .= "\r\n";
$payload .= $eio_filesystem->get_contents( $file );
$payload .= "\r\n";
$payload .= '--' . $boundary;
$payload .= 'Content-Disposition: form-data; name="submitHandler"' . "\r\n";
$payload .= "\r\n";
$payload .= "Upload\r\n";
$payload .= '--' . $boundary . '--';
add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
$response = wp_remote_post(
$url,
array(
'timeout' => 20,
'headers' => $headers,
'sslverify' => false,
'body' => $payload,
)
);
if ( is_wp_error( $response ) ) {
$error_message = $response->get_error_message();
ewwwio_debug_message( "backup failed: $error_message" );
return false;
} else {
if ( false !== strpos( $response['body'], 'error' ) ) {
return false;
} elseif ( false !== strpos( $response['body'], 'success' ) ) {
ewwwio_debug_message( 'cloud backup success' );
return true;
} else {
return false;
}
}
ewwwio_memory( __FUNCTION__ );
return false;
}
/**
* Uses the API to resize images.
*
* @since 4.4.0
*
* @param string $file The file to resize.
* @param string $type File type of the file.
* @param int $dst_x X-coordinate of destination image (usually 0).
* @param int $dst_y Y-coordinate of destination image (usually 0).
* @param int $src_x X-coordinate of source image (usually 0 unless cropping).
* @param int $src_y Y-coordinate of source image (usually 0 unless cropping).
* @param int $dst_w Desired image width.
* @param int $dst_h Desired image height.
* @param int $src_w Source width.
* @param int $src_h Source height.
* @return string|WP_Error The image contents or the error message.
*/
function ewww_image_optimizer_cloud_resize( $file, $type, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( ! ewwwio_check_memory_available( filesize( $file ) * 2.2 ) ) { // 2.2 = upload buffer + download buffer (2) multiplied by a factor of 1.1 for extra wiggle room.
$memory_required = filesize( $file ) * 2.2;
ewwwio_debug_message( "possibly insufficient memory for cloud (resize) operation: $memory_required" );
if ( function_exists( 'wp_raise_memory_limit' ) ) {
add_filter( 'image_memory_limit', 'ewww_image_optimizer_raise_memory_limit' );
wp_raise_memory_limit( 'image' );
}
}
$api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
if ( empty( $api_key ) ) {
return new WP_Error( 'invalid_key', __( 'Could not verify API key', 'ewww-image-optimizer' ) );
}
$started = microtime( true );
if ( 'exceeded' === get_transient( 'ewww_image_optimizer_cloud_status' ) ) {
if ( ! ewww_image_optimizer_cloud_verify( $api_key ) ) {
ewwwio_debug_message( 'cloud verify failed, image not resized' );
return new WP_Error( 'invalid_key', __( 'Could not verify API key', 'ewww-image-optimizer' ) );
}
}
// Calculate how much time has elapsed since we started.
$elapsed = microtime( true ) - $started;
ewwwio_debug_message( "cloud verify took $elapsed seconds" );
if ( 'exceeded' === get_transient( 'ewww_image_optimizer_cloud_status' ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_exceeded' ) > time() ) {
ewwwio_debug_message( 'license exceeded, image not rotated' );
return new WP_Error( 'invalid_key', __( 'License Exceeded', 'ewww-image-optimizer' ) );
}
global $eio_filesystem;
ewwwio_get_filesystem();
ewwwio_debug_message( "file: $file " );
ewwwio_debug_message( "width: $dst_w" );
ewwwio_debug_message( "height: $dst_h" );
$url = 'http://optimize.exactlywww.com/resize/';
$ssl = wp_http_supports( array( 'ssl' ) );
if ( $ssl ) {
$url = set_url_scheme( $url, 'https' );
}
$boundary = wp_generate_password( 24, false );
$headers = array(
'content-type' => 'multipart/form-data; boundary=' . $boundary,
'timeout' => 60,
'httpversion' => '1.0',
'blocking' => true,
);
$post_fields = array(
'filename' => $file,
'api_key' => $api_key,
'dst_x' => (int) $dst_x,
'dst_y' => (int) $dst_y,
'src_x' => (int) $src_x,
'src_y' => (int) $src_y,
'dst_w' => (int) $dst_w,
'dst_h' => (int) $dst_h,
'src_w' => (int) $src_w,
'src_h' => (int) $src_h,
);
$payload = '';
foreach ( $post_fields as $name => $value ) {
$payload .= '--' . $boundary;
$payload .= "\r\n";
$payload .= 'Content-Disposition: form-data; name="' . $name . '"' . "\r\n\r\n";
$payload .= $value;
$payload .= "\r\n";
}
$payload .= '--' . $boundary;
$payload .= "\r\n";
$payload .= 'Content-Disposition: form-data; name="file"; filename="' . wp_basename( $file ) . '"' . "\r\n";
$payload .= 'Content-Type: ' . $type . "\r\n";
$payload .= "\r\n";
$payload .= $eio_filesystem->get_contents( $file );
$payload .= "\r\n";
$payload .= '--' . $boundary;
$payload .= 'Content-Disposition: form-data; name="submitHandler"' . "\r\n";
$payload .= "\r\n";
$payload .= "Upload\r\n";
$payload .= '--' . $boundary . '--';
add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
$response = wp_remote_post(
$url,
array(
'timeout' => 60,
'headers' => $headers,
'sslverify' => false,
'body' => $payload,
)
);
if ( is_wp_error( $response ) ) {
$error_message = $response->get_error_message();
ewwwio_debug_message( "resize failed: $error_message" );
return $response;
} else {
$tempfile = $file . '.tmp';
file_put_contents( $tempfile, $response['body'] );
$orig_size = filesize( $file );
$newsize = $orig_size;
if ( false !== strpos( $response['body'], 'error' ) ) {
$response = json_decode( $response['body'], true );
ewwwio_debug_message( 'API resize error: ' . $response['error'] );
ewwwio_delete_file( $tempfile );
return new WP_Error( 'image_resize_error', $response['error'] );
} elseif ( false !== strpos( ewww_image_optimizer_mimetype( $tempfile, 'i' ), 'image' ) ) {
$newsize = filesize( $tempfile );
ewww_image_optimizer_is_animated( $tempfile );
ewwwio_debug_message( "API resize success: $newsize (new) vs. $orig_size (original)" );
ewwwio_delete_file( $tempfile );
return $response['body'];
}
ewwwio_delete_file( $tempfile );
ewwwio_debug_message( 'API resize error: unknown' );
return new WP_Error( 'image_resize_error', __( 'Unknown resize error', 'ewww-image-optimizer' ) );
}
}
/**
* Setup our own database connection with full utf8 capability.
*
* @global object $ewwwdb A new database connection with super powers.
* @global string $table_prefix The table prefix for the WordPress database.
*/
function ewww_image_optimizer_db_init() {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
global $ewwwdb, $table_prefix;
require_once EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-ewwwdb.php';
if ( ! defined( 'DB_USER' ) || ! defined( 'DB_PASSWORD' ) || ! defined( 'DB_NAME' ) || ! defined( 'DB_HOST' ) ) {
global $wpdb;
$ewwwdb = $wpdb;
return;
} elseif ( ! isset( $ewwwdb ) ) {
$ewwwdb = new EwwwDB( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
}
if ( ! empty( $ewwwdb->error ) ) {
dead_db();
}
$ewwwdb->field_types = array(
'post_author' => '%d',
'post_parent' => '%d',
'menu_order' => '%d',
'term_id' => '%d',
'term_group' => '%d',
'term_taxonomy_id' => '%d',
'parent' => '%d',
'count' => '%d',
'object_id' => '%d',
'term_order' => '%d',
'ID' => '%d',
'comment_ID' => '%d',
'comment_post_ID' => '%d',
'comment_parent' => '%d',
'user_id' => '%d',
'link_id' => '%d',
'link_owner' => '%d',
'link_rating' => '%d',
'option_id' => '%d',
'blog_id' => '%d',
'meta_id' => '%d',
'post_id' => '%d',
'user_status' => '%d',
'umeta_id' => '%d',
'comment_karma' => '%d',
'comment_count' => '%d',
// multisite.
'active' => '%d',
'cat_id' => '%d',
'deleted' => '%d',
'lang_id' => '%d',
'mature' => '%d',
'public' => '%d',
'site_id' => '%d',
'spam' => '%d',
);
$prefix = $ewwwdb->set_prefix( $table_prefix );
// Setup blog_id and prefix for multisite (and fallback).
if ( is_wp_error( $prefix ) || is_multisite() ) {
global $wpdb;
$ewwwdb->prefix = $wpdb->prefix;
$ewwwdb->blogid = $wpdb->blogid;
// and just in case we need it...
$ewwwdb->base_prefix = $wpdb->base_prefix;
}
if ( ! isset( $ewwwdb->ewwwio_images ) ) {
$ewwwdb->ewwwio_images = $ewwwdb->prefix . 'ewwwio_images';
}
if ( ! isset( $ewwwdb->ewwwio_queue ) ) {
$ewwwdb->ewwwio_queue = $ewwwdb->prefix . 'ewwwio_queue';
}
}
/**
* Inserts a single record into the table as pending, or marks it pending if it exists.
*
* @global object $ewwwdb A new database connection with super powers.
*
* @param string $path The filename of the image.
* @param string $gallery The type (origin) of the image.
* @param int $attachment_id The attachment ID, if there is one.
* @param string $size The name of the resize for the image.
* @return int The row ID of the record updated/inserted.
*/
function ewww_image_optimizer_single_insert( $path, $gallery = '', $attachment_id = '', $size = '' ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
ewww_image_optimizer_db_init();
global $ewwwdb;
$already_optimized = ewww_image_optimizer_find_already_optimized( $path );
if ( is_array( $already_optimized ) && ! empty( $already_optimized ) ) {
if ( ! empty( $already_optimized['pending'] ) ) {
ewwwio_debug_message( "already pending record for $path - {$already_optimized['id']}" );
return $already_optimized['id'];
}
$ewwwdb->update(
$ewwwdb->ewwwio_images,
array(
'pending' => 1,
),
array(
'id' => $already_optimized['id'],
)
);
return $already_optimized['id'];
} else {
ewwwio_debug_message( "queuing $path" );
$orig_size = ewww_image_optimizer_filesize( $path );
$path = ewww_image_optimizer_relativize_path( $path );
if ( seems_utf8( $path ) ) {
$utf8_file_path = $path;
} else {
$utf8_file_path = mb_convert_encoding( $path, 'UTF-8' );
}
$to_insert = array(
'path' => $utf8_file_path,
'orig_size' => $orig_size,
'pending' => 1,
);
if ( $gallery ) {
$to_insert['gallery'] = $gallery;
}
if ( $attachment_id ) {
$to_insert['attachment_id'] = $attachment_id;
}
if ( $size ) {
$to_insert['resize'] = $size;
}
$ewwwdb->insert( $ewwwdb->ewwwio_images, $to_insert );
ewwwio_debug_message( "inserted pending record for $path - {$ewwwdb->insert_id}" );
return $ewwwdb->insert_id;
}
}
/**
* Finds the path of a file from the ewwwio_images table.
*
* @param int $id The db record to retrieve for the file path.
* @return string The full file path from the db.
*/
function ewww_image_optimizer_find_file_by_id( $id ) {
if ( ! $id ) {
return false;
}
ewwwio_debug_message( '' . __METHOD__ . '()' );
global $wpdb;
if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
ewww_image_optimizer_db_init();
global $ewwwdb;
} else {
$ewwwdb = $wpdb;
}
$id = (int) $id;
$file = $ewwwdb->get_var( $ewwwdb->prepare( "SELECT path FROM $ewwwdb->ewwwio_images WHERE id = %d", $id ) );
if ( is_null( $file ) ) {
return false;
}
$file = ewww_image_optimizer_absolutize_path( $file );
ewwwio_debug_message( "found $file by id" );
if ( ewwwio_is_file( $file ) ) {
return $file;
}
return false;
}
/**
* Inserts multiple records into the table at once.
*
* Each sub-array in $data should have the same number of items as $format.
*
* @global object $wpdb
* @global object $ewwwdb A clone of $wpdb unless it is lacking utf8 connectivity.
*
* @param string $table The table to insert records into.
* @param array $data Can be any multi-dimensional array with records to insert.
* @param array $format A list of formats for the values in each record of $data.
*/
function ewww_image_optimizer_mass_insert( $table, $data, $format ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( empty( $table ) || ! ewww_image_optimizer_iterable( $data ) || ! ewww_image_optimizer_iterable( $format ) ) {
return false;
}
global $wpdb;
if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
ewww_image_optimizer_db_init();
global $ewwwdb;
} else {
$ewwwdb = $wpdb;
}
$record_count = count( $data );
ewwwio_debug_message( "inserting $record_count records" );
$multi_formats = array();
$values = array();
foreach ( $data as $record ) {
if ( ! ewww_image_optimizer_iterable( $record ) ) {
continue;
}
foreach ( $record as $value ) {
$values[] = $value;
}
$multi_formats[] = '(' . implode( ',', $format ) . ')';
}
$first = reset( $data );
$fields = '`' . implode( '`, `', array_keys( $first ) ) . '`';
$multi_formats = implode( ',', $multi_formats );
return $ewwwdb->query( $ewwwdb->prepare( "INSERT INTO `$table` ($fields) VALUES $multi_formats", $values ) );
}
/**
* Search the database to see if we've done this image before.
*
* @global object $wpdb
*
* @param string $file The filename of the image.
* @param int $orig_size The current filesize of the image.
* @return string The image results from the table, if found.
*/
function ewww_image_optimizer_check_table( $file, $orig_size ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
ewwwio_debug_message( "checking for $file with size: $orig_size" );
global $ewww_image;
global $ewww_force_smart;
$image = array();
if ( ! is_object( $ewww_image ) || ! $ewww_image instanceof EWWW_Image || $ewww_image->file !== $file ) {
$ewww_image = new EWWW_Image( 0, '', $file );
}
if ( ! empty( $ewww_image->record ) ) {
$image = $ewww_image->record;
} else {
$image = false;
}
if ( is_array( $image ) && (int) $image['image_size'] === (int) $orig_size ) {
$prev_string = ' - ' . __( 'Previously Optimized', 'ewww-image-optimizer' );
if ( preg_match( '/' . __( 'License exceeded', 'ewww-image-optimizer' ) . '/', $image['results'] ) ) {
return '';
}
$already_optimized = preg_replace( "/$prev_string/", '', $image['results'] );
$already_optimized = $already_optimized . $prev_string;
ewwwio_debug_message( "already optimized: {$image['path']} - $already_optimized" );
ewwwio_memory( __FUNCTION__ );
// Make sure the image isn't pending.
if ( $image['pending'] && empty( $ewww_force_smart ) ) {
global $wpdb;
$wpdb->update(
$wpdb->ewwwio_images,
array(
'pending' => 0,
),
array(
'id' => $image['id'],
)
);
}
return $already_optimized;
} elseif ( is_array( $image ) && ! empty( $image['updates'] ) && $image['updates'] > 5 ) {
ewwwio_debug_message( "prevented excessive re-opt: {$image['path']}" );
// Make sure the image isn't pending.
if ( $image['pending'] ) {
global $wpdb;
$wpdb->update(
$wpdb->ewwwio_images,
array(
'pending' => 0,
),
array(
'id' => $image['id'],
)
);
}
return __( 'Re-optimize prevented', 'ewww-image-optimizer' );
}
return '';
}
/**
* Updates the savings statistics cache.
*
* @param int $opt_size The new size of the image.
* @param int $orig_size The original size of the image.
*/
function ewww_image_optimizer_update_savings( $opt_size, $orig_size ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
if ( ! $opt_size || ! $orig_size ) {
return;
}
$cache_savings = get_transient( 'ewww_image_optimizer_savings' );
if ( ! empty( $cache_savings ) && is_array( $cache_savings ) && 2 === count( $cache_savings ) ) {
$total_opt = (int) $cache_savings[0];
$total_orig = (int) $cache_savings[1];
ewwwio_debug_message( "increasing $total_opt by $opt_size" );
$total_opt += (int) $opt_size;
ewwwio_debug_message( "increasing $total_orig by $orig_size" );
$total_orig += (int) $orig_size;
set_transient( 'ewww_image_optimizer_savings', array( $total_opt, $total_orig ), DAY_IN_SECONDS );
}
if ( is_multisite() ) {
$cache_savings = get_site_transient( 'ewww_image_optimizer_savings' );
if ( ! empty( $cache_savings ) && is_array( $cache_savings ) && 2 === count( $cache_savings ) ) {
$total_opt = (int) $cache_savings[0];
$total_orig = (int) $cache_savings[1];
ewwwio_debug_message( "increasing $total_opt by $opt_size" );
$total_opt += (int) $opt_size;
ewwwio_debug_message( "increasing $total_orig by $orig_size" );
$total_orig += (int) $orig_size;
set_site_transient( 'ewww_image_optimizer_savings', array( $total_opt, $total_orig ), DAY_IN_SECONDS );
}
}
}
/**
* Inserts or updates an image record in the database.
*
* @global object $wpdb
* @global object $ewwwdb A clone of $wpdb unless it is lacking utf8 connectivity.
* @global object $ewww_image Contains more information about the image currently being processed.
*
* @param string $attachment The filename of the image.
* @param int $opt_size The new size of the image.
* @param int $orig_size The original size of the image.
* @param string $original Optional. The name of the file before it was converted. Default ''.
* @param string $backup_hash Optional. A unique identifier for this file. Default ''.
*/
function ewww_image_optimizer_update_table( $attachment, $opt_size, $orig_size, $original = '', $backup_hash = '' ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
global $wpdb;
if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
ewww_image_optimizer_db_init();
global $ewwwdb;
} else {
$ewwwdb = $wpdb;
}
global $ewww_image;
// First check if the image was converted, so we don't orphan records.
if ( $original && $original !== $attachment ) {
$already_optimized = ewww_image_optimizer_find_already_optimized( $original );
$converted = ewww_image_optimizer_relativize_path( $original );
} else {
$already_optimized = ewww_image_optimizer_find_already_optimized( $attachment );
if ( is_array( $already_optimized ) && ! empty( $already_optimized['converted'] ) ) {
$converted = $already_optimized['converted'];
} else {
$converted = '';
}
}
if ( is_array( $already_optimized ) && ! empty( $already_optimized['updates'] ) && $opt_size >= $orig_size ) {
$prev_string = ' - ' . __( 'Previously Optimized', 'ewww-image-optimizer' );
} else {
$prev_string = '';
}
if ( is_array( $already_optimized ) && ! empty( $already_optimized['orig_size'] ) && $already_optimized['orig_size'] > $orig_size ) {
$orig_size = $already_optimized['orig_size'];
}
ewwwio_debug_message( "savings: $opt_size (new) vs. $orig_size (orig)" );
// Calculate how much space was saved.
$results_msg = ewww_image_optimizer_image_results( $orig_size, $opt_size, $prev_string );
$updates = array(
'path' => ewww_image_optimizer_relativize_path( $attachment ),
'converted' => $converted,
'level' => 0,
'image_size' => $opt_size,
'results' => $results_msg,
'updates' => 1,
'backup' => preg_replace( '/[^\w]/', '', $backup_hash ),
);
if ( ! seems_utf8( $updates['path'] ) ) {
$updates['path'] = mb_convert_encoding( $updates['path'], 'UTF-8' );
}
// Store info on the current image for future reference.
if ( empty( $already_optimized ) || ! is_array( $already_optimized ) ) {
ewwwio_debug_message( "creating new record, path: $attachment, size: $opt_size" );
ewww_image_optimizer_update_savings( $opt_size, $orig_size );
if ( is_object( $ewww_image ) && $ewww_image instanceof EWWW_Image && $ewww_image->gallery ) {
$updates['gallery'] = $ewww_image->gallery;
}
if ( is_object( $ewww_image ) && $ewww_image instanceof EWWW_Image && $ewww_image->attachment_id ) {
$updates['attachment_id'] = $ewww_image->attachment_id;
}
if ( is_object( $ewww_image ) && $ewww_image instanceof EWWW_Image && $ewww_image->resize ) {
$updates['resize'] = $ewww_image->resize;
}
if ( is_object( $ewww_image ) && $ewww_image instanceof EWWW_Image && $ewww_image->level ) {
$updates['level'] = $ewww_image->level;
}
$updates['orig_size'] = $orig_size;
/* $updates['updated'] = gmdate( 'Y-m-d H:i:s' ); */
$ewwwdb->insert( $ewwwdb->ewwwio_images, $updates );
} else {
if ( is_array( $already_optimized ) && empty( $already_optimized['orig_size'] ) ) {
$updates['orig_size'] = $orig_size;
}
ewwwio_debug_message( "updating existing record ({$already_optimized['id']}), path: $attachment, size: $opt_size" );
if ( $already_optimized['updates'] && apply_filters( 'ewww_image_optimizer_allowed_reopt', false ) ) {
$updates['updates'] = $already_optimized['updates'];
} elseif ( $already_optimized['updates'] ) {
$updates['updates'] = $already_optimized['updates'] + 1;
}
$updates['pending'] = 0;
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && $already_optimized['updates'] > 1 ) {
$updates['trace'] = ewwwio_debug_backtrace();
}
if ( empty( $already_optimized['gallery'] ) && is_object( $ewww_image ) && $ewww_image instanceof EWWW_Image && $ewww_image->gallery ) {
$updates['gallery'] = $ewww_image->gallery;
}
if ( empty( $already_optimized['attachment_id'] ) && is_object( $ewww_image ) && $ewww_image instanceof EWWW_Image && $ewww_image->attachment_id ) {
$updates['attachment_id'] = $ewww_image->attachment_id;
}
if ( empty( $already_optimized['resize'] ) && is_object( $ewww_image ) && $ewww_image instanceof EWWW_Image && $ewww_image->resize ) {
$updates['resize'] = $ewww_image->resize;
}
if ( is_object( $ewww_image ) && $ewww_image instanceof EWWW_Image && $ewww_image->level ) {
$updates['level'] = $ewww_image->level;
}
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && ewww_image_optimizer_function_exists( 'print_r' ) ) {
ewwwio_debug_message( print_r( $updates, true ) );
}
// Update information for the image.
$record_updated = $ewwwdb->update(
$ewwwdb->ewwwio_images,
$updates,
array(
'id' => $already_optimized['id'],
)
);
if ( false === $record_updated ) {
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && ewww_image_optimizer_function_exists( 'print_r' ) ) {
ewwwio_debug_message( 'db error: ' . print_r( $wpdb->last_error, true ) );
}
} else {
ewwwio_debug_message( "updated $record_updated records successfully" );
}
} // End if().
ewwwio_memory( __FUNCTION__ );
$ewwwdb->flush();
ewwwio_memory( __FUNCTION__ );
return $results_msg;
}
/**
* Creates a human-readable message based on the original and optimized sizes.
*
* @param int $orig_size The original size of the image.
* @param int $opt_size The new size of the image.
* @param string $prev_string Optional. A message to append for previously optimized images.
* @return string A message with the percentage and size savings.
*/
function ewww_image_optimizer_image_results( $orig_size, $opt_size, $prev_string = '' ) {
if ( $opt_size >= $orig_size ) {
ewwwio_debug_message( 'original and new file are same size (or something weird made the new one larger), no savings' );
$results_msg = __( 'No savings', 'ewww-image-optimizer' );
} else {
// Calculate how much space was saved.
$savings = intval( $orig_size ) - intval( $opt_size );
$savings_str = ewww_image_optimizer_size_format( $savings );
// Determine the percentage savings.
$percent = number_format_i18n( 100 - ( 100 * ( $opt_size / $orig_size ) ), 1 ) . '%';
// Use the percentage and the savings size to output a nice message to the user.
$results_msg = sprintf(
/* translators: 1: Size of savings in bytes, kb, mb 2: Percentage savings */
__( 'Reduced by %1$s (%2$s)', 'ewww-image-optimizer' ),
$percent,
$savings_str
) . $prev_string;
ewwwio_debug_message( "original and new file are different size: $results_msg" );
}
return $results_msg;
}
/**
* Wrapper around size_format to remove the decimal from sizes in bytes.
*
* @param int $size A filesize in bytes.
* @param int $precision Number of places after the decimal separator.
* @return string Human-readable filesize.
*/
function ewww_image_optimizer_size_format( $size, $precision = 1 ) {
// Convert it to human readable format.
$size_str = size_format( $size, $precision );
// Remove spaces and extra decimals when measurement is in bytes.
return preg_replace( '/\.0+ B ?/', ' B', $size_str );
}
/**
* Called to process each image during scheduled optimization.
*
* @global object $wpdb
* @global object $ewwwdb A clone of $wpdb unless it is lacking utf8 connectivity.
* @global bool $ewww_defer Set to false to avoid deferring image optimization.
* @global object $ewww_image Contains more information about the image currently being processed.
*
* @param array $attachment {
* Optional. The file to optimize. Default null.
*
* @type int $id The id number in the ewwwio_images table.
* @type string $path The filename of the image.
* }
* @param bool $auto Optional. True if scheduled optimization is running. Default false.
* @param bool $cli Optional. True if WP-CLI is running. Default false.
* @return string When called from WP-CLI, a message with compression results.
*/
function ewww_image_optimizer_aux_images_loop( $attachment = null, $auto = false, $cli = false ) {
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
global $wpdb;
if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
ewww_image_optimizer_db_init();
global $ewwwdb;
} else {
$ewwwdb = $wpdb;
}
global $ewww_defer;
$ewww_defer = false;
$output = array();
// Verify that an authorized user has started the optimizer.
$permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
if ( ! $auto && ( empty( $_REQUEST['ewww_wpnonce'] ) || ! wp_verify_nonce( sanitize_key( $_REQUEST['ewww_wpnonce'] ), 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) ) {
$output['error'] = esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' );
wp_die( wp_json_encode( $output ) );
}
session_write_close();
if ( ! empty( $_REQUEST['ewww_wpnonce'] ) ) {
// Find out if our nonce is on it's last leg/tick.
$tick = wp_verify_nonce( sanitize_key( $_REQUEST['ewww_wpnonce'] ), 'ewww-image-optimizer-bulk' );
if ( 2 === $tick ) {
ewwwio_debug_message( 'nonce on its last leg' );
$output['new_nonce'] = wp_create_nonce( 'ewww-image-optimizer-bulk' );
} else {
ewwwio_debug_message( 'nonce still alive and kicking' );
$output['new_nonce'] = '';
}
}
// Retrieve the time when the optimizer starts.
$started = microtime( true );
if ( ewww_image_optimizer_stl_check() && ewww_image_optimizer_function_exists( 'ini_get' ) && ini_get( 'max_execution_time' ) < 60 ) {
set_time_limit( 0 );
}
// Get the next image in the queue.
if ( empty( $attachment ) ) {
list( $id, $attachment ) = $ewwwdb->get_row( "SELECT id,path FROM $ewwwdb->ewwwio_images WHERE pending=1 LIMIT 1", ARRAY_N );
} else {
$id = $attachment['id'];
$attachment = $attachment['path'];
}
if ( $attachment ) {
$attachment = ewww_image_optimizer_absolutize_path( $attachment );
}
global $ewww_image;
$ewww_image = new EWWW_Image( 0, '', $attachment );
// Resize the image, if possible.
if ( empty( $ewww_image->resize ) && ewww_image_optimizer_should_resize_other_image( $ewww_image->file ) ) {
$new_dimensions = ewww_image_optimizer_resize_upload( $attachment );
}
// Do the optimization for the current image.
$results = ewww_image_optimizer( $attachment );
if ( ! $results[0] && is_numeric( $id ) ) {
$ewwwdb->delete(
$ewwwdb->ewwwio_images,
array(
'id' => $id,
),
array(
'%d',
)
);
}
if ( 'exceeded' === get_transient( 'ewww_image_optimizer_cloud_status' ) ) {
if ( ! $auto ) {
$output['error'] = '' . esc_html__( 'License Exceeded', 'ewww-image-optimizer' ) . '';
echo wp_json_encode( $output );
}
if ( $cli ) {
WP_CLI::error( __( 'License Exceeded', 'ewww-image-optimizer' ) );
}
die();
}
if ( 'exceeded quota' === get_transient( 'ewww_image_optimizer_cloud_status' ) ) {
if ( ! $auto ) {
$output['error'] = '' . esc_html__( 'Soft quota reached, contact us for more', 'ewww-image-optimizer' ) . '';
echo wp_json_encode( $output );
}
if ( $cli ) {
WP_CLI::error( __( 'Soft quota reached, contact us for more', 'ewww-image-optimizer' ) );
}
die();
}
if ( ! $auto ) {
// Output the path.
$output['results'] = '
' . esc_html__( 'Optimized', 'ewww-image-optimizer' ) . ' ' . esc_html( $attachment ) . ' ';
// Tell the user what the results were for the original image.
$output['results'] .= $results[1] . ' ';
// Calculate how much time has elapsed since we started.
$elapsed = microtime( true ) - $started;
// Output how much time has elapsed since we started.
$output['results'] .= sprintf(
esc_html(
/* translators: %s: number of seconds */
_n( 'Elapsed: %s second', 'Elapsed: %s seconds', $elapsed, 'ewww-image-optimizer' )
) . '
';
} else {
$convert_link = __( 'JPG to PNG', 'ewww-image-optimizer' );
$convert_desc = __( 'WARNING: Removes metadata. Requires GD or ImageMagick. PNG is generally much better than JPG for logos and other images with a limited range of colors.', 'ewww-image-optimizer' );
}
break;
case 'image/png':
// If pngout and optipng are missing and should not be skipped.
if ( $tools['optipng']['enabled'] && ! $tools['optipng']['path'] ) {
$msg = '
' . sprintf(
/* translators: %s: name of a tool like jpegtran */
__( '%s is missing', 'ewww-image-optimizer' ),
'optipng'
) . '
';
} else {
$convert_link = __( 'PNG to JPG', 'ewww-image-optimizer' );
$convert_desc = __( 'WARNING: This is not a lossless conversion and requires GD or ImageMagick. JPG is much better than PNG for photographic use because it compresses the image and discards data. Transparent images will only be converted if a background color has been set.', 'ewww-image-optimizer' );
}
break;
case 'image/gif':
// If gifsicle is missing and should not be skipped.
if ( $tools['gifsicle']['enabled'] && ! $tools['gifsicle']['path'] ) {
$msg = '
' . sprintf(
/* translators: %s: name of a tool like jpegtran */
__( '%s is missing', 'ewww-image-optimizer' ),
'gifsicle'
) . '
';
} else {
$convert_link = __( 'GIF to PNG', 'ewww-image-optimizer' );
$convert_desc = __( 'PNG is generally better than GIF, but does not support animation. Animated images will not be converted.', 'ewww-image-optimizer' );
}
break;
case 'application/pdf':
if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) ) {
$msg = '
';
$in_progress = true;
}
if ( ! $in_progress ) {
$optimized_images = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->ewwwio_images WHERE attachment_id = %d AND gallery = 'media' AND image_size <> 0 ORDER BY orig_size DESC", $id ), ARRAY_A );
if ( ! $optimized_images ) {
// Attempt migration, but only if the original image is in the db, $migrated will be metadata on success, false on failure.
$migrated = ewww_image_optimizer_migrate_meta_to_db( $id, $meta, true );
}
if ( $migrated ) {
$optimized_images = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->ewwwio_images WHERE attachment_id = %d AND gallery = 'media' AND image_size <> 0 ORDER BY orig_size DESC", $id ), ARRAY_A );
}
if ( ! $optimized_images ) {
list( $possible_action_id, $optimized_images ) = ewww_image_optimizer_get_translated_media_results( $id );
if ( $optimized_images ) {
$action_id = $possible_action_id;
}
}
}
// If optimizer data exists in the db.
if ( ! empty( $optimized_images ) ) {
list( $detail_output, $converted, $backup_available ) = ewww_image_optimizer_custom_column_results( $action_id, $optimized_images );
echo wp_kses_post( $detail_output );
// Output the optimizer actions.
if ( current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
// Display a link to re-optimize manually.
echo '
';
}
} elseif ( ! $in_progress && current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
// Give the user the option to optimize the image right now.
if ( ewww_image_optimizer_easy_active() ) {
echo '
';
}
if ( current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
// Give the user the option to optimize the image right now.
printf(
'
';
}
} // End if().
echo '';
} // End if().
}
/**
* Check the stored results to see if 'restore & re-optimize' is possible and applicable.
*
* @param array $optimized_images The list of image records from the database.
* @param int $compression_level The currently active compression level.
*/
function ewww_image_optimizer_restore_possible( $optimized_images, $compression_level ) {
if ( empty( $compression_level ) ) {
return '';
}
if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) ) {
return '';
}
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
foreach ( $optimized_images as $optimized_image ) {
if ( 'full' === $optimized_image['resize'] ) {
ewwwio_debug_message( "comparing $compression_level (current) vs. {$optimized_image['level']} (previous)" );
if ( $compression_level < 30 && $compression_level < $optimized_image['level'] && $optimized_image['level'] > 20 ) {
global $eio_backup;
return $eio_backup->is_backup_available( $optimized_image['path'], $optimized_image );
}
}
}
return false;
}
/**
* Check the stored results to detect deviation from the current settings.
*
* @param array $optimized_images The list of image records from the database.
* @param int $compression_level The currently active compression level.
*/
function ewww_image_optimizer_variant_level_notice( $optimized_images, $compression_level ) {
if ( empty( $compression_level ) ) {
return '';
}
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
foreach ( $optimized_images as $optimized_image ) {
if ( 'full' === $optimized_image['resize'] ) {
if ( is_numeric( $optimized_image['level'] ) && (int) $compression_level > (int) $optimized_image['level'] ) {
return ' !';
}
}
}
return '';
}
/**
* Determine how many sizes need optimization.
*
* @param array $sizes The 'sizes' portion of the attachment metadata.
* @return int The number of unoptimized sizes.
*/
function ewww_image_optimizer_count_unoptimized_sizes( $sizes ) {
if ( ! ewww_image_optimizer_iterable( $sizes ) ) {
ewwwio_debug_message( 'unoptimized sizes cannot be counted' );
return 0;
}
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
$sizes_to_opt = 0;
$disabled_sizes = ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_resizes_opt', false, true );
// To keep track of the ones we have already processed.
$processed = array();
foreach ( $sizes as $size => $data ) {
ewwwio_debug_message( "checking for size: $size" );
if ( strpos( $size, 'webp' ) === 0 ) {
continue;
}
if ( ! empty( $disabled_sizes[ $size ] ) ) {
continue;
}
if ( ! empty( $disabled_sizes['pdf-full'] ) && 'full' === $size ) {
continue;
}
if ( empty( $data['file'] ) ) {
continue;
}
// Check through all the sizes we've processed so far.
foreach ( $processed as $proc => $scan ) {
// If a previous resize had identical dimensions...
if ( $scan['height'] === $data['height'] && $scan['width'] === $data['width'] ) {
// Found a duplicate size, get outta here!
continue( 2 );
}
}
++$sizes_to_opt;
// Store info on the sizes we've processed, so we can check the list for duplicate sizes.
$processed[ $size ]['width'] = $data['width'];
$processed[ $size ]['height'] = $data['height'];
} // End foreach().
return $sizes_to_opt;
}
/**
* Display cumulative image compression results with individual images displayed in a modal.
*
* @param int $id The ID number of the attachment.
* @param array $optimized_images A list of image records related to $id.
* @return array {
* Information compiled from the database records.
*
* @type string $output The image results plus a table of individual image results in a modal.
* @type string|bool $converted The original image if the attachment was converted or false.
* @type string|bool $backup_available The backup hash if available or false.
* }
*/
function ewww_image_optimizer_custom_column_results( $id, $optimized_images ) {
if ( empty( $id ) || empty( $optimized_images ) || ! is_array( $optimized_images ) ) {
return array( '', false, false );
}
ewwwio_debug_message( '' . __FUNCTION__ . '()' );
global $ewwwio_resize_status;
$orig_size = 0;
$opt_size = 0;
$converted = false;
$backup_available = false;
$sizes_to_opt = 0;
$output = '';
$detail_output = '
' . esc_html__( 'In order to use server-based delivery, Cloudways sites must have WebP Redirection enabled in their Application Settings.', 'ewww-image-optimizer' ) . "\n";
else :
if ( defined( 'PHP_SAPI' ) && false === strpos( PHP_SAPI, 'apache' ) && false === strpos( PHP_SAPI, 'litespeed' ) ) {
$false_positive_headers = esc_html__( 'This may be a false positive. If so, the warning should go away once you implement the rewrite rules.', 'ewww-image-optimizer' );
}
if ( ! apache_mod_loaded( 'mod_rewrite' ) ) {
/* translators: %s: mod_rewrite or mod_headers */
$header_error = '
' . sprintf( esc_html__( 'Your site appears to be missing %s, please contact your webhost or system administrator to enable this Apache module.', 'ewww-image-optimizer' ), 'mod_rewrite' ) . " $false_positive_headers
\n";
}
if ( ! apache_mod_loaded( 'mod_headers' ) ) {
/* translators: %s: mod_rewrite or mod_headers */
$header_error = '
' . sprintf( esc_html__( 'Your site appears to be missing %s, please contact your webhost or system administrator to enable this Apache module.', 'ewww-image-optimizer' ), 'mod_headers' ) . " $false_positive_headers
\n";
}
endif;
$webp_mime_error = ewww_image_optimizer_test_webp_mime_error();
if ( $webp_mime_error ) {
echo wp_kses_post( $header_error );
}
$webp_rewrite_verify = ! (bool) ewww_image_optimizer_webp_rewrite_verify();
endif;
if ( $webp_mime_error && $webp_rewrite_verify ) :
printf(
/* translators: %s: an error message from the WebP self-test */
'