WordPress Meta Box’ta Görsel Seçtirmek

Herkese Merhaba 👋🏻 Şu anda bu yazıyı okuduğunuz blogumun temasını hazırlarken Wordpress hakkında birçok güzel ipucu ve güzel özellik öğrendim. Bunlar içerisinde en çok sevdiğim özelliklerden birisi de (ki bunu daha önce birçok kez yapmaya çalışıp becerememiştim) metabox içerisinde ortam kütüphanesinden resim seçtirmek oldu. Bunu yapabilmek için iki adımımız var. Birinci adımımız bir metabox oluşturmak ve içerisine ortam kütüphanesini açmak için bir buton koymak (oldukça kolay değil mi?). Diğer adımımız ise birazcık Javascript içeriyor. En temel anlamda ortam kütüphanesi için bir frame oluşturuyoruz ve buradaki seçim olaylarını yakalayıp seçilen görsellerin ID'lerini alıp kaydediyoruz. Hemen başlayalım. Öncelikle temamızın functions.php dosyasına şu satırları ekleyelim.
function lahmacun_add_meta_boxes() {
  add_meta_box( 'lahmacun_gallery_metabox', __( 'Galeri', 'lahmacun' ), 'lahmacun_gallery_metabox_callback', 'post', 'side', 'default' );
}

add_action('add_meta_boxes', 'lahmacun_add_meta_boxes');
Buradaki her şeyi tek tek açıklamayacağım. Kısaca yaptığımız şeyi açıklayıp detaylar için link vereceğim. Her şeyden önce add_meta_box fonksiyonu hakkında detaylı bilgi için şuraya gidebilirsiniz. lahmacun_add_meta_boxes adında bir fonksiyon oluşturduk. Bunun içerisinde yeni bir meta box oluşturduk. Meta box'ımızın başlığı "Galeri", sadece yazı tipindeki gönderilerde görünecek ve içerik oluşturma ekranında sağ tarafta görünecek. Bu meta box'ın oluşturulması için fonksiyonumuzun çağırılması gerekiyor. Bu fonksiyonu kendimiz çağırmayacağız. Bunu bir kancanın ucuna ekleyeceğiz ve zamanı geldiğinde Wordpress tarafından çağırılacak. Tahmin edeceğiniz üzere kancamız da add_meta_boxes kancası. Eğer bu kanca (hook) sistemi hakkında yeteri kadar bilgi sahibi değilseniz Tayfun Erbilen tarafından hazırlanmış olan şu videoyu izlemenizi tavsiye ederim: Meta box oluşturan fonksiyonumuzu add_meta_boxes kancasına ekledik. Şimdi bu meta boxımız için callback fonksiyonumuzu yazmamız lazım. Parametremizde belirttiğimiz üzere callback fonksiyonumuzun ismi lahmacun_gallery_metabox_callback. Callback fonksiyonumuzda yapacağımız şey ortam kütüphanesini açmak için bir buton koymak.
function lahmacun_gallery_metabox_callback($post)
{
    ?>
    <button type="button" id="open-gallery">Görsel Seç</button>
    <?php
}
PHP etiketlerini açıp kapattığımız yer belki biraz kafa karıştırıcı olabilir. Direkt olarak PHP'nin echo komutuyla ekrana button etiketini basmak yerine php etiketlerini kapatıyoruz, button etiketimizi oluşturuyoruz ve tekrar PHP etiketlerimizi açıyoruz. Bildiğiniz üzere PHP'nin en önemli özelliklerinden birisi de HTML'in içine gömülebiliyor olmasıdır. Bu olayı anladığınızı varsayıyorum. Şimdi ufak bir Javascript koduna ihtiyacımız var. Ben tema klasörümün altında admin/js klasörüne gallery.js adında bir dosya oluşturmayı tercih ettim. İlk olarak sadece butona tıklandığı zaman ortam kütüphanesi penceresi açılmasını sağlayalım. Javascript dosyasının içeriği şimdilik şu şekilde olsun.
jQuery(document).ready(function ($) {
    var mediaFrame;

    mediaFrame = wp.media.frames.file_frame = wp.media({
        //button_text set by wp_localize_script()
        title: "Görselleri Seçin",
        button: {text: "Tamam"},
        multiple: true // Çoklu Seçime izin ver.
    });

    $('#open-gallery').on('click', function (e) {

        e.preventDefault();

        if (mediaFrame) {
            mediaFrame.open();
            return;
        }

    });
});
Kodlarımızın bir kısmı açıklayalım. Öncelikle mediaFrame adında bir değişken oluşturuyoruz ve bunu da wp.media.frames.file_frame'e eşitliyoruz ve onu da wp.media diyerek yeni bir objeye eşitliyoruz. wp.media fonksiyonu bize ortam kütüphanesi penceresi döndürüyor. Bunun içerisinde birkaç tane ufak ayar var. Birincisi title. Ortam kütüphanesinin sol üst tarafında görünen başlık kısmına tekabül ediyor bu kısım. İkincisi button. Button özelliği bir obje. İçerisindeki "text" anahtarı sağ aşağıda görünecek olan butonumuzun üzerindeki yazı oluyor. Butonun yazısını bu şekilde ayarlayabilirsiniz. Ve son olarak da multiple seçeneğimiz var. Eğer buna true derseniz kullanıcınız ortam kütüphanesinden çoklu resim seçebiliyor. Sonrasında #open-gallery butonuna tıklanma olayını yakaladık ve burada bir kontrol yaptık. Eğer mediaFrame değişkenimiz tanımlandıysa, yani bir ortam kütüphanesi penceremiz varsa eğer open metodu ile bu pencereyi açıyoruz. Şimdi tek yapmamız gereken bu Javascript dosyasını çağırmak. Admin panelinin kodlarını düzenlemeyeceğimize göre bu Javascript dosyasını çağırmak için de kancaları kullanmamız gerekiyor. Wordpress'te admin_enqueue_scripts adında bir kanca var. Admin panelinin Javascript dosyaları çağırılırken bu kancamız çalışıyor. Böylece siz de admin panelinde kendi Javascript dosyalarınızı çağırabiliyorsunuz. Yeni bir fonksiyon oluşturalım ve bu fonksiyon içerisinde wp_enqueue_script fonksiyonu ile bu oluşturduğumuz Javascript dosyasını çağıralım ve sonrasında da bu fonksiyonumuzu uygun kancaya ekleyelim.
function lahmacun_enqueue_meta_box_scripts() {
    wp_enqueue_script(
        'lahmacun_media_select',
        get_template_directory_uri() . '/admin/js/gallery.js',
        [ 'jquery' ],
        '',
        true
    );
}

add_action( 'admin_enqueue_scripts', 'lahmacun_enqueue_meta_box_scripts' );
Buradaki fonksiyonları ve parametreleri de tek tek açıklamayacağım. Bu kısımları zaten bildiğinizi varsayıyorum. Eğer bilmiyorsanız da şuradaki dokümantasyonu inceleyebilirsiniz. Böylece Javascript dosyamızı da çağırmış olduk. Şimdi ilk denememizi yapabiliriz. Şöyle bir görüntüyle karşılaşmış olmanız gerekiyor. Şimdi yapmamız gereken şey görsellerin seçilme olayını yakalayıp seçilen görsellerin ID'sini almak ve bunları bir gizli inputun içine atmak. Meta boxımız için oluşturduğumuz callback fonksiyonunu biraz değiştireceğiz. İçerisinde bir tane hidden input ve bir tane de ul etiketi koyacağız. Gizli inputumuz bizim görsellerimizin ID'lerini saklarken ul etiketimizin içerisine de görsellerimizi koyacağız ki kullanıcı hangilerini seçtiğini görebilsin. Düzenleme sonrasında fonksiyonumuz şu şekilde olmalı.
function lahmacun_gallery_metabox_callback($post)
{
    ?>
    <input type="hidden" name="gallery_images">
    <button type="button" id="open-gallery">Görsel Seç</button>
    <ul class="gallery-images"></ul>
    <?php
}
ismini gallery_images olarak ayarladık. Şimdi tekrar javascript dosyamıza gideceğiz ve şu satırları ekleyeceğiz.
mediaFrame.on('select', function() {
    var attachments = mediaFrame.state().get('selection').map(function (attachment) {
        attachment.toJSON();
        return attachment;
    });

    $("ul.gallery-images").html("");
    var galleryImageIds = [];

    for (var i = 0; i < attachments.length; ++i) {
        $('ul.gallery-images').append(
            '<li>' +
            '<img src="' +
            attachments[i].attributes.url + '" style="width: 150px; height: auto;" />' +
            '</li>'
        );
        galleryImageIds.push(attachments[i].attributes.id);
    }
    $("input[name=gallery_images]").val(galleryImageIds.join());
})
Burada biraz açıklama yapmamız lazım. Öncelikle daha önce oluşturduğumuz media çerçevemizin select olayını yakaladık. Yani bir resim seçme işlemi yapıldığında bizim burada yazdığımız kodlar çalışacak. Öncelikle mediaFrame değişkenimizin içerisindeki seçili olan bütün elemanları aldık ve bunları map fonksiyonu yardımıyla JSON formatına çevirdik. Artık her bir attachmentı bir obje olarak kullanabiliriz. Daha sonra bütün seçili görselleri arayüzden kaldırmak için ul'mizin içerisindeki bütün her şeyi temizliyoruz. Sonrasında eklerimizin idlerini koyacağımız değişkenimizi oluşturup bunu boş bir dizi olarak tanımlıyoruz. Hemen arkasından bütün eklerimizi bir for döngüsü yardımıyla bir döngüye sokuyoruz. Bu görsellerin bütün özellikleri attributes propertysi altında bulunuyor. Görselin URL'si veya ID'si gibi birçok veriyi buradan elde edebiliyoruz. ul etiketimizin içerisine bir li etiketi ekleyip onun içerisine de bir görsel ekliyoruz ve src özelliği olarak da ekimizin adresini yazıyoruz. Şu anda görselimiz ul'mizin içerisine bir liste elemanı olarak eklendi. Bundan sonra yapmamız gereken şey bu ekimizin id'sini alıp dizimize eklemek. Javascript'in push fonksiyonu yardımıyla id'mizi dizimize ekliyoruz. Döngüden çıktıktan sonra ise bu id'lerimizin bulunduğu diziyi join fonksiyonu yardımıyla virgüllerle ayrılmış bir string haline getiriyoruz ve gizli inputumuza değer olarak veriyoruz. Artık görsellerimizin id'lerini elde etmiş olduk. Bu işlemleri düzgün bir şekilde yaptıysak eğer şu şekilde bir çıktıyla karşılaşmamız lazım. Yapmamız gereken son bir adım kaldı. O da bu seçtimiz görselleri kaydetmek. Kaydetme işlemi için Wordpress'in update_post_meta fonksiyonunu ve edit_post kancasını kullanacağız. Hemen yeni bir fonksiyon oluşturalım. Bu fonksiyonumuzun ismi de lahmacun_save_meta_boxes olsun. Bu fonksiyonun içerisinde de POST metodu ile gelen galeri resimleri idlerini alıp gönderimize bir meta olarak ekleyeceğiz.
function lahmacun_save_meta_boxes( $post_id ) {
    if ( array_key_exists( "gallery_images", $_POST ) ) {
        $metaValue = $_POST["gallery_images"];
    } else {
        $metaValue = null;
    }
    update_post_meta(
        $post_id,
        "lahmacun_gallery_images",
        $metaValue
    );
}

add_action( 'edit_post', 'lahmacun_save_meta_boxes' );
Metamızı bu şekilde eklemiş olduk. Şimdi yapmamız gereken tek şey sayfamız yüklendiği zaman önceden seçilmiş görseller varsa bunları listelemek ve bu görselleri göstermek. Bunun için yine meta boxımızın callback fonksiyonunu biraz düzenlememiz gerekecek. Öncelikle get_post_meta ile görsellerimizin id'sini alalım ve bunu explode ile parçalayıp bir döngüye sokalım. Sonrasında da hepsini teker teker gösterelim. Fonksiyonumuzun yeni hali şu şekilde olacak.
function lahmacun_gallery_metabox_callback($post)
{
  $galleryImages = get_post_meta($post->ID, 'lahmacun_gallery_images', true);
    ?>
    <input type="hidden" name="gallery_images" value="<?php echo $galleryImages; ?>">
    <button type="button" id="open-gallery">Görsel Seç</button>
    <ul class="gallery-images">
    	<?php
    	$galleryImages = explode(",", $galleryImages);
    	foreach ($galleryImages as $imageId) {
    	?>
    		<img src="<?php echo wp_get_attachment_url($imageId); ?>" style="width: 150px; height: auto;">
    	<?php
    	}
    	?>
    </ul>
    <?php
}
Ufak bir inceleme yapalım. Burada lahmacun_gallery_images metasını çektik. Bu bize idlerin virgülle birleşmiş hali olan bir string verdi. Biz de bu stringi önce alip gizli inputumuza değer olarak verdik. Daha sonra ul'nin içerisinde bunu explode ile virgül karakterine göre parçaladık ve tek tek idleri elde ettik. Daha sonra da wp_get_attachment_url fonksiyonu yardımı ile bu görselleri çağırdık. Şu anda her şey yolunda. Şimdi tek yapmamız gereken tekrar görsel seç butonuna bastığımız zaman mevcut görsellerimizi seçili hale getirmek. Bundan sonra eksiksiz ve güzel bir meta boxımız olacak. Bunun için tekrar Javascript kodlarımızı düzenlememiz lazım. Bunun için yapmamız gereken de inputumuzun değerini alıp virgül ile parçalayıp daha sonra bu id'ye ait görselleri seçili hale getirmek.
mediaFrame.on('open', function() {
    var attachments = [];
    var attachmentsString = $("input[name=gallery_images]").val();
    attachments = attachmentsString.split(",");

    attachments.forEach(function(id) {
        attachment = wp.media.attachment(id);
        attachment.fetch();
        mediaFrame.state().get('selection').add(attachment ? [attachment] : []);
    });
});
Öncelikle attachments adında boş bir dizi oluşturduk. Daha sonra inputumuzun değerini alıp bir değişkene atadık. inputumuzun değerini split fonksiyonu ile virgül karakterine göre parçaladık ve bir dizi oluşturup bunu attachments dizisine atadık. Daha sonra attachments dizisindeki her bir eleman için wp.media.attachment diyerek görselin id'sini kullanarak attachmentımızı çağırdık. Sonrasında mediaFrame değişkenimizin state'indeki seçim kısmına tek tek bu attachmentları eklemiş olduk. Böylece mevcut seçili görsellerimiz varsa penceremiz açıldığında bunları göstermiş olduk. Buraya dosyalarımızın tam hallerini bırakıp bu yazıyı da burada sonlandırmak istiyorum. Öncelikle functions.php
<?php

function lahmacun_add_meta_boxes() {
  add_meta_box( 'lahmacun_gallery_metabox', __( 'Galeri', 'lahmacun' ), 'lahmacun_gallery_metabox_callback', 'post', 'side', 'default' );
}

add_action('add_meta_boxes', 'lahmacun_add_meta_boxes');

function lahmacun_gallery_metabox_callback($post)
{
  $galleryImages = get_post_meta($post->ID, 'lahmacun_gallery_images', true);
    ?>
    <input type="hidden" name="gallery_images" value="<?php echo $galleryImages; ?>">
    <button type="button" id="open-gallery">Görsel Seç</button>
    <ul class="gallery-images">
    	<?php
    	$galleryImages = explode(",", $galleryImages);
    	foreach ($galleryImages as $imageId) {
    	?>
    		<img src="<?php echo wp_get_attachment_url($imageId); ?>" style="width: 150px; height: auto;">
    	<?php
    	}
    	?>
    </ul>
    <?php
}

function lahmacun_enqueue_meta_box_scripts() {
    wp_enqueue_script(
        'lahmacun_media_select',
        get_template_directory_uri() . '/admin/js/gallery.js',
        [ 'jquery' ],
        '',
        true
    );
}

add_action( 'admin_enqueue_scripts', 'lahmacun_enqueue_meta_box_scripts' );

function lahmacun_save_meta_boxes( $post_id ) {
  if ( array_key_exists( "gallery_images", $_POST ) ) {
    $metaValue = $_POST["gallery_images"];
  } else {
    $metaValue = null;
  }
  update_post_meta(
    $post_id,
    "lahmacun_gallery_images",
    $metaValue
  );
}

add_action( 'edit_post', 'lahmacun_save_meta_boxes' );
gallery.js dosyamız:
jQuery(document).ready(function ($) {
    var mediaFrame;

    mediaFrame = wp.media.frames.file_frame = wp.media({
        //button_text set by wp_localize_script()
        title: "Görselleri Seçin",
        button: {text: "Tamam"},
        multiple: true // Çoklu Seçime izin ver.
    });

    $('#open-gallery').on('click', function (e) {

        e.preventDefault();

        if (mediaFrame) {
            mediaFrame.open();
            return;
        }

    });

    mediaFrame.on('select', function() {
    var attachments = mediaFrame.state().get('selection').map(function (attachment) {
                attachment.toJSON();
                return attachment;
        });

        $("ul.gallery-images").html("");
        var galleryImageIds = [];

        for (var i = 0; i < attachments.length; ++i) {
            $('ul.gallery-images').append(
                '<li>' +
                '<img src="' +
            	attachments[i].attributes.url + '" style="width: 150px; height: auto;" />' +
                '</li>'
            );
            galleryImageIds.push(attachments[i].attributes.id);
        }

        $("input[name=gallery_images]").val(galleryImageIds.join());
    })

    mediaFrame.on('open', function() {
        var attachments = [];
        var attachmentsString = $("input[name=gallery_images]").val();
        attachments = attachmentsString.split(",");

        attachments.forEach(function(id) {
            attachment = wp.media.attachment(id);
            attachment.fetch();
            mediaFrame.state().get('selection').add(attachment ? [attachment] : []);
        });
    });
});
Aklınıza takılan bir şeyler varsa bunları yorumlar bölümünden sorabilirsiniz. Umarım faydalı olmuştur. Herkese iyi çalışmalar dilerim.

1 Yorum

  1. Berke Yağız Sevim
    Yanıtla

    Bu benim öyküm birazcık yaralı

Yorum Bırakın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir