get_uncompressed_images_count();
$uncompressed_pages = ceil( $uncompressed_count / self::$MEDIA_PER_PAGE );
$total_count = self::$SqueezeHelpers->get_total_images_count();
$total_pages = ceil( $total_count / self::$MEDIA_PER_PAGE );
$compressed_count = $total_count - $uncompressed_count;
$compressed_percentage = ( $total_count > 0 ? round( $compressed_count / $total_count * 100, 2 ) : 0 );
//$total_count = array_sum((array)wp_count_attachments("image"));
$not_compressed_posts = implode( ",", self::$SqueezeHelpers->get_uncompressed_images() );
$all_posts = implode( ",", self::$SqueezeHelpers->get_total_images() );
$directory_path = ( get_transient( 'squeeze_bulk_path' ) ? get_transient( 'squeeze_bulk_path' ) : array('/wp-content/uploads/') );
$directory_path = array_map( array(self::$SqueezeHelpers, 'normalize_bulk_directory_storage_path'), (array) $directory_path );
$directory_path_json = wp_json_encode( $directory_path );
$is_direct_webp = self::$SqueezeHelpers->get_option( 'direct_webp' );
?>
(change)', 'squeeze' ), esc_url( admin_url( 'options-general.php?page=squeeze#squeeze_basic' ) ) );
?>
apache_get_modules();
// Only warn when PHP can list modules and mod_rewrite is missing. null means
// undetectable (CGI/FPM) — do not treat that as "mod_rewrite off".
if ( is_array( $modules ) && !in_array( 'mod_rewrite', $modules, true ) ) {
$is_auto_webp = self::$SqueezeHelpers->get_option( 'auto_webp' );
$is_webp_replace_urls = self::$SqueezeHelpers->get_option( 'webp_replace_urls' );
if ( $is_auto_webp && !$is_webp_replace_urls ) {
add_settings_error(
'squeeze_notices',
'squeeze_notices',
__( 'The Apache mod_rewrite module is not enabled on your server OR your server is not running Apache.', 'squeeze' ) . ' ' . __( 'To serve WebP, enable mod_rewrite, or switch to "Rewrite src to WebP URLs in HTML" delivery.', 'squeeze' ),
'warning'
);
}
}
}
public function options_page_html() {
// check user capabilities
if ( !current_user_can( 'manage_options' ) ) {
return;
}
?>
get_option( 'auto_webp' );
$webp_lossless = self::$SqueezeHelpers->get_option( 'webp_lossless' );
register_setting( 'squeeze_options', 'squeeze_options', [$this, 'options_validate'] );
add_settings_section(
'squeeze_basic_quick',
'',
'__return_false',
'squeeze_options'
);
add_settings_field(
'squeeze_setting_auto_compress',
__( 'Squeeze on upload', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'Compresses images in the browser before they are uploaded.', 'squeeze' ) ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_basic_quick',
array(
'label_for' => 'auto_compress',
'class' => 'squeeze_setting_auto_compress squeeze-settings-row',
'type' => 'checkbox',
)
);
add_settings_field(
'squeeze_setting_backup_original',
__( 'Backup original image', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_basic_quick',
array(
'label_for' => 'backup_original',
'class' => 'squeeze_setting_backup_original squeeze-settings-row',
'type' => 'checkbox',
)
);
add_settings_field(
'squeeze_setting_clear_data_on_uninstall',
__( 'Delete plugin data on uninstall', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'When enabled, uninstalling Squeeze removes its settings, stats, and compression status metadata. Image files are never deleted.', 'squeeze' ) ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_basic_quick',
array(
'label_for' => 'clear_data_on_uninstall',
'class' => 'squeeze_setting_clear_data_on_uninstall squeeze-settings-row',
'type' => 'checkbox',
)
);
add_settings_field(
'squeeze_setting_compress_formats',
__( 'Image formats', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'Select which image formats you want to be squeezed.', 'squeeze' ) ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_basic_quick',
array(
'label_for' => 'compress_formats',
'class' => 'squeeze_setting_compress_formats squeeze-settings-row',
'type' => 'formats_checkbox_group',
)
);
add_settings_section(
'squeeze_basic_webp',
'',
'__return_false',
'squeeze_options'
);
add_settings_section(
'squeeze_basic_thumbs',
'',
'__return_false',
'squeeze_options'
);
add_settings_field(
'squeeze_setting_compress_thumbs',
__( 'Squeeze thumbnails', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'Choose which image thumbnail sizes you want to squeeze along with the original image.', 'squeeze' ) ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_basic_thumbs',
array(
'label_for' => 'compress_thumbs',
'class' => 'squeeze_setting_compress_thumbs squeeze-settings-row',
'type' => 'thumbs_checkbox_group',
)
);
add_settings_section(
'squeeze_basic_limits',
'',
'__return_false',
'squeeze_options'
);
add_settings_field(
'squeeze_setting_max_width',
__( 'Max. image width', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'Limit a width of an original image. Leave this field empty if you do not want to crop the image by width.', 'squeeze' ) ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_basic_limits',
array(
'label_for' => 'max_width',
'class' => 'squeeze_setting_max_width squeeze-settings-row',
'type' => 'placeholder',
)
);
add_settings_field(
'squeeze_setting_max_height',
__( 'Max. image height', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'Limit a height of an original image. Leave this field empty if you do not want to crop the image by height.', 'squeeze' ) ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_basic_limits',
array(
'label_for' => 'max_height',
'class' => 'squeeze_setting_max_height squeeze-settings-row',
'type' => 'placeholder',
)
);
add_settings_field(
'squeeze_setting_timeout',
__( 'Squeeze timeout', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'Time limit for squeezing an image. If you get an error during image squeezing, try to increase this value.', 'squeeze' ) ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_basic_limits',
array(
'label_for' => 'timeout',
'class' => 'squeeze_setting_timeout squeeze-settings-row squeeze-inline-limit',
'type' => 'number',
'units' => 'sec',
'min' => 1,
)
);
add_settings_section(
'squeeze_basic_exclusions',
'',
'__return_false',
'squeeze_options'
);
add_settings_field(
'squeeze_setting_excluded_images',
__( 'Excluded images', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'Enter a list of images that you want to exclude from squeezing. Both full URLs and partial strings can be used. One URL per line.', 'squeeze' ) ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_basic_exclusions',
array(
'label_for' => 'excluded_images',
'class' => 'squeeze_setting_excluded_images squeeze-settings-row',
'type' => 'textarea',
)
);
add_settings_section(
'squeeze_basic_hidden',
'',
'__return_false',
'squeeze_options'
);
add_settings_field(
'squeeze_setting_restore_defaults',
'',
[$this, 'options_callback'],
'squeeze_options',
'squeeze_basic_hidden',
array(
'label_for' => 'restore_defaults',
'class' => 'squeeze_setting_restore_defaults',
'type' => 'hidden',
)
);
add_settings_section(
'squeeze_jpeg_settings',
__( 'JPEG Settings', 'squeeze' ),
'squeeze_setting_jpeg_desc',
'squeeze_options',
array(
'section_class' => 'squeeze_jpeg',
)
);
add_settings_field(
'squeeze_setting_jpeg_quality',
__( 'Quality', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_jpeg_settings',
array(
'label_for' => 'jpeg_quality',
'class' => 'squeeze_setting_jpeg_quality',
'type' => 'range',
)
);
add_settings_field(
'squeeze_setting_jpeg_smoothing',
__( 'Smoothing', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_jpeg_settings',
array(
'label_for' => 'jpeg_smoothing',
'class' => 'squeeze_setting_jpeg_smoothing',
'type' => 'range',
)
);
add_settings_field(
'squeeze_setting_jpeg_baseline',
__( 'Pointless spec compliance', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_jpeg_advanced_settings',
array(
'label_for' => 'jpeg_baseline',
'class' => 'squeeze_setting_jpeg_baseline',
'type' => 'checkbox',
)
);
// deactivated, because throws error when enabled
//add_settings_field('squeeze_setting_jpeg_arithmetic', __('Arithmetic', 'squeeze'), [$this, 'options_callback'], 'squeeze_options', 'squeeze_jpeg_advanced_settings', array('label_for' => 'jpeg_arithmetic', 'class' => 'squeeze_setting_jpeg_arithmetic', 'type' => 'checkbox'));
add_settings_field(
'squeeze_setting_jpeg_progressive',
__( 'Progressive rendering', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_jpeg_advanced_settings',
array(
'label_for' => 'jpeg_progressive',
'class' => 'squeeze_setting_jpeg_progressive',
'type' => 'checkbox',
)
);
add_settings_field(
'squeeze_setting_jpeg_optimize_coding',
__( 'Optimize Huffman table', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_jpeg_advanced_settings',
array(
'label_for' => 'jpeg_optimize_coding',
'class' => 'squeeze_setting_jpeg_optimize_coding',
'type' => 'checkbox',
)
);
add_settings_field(
'squeeze_setting_jpeg_color_space',
__( 'Channels', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_jpeg_advanced_settings',
array(
'label_for' => 'jpeg_color_space',
'class' => 'squeeze_setting_jpeg_color_space',
'type' => 'select',
'options' => array(
'3' => 'YCbCr',
'1' => 'Grayscale',
'2' => 'RGB',
),
)
);
add_settings_field(
'squeeze_setting_jpeg_quant_table',
__( 'Quantization', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_jpeg_advanced_settings',
array(
'label_for' => 'jpeg_quant_table',
'class' => 'squeeze_setting_jpeg_quant_table',
'type' => 'select',
'options' => array(
'0' => 'JPEG Annex K',
'1' => 'Flat',
'2' => 'MSSIM-tuned Kodak',
'3' => 'ImageMagick',
'4' => 'PSNR-HVS-M-tuned Kodak',
'5' => 'Klein et al',
'6' => 'Watson et al',
'7' => 'Ahumada et al',
'8' => 'Peterson et al',
),
)
);
add_settings_field(
'squeeze_setting_jpeg_trellis_multipass',
__( 'Trellis multipass', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_jpeg_advanced_settings',
array(
'label_for' => 'jpeg_trellis_multipass',
'class' => 'squeeze_setting_jpeg_trellis_multipass',
'type' => 'checkbox',
)
);
add_settings_field(
'squeeze_setting_jpeg_trellis_opt_zero',
__( 'Optimize zero block runs', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_jpeg_advanced_settings',
array(
'label_for' => 'jpeg_trellis_opt_zero',
'class' => 'squeeze_setting_jpeg_trellis_opt_zero',
'type' => 'checkbox',
)
);
add_settings_field(
'squeeze_setting_jpeg_trellis_opt_table',
__( 'Optimize after trellis quantization', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_jpeg_advanced_settings',
array(
'label_for' => 'jpeg_trellis_opt_table',
'class' => 'squeeze_setting_jpeg_trellis_opt_table',
'type' => 'checkbox',
)
);
add_settings_field(
'squeeze_setting_jpeg_trellis_loops',
__( 'Trellis quantization passes', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_jpeg_advanced_settings',
array(
'label_for' => 'jpeg_trellis_loops',
'class' => 'squeeze_setting_jpeg_trellis_loops',
'type' => 'range',
'min' => 1,
'max' => 50,
)
);
add_settings_field(
'squeeze_setting_jpeg_auto_subsample',
__( 'Auto subsample chroma', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_jpeg_advanced_settings',
array(
'label_for' => 'jpeg_auto_subsample',
'class' => 'squeeze_setting_jpeg_auto_subsample',
'type' => 'checkbox',
)
);
add_settings_field(
'squeeze_setting_jpeg_chroma_subsample',
__( 'Subsample chroma by', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_jpeg_advanced_settings',
array(
'label_for' => 'jpeg_chroma_subsample',
'class' => 'squeeze_setting_jpeg_chroma_subsample',
'type' => 'range',
'min' => 1,
'max' => 4,
)
);
add_settings_field(
'squeeze_setting_jpeg_separate_chroma_quality',
__( 'Separate chroma quality', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_jpeg_advanced_settings',
array(
'label_for' => 'jpeg_separate_chroma_quality',
'class' => 'squeeze_setting_jpeg_separate_chroma_quality',
'type' => 'checkbox',
)
);
add_settings_field(
'squeeze_setting_jpeg_chroma_quality',
__( 'Chroma quality', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_jpeg_advanced_settings',
array(
'label_for' => 'jpeg_chroma_quality',
'class' => 'squeeze_setting_jpeg_chroma_quality',
'type' => 'range',
)
);
add_settings_section(
'squeeze_png_settings',
__( 'PNG Settings', 'squeeze' ),
'squeeze_setting_png_desc',
'squeeze_options',
array(
'section_class' => 'squeeze_png',
)
);
add_settings_field(
'squeeze_setting_png_quality',
__( 'Quality', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_png_settings',
array(
'label_for' => 'png_quality',
'class' => 'squeeze_setting_png_quality',
'type' => 'range',
'min' => 0.01,
'max' => 1,
'step' => 0.01,
)
);
add_settings_section(
'squeeze_webp_settings',
__( 'WEBP Settings', 'squeeze' ),
'squeeze_setting_webp_desc',
'squeeze_options',
array(
'section_class' => 'squeeze_webp',
)
);
add_settings_field(
'squeeze_setting_webp_method',
__( 'Effort', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_webp_settings',
array(
'label_for' => 'webp_method',
'class' => 'squeeze_setting_webp_method',
'type' => 'range',
'min' => 0,
'max' => 6,
)
);
add_settings_field(
'squeeze_setting_webp_quality',
__( 'Quality', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_webp_settings',
array(
'label_for' => 'webp_quality',
'class' => 'squeeze_setting_webp_quality',
'type' => 'range',
'min' => 0,
'max' => 100,
'hidden' => ( $webp_lossless ? true : '' ),
)
);
add_settings_field(
'squeeze_setting_webp_lossless',
__( 'Lossless', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_webp_settings',
array(
'label_for' => 'webp_lossless',
'class' => 'squeeze_setting_webp_lossless',
'type' => 'checkbox',
)
);
add_settings_field(
'squeeze_setting_webp_near_lossless',
__( 'Near lossless', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_webp_settings',
array(
'label_for' => 'webp_near_lossless',
'class' => 'squeeze_setting_webp_near_lossless',
'type' => 'range',
'min' => 0,
'max' => 100,
)
);
add_settings_section(
'squeeze_avif_settings',
__( 'AVIF Settings', 'squeeze' ),
'squeeze_setting_avif_desc',
'squeeze_options',
array(
'section_class' => 'squeeze_avif',
)
);
add_settings_field(
'squeeze_setting_avif_cqLevel',
__( 'Quality', 'squeeze' ),
[$this, 'options_callback'],
'squeeze_options',
'squeeze_avif_settings',
array(
'label_for' => 'avif_cqLevel',
'class' => 'squeeze_setting_avif_cqLevel',
'type' => 'range',
'min' => 1,
'max' => 100,
)
);
}
/**
* Map stored options to a single WebP delivery mode for the settings UI.
*
* @param array $options squeeze_options array.
* @return string direct|sidecar|sidecar_replace (internal keys; UI labels use "Separate WebP folder".)
*/
protected function get_webp_delivery_mode( $options ) {
$direct = !empty( $options['direct_webp'] );
$auto = !empty( $options['auto_webp'] );
$replace = !empty( $options['webp_replace_urls'] );
if ( $direct ) {
return 'direct';
}
if ( $auto && $replace ) {
return 'sidecar_replace';
}
if ( $auto ) {
return 'sidecar';
}
return 'direct';
}
/**
* Unified WebP delivery control (radios + collapsible examples).
*/
public function render_webp_delivery_field() {
$options = get_option( 'squeeze_options' );
if ( !is_array( $options ) ) {
$options = array();
}
$mode = $this->get_webp_delivery_mode( $options );
$advanced_open = 'direct' !== $mode;
?>
/>
>
/>
src to WebP URLs in HTML', 'squeeze' );
?>
/>
⚠️
Direct WebP conversion — it converts images to WebP in-place and WP Offload Media handles uploading automatically.', 'squeeze' ), array(
'strong' => array(),
) );
?>
⚠️
src to WebP URLs in HTML" mode is not compatible with WP Offload Media. WebP sidecar files are stored in a local squeeze-webp/ folder and are never pushed to your external storage provider (S3, GCS, DigitalOcean Spaces, etc.), so they cannot be served from your CDN URL.', 'squeeze' );
?>
Direct WebP conversion — it converts images to WebP in-place and WP Offload Media handles uploading automatically.', 'squeeze' ), array(
'strong' => array(),
) );
?>
src to WebP URLs in HTML', 'squeeze' );
?>
<img src="//yoursite.example/wp-content/uploads/2025/07/photo.jpg" alt="…" />
<img src="//yoursite.example/wp-content/squeeze-webp/uploads/2025/07/photo.jpg.webp" alt="…" />
<img src="//yoursite.example/wp-content/uploads/2025/07/photo.jpg" alt="…" />
/wp-content/uploads/2025/07/image.jpg ~500 KB
/wp-content/squeeze-webp/uploads/2025/07/image.jpg.webp ~50 KB
/wp-content/uploads/2025/07/image.jpg ~500 KB
/wp-content/uploads/2025/07/image-300x300.jpg ~230 KB
/wp-content/uploads/2025/07/image.webp ~50 KB
/wp-content/uploads/2025/07/image-300x300.webp ~20 KB
get_webp_delivery_mode( $options );
$mode_label = __( 'Direct WebP', 'squeeze' );
if ( 'sidecar' === $mode ) {
$mode_label = __( 'Keep JPEG/PNG URLs — server serves WebP', 'squeeze' );
} elseif ( 'sidecar_replace' === $mode ) {
$mode_label = __( 'Rewrite src to WebP URLs in HTML', 'squeeze' );
}
$upload_on = !empty( $options['auto_compress'] );
$backup_on = !empty( $options['backup_original'] );
?>
' . esc_html( $mode_label ) . '');
if ( $upload_on ) {
$profile_bits[] = esc_html__( 'Squeeze on upload', 'squeeze' );
}
if ( $backup_on ) {
$profile_bits[] = esc_html__( 'Backup on', 'squeeze' );
}
echo '
' . wp_kses( implode( ' · ', $profile_bits ), array(
'strong' => array(),
) ) . '
';
?>
get_webp_delivery_mode( $previous_options );
if ( isset( $input['webp_delivery_mode'] ) && is_string( $input['webp_delivery_mode'] ) ) {
$mode = sanitize_text_field( wp_unslash( $input['webp_delivery_mode'] ) );
unset($input['webp_delivery_mode']);
switch ( $mode ) {
case 'sidecar':
case 'sidecar_picture':
$input['direct_webp'] = false;
$input['auto_webp'] = true;
$input['webp_replace_urls'] = false;
break;
case 'sidecar_replace':
$input['direct_webp'] = false;
$input['auto_webp'] = true;
$input['webp_replace_urls'] = true;
break;
case 'direct':
default:
$input['direct_webp'] = true;
$input['auto_webp'] = false;
$input['webp_replace_urls'] = false;
break;
}
}
$input['jpeg_quality'] = absint( $input['jpeg_quality'] );
$input['jpeg_smoothing'] = ( isset( $input['jpeg_smoothing'] ) ? absint( $input['jpeg_smoothing'] ) : self::$SqueezeHelpers->get_default_value( 'jpeg_smoothing' ) );
$input['jpeg_color_space'] = ( isset( $input['jpeg_color_space'] ) ? absint( $input['jpeg_color_space'] ) : self::$SqueezeHelpers->get_default_value( 'jpeg_color_space' ) );
$input['jpeg_quant_table'] = ( isset( $input['jpeg_quant_table'] ) ? absint( $input['jpeg_quant_table'] ) : self::$SqueezeHelpers->get_default_value( 'jpeg_quant_table' ) );
$input['jpeg_trellis_loops'] = ( isset( $input['jpeg_trellis_loops'] ) ? absint( $input['jpeg_trellis_loops'] ) : self::$SqueezeHelpers->get_default_value( 'jpeg_trellis_loops' ) );
$input['jpeg_chroma_subsample'] = ( isset( $input['jpeg_chroma_subsample'] ) ? absint( $input['jpeg_chroma_subsample'] ) : self::$SqueezeHelpers->get_default_value( 'jpeg_chroma_subsample' ) );
$input['jpeg_chroma_quality'] = ( isset( $input['jpeg_chroma_quality'] ) ? absint( $input['jpeg_chroma_quality'] ) : self::$SqueezeHelpers->get_default_value( 'jpeg_chroma_quality' ) );
$input['png_level'] = ( isset( $input['png_level'] ) ? absint( $input['png_level'] ) : self::$SqueezeHelpers->get_default_value( 'png_level' ) );
$input['png_quality'] = ( isset( $input['png_quality'] ) ? floatval( $input['png_quality'] ) : self::$SqueezeHelpers->get_default_value( 'png_quality' ) );
$input['webp_method'] = ( isset( $input['webp_method'] ) ? absint( $input['webp_method'] ) : self::$SqueezeHelpers->get_default_value( 'webp_method' ) );
$input['webp_quality'] = ( isset( $input['webp_quality'] ) ? absint( $input['webp_quality'] ) : self::$SqueezeHelpers->get_default_value( 'webp_quality' ) );
$input['webp_near_lossless'] = ( isset( $input['webp_near_lossless'] ) ? absint( $input['webp_near_lossless'] ) : self::$SqueezeHelpers->get_default_value( 'webp_near_lossless' ) );
$input['avif_cqLevel'] = ( isset( $input['avif_cqLevel'] ) ? absint( $input['avif_cqLevel'] ) : self::$SqueezeHelpers->get_default_value( 'avif_cqLevel' ) );
$input['jpeg_baseline'] = ( isset( $input['jpeg_baseline'] ) ? boolval( $input['jpeg_baseline'] ) : '0' );
//$input[ 'jpeg_arithmetic' ] = isset($input[ 'jpeg_arithmetic' ]) ? boolval($input[ 'jpeg_arithmetic' ]) : '0';
$input['jpeg_progressive'] = ( isset( $input['jpeg_progressive'] ) ? boolval( $input['jpeg_progressive'] ) : '0' );
$input['jpeg_optimize_coding'] = ( isset( $input['jpeg_optimize_coding'] ) ? boolval( $input['jpeg_optimize_coding'] ) : '0' );
$input['jpeg_trellis_multipass'] = ( isset( $input['jpeg_trellis_multipass'] ) ? boolval( $input['jpeg_trellis_multipass'] ) : '0' );
$input['jpeg_trellis_opt_zero'] = ( isset( $input['jpeg_trellis_opt_zero'] ) ? boolval( $input['jpeg_trellis_opt_zero'] ) : '0' );
$input['jpeg_trellis_opt_table'] = ( isset( $input['jpeg_trellis_opt_table'] ) ? boolval( $input['jpeg_trellis_opt_table'] ) : '0' );
$input['jpeg_auto_subsample'] = ( isset( $input['jpeg_auto_subsample'] ) ? boolval( $input['jpeg_auto_subsample'] ) : '0' );
$input['jpeg_separate_chroma_quality'] = ( isset( $input['jpeg_separate_chroma_quality'] ) ? boolval( $input['jpeg_separate_chroma_quality'] ) : '0' );
$input['png_interlace'] = ( isset( $input['png_interlace'] ) ? boolval( $input['png_interlace'] ) : '0' );
$input['webp_lossless'] = ( isset( $input['webp_lossless'] ) ? boolval( $input['webp_lossless'] ) : '0' );
$input['auto_compress'] = ( isset( $input['auto_compress'] ) ? boolval( $input['auto_compress'] ) : '0' );
// TBD: maybe get default value from the database
$input['auto_webp'] = ( isset( $input['auto_webp'] ) ? boolval( $input['auto_webp'] ) : '0' );
$input['webp_replace_urls'] = ( isset( $input['webp_replace_urls'] ) && $input['auto_webp'] ? boolval( $input['webp_replace_urls'] ) : '0' );
$input['direct_webp'] = ( isset( $input['direct_webp'] ) ? boolval( $input['direct_webp'] ) : '0' );
$new_webp_mode = $this->get_webp_delivery_mode( $input );
if ( $previous_webp_mode !== $new_webp_mode ) {
add_settings_error(
'squeeze_notices',
'webp_delivery_mode_changed',
__( 'WebP delivery mode changed. Existing files are not migrated automatically — re-squeeze images after switching. Leftover JPEG/PNG + WebP pairs or orphaned files under squeeze-webp may remain until cleaned up.', 'squeeze' ),
'warning'
);
}
if ( isset( $input['cdn_url'] ) ) {
$cdn_raw = trim( wp_unslash( (string) $input['cdn_url'] ) );
$input['cdn_url'] = ( $cdn_raw === '' ? '' : esc_url_raw( $cdn_raw ) );
} else {
$input['cdn_url'] = '';
}
$input['backup_original'] = ( isset( $input['backup_original'] ) ? boolval( $input['backup_original'] ) : '0' );
$input['clear_data_on_uninstall'] = ( isset( $input['clear_data_on_uninstall'] ) ? boolval( $input['clear_data_on_uninstall'] ) : '0' );
$input['compress_formats'] = ( isset( $input['compress_formats'] ) && is_array( $input['compress_formats'] ) ? $this->validate_image_formats( $input['compress_formats'], $input['direct_webp'] ) : array() );
$input['compress_thumbs'] = ( isset( $input['compress_thumbs'] ) && is_array( $input['compress_thumbs'] ) ? $input['compress_thumbs'] : array() );
$input['max_width'] = ( isset( $input['max_width'] ) && $input['max_width'] > 0 ? absint( $input['max_width'] ) : '' );
$input['max_height'] = ( isset( $input['max_height'] ) && $input['max_height'] > 0 ? absint( $input['max_height'] ) : '' );
$input['excluded_images'] = ( isset( $input['excluded_images'] ) ? $input['excluded_images'] : '' );
$input['timeout'] = ( isset( $input['timeout'] ) && $input['timeout'] > 0 ? absint( $input['timeout'] ) : 1 );
$input['restore_defaults'] = ( isset( $input['restore_defaults'] ) ? $input['restore_defaults'] : '0' );
if ( !isset( $input['restore_defaults'] ) || $input['restore_defaults'] !== '1' ) {
add_settings_error(
'squeeze_notices',
'settings_updated',
__( 'Settings have been updated.', 'squeeze' ),
'success'
);
}
unset($input['webp_picture_markup']);
return $input;
}
protected function validate_image_formats( $input, $is_direct_webp = false ) {
$formats = self::ALLOWED_IMAGE_FORMATS;
if ( !isset( $input ) || !is_array( $input ) ) {
return array();
}
// remove all formats that are not in the allowed formats list
$input = array_filter( $input, function ( $format ) use($formats) {
//check by key
return array_key_exists( $format, $formats );
}, ARRAY_FILTER_USE_KEY );
// if direct webp conversion is enabled, webp format is mandatory
if ( $is_direct_webp && !array_key_exists( 'webp', $input ) ) {
$input['webp'] = 'on';
}
return $input;
}
public function options_callback( $args ) {
$label_for = ( isset( $args['label_for'] ) ? $args['label_for'] : '' );
if ( empty( $label_for ) ) {
return;
}
$type = ( isset( $args['type'] ) ? $args['type'] : 'text' );
$class = ( isset( $args['class'] ) ? $args['class'] : '' );
$default = self::$SqueezeHelpers->get_default_value( $label_for );
$options = get_option( 'squeeze_options' );
$is_hidden = ( isset( $args['hidden'] ) && $args['hidden'] ? 'hidden' : '' );
$extra_classes = [];
if ( $is_hidden ) {
$extra_classes[] = 'squeeze-hidden';
}
$extra_classes = implode( ' ', $extra_classes );
switch ( $type ) {
case 'text':
$value = ( isset( $options[$label_for] ) ? $options[$label_for] : $default );
$placeholder = ( isset( $args['placeholder'] ) ? $args['placeholder'] : '' );
echo "";
break;
case 'number':
$value = ( isset( $options[$label_for] ) ? $options[$label_for] : $default );
$units = ( isset( $args['units'] ) ? $args['units'] : '' );
$min = ( isset( $args['min'] ) ? $args['min'] : '' );
$max = ( isset( $args['max'] ) ? $args['max'] : '' );
echo "";
if ( $units ) {
echo "" . esc_html( $units ) . " ";
}
break;
case 'range':
$value = ( isset( $options[$label_for] ) ? $options[$label_for] : $default );
$min = ( isset( $args['min'] ) ? $args['min'] : 0 );
$max = ( isset( $args['max'] ) ? $args['max'] : 100 );
$step = ( isset( $args['step'] ) ? $args['step'] : 1 );
echo "";
echo ' ';
?>
";
echo ' ';
break;
case 'select':
$value = ( isset( $options[$label_for] ) ? $options[$label_for] : $default );
echo "";
break;
case 'thumbs_checkbox_group':
$thumbs = array();
$value = ( isset( $options[$label_for] ) ? (array) $options[$label_for] : $default );
$available_sizes = wp_get_registered_image_subsizes();
foreach ( $available_sizes as $key => $size ) {
$thumbs[$key] = ucwords( str_replace( '_', ' ', $key ) ) . ' (' . $size['width'] . 'x' . $size['height'] . ')';
}
// Add the scaled image size option
$big_image_size_threshold = apply_filters( 'big_image_size_threshold', 2560 );
$thumbs['full'] = 'Scaled (' . $big_image_size_threshold . 'x' . $big_image_size_threshold . ')';
echo '';
echo '' . esc_html__( 'Select all', 'squeeze' ) . ' ';
echo '' . esc_html__( 'Clear all', 'squeeze' ) . ' ';
echo '' . esc_html__( 'WordPress defaults', 'squeeze' ) . ' ';
echo '
';
echo '';
echo '
';
foreach ( $thumbs as $key => $option ) {
echo '
';
echo " ";
echo "" . esc_html( $option ) . " ";
echo '
';
}
echo '
';
echo '
';
break;
case 'formats_checkbox_group':
$is_direct_webp = ( isset( $options['direct_webp'] ) ? (bool) $options['direct_webp'] : false );
$formats = self::ALLOWED_IMAGE_FORMATS;
$value = ( isset( $options[$label_for] ) ? (array) $options[$label_for] : $default );
echo '';
break;
case 'hidden':
$value = ( isset( $options[$label_for] ) ? $options[$label_for] : $default );
echo " ";
break;
case 'textarea':
$value = ( isset( $options[$label_for] ) ? $options[$label_for] : $default );
echo "";
break;
case 'placeholder':
echo '' . sprintf( __( 'This feature is available only in the premium version .', 'squeeze' ), esc_url( self::$UPGRADE_URL ) ) . '
';
break;
}
}
public function setting_basic_desc() {
echo '' . esc_html__( 'Basic squeezing settings.', 'squeeze' ) . '
';
}
public function setting_jpeg_desc() {
echo '' . esc_html__( 'Squeezing settings for JPEG images.', 'squeeze' ) . '
';
}
public function setting_jpeg_advanced_desc() {
echo '' . esc_html__( 'More precise settings for experienced users.', 'squeeze' ) . '
';
}
public function setting_png_desc() {
echo '' . esc_html__( 'Squeezing settings for PNG images.', 'squeeze' ) . '
';
}
public function setting_webp_desc() {
echo '' . esc_html__( 'Squeezing settings for WebP images.', 'squeeze' ) . '
';
}
public function setting_avif_desc() {
echo '' . esc_html__( 'Squeezing settings for Avif images.', 'squeeze' ) . '
';
}
public function setting_upgrade_desc() {
echo '' . esc_html__( 'Upgrade to premium version for more features.', 'squeeze' ) . '
';
}
public function setting_license_desc() {
}
public function restore_defaults( $old_value, $value ) {
if ( isset( $value['restore_defaults'] ) && $value['restore_defaults'] === '1' ) {
$result = delete_option( 'squeeze_options', "" );
if ( $result ) {
add_settings_error(
'squeeze_notices',
'settings_restored',
__( 'Settings have been restored.', 'squeeze' ),
'success'
);
} else {
add_settings_error(
'squeeze_notices',
'settings_not_restored',
__( 'Settings have not been restored.', 'squeeze' ),
'error'
);
}
}
}
public function flush_rewrite_rules( $old_value, $value ) {
if ( isset( $value['auto_webp'] ) && $value['auto_webp'] !== $old_value['auto_webp'] ) {
flush_rewrite_rules();
add_settings_error(
'squeeze_notices',
'rewrite_rules_flushed',
__( 'Rewrite rules have been flushed.', 'squeeze' ),
'success'
);
}
}
public function add_custom_field_to_attachment( $form_fields, $post ) {
$all_formats = self::ALLOWED_IMAGE_FORMATS;
$all_mimes = self::$SqueezeHelpers->get_image_formats( true, $all_formats );
if ( in_array( $post->post_mime_type, $all_mimes ) ) {
$selected_mimes = self::$SqueezeHelpers->get_image_formats( true );
$is_compressed = get_post_meta( $post->ID, 'squeeze_is_compressed', true );
$compression_failed = get_post_meta( $post->ID, 'squeeze_compression_failed', true );
$can_restore = self::$SqueezeHelpers->can_restore( $post->ID );
$is_excluded = false;
$url = wp_get_original_image_url( $post->ID );
if ( $url ) {
$excluded_images = self::$SqueezeHelpers->get_excluded_images();
$is_excluded = self::$SqueezeHelpers->is_excluded_image( $url, $excluded_images );
}
$form_fields['squeeze_is_compressed'] = array(
'label' => __( 'Squeeze', 'squeeze' ),
'input' => 'html',
'html' => ( !in_array( $post->post_mime_type, $selected_mimes ) ? ' ' . __( 'Image format is not selected for compression in the plugin settings', 'squeeze' ) . ' ' : (( $is_excluded ? ' ' . __( 'Image is excluded from compression', 'squeeze' ) . ' (' . esc_html__( 'found substring: ', 'squeeze' ) . $is_excluded['exclude_reason'] . ') ' : (( $compression_failed === 'larger_than_original' ? ' ' . sprintf( __( 'Could not compress — result was larger than original. Try adjusting compression settings , then re-squeeze.', 'squeeze' ), self::$SETTINGS_URL . '#squeeze_' . pathinfo( get_attached_file( $post->ID ), PATHINFO_EXTENSION ) ) . '
' . (( $can_restore ? '' . __( 'Restore original image', 'squeeze' ) . '
' : '' )) . '' . __( 'Re-Squeeze image', 'squeeze' ) . '
' : (( $is_compressed ? ' ' . __( 'Squeezed', 'squeeze' ) . '
' . (( $can_restore ? '
' . __( 'Restore original image', 'squeeze' ) . '
' : '' )) . '
' . __( 'Re-Squeeze image', 'squeeze' ) . '
' : ' ' . __( 'Not squeezed', 'squeeze' ) . '
' . __( 'Squeeze Now', 'squeeze' ) . '
' )) )) )) ),
);
}
return $form_fields;
}
public function add_media_columns( $posts_columns ) {
$posts_columns['squeeze'] = __( 'Squeeze', 'squeeze' );
return $posts_columns;
}
public function media_custom_column( $column_name, $post_id ) {
if ( 'squeeze' !== $column_name ) {
return;
}
$form_fields = $this->add_custom_field_to_attachment( array(), get_post( $post_id ) );
if ( $form_fields ) {
echo wp_kses_post( $form_fields['squeeze_is_compressed']['html'] );
}
}
public function sortable_columns( $columns ) {
$columns['squeeze'] = 'squeeze';
return $columns;
}
public function sortable_columns_orderby( $query ) {
if ( !is_admin() || !$query->is_main_query() ) {
return;
}
$orderby = $query->get( 'orderby' );
if ( 'squeeze' === $orderby ) {
// Define the allowed image formats
$allowed_formats = self::$SqueezeHelpers->get_image_formats( true );
// include all media
$query->set( 'meta_query', array(
'relation' => 'OR',
array(
'key' => 'squeeze_is_compressed',
'compare' => 'NOT EXISTS',
),
array(
'key' => 'squeeze_is_compressed',
'compare' => 'EXISTS',
),
) );
// Add the meta_query to filter by specific image formats
//$query->set('post_mime_type', $allowed_formats);
$query->set( 'orderby', 'meta_value' );
}
}
public function media_filter_dropdown() {
global $wp_query;
$post_type = 'attachment';
if ( isset( $_GET['post_type'] ) ) {
$post_type = sanitize_text_field( wp_unslash( $_GET['post_type'] ) );
}
if ( 'attachment' !== $post_type ) {
return;
}
$selected = ( isset( $_GET['squeeze_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['squeeze_filter'] ) ) : '' );
$options = array(
'all' => __( 'Squeeze: All images', 'squeeze' ),
'non-squeezed' => __( 'Non Squeezed Images', 'squeeze' ),
);
echo '';
foreach ( $options as $value => $label ) {
printf(
'%s ',
esc_attr( $value ),
selected( $selected, $value, false ),
esc_html( $label )
);
}
echo ' ';
}
public function media_filter_query( $query ) {
global $current_screen;
if ( !is_admin() || !empty( $current_screen ) && 'upload' !== $current_screen->base || 'attachment' !== $query->get( 'post_type' ) ) {
return $query;
}
if ( isset( $_GET['squeeze_filter'] ) ) {
$squeeze_filter = sanitize_text_field( wp_unslash( $_GET['squeeze_filter'] ) );
if ( 'non-squeezed' === $squeeze_filter ) {
$query->set( 'meta_query', self::$SqueezeHelpers->get_non_squeezed_media_meta_query() );
$query->set( 'squeeze_exclude_excluded', true );
$query->set( 'orderby', 'meta_value' );
$query->set( 'post_mime_type', self::$SqueezeHelpers->get_image_formats( true ) );
}
}
return $query;
}
public function media_filter_ajax_query( $query ) {
if ( !isset( $_POST['query']['squeeze_filter'] ) ) {
return $query;
}
$squeeze_filter = sanitize_text_field( wp_unslash( $_POST['query']['squeeze_filter'] ) );
if ( 'non-squeezed' === $squeeze_filter ) {
$query['meta_query'] = self::$SqueezeHelpers->get_non_squeezed_media_meta_query();
$query['squeeze_exclude_excluded'] = true;
$query['orderby'] = 'meta_value';
$query['post_mime_type'] = self::$SqueezeHelpers->get_image_formats( true );
}
return $query;
}
public function media_filter_exclude_excluded( $posts, $query ) {
if ( empty( $posts ) || !$query instanceof \WP_Query ) {
return $posts;
}
if ( !$query->get( 'squeeze_exclude_excluded' ) ) {
return $posts;
}
if ( empty( self::$SqueezeHelpers->get_excluded_images() ) ) {
return $posts;
}
return array_values( array_filter( $posts, function ( $post ) {
return !self::$SqueezeHelpers->is_attachment_excluded( $post->ID );
} ) );
}
public function handle_excluded_images_option_change( $old_value, $new_value ) {
$old_excluded = ( isset( $old_value['excluded_images'] ) ? $old_value['excluded_images'] : '' );
$new_excluded = ( isset( $new_value['excluded_images'] ) ? $new_value['excluded_images'] : '' );
if ( $old_excluded === $new_excluded ) {
return;
}
self::$SqueezeHelpers->clear_excluded_images_cache();
self::$SqueezeHelpers->clear_options_cache();
self::$SqueezeHelpers->invalidate_uncompressed_stats_cache();
}
public function svg_sprite_output() {
global $pagenow;
if ( $pagenow === 'upload.php' && isset( $_GET['page'] ) && $_GET['page'] === 'squeeze-bulk' ) {
include self::$PLUGIN_DIR . 'assets/images/sprite.svg';
}
}
public function add_preview_button_placeholder( $post ) {
if ( !wp_attachment_is_image( $post->ID ) ) {
return;
}
echo '';
}
public function incompatibility_notices() {
// Bail if we're not in the admin or the screen helper isn't available.
if ( !is_admin() || !function_exists( 'get_current_screen' ) ) {
return;
}
$screen = get_current_screen();
// List of screen IDs where we want the warning.
$target_screens = array(
'settings_page_squeeze',
// options-general.php?page=squeeze
'media_page_squeeze-bulk',
// upload.php?page=squeeze-bulk
'upload',
// the core Media → Library (list table)
'media',
// the core Media → Add New
'plugins',
);
if ( !$screen || !in_array( $screen->id, $target_screens, true ) ) {
return;
}
// check if webp-express/webp-express.php plugin is active and show a notice
if ( is_plugin_active( 'webp-express/webp-express.php' ) ) {
?>
Squeeze plugin.', 'squeeze' );
?>
Squeeze plugin.', 'squeeze' );
?>