• 29-08-2026, 18:38:16
    #1
    görselleri webp. çeviren bir kaç eklenti denedim ama çoğunu çevirmedi yada yarım kaldı. ücretsiz olarak kullanabileceğim eklenti varmı
  • 29-08-2026, 18:39:20
    #2
    500 tlye kurarım.
  • 29-08-2026, 18:42:08
    #3
    imagify var ortalama 200 tl de lisans ücreti var çok memnunuz kullanıyoruz her müşterimizde
  • 29-08-2026, 18:43:15
    #4
    WxTimer adlı üyeden alıntı: mesajı görüntüle
    imagify var ortalama 200 tl de lisans ücreti var çok memnunuz kullanıyoruz her müşterimizde
    çevirmede bir sınır varmı hocam
  • 29-08-2026, 18:43:50
    #5
    https://saerasoft.com/caesium/

    buradaki ücretsiz programı kullanıyorum. Çok fazla görseliniz yoksa hepsini indirip toplu halde program ile webp formatına çevirip tek tek ilgili konularda güncelleyebilirsiniz. Sonraki süreçte de 1 dakika vakit ayırıp önceden görselinizi webp formatına çevirip öyle sitenizdeki yazıya ekleyebilirsiniz.
  • 29-08-2026, 18:44:09
    #6
    Alpagu adlı üyeden alıntı: mesajı görüntüle
    çevirmede bir sınır varmı hocam
    7gb görselleri 3 4gb düşürdüğünü hatırlıyorum hocam öyle anlatayım size her optimizasyon yaptığımız sitede kullanırız. Hiçbir sorun yaşamadık bu zamana kadar
  • 29-08-2026, 18:45:14
    #7
    WxTimer adlı üyeden alıntı: mesajı görüntüle
    7gb görselleri 3 4gb düşürdüğünü hatırlıyorum hocam öyle anlatayım size her optimizasyon yaptığımız sitede kullanırız. Hiçbir sorun yaşamadık bu zamana kadar
    hocam sınır derken şöyle diyim wordpress 1 görseli evirip çevirip 8 tane çogaltıyor . şimdilik 1000'e yakın görsel var şuan için. ileride daha fazla olur diye düşünüyorum görsel çevirmede sınırlımıdır.
  • 29-08-2026, 18:46:17
    #8
    convertmaster.net sitemiz üzerinden bir çok convert işinizi halledebilirsiniz.
  • 29-08-2026, 18:51:23
    #9
    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.