Ana Sayfa Web Webp Converter for WP

Webp Converter for WP

22
0
Webp Converter for WP
Webp Converter for WP

Kolaylıkla ve ücretsiz bir çevirici var aşağıda kodu size veriyorum, geliştirmesi size kalmış. Bir kısmı chatgpt yardımı ile geliştirilmiş ve size sunulmuştur. Kodu kopyalayarak eklenti olarak ekleyebilir, çalıştırabilirsiniz. Öncesinde sitenizi yedeklemeyi unutmayın.

<?php
/*
Plugin Name: Upload WebP Converter
Description: Creates WebP copies of uploaded images (original + all sizes). Optional: serve WebP URLs on the front‑end and bulk‑convert existing Media Library. No external services.
Version: 1.0.0
Author: Cem, ChatGPT
License: GPLv2 or later
*/

if (!defined(‘ABSPATH’)) { exit; }

class MS_WebP_Converter {
const OPT_KEY = ‘ms_webp_settings’;
const META_MAP = ‘_ms_webp_map’;

public function __construct(){
    // Settings defaults
    add_action('admin_init', [$this, 'register_settings']);
    add_action('admin_menu', [$this, 'admin_menu']);

    // Convert on upload/generation
    add_filter('wp_generate_attachment_metadata', [$this, 'after_generate_metadata'], 10, 2);

    // Optionally serve WebP
    add_filter('wp_get_attachment_image_src', [$this, 'swap_src_to_webp'], 10, 4);
    add_filter('wp_calculate_image_srcset', [$this, 'swap_srcset_to_webp'], 10, 5);

    // WP‑CLI bulk
    if (defined('WP_CLI') && WP_CLI) {
        \WP_CLI::add_command('mswebp', [$this, 'cli']);
    }
}

/*** SETTINGS ***/
public static function get_settings(){
    $def = [
        'quality' => 82,           // 60–90 typical
        'serve_webp' => 1,         // front‑end URL swap
        'skip_if_webp_source' => 1 // if source already .webp, don't reconvert
    ];
    $s = get_option(self::OPT_KEY, []);
    return wp_parse_args(is_array($s)?$s:[], $def);
}

public function register_settings(){
    register_setting('ms_webp_group', self::OPT_KEY, [
        'type' => 'array',
        'sanitize_callback' => function($in){
            $out = self::get_settings();
            if (isset($in['quality'])) $out['quality'] = max(40, min(100, (int)$in['quality']));
            $out['serve_webp'] = empty($in['serve_webp']) ? 0 : 1;
            $out['skip_if_webp_source'] = empty($in['skip_if_webp_source']) ? 0 : 1;
            return $out;
        }
    ]);
}

public function admin_menu(){
    add_options_page('Upload WebP Converter', 'Upload WebP', 'manage_options', 'ms-webp', [$this, 'settings_page']);
}

public function settings_page(){
    $s = self::get_settings();
    ?>
    <div class="wrap">
        <h1>Upload WebP Converter</h1>
        <form method="post" action="options.php">
            <?php settings_fields('ms_webp_group'); ?>
            <table class="form-table" role="presentation">
                <tr>
                    <th scope="row"><label for="quality">WebP Quality</label></th>
                    <td>
                        <input name="<?=esc_attr(self::OPT_KEY)?>[quality]" id="quality" type="number" min="40" max="100" value="<?=esc_attr($s['quality'])?>" />
                        <p class="description">Varsayılan: 82 (Önerilen aralık 60–90).</p>
                    </td>
                </tr>
                <tr>
                    <th scope="row">Ön yüzde WebP sun (URL değişimi)</th>
                    <td>
                        <label><input type="checkbox" name="<?=esc_attr(self::OPT_KEY)?>[serve_webp]" value="1" <?=checked(1, $s['serve_webp'], false)?> /> Etkin</label>
                        <p class="description">Tarayıcı desteği çok yaygındır. Bu seçenek, &lt;img&gt; kaynaklarını mevcutsa .webp dosyalarına çevirir.</p>
                    </td>
                </tr>
                <tr>
                    <th scope="row">Kaynak zaten WebP ise atla</th>
                    <td>
                        <label><input type="checkbox" name="<?=esc_attr(self::OPT_KEY)?>[skip_if_webp_source]" value="1" <?=checked(1, $s['skip_if_webp_source'], false)?> /> Etkin</label>
                    </td>
                </tr>
            </table>
            <?php submit_button(); ?>
        </form>

        <hr />
        <h2>Toplu Dönüştürme</h2>
        <p>WP‑CLI ile: wp mswebp regenerate — Tüm ortamı .webp kopyalarıyla doldurur.</p>
    </div>
    <?php
}

/*** CONVERT ON UPLOAD ***/
public function after_generate_metadata($metadata, $attachment_id){
    $file = get_attached_file($attachment_id);
    $type = get_post_mime_type($attachment_id);
    $s = self::get_settings();

    if (!self::image_mime_supported($type)) return $metadata; // only images
    if ($s['skip_if_webp_source'] && self::ends_with_ci($file, '.webp')) return $metadata;

    $map = [];
    // Original
    $orig_webp = self::convert_path_to_webp($file, $s['quality']);
    if ($orig_webp) $map[ self::url_from_path($orig_webp) ] = true;

    // Sizes
    if (!empty($metadata['sizes']) && is_array($metadata['sizes'])){
        $base_dir = pathinfo($file, PATHINFO_DIRNAME);
        foreach ($metadata['sizes'] as $size => $data){
            if (empty($data['file'])) continue;
            $p = $base_dir . '/' . $data['file'];
            $w = self::convert_path_to_webp($p, $s['quality']);
            if ($w) $map[ self::url_from_path($w) ] = true;
        }
    }

    if (!empty($map)) update_post_meta($attachment_id, self::META_MAP, array_keys($map));
    return $metadata;
}

/*** FRONT‑END SWAP ***/
public function swap_src_to_webp($image, $attachment_id, $size, $icon){
    $s = self::get_settings();
    if (empty($s['serve_webp'])) return $image;
    if (!is_array($image) || empty($image[0])) return $image;
    $maybe = self::maybe_webp_url($image[0]);
    if ($maybe) $image[0] = $maybe; // swap URL only
    return $image;
}

public function swap_srcset_to_webp($sources, $size_array, $image_src, $image_meta, $attachment_id){
    $s = self::get_settings();
    if (empty($s['serve_webp']) || empty($sources) || !is_array($sources)) return $sources;
    foreach ($sources as $w => $src){
        if (!empty($src['url'])){
            $maybe = self::maybe_webp_url($src['url']);
            if ($maybe) $sources[$w]['url'] = $maybe;
        }
    }
    return $sources;
}

/*** HELPERS ***/
public static function image_mime_supported($mime){
    return in_array($mime, ['image/jpeg','image/png','image/gif','image/webp'], true);
}

public static function ends_with_ci($haystack, $needle){
    return substr_compare(strtolower($haystack), strtolower($needle), -strlen($needle)) === 0;
}

public static function maybe_webp_url($url){
    // only swap for common image endings
    if (!preg_match('~\.(jpe?g|png|gif|webp)(\?.*)?$~i', $url)) return null;
    $path = self::path_from_url($url);
    if (!$path) return null;
    $webp = self::replace_ext($path, 'webp');
    if (file_exists($webp)) return self::url_from_path($webp);
    return null;
}

public static function replace_ext($path, $new_ext){
    $pi = pathinfo($path);
    return $pi['dirname'] . '/' . $pi['filename'] . '.' . $new_ext;
}

public static function path_from_url($url){
    $upload = wp_get_upload_dir();
    if (strpos($url, $upload['baseurl']) !== 0) return false;
    $rel = ltrim(substr($url, strlen($upload['baseurl'])), '/');
    return trailingslashit($upload['basedir']) . $rel;
}

public static function url_from_path($path){
    $upload = wp_get_upload_dir();
    if (strpos($path, $upload['basedir']) !== 0) return false;
    $rel = ltrim(substr($path, strlen($upload['basedir'])), '/');
    return trailingslashit($upload['baseurl']) . str_replace(DIRECTORY_SEPARATOR, '/', $rel);
}

public static function convert_path_to_webp($path, $quality=82){
    if (!file_exists($path)) return false;
    $webp = self::replace_ext($path, 'webp');
    // If exists and newer source is not newer, keep it
    if (file_exists($webp) && filemtime($webp) >= filemtime($path)) return $webp;

    // Use WP_Image_Editor first (Imagick/GD abstraction)
    $editor = wp_get_image_editor($path);
    if (!is_wp_error($editor)){
        $editor->set_quality($quality);
        // Some editors need an explicit mime
        if (method_exists($editor, 'save')){
            $res = $editor->save($webp, 'image/webp');
            if (!is_wp_error($res) && !empty($res['path'])) return $webp;
        }
    }

    // Fallback: native Imagick
    if (class_exists('Imagick')){
        try {
            $im = new \Imagick($path);
            if (method_exists($im, 'setImageAlphaChannel')) $im->setImageAlphaChannel(\Imagick::ALPHACHANNEL_ACTIVATE);
            $im->setImageFormat('webp');
            $im->setImageCompressionQuality($quality);
            $ok = $im->writeImage($webp);
            $im->clear(); $im->destroy();
            if ($ok) return $webp;
        } catch (\Exception $e) {}
    }

    // Fallback: GD
    if (function_exists('imagecreatefromstring') && function_exists('imagewebp')){
        $binary = file_get_contents($path);
        if ($binary !== false){
            $img = imagecreatefromstring($binary);
            if ($img){
                // quality: 0–100 in PHP 7.4+, else 0–9 quality scale — try to detect
                $ok = false;
                $ref = new \ReflectionFunction('imagewebp');
                $params = $ref->getParameters();
                if (count($params) >= 3){
                    $ok = imagewebp($img, $webp, (int)$quality);
                } else {
                    // Older signature uses compression level 0–9; map roughly
                    $lvl = (int)round((100 - $quality) / 11);
                    $ok = imagewebp($img, $webp, max(0, min(9, $lvl)));
                }
                imagedestroy($img);
                if ($ok) return $webp;
            }
        }
    }
    return false;
}

/*** WP‑CLI ***/
public function cli($args, $assoc){
    $cmd = isset($args[0]) ? $args[0] : '';
    $s = self::get_settings();
    if ($cmd === 'regenerate'){
        $q = new \WP_Query([
            'post_type' => 'attachment',
            'post_status' => 'inherit',
            'posts_per_page' => -1,
            'post_mime_type' => ['image/jpeg','image/png','image/gif','image/webp']
        ]);
        \WP_CLI::log('Converting ' . $q->found_posts . ' attachments to WebP...');
        $count = 0; $fail = 0;
        while ($q->have_posts()){ $q->the_post();
            $id = get_the_ID();
            $meta = wp_generate_attachment_metadata($id, get_attached_file($id));
            if (!empty($meta)) wp_update_attachment_metadata($id, $meta);
            $map = get_post_meta($id, self::META_MAP, true);
            if ($map) $count++; else $fail++;
        }
        wp_reset_postdata();
        \WP_CLI::success("Done. Success: $count, Possibly skipped/failed: $fail");
    } else {
        \WP_CLI::line('Usage: wp mswebp regenerate');
    }
}

}

add_action(‘plugins_loaded’, function(){ new MS_WebP_Converter(); });


Hazır! Tek dosyalık bir eklenti hazırladım: “Upload WebP Converter”.
Yüklenen görsellerin orijinalini ve tüm ara boyutlarını WebP olarak da kaydediyor; istersen ön yüzde .webp URL’lerini otomatik kullanıyor. Ayrıca WP-CLI ile toplu dönüştürme var.

Sağ taraftaki canvas’ta kod hazır. Şöyle kurarsın:

Kurulum

  1. Canvas’taki kodu wp-content/plugins/ms-webp-converter.php adıyla kaydet.
  2. WP Yönetim → Eklentiler → Upload WebP Converter → Etkinleştir.
  3. Ayarlar → Upload WebP menüsünden:
    • Quality (varsayılan 82),
    • Ön yüzde WebP sun (URL değişimi) (işaretli önerilir),
    • Kaynak zaten WebP ise atla (işaretli önerilir) seçeneklerini ayarla.

Nasıl çalışır?

  • Yükleme sırasında: JPEG/PNG/GIF (ve WebP) için .webp kardeş dosya üretir (orijinal dosyayı silmez).
  • Tema tarafında (aktifse): wp_get_attachment_image_src ve srcset çıktılarındaki URL’leri varsa WebP sürümlerle değiştirir.
  • Medya Kütüphanesi görünümü değişmez; sadece front-end’de .webp servedir.

Toplu Dönüştürme

Sunucuda WP-CLI varsa:

wp mswebp regenerate

Tüm ortam dosyalarına WebP kopyaları üretir.

Notlar

  • Imagick varsa onu, yoksa GD’yi kullanır; en başta WordPress Image Editor (wp_get_image_editor) tercih edilir.
  • Güvenli: mevcut .webp daha yeni ise yeniden yazmaz.
  • WebP desteği olmayan aşırı eski tarayıcılar çok nadir; yine de orijinal dosya mevcut olduğundan sorun olmaz.

CEVAP VER

Lütfen yorumunuzu giriniz!
Lütfen isminizi buraya giriniz