*/
        public static function replace_filename_with_encoding_errors($filename)
        {
            // Get associative array of fixes
            $fix_list = self::get_encoding_fix_list();
            // Check if developer filtered all of these away
            if (empty($fix_list)) {
                return $filename;
            }
            // Get encoding errors
            $error_chars = array_keys($fix_list);
            $real_chars = array_values($fix_list);
            // The errors can happen in both nfd/nfc format so convert chars into nfd
            // Check which one $filename uses and use it
            // If $filename doesn't use FORM_D or FORM_C don't convert errors
            if (Normalizer::isNormalized($filename, Normalizer::FORM_D)) {
                $error_chars = array_map(function ($n) {
                    return Normalizer::normalize($n, Normalizer::FORM_D);
                }, $error_chars);
            } elseif (Normalizer::isNormalized($filename, Normalizer::FORM_C)) {
                $error_chars = array_map(function ($n) {
                    return Normalizer::normalize($n, Normalizer::FORM_C);
                }, $error_chars);
            }
            // Replaces all accented characters with encoding errors
            return str_replace($real_chars, $error_chars, $filename);
        }
    }
}
Sanitizer::load();
 /**
  * Helper: Removes accents from all attachments and posts where those attachments were used
  */
 private static function replace_content($args, $assoc_args)
 {
     if (isset($assoc_args['without-sanitize'])) {
         $assoc_args['sanitize'] = false;
     } else {
         $assoc_args['sanitize'] = true;
     }
     if (isset($assoc_args['network'])) {
         if (is_multisite()) {
             $sites = wp_get_sites();
         } else {
             WP_CLI::error("This is not multisite installation.");
             return 0;
         }
     } else {
         // This way we can use it in network but only to one site
         $sites = array('blog_id' => get_current_blog_id());
     }
     // Replace mysql later
     global $wpdb;
     // Loop all sites
     foreach ($sites as $site) {
         if (is_multisite()) {
             WP_CLI::line("Processing network site: {$site['blog_id']}");
             switch_to_blog($site['blog_id']);
         }
         // Get all uploads
         $uploads = get_posts(array('post_type' => 'attachment', 'numberposts' => -1));
         $all_posts_count = count($uploads);
         $replaced_count = 0;
         WP_CLI::line("Found: " . count($uploads) . " attachments.");
         WP_CLI::line("This may take a while...");
         foreach ($uploads as $index => $upload) {
             $ascii_guid = Sanitizer::remove_accents($upload->guid, $assoc_args['sanitize']);
             // Replace all files and content if file is different after removing accents
             if ($ascii_guid != $upload->guid) {
                 $replaced_count += 1;
                 /**
                  * Replace all thumbnail sizes of this file from all post contents
                  * Attachment in post content is only rarely file.jpg
                  * More ofter it's like file-800x500.jpg
                  * Only search for the file basename like /wp-content/uploads/2017/01/file without extension
                  */
                 $file_info = pathinfo($upload->guid);
                 // Check filename without extension so we can replace all thumbnail sizes at once
                 $attachment_string = $file_info['dirname'] . '/' . $file_info['filename'];
                 $escaped_attachment_string = Sanitizer::remove_accents($attachment_string, $assoc_args['sanitize']);
                 // We don't need to replace excerpt for example since it doesn't have attachments...
                 WP_CLI::line("REPLACING: {$file_info['basename']} ---> " . Sanitizer::remove_accents($file_info['basename'], $assoc_args['sanitize']) . " ");
                 $sql = $wpdb->prepare("UPDATE {$wpdb->prefix}posts SET post_content = REPLACE (post_content, '%s', '%s') WHERE post_content LIKE '%s';", $attachment_string, $escaped_attachment_string, '%' . $wpdb->esc_like($attachment_string) . '%');
                 if (isset($assoc_args['verbose'])) {
                     WP_CLI::line("RUNNING SQL: {$sql}");
                 }
                 if (!isset($assoc_args['dry-run'])) {
                     $wpdb->query($sql);
                 }
                 // DB Replace post meta except _wp_attached_file because it is serialized
                 // This will be done later
                 $sql = $wpdb->prepare("UPDATE {$wpdb->prefix}postmeta SET meta_value = REPLACE (meta_value, '%s', '%s') WHERE meta_value LIKE '%s' AND meta_key!='_wp_attachment_metadata' AND meta_key!='_wp_attached_file';", $attachment_string, $escaped_attachment_string, '%' . $wpdb->esc_like($attachment_string) . '%');
                 if (isset($assoc_args['verbose'])) {
                     WP_CLI::line("RUNNING SQL: {$sql}");
                 }
                 if (!isset($assoc_args['dry-run'])) {
                     $wpdb->query($sql);
                 }
                 // Get full path for file and replace accents for the future filename
                 $full_path = get_attached_file($upload->ID);
                 $ascii_full_path = Sanitizer::remove_accents($full_path, $assoc_args['sanitize']);
                 // Move the file
                 WP_CLI::line("----> Checking image:     {$full_path}");
                 if (!isset($assoc_args['dry-run'])) {
                     $old_file = Sanitizer::rename_accented_files_in_any_form($full_path, $ascii_full_path);
                     if ($old_file) {
                         WP_CLI::line("----> Replaced file:      " . basename($old_file) . " -> " . basename($ascii_full_path));
                     } else {
                         WP_CLI::line("----> ERROR: File can't be found: " . basename($full_path));
                     }
                 }
                 // Replace thumbnails too
                 $file_path = dirname($full_path);
                 $metadata = wp_get_attachment_metadata($upload->ID);
                 // Correct main file for later usage
                 $ascii_file = Sanitizer::remove_accents($metadata['file'], $assoc_args['sanitize']);
                 $metadata['file'] = $ascii_file;
                 // Usually this is image but if this is document instead it won't have different thumbnail sizes
                 if (isset($metadata['sizes'])) {
                     foreach ($metadata['sizes'] as $name => $thumbnail) {
                         $metadata['sizes'][$name]['file'];
                         $thumbnail_path = $file_path . '/' . $thumbnail['file'];
                         $ascii_thumbnail = Sanitizer::remove_accents($thumbnail['file'], $assoc_args['sanitize']);
                         // Update metadata on thumbnail so we can push it back to database
                         $metadata['sizes'][$name]['file'] = $ascii_thumbnail;
                         $ascii_thumbnail_path = $file_path . '/' . $ascii_thumbnail;
                         WP_CLI::line("----> Checking thumbnail: {$thumbnail_path}");
                         if (!isset($assoc_args['dry-run'])) {
                             $old_file = Sanitizer::rename_accented_files_in_any_form($thumbnail_path, $ascii_thumbnail_path);
                             if ($old_file) {
                                 WP_CLI::line("----> Replaced thumbnail: " . basename($old_file) . " -> " . basename($ascii_thumbnail_path));
                             } else {
                                 WP_CLI::line("----> ERROR: File can't be found: " . basename($thumbnail_path));
                             }
                         }
                     }
                 }
                 // Serialize fixed metadata so that we can insert it back to database
                 $fixed_metadata = serialize($metadata);
                 /**
                  * Replace Database
                  */
                 if (isset($assoc_args['verbose'])) {
                     WP_CLI::line("Replacing attachment {$upload->ID} data in database...");
                 }
                 if (!isset($assoc_args['dry-run'])) {
                     // Replace guid
                     $sql = $wpdb->prepare("UPDATE {$wpdb->prefix}posts SET guid = %s WHERE ID=%d;", $ascii_guid, $upload->ID);
                     $wpdb->query($sql);
                     // Replace upload name
                     $sql = $wpdb->prepare("UPDATE {$wpdb->prefix}postmeta SET meta_value = %s WHERE post_id=%d and meta_key='_wp_attached_file';", $ascii_file, $upload->ID);
                     $wpdb->query($sql);
                     // Replace meta data like thumbnail fields
                     $sql = $wpdb->prepare("UPDATE {$wpdb->prefix}postmeta SET meta_value = %s WHERE post_id=%d and meta_key='_wp_attachment_metadata';", $fixed_metadata, $upload->ID);
                     $wpdb->query($sql);
                 }
                 // Calculate remaining files
                 $remaining_files = $all_posts_count - $index - 1;
                 // Show some kind of progress to wp-cli user
                 WP_CLI::line("");
                 WP_CLI::line("Remaining workload: {$remaining_files} attachments...");
                 WP_CLI::line("");
             }
         }
     }
     return array('replaced_count' => $replaced_count, 'considered_count' => $all_posts_count);
 }