Alpagu adlı üyeden alıntı: mesajı görüntüle
görselleri webp. çeviren bir kaç eklenti denedim ama çoğunu çevirmedi yada yarım kaldı. ücretsiz olarak kullanabileceğim eklenti varmı
<?php
/**
 * Plugin Name:       WD WebP Dönüştürücü
 * Plugin URI:        https://webdanismani.com
 * Description:       WordPress & WooCommerce'e yüklenen tüm JPEG/PNG görselleri otomatik olarak WebP formatına dönüştürür. Mevcut medya kütüphanesi için toplu dönüştürme aracı içerir.
 * Version:           1.0.0
 * Author:            Web Danışmanı
 * Author URI:        https://webdanismani.com
 * License:           GPL-2.0-or-later
 * Text Domain:       wd-webp
 * Requires at least: 5.8
 * Requires PHP:      7.4
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

final class WD_WebP_Converter {

    const OPTION = 'wd_webp_settings';

    private static $instance = null;

    public static function instance() {
        if ( null === self::$instance ) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct() {
        // Yükleme anında dönüştürme (medya kütüphanesi, WooCommerce, REST, sideload — hepsi bu iki filtreden geçer)
        add_filter( 'wp_handle_upload', array( $this, 'convert_on_upload' ) );
        add_filter( 'wp_handle_sideload', array( $this, 'convert_on_upload' ) );

        // Yönetim
        add_action( 'admin_menu', array( $this, 'admin_menu' ) );
        add_action( 'admin_init', array( $this, 'register_settings' ) );
        add_action( 'wp_ajax_wd_webp_bulk', array( $this, 'ajax_bulk' ) );

        add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'action_links' ) );

        register_uninstall_hook( __FILE__, array( 'WD_WebP_Converter', 'uninstall' ) );
    }

    public static function uninstall() {
        delete_option( self::OPTION );
        delete_post_meta_by_key( '_wd_webp_failed' );
    }

    /* ------------------------------------------------------------------
     * Ayarlar
     * ---------------------------------------------------------------- */

    public function settings() {
        $defaults = array(
            'enabled'       => 1,
            'quality'       => 82,
            'convert_jpeg'  => 1,
            'convert_png'   => 1,
            'keep_original' => 0,
        );
        return wp_parse_args( (array) get_option( self::OPTION, array() ), $defaults );
    }

    public function register_settings() {
        register_setting(
            'wd_webp',
            self::OPTION,
            array( 'sanitize_callback' => array( $this, 'sanitize_settings' ) )
        );
    }

    public function sanitize_settings( $in ) {
        $in = (array) $in;
        return array(
            'enabled'       => empty( $in['enabled'] ) ? 0 : 1,
            'quality'       => max( 1, min( 100, (int) ( isset( $in['quality'] ) ? $in['quality'] : 82 ) ) ),
            'convert_jpeg'  => empty( $in['convert_jpeg'] ) ? 0 : 1,
            'convert_png'   => empty( $in['convert_png'] ) ? 0 : 1,
            'keep_original' => empty( $in['keep_original'] ) ? 0 : 1,
        );
    }

    public function action_links( $links ) {
        array_unshift(
            $links,
            '<a href="' . esc_url( admin_url( 'options-general.php?page=wd-webp' ) ) . '">Ayarlar</a>'
        );
        return $links;
    }

    /* ------------------------------------------------------------------
     * Sunucu yetenekleri
     * ---------------------------------------------------------------- */

    private function imagick_webp() {
        if ( ! class_exists( 'Imagick' ) ) {
            return false;
        }
        try {
            return count( Imagick::queryFormats( 'WEBP' ) ) > 0;
        } catch ( Exception $e ) {
            return false;
        }
    }

    private function gd_webp() {
        if ( ! function_exists( 'imagewebp' ) || ! function_exists( 'gd_info' ) ) {
            return false;
        }
        $gd = gd_info();
        return ! empty( $gd['WebP Support'] );
    }

    private function webp_supported() {
        return $this->imagick_webp() || $this->gd_webp();
    }

    /* ------------------------------------------------------------------
     * Yükleme anında dönüştürme
     * ---------------------------------------------------------------- */

    public function convert_on_upload( $upload ) {
        $s = $this->settings();

        if ( empty( $s['enabled'] ) ) {
            return $upload;
        }
        if ( ! is_array( $upload ) || empty( $upload['file'] ) || empty( $upload['type'] ) || ! empty( $upload['error'] ) ) {
            return $upload;
        }

        $allowed = array();
        if ( ! empty( $s['convert_jpeg'] ) ) {
            $allowed[] = 'image/jpeg';
        }
        if ( ! empty( $s['convert_png'] ) ) {
            $allowed[] = 'image/png';
        }
        if ( ! in_array( $upload['type'], $allowed, true ) ) {
            return $upload;
        }

        // Sunucu WebP üretemiyorsa veya WP küçük boyutları WebP'den oluşturamayacaksa dokunma
        if ( ! $this->webp_supported() || ! wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ) ) {
            return $upload;
        }

        $file = wp_normalize_path( $upload['file'] );
        $webp = $this->unique_webp_path( $file );

        if ( ! $this->convert_image( $file, $webp, (int) $s['quality'] ) ) {
            return $upload; // dönüştürülemezse orijinal akış devam eder
        }

        // Nadiren WebP daha büyük çıkabilir; o zaman vazgeç
        if ( filesize( $webp ) >= filesize( $file ) ) {
            @unlink( $webp );
            return $upload;
        }

        if ( empty( $s['keep_original'] ) ) {
            @unlink( $file );
        }

        $upload['url']  = str_replace( wp_basename( $upload['file'] ), wp_basename( $webp ), $upload['url'] );
        $upload['file'] = $webp;
        $upload['type'] = 'image/webp';

        return $upload;
    }

    /* ------------------------------------------------------------------
     * Çekirdek dönüştürücü (Imagick öncelikli, GD yedek)
     * ---------------------------------------------------------------- */

    private function convert_image( $source, $dest, $quality ) {
        $quality = max( 1, min( 100, (int) $quality ) );

        $info = @getimagesize( $source );
        if ( ! $info || empty( $info['mime'] ) ) {
            return false;
        }
        $mime = $info['mime'];
        if ( ! in_array( $mime, array( 'image/jpeg', 'image/png' ), true ) ) {
            return false;
        }

        // 1) Imagick
        if ( $this->imagick_webp() ) {
            try {
                $im = new Imagick( $source );

                // EXIF yönünü piksellere uygula (telefon fotoğrafları yan dönmesin)
                switch ( $im->getImageOrientation() ) {
                    case Imagick::ORIENTATION_BOTTOMRIGHT:
                        $im->rotateImage( '#000', 180 );
                        break;
                    case Imagick::ORIENTATION_RIGHTTOP:
                        $im->rotateImage( '#000', 90 );
                        break;
                    case Imagick::ORIENTATION_LEFTBOTTOM:
                        $im->rotateImage( '#000', -90 );
                        break;
                }
                $im->setImageOrientation( Imagick::ORIENTATION_TOPLEFT );

                // Renk profili varsa sRGB'ye çevirip metadata'yı temizle (dosya küçülür, renk kaymaz)
                if ( method_exists( $im, 'transformImageColorspace' ) && Imagick::COLORSPACE_SRGB !== $im->getImageColorspace() ) {
                    $im->transformImageColorspace( Imagick::COLORSPACE_SRGB );
                }
                $im->stripImage();

                $im->setImageFormat( 'webp' );
                $im->setImageCompressionQuality( $quality );

                $ok = $im->writeImage( $dest );
                $im->clear();
                $im->destroy();

                if ( $ok && file_exists( $dest ) && filesize( $dest ) > 0 ) {
                    return true;
                }
            } catch ( Exception $e ) {
                // GD'ye düş
            }
        }

        // 2) GD
        if ( $this->gd_webp() ) {
            $img = false;

            if ( 'image/jpeg' === $mime ) {
                $img = @imagecreatefromjpeg( $source );
                if ( $img && function_exists( 'exif_read_data' ) ) {
                    $exif = @exif_read_data( $source );
                    if ( ! empty( $exif['Orientation'] ) ) {
                        $deg = 0;
                        switch ( (int) $exif['Orientation'] ) {
                            case 3:
                                $deg = 180;
                                break;
                            case 6:
                                $deg = -90;
                                break;
                            case 8:
                                $deg = 90;
                                break;
                        }
                        if ( $deg ) {
                            $rot = imagerotate( $img, $deg, 0 );
                            if ( $rot ) {
                                imagedestroy( $img );
                                $img = $rot;
                            }
                        }
                    }
                }
            } elseif ( 'image/png' === $mime ) {
                $img = @imagecreatefrompng( $source );
                if ( $img ) {
                    imagepalettetotruecolor( $img ); // palet PNG'ler imagewebp'te patlar
                    imagealphablending( $img, false );
                    imagesavealpha( $img, true );    // şeffaflık korunur
                }
            }

            if ( ! $img ) {
                return false;
            }

            $ok = imagewebp( $img, $dest, $quality );
            imagedestroy( $img );

            return $ok && file_exists( $dest ) && filesize( $dest ) > 0;
        }

        return false;
    }

    private function unique_webp_path( $file ) {
        $dir  = dirname( $file );
        $name = preg_replace( '/\.[^.\/\\\\]+$/', '', wp_basename( $file ) ) . '.webp';

        if ( file_exists( trailingslashit( $dir ) . $name ) ) {
            $name = wp_unique_filename( $dir, $name );
        }
        return trailingslashit( $dir ) . $name;
    }

    /* ------------------------------------------------------------------
     * Toplu dönüştürme (mevcut medya kütüphanesi)
     * ---------------------------------------------------------------- */

    private function count_remaining() {
        $q = new WP_Query(
            array(
                'post_type'      => 'attachment',
                'post_status'    => 'inherit',
                'post_mime_type' => array( 'image/jpeg', 'image/png' ),
                'posts_per_page' => 1,
                'fields'         => 'ids',
                'meta_query'     => array(
                    array(
                        'key'     => '_wd_webp_failed',
                        'compare' => 'NOT EXISTS',
                    ),
                ),
            )
        );
        return (int) $q->found_posts;
    }

    public function ajax_bulk() {
        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( array( 'message' => 'Yetkiniz yok.' ), 403 );
        }
        check_ajax_referer( 'wd_webp_bulk' );

        $mode = isset( $_POST['mode'] ) ? sanitize_key( $_POST['mode'] ) : 'status';

        if ( 'reset_failed' === $mode ) {
            delete_post_meta_by_key( '_wd_webp_failed' );
            wp_send_json_success( array( 'message' => 'Başarısız işaretleri temizlendi, tekrar denenebilir.' ) );
        }

        if ( 'status' === $mode ) {
            wp_send_json_success(
                array(
                    'remaining' => $this->count_remaining(),
                    'webp'      => $this->webp_supported(),
                )
            );
        }

        // mode === run
        if ( ! $this->webp_supported() ) {
            wp_send_json_error( array( 'message' => 'Sunucuda WebP desteği yok (GD webp veya Imagick gerekli).' ) );
        }

        @set_time_limit( 120 );
        if ( function_exists( 'wp_raise_memory_limit' ) ) {
            wp_raise_memory_limit( 'image' );
        }

        $s   = $this->settings();
        $ids = get_posts(
            array(
                'post_type'      => 'attachment',
                'post_status'    => 'inherit',
                'post_mime_type' => array( 'image/jpeg', 'image/png' ),
                'posts_per_page' => 4,
                'orderby'        => 'ID',
                'order'          => 'ASC',
                'fields'         => 'ids',
                'meta_query'     => array(
                    array(
                        'key'     => '_wd_webp_failed',
                        'compare' => 'NOT EXISTS',
                    ),
                ),
            )
        );

        $log    = array();
        $done   = 0;
        $failed = 0;

        foreach ( $ids as $id ) {
            $result = $this->convert_attachment( (int) $id, (int) $s['quality'], ! empty( $s['keep_original'] ) );

            if ( is_wp_error( $result ) ) {
                update_post_meta( $id, '_wd_webp_failed', $result->get_error_message() );
                $failed++;
                $log[] = sprintf( '#%d HATA: %s', $id, $result->get_error_message() );
            } else {
                $done++;
                $log[] = sprintf( '#%d dönüştürüldü (%d dosya).', $id, $result );
            }
        }

        wp_send_json_success(
            array(
                'processed' => count( $ids ),
                'done'      => $done,
                'failed'    => $failed,
                'remaining' => $this->count_remaining(),
                'log'       => $log,
            )
        );
    }

    /**
     * Bir eki tüm boyutlarıyla WebP'ye çevirir, metadata + içerik URL'lerini günceller.
     *
     * @return int|WP_Error Dönüştürülen dosya sayısı ya da hata.
     */
    private function convert_attachment( $id, $quality, $keep_original ) {
        $file = get_attached_file( $id );
        if ( ! $file || ! file_exists( $file ) ) {
            return new WP_Error( 'missing_file', 'Dosya diskte bulunamadı' );
        }
        $file = wp_normalize_path( $file );

        $mime = get_post_mime_type( $id );
        if ( ! in_array( $mime, array( 'image/jpeg', 'image/png' ), true ) ) {
            return new WP_Error( 'bad_mime', 'Desteklenmeyen tür: ' . $mime );
        }

        $meta = wp_get_attachment_metadata( $id );
        if ( ! is_array( $meta ) ) {
            $meta = array();
        }

        $dir     = trailingslashit( dirname( $file ) );
        $uploads = wp_get_upload_dir();
        $basedir = wp_normalize_path( $uploads['basedir'] );
        $baseurl = $uploads['baseurl'];

        $map = array(); // eski disk yolu => yeni disk yolu

        // 1) Ana dosya (büyük görsel ölçeklendiyse bu "-scaled" dosyasıdır)
        $new_main = $this->unique_webp_path( $file );
        if ( ! $this->convert_image( $file, $new_main, $quality ) ) {
            return new WP_Error( 'convert_failed', 'Ana dosya dönüştürülemedi' );
        }
        $map[ $file ] = $new_main;

        // 2) Ölçeklenmemiş orijinal (varsa)
        if ( ! empty( $meta['original_image'] ) ) {
            $orig = $dir . $meta['original_image'];
            if ( file_exists( $orig ) && ! isset( $map[ $orig ] ) ) {
                $new_orig = $this->unique_webp_path( $orig );
                if ( $this->convert_image( $orig, $new_orig, $quality ) ) {
                    $map[ $orig ]           = $new_orig;
                    $meta['original_image'] = wp_basename( $new_orig );
                }
            }
        }

        // 3) Ara boyutlar (thumbnail, medium, woocommerce_thumbnail vb.)
        if ( ! empty( $meta['sizes'] ) && is_array( $meta['sizes'] ) ) {
            foreach ( $meta['sizes'] as $size => $data ) {
                if ( empty( $data['file'] ) ) {
                    continue;
                }
                $p = $dir . $data['file'];

                // Aynı dosyayı paylaşan boyutlar tekrar dönüştürülmesin
                if ( isset( $map[ $p ] ) ) {
                    $meta['sizes'][ $size ]['file']      = wp_basename( $map[ $p ] );
                    $meta['sizes'][ $size ]['mime-type'] = 'image/webp';
                    continue;
                }
                if ( ! file_exists( $p ) ) {
                    continue;
                }

                $np = $this->unique_webp_path( $p );
                if ( $this->convert_image( $p, $np, $quality ) ) {
                    $map[ $p ]                           = $np;
                    $meta['sizes'][ $size ]['file']      = wp_basename( $np );
                    $meta['sizes'][ $size ]['mime-type'] = 'image/webp';
                    if ( isset( $meta['sizes'][ $size ]['filesize'] ) ) {
                        $meta['sizes'][ $size ]['filesize'] = (int) filesize( $np );
                    }
                }
            }
        }

        // 4) Ek kaydını güncelle
        update_attached_file( $id, $new_main );
        $meta['file'] = ltrim( str_replace( $basedir, '', $new_main ), '/' );
        if ( isset( $meta['filesize'] ) ) {
            $meta['filesize'] = (int) filesize( $new_main );
        }
        wp_update_attachment_metadata( $id, $meta );

        $new_main_url = str_replace( $basedir, $baseurl, $new_main );
        wp_update_post(
            array(
                'ID'             => $id,
                'post_mime_type' => 'image/webp',
                'guid'           => $new_main_url,
            )
        );

        // 5) Yazı/ürün içeriklerindeki eski URL'leri değiştir + eski dosyaları sil
        global $wpdb;
        foreach ( $map as $old_path => $new_path ) {
            $old_url = str_replace( $basedir, $baseurl, $old_path );
            $new_url = str_replace( $basedir, $baseurl, $new_path );

            if ( $old_url !== $new_url ) {
                $wpdb->query(
                    $wpdb->prepare(
                        "UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)",
                        $old_url,
                        $new_url
                    )
                );
            }
            if ( ! $keep_original ) {
                @unlink( $old_path );
            }
        }

        clean_post_cache( $id );

        return count( $map );
    }

    /* ------------------------------------------------------------------
     * Yönetim sayfası
     * ---------------------------------------------------------------- */

    public function admin_menu() {
        add_options_page(
            'WebP Dönüştürücü',
            'WebP Dönüştürücü',
            'manage_options',
            'wd-webp',
            array( $this, 'render_page' )
        );
    }

    public function render_page() {
        if ( ! current_user_can( 'manage_options' ) ) {
            return;
        }

        $s          = $this->settings();
        $imagick_ok = $this->imagick_webp();
        $gd_ok      = $this->gd_webp();
        $remaining  = $this->count_remaining();
        ?>
        <div class="wrap">
            <h1>WD WebP Dönüştürücü</h1>

            <p>
                Sunucu desteği:
                <strong style="color:<?php echo $imagick_ok ? '#00a32a' : '#d63638'; ?>">Imagick <?php echo $imagick_ok ? '✓' : '✗'; ?></strong> &nbsp;|&nbsp;
                <strong style="color:<?php echo $gd_ok ? '#00a32a' : '#d63638'; ?>">GD WebP <?php echo $gd_ok ? '✓' : '✗'; ?></strong>
            </p>

            <?php if ( ! $imagick_ok && ! $gd_ok ) : ?>
                <div class="notice notice-error"><p><strong>Sunucunuzda WebP desteği yok.</strong> Hosting sağlayıcınızdan GD'nin WebP desteğiyle derlenmesini veya Imagick kurulmasını isteyin. Eklenti bu durumda hiçbir şey yapmaz.</p></div>
            <?php endif; ?>

            <form method="post" action="options.php">
                <?php settings_fields( 'wd_webp' ); ?>
                <table class="form-table" role="presentation">
                    <tr>
                        <th scope="row">Otomatik dönüştürme</th>
                        <td>
                            <label>
                                <input type="checkbox" name="<?php echo esc_attr( self::OPTION ); ?>[enabled]" value="1" <?php checked( $s['enabled'], 1 ); ?>>
                                Yüklenen görselleri otomatik olarak WebP'ye dönüştür
                            </label>
                        </td>
                    </tr>
                    <tr>
                        <th scope="row">Dönüştürülecek türler</th>
                        <td>
                            <label><input type="checkbox" name="<?php echo esc_attr( self::OPTION ); ?>[convert_jpeg]" value="1" <?php checked( $s['convert_jpeg'], 1 ); ?>> JPEG</label><br>
                            <label><input type="checkbox" name="<?php echo esc_attr( self::OPTION ); ?>[convert_png]" value="1" <?php checked( $s['convert_png'], 1 ); ?>> PNG (şeffaflık korunur)</label>
                            <p class="description">GIF ve SVG dosyalarına dokunulmaz.</p>
                        </td>
                    </tr>
                    <tr>
                        <th scope="row"><label for="wd-webp-quality">Kalite</label></th>
                        <td>
                            <input type="number" id="wd-webp-quality" name="<?php echo esc_attr( self::OPTION ); ?>[quality]" value="<?php echo esc_attr( $s['quality'] ); ?>" min="1" max="100" step="1" class="small-text"> / 100
                            <p class="description">Önerilen: 75–85. Değer düştükçe dosya küçülür, kalite azalır.</p>
                        </td>
                    </tr>
                    <tr>
                        <th scope="row">Orijinal dosya</th>
                        <td>
                            <label>
                                <input type="checkbox" name="<?php echo esc_attr( self::OPTION ); ?>[keep_original]" value="1" <?php checked( $s['keep_original'], 1 ); ?>>
                                Orijinal JPEG/PNG dosyasını diskte tut (yedek olarak; medya kütüphanesinde görünmez)
                            </label>
                        </td>
                    </tr>
                </table>
                <?php submit_button( 'Ayarları Kaydet' ); ?>
            </form>

            <hr>

            <h2>Mevcut Görselleri Toplu Dönüştür</h2>
            <p>Medya kütüphanesindeki dönüştürülebilir görsel sayısı: <strong id="wd-webp-remaining"><?php echo esc_html( $remaining ); ?></strong></p>
            <p class="description"><strong>Uyarı:</strong> Başlamadan önce mutlaka dosya + veritabanı yedeği alın. Tüm boyutlar (küçük görseller dahil) dönüştürülür, ek kayıtları ve yazı/ürün içeriklerindeki görsel adresleri güncellenir, eski dosyalar (ayara göre) silinir.</p>

            <p>
                <button type="button" class="button button-primary" id="wd-webp-start">Toplu Dönüştürmeyi Başlat</button>
                <button type="button" class="button" id="wd-webp-stop" disabled>Durdur</button>
                <button type="button" class="button" id="wd-webp-reset">Başarısızları Sıfırla</button>
            </p>

            <div style="max-width:640px;background:#dcdcde;border-radius:3px;height:22px;overflow:hidden;margin-bottom:6px;">
                <div id="wd-webp-bar" style="height:100%;width:0;background:#2271b1;transition:width .3s;"></div>
            </div>
            <p id="wd-webp-pct" style="margin-top:0;"></p>

            <pre id="wd-webp-log" style="max-width:640px;height:220px;overflow:auto;background:#1d2327;color:#9ec2e6;padding:10px;font-size:12px;"></pre>
        </div>

        <script>
        (function () {
            var nonce   = '<?php echo esc_js( wp_create_nonce( 'wd_webp_bulk' ) ); ?>';
            var running = false;
            var total   = 0;
            var done    = 0;

            function el( id ) { return document.getElementById( id ); }

            function post( mode ) {
                var body = new URLSearchParams( { action: 'wd_webp_bulk', mode: mode, _wpnonce: nonce } );
                return fetch( ajaxurl, { method: 'POST', credentials: 'same-origin', body: body } )
                    .then( function ( r ) { return r.json(); } );
            }

            function log( lines ) {
                var box = el( 'wd-webp-log' );
                ( lines || [] ).forEach( function ( l ) { box.textContent += l + '\n'; } );
                box.scrollTop = box.scrollHeight;
            }

            function setProgress() {
                var pct = total > 0 ? Math.round( ( done / total ) * 100 ) : 100;
                el( 'wd-webp-bar' ).style.width = pct + '%';
                el( 'wd-webp-pct' ).textContent = done + ' / ' + total + ' (%' + pct + ')';
            }

            function toggle() {
                el( 'wd-webp-start' ).disabled = running;
                el( 'wd-webp-stop' ).disabled  = ! running;
            }

            function step() {
                if ( ! running ) { return; }
                post( 'run' ).then( function ( res ) {
                    if ( ! res || ! res.success ) {
                        log( [ 'HATA: ' + ( res && res.data && res.data.message ? res.data.message : 'İstek başarısız oldu.' ) ] );
                        running = false; toggle(); return;
                    }
                    done += res.data.processed;
                    log( res.data.log );
                    setProgress();
                    el( 'wd-webp-remaining' ).textContent = res.data.remaining;

                    if ( res.data.remaining > 0 && res.data.processed > 0 ) {
                        step();
                    } else {
                        log( [ '--- Tamamlandı ---' ] );
                        running = false; toggle();
                    }
                } ).catch( function ( e ) {
                    log( [ 'HATA: ' + e ] );
                    running = false; toggle();
                } );
            }

            el( 'wd-webp-start' ).addEventListener( 'click', function () {
                post( 'status' ).then( function ( res ) {
                    if ( ! res || ! res.success ) { return; }
                    if ( ! res.data.webp ) { log( [ 'Sunucuda WebP desteği yok.' ] ); return; }
                    total = res.data.remaining;
                    done  = 0;
                    el( 'wd-webp-log' ).textContent = '';
                    if ( total < 1 ) { log( [ 'Dönüştürülecek görsel yok.' ] ); return; }
                    running = true;
                    toggle();
                    setProgress();
                    step();
                } );
            } );

            el( 'wd-webp-stop' ).addEventListener( 'click', function () {
                running = false;
                toggle();
                log( [ 'Durduruldu. Kaldığı yerden tekrar başlatabilirsiniz.' ] );
            } );

            el( 'wd-webp-reset' ).addEventListener( 'click', function () {
                post( 'reset_failed' ).then( function ( res ) {
                    log( [ res && res.success ? res.data.message : 'Sıfırlama başarısız.' ] );
                    post( 'status' ).then( function ( r2 ) {
                        if ( r2 && r2.success ) { el( 'wd-webp-remaining' ).textContent = r2.data.remaining; }
                    } );
                } );
            } );
        })();
        </script>
        <?php
    }
}

WD_WebP_Converter::instance();
Ücretsiz kullanabilirsiniz.