: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
use Smush\Core\Media\Media_Item;
use Smush\Core\Media\Media_Item_Cache;
use Smush\Core\Media\Media_Item_Optimizer;
use Smush\Core\Stats\Global_Stats;
if ( ! defined( 'WPINC' ) ) {
const IGNORE_KEY = 'wp-smush-ignore-bulk';
const ERROR_KEY = 'wp-smush-error';
const ANIMATED_ERROR_CODE = 'animated';
private static $locked_error_codes = array(
private static $skipped_error_codes = array(
* Should regenerate thumbnail error codes.
private static $regenerate_error_codes = array(
* @param string $error_code Error code.
* @param int $image_id Attachment ID.
public static function get_error_message( $error_code, $image_id = 0 ) {
$error_messages = self::get_default_error_messages();
$error_message = ! empty( $error_messages[ $error_code ] ) ? $error_messages[ $error_code ] : '';
return self::format_error_message( $error_message, $error_code, $image_id );
* Get sprintf error message.
* @param string $error_message Error message.
* @param string $error_code Error code.
* @param int $image_id Attachment ID.
private static function format_error_message( $error_message, $error_code, $image_id ) {
if ( empty( $image_id ) || empty( $error_message ) || false === strpos( $error_message, '%s' ) ) {
$size_exceeded = Helper::size_limit_exceeded( $image_id );
$error_message = sprintf( $error_message, size_format( $size_exceeded ) );
$file_path = Helper::get_attached_file( $image_id );
$error_message = sprintf( $error_message, Helper::clean_file_path( dirname( $file_path ) ) );
$file_path = Helper::get_attached_file( $image_id );
$file_not_found = $file_path;
if ( file_exists( $file_path ) ) {
// Try go get the not found thumbnail file.
$all_file_sizes = wp_get_attachment_metadata( $image_id );
$dir_path = dirname( $file_path );
if ( ! empty( $all_file_sizes['sizes'] ) ) {
foreach ( $all_file_sizes['sizes'] as $size => $size_data ) {
$size_file = $dir_path . '/' . $size_data['file'];
if ( ! file_exists( $size_file ) ) {
$file_not_found = $size_file;
$error_message = sprintf( $error_message, basename( $file_not_found ) );
public static function get_all_failed_images() {
$media_item_error_ids = Global_Stats::get()->get_error_list()->get_ids();
$optimization_error_ids = self::get_last_optimization_error_ids( PHP_INT_MAX );
return array_unique( array_merge( $media_item_error_ids, $optimization_error_ids ) );
* Get last optimization errors.
* @param int $limit Query limit.
private static function get_last_optimization_error_ids( $limit ) {
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
"SELECT DISTINCT post_meta_error.post_id FROM $wpdb->postmeta as post_meta_error
LEFT JOIN $wpdb->postmeta as post_meta_ignore ON post_meta_ignore.post_id = post_meta_error.post_id AND post_meta_ignore.meta_key= %s
WHERE post_meta_ignore.meta_value IS NULL AND post_meta_error.meta_key = %s
ORDER BY post_meta_error.post_id DESC LIMIT %d;",
Media_Item::IGNORED_META_KEY,
Media_Item_Optimizer::ERROR_META_KEY,
* Due to performance, we do not join with table wp_posts to exclude the deleted attachments,
* leave a filter for third-party custom it.
$query = apply_filters( 'wp_smush_query_get_last_optimize_errors', $query );
// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.NotPrepared
return $wpdb->get_col( $query );
private static function get_last_media_item_errors( $limit ) {
$error_list_ids = Global_Stats::get()->get_error_list()->get_ids();
if ( empty( $error_list_ids ) ) {
foreach( $error_list_ids as $attachment_id ) {
$media_item = Media_Item_Cache::get_instance()->get( $attachment_id );
if ( ! $media_item->has_errors() ) {
$last_errors[ $attachment_id ] = self::get_error( $media_item->get_errors(), $media_item );
if ( count( $last_errors ) >= $limit ) {
private static function get_last_optimize_errors( $limit ) {
$last_errors_ids = self::get_last_optimization_error_ids( $limit );
if ( empty( $last_errors_ids ) ) {
foreach( $last_errors_ids as $attachment_id ) {
$media_item = Media_Item_Cache::get_instance()->get( $attachment_id );
$optimizer = new Media_Item_Optimizer($media_item);
if( ! $optimizer->has_errors() ) {
$last_errors[ $attachment_id ] = self::get_error( $optimizer->get_errors(), $media_item );
if ( count( $last_errors ) >= $limit ) {
* @param int $limit Limit number of errors to return.
public static function get_last_errors( $limit = 10 ) {
$last_errors = self::get_last_media_item_errors( $limit );
$no_item_errors = count( $last_errors );
if ( $no_item_errors >= $limit ) {
$optimize_errors = self::get_last_optimize_errors( $limit - $no_item_errors );
return $last_errors + $optimize_errors;
public static function get_error( WP_Error $errors, Media_Item $media_item ) {
$thumbnail = $media_item->get_size('thumbnail' );
'error_code' => $errors->get_error_code(),
'error_message' => $errors->get_error_message(),
'file_name' => $media_item->get_scaled_or_full_size()->get_file_name(),
'thumbnail' => $thumbnail ? $thumbnail->get_file_url() : false,
private static function get_default_error_messages() {
'wp_smush_error_messages',
'missing_id' => esc_html__( 'No attachment ID was received.', 'wp-smushit' ),
'ignored' => esc_html__( 'Skip ignored file.', 'wp-smushit' ),
'animated' => esc_html__( 'Skipped animated file.', 'wp-smushit' ),
'in_progress' => esc_html__( 'File processing is in progress.', 'wp-smushit' ),
'no_file_meta' => esc_html__( 'No file data found in image meta', 'wp-smushit' ),
'skipped_filter' => esc_html__( 'Skipped with wp_smush_image filter', 'wp-smushit' ),
'empty_path' => esc_html__( 'File path is empty', 'wp-smushit' ),
'empty_response' => esc_html__( 'Webp no response was received.', 'wp-smushit' ),
'not_processed' => esc_html__( 'Not processed', 'wp-smushit' ),
/* translators: %s: image size */
'size_limit' => __( 'Skipped (%s), file size limit of 5mb exceeded', 'wp-smushit' ),
/* translators: %s: image size */
'size_pro_limit' => __( 'Skipped (%s), file size limit of 256mb exceeded', 'wp-smushit' ),
/* translators: %s: Directory path */
'not_writable' => __( '%s is not writable', 'wp-smushit' ),
/* translators: %s: File path */
'file_not_found' => __( 'Skipped (%s), File not found.', 'wp-smushit' ),