Kayıt başına açık / kapalı ve gizli / gösterilen meta kutular durumu nasıl kaydedilir?


9

Asıl sorunum biraz karmaşık, bu yüzden burada soyutlamaya ve basit tutmaya çalışacağım.

WordPress tabanlı özel bir uygulama üzerinde çalışıyorum. Özel bir yazı türü kaydettim, buna "insanlar" diyorum ... insanlar hakkında bilgi depolayacağım.

CPT yalnızca gönderi başlığı ve gönderi içeriği varsayılan alanlarını destekler, ancak kişi bilgilerini depolamak için bazı meta kutular vardır (uygulamamı bir adres defteri olarak düşün).

Bu yüzden kişisel bilgileri saklamak için bir meta kutusu, biri sosyal ağ bilgilerini saklamak için, diğeri işle ilgili bilgileri saklamak için bir meta kutusu var, yani bu kişi bana bir müşteri, bir tedarikçi, kredi veya borçlarımız varsa ...

Burada basitleştirdim, ancak tutarlı bir miktarda meta kutu var, diyelim 12.

Benim sorunum, bilgi saklamak istediğim bazı kişilerin sadece rastgele kişiler olduğu ve sadece kişisel bilgileri saklamak istediğim, diğerlerinin arkadaş olduğu ve kişisel bilgileri ve sosyal ağ bilgilerini saklamak istediğim, diğerlerinin ise müşteri veya tedarikçi olduğum ve işle ilgili bilgileri saklamak istemek.

Bir yayını düzenlerken ( ekran seçenek menüsü aracılığıyla ) saklıyorsam veya ihtiyacım olmayan herhangi bir meta kutuyu kapatırsam, onlara ihtiyacım olan başka bir yazı açtığımda bunları göstermem veya tekrar açmam gerekir. Bunun nedeni, meta kutuların konumu / durumu / sırası, kullanıcı başına meta veri olarak kaydedilir .

Bazı yayınlarda 2 meta kutuya ihtiyacım olduğunu tahmin ediyorsanız, bazı 10 ve bazılarında 5, bunların can sıkıcı olduğunu anlıyorsunuz, çünkü bunları açık / kapalı tutmak düzenleme ekranını düşük erişilebilir hale getiriyor (kaydırma çubuğu sonsuz görünüyor) ve bazen aradığım bilgiler bilgi içermeyen bir grup meta kutudan sonra sayfanın sonunda ...

Soru:

Belirli bir yazı türü için meta kutuların konumunu / durumunu / sırasını her yayın için ayrı ayrı kaydetmek mümkün müdür?


Not: Bazı js / jQuery sorunu çözebilir biliyorum, ancak mümkünse javascript çözümlerini önlemek istiyorum.

Yanıtlar:


8

Ana problem:

Burada asıl sorun içinde olduğunu closing- , hiding- ve ordering- ajax çağrıları, yük ile gönderilen hiçbir yayın kimliği var. İki form verisi örneği:

1) action:closed-postboxes
closed:formatdiv,tagsdiv-post_tag,trackbacksdiv,authordiv
hidden:slugdiv
closedpostboxesnonce:8723ee108f
page:post

2) action:meta-box-order
_ajax_nonce:b6b48d2d16
page_columns:2
page:post
order[side]:submitdiv,formatdiv,categorydiv,tagsdiv-post_tag,postimagediv
order[normal]:postexcerpt,postcustom,trackbacksdiv,commentsdiv,authordiv
order[advanced]:

Başka bir özel ajax çağrısı kullanarak bu sorunu çözebiliriz.

Tabii ki sadece kancaya takılabilir save_postve gönderi her kaydedildiğinde verileri değiştirebiliriz. Ancak bu normal UI deneyimi değildir, bu yüzden burada dikkate alınmaz

Aşağıda açıklanan PHP ile kullanılabilen şık olmayan bir çözüm daha var:

Javascript Dışı Bir Çözüm:

Soru, verilerin nerede saklanacağıdır? Gibi kullanıcı meta veriler, yazılan meta veri veya belki özel bir tabloda?

Burada kullanıcı meta veri olarak saklayın ve almak kapanış ait sonrası bir örnek olarak meta kutuları.

Ne zaman closedpostboxes_postmeta değer güncellenir, biz içine kaydetmek closedpostboxes_post_{post_id}meta değeri de.

Ardından closedpostboxes_post, kullanıcı kimliğine ve posta kimliğine dayalı olarak karşılık gelen meta değeriyle geçersiz kılmak için getirilmesini ele geçiririz .

a) closed-postboxesAjax işlemi sırasında güncelleme :

Posta kimliğini getirip wp_get_referer()kullanışlı url_to_postid()işlevi kullanabiliriz . Birkaç ay önce @s_ha_dum'ın cevabını okuduktan sonra bu "komik" işlevi ilk kez biliyordum ;-) Ne yazık ki işlev ?post=123GET değişkenlerini tanımıyor , ancak sadece onu almak p=123için değiştirerek biraz hile yapabiliriz .

Bağlanabiliriz updated_user_meta, bunun için kullanıcı meta verileri closedpostboxes_postgüncellendikten hemen sonra tetiklenir :

add_action( 'updated_user_meta',                           
    function ( $meta_id, $object_id, $meta_key, $_meta_value )
    {
        $post_id = url_to_postid( str_replace( 'post=', 'p=', wp_get_referer() ) );
        if( 'closedpostboxes_post' === $meta_key && $post_id > 0 )
            update_user_meta( 
                $object_id, 
                'closedpostboxes_post_' . $post_id, 
                $_meta_value 
            );
    }
, 10, 4 );

b) Veri getiriliyor:

Kullanıcı get_user_option_closedpostboxes_postmetasından getirilen verileri değiştirmek için kancaya bağlanabiliriz closedpostboxes_post:

add_filter( 'get_user_option_closedpostboxes_post',
    function ( $result, $option, $user )
    {
        $post_id = filter_input( INPUT_GET, 'post', FILTER_SANITIZE_NUMBER_INT );
        $newresult = get_user_option( 'closedpostboxes_post_'. $post_id , $user->ID );
        return ( $newresult ) ? $newresult : $result;
    }
, 10, 3 );

Ayrıca, posta tabanlı closedpostboxes_post_{post_id}mevcut olmayan durum hakkında da düşünmek isteyebiliriz . Böylece en son kaydedilen ayarları kullanacaktır closedpostboxes_post. Belki de bu varsayılan durumda hepsinin açık veya kapalı olmasını istersiniz. Bu davranışı değiştirmek kolay olurdu.

Diğer özel direk tipleri için ilgili closedpostboxes_{post_type}kancayı kullanabiliriz .

Aynı şey ve kullanıcı meta ile meta kutuların sıralanması ve gizlenmesi için de mümkün olmalıdır .metaboxhidden_{post_type}meta-box-order_{post_data}

ps: bu çok uzun hafta sonu cevabı için özür dilerim, çünkü her zaman kısa olmalılar & jolly ;-)


Harika +1. N / P uzun cevap için, kısa olanları beklemem. Dürüst olmak gerekirse ben hafta sonu herhangi bir beklemiyordum :) Çok sevdim iki şey: 1. kullanıcı başına ve sonrası bazda veri saklama fikri: benim fikrim post meta depolamak oldu, ama bu şekilde kullanıcılar aynı statüye sahip olacak. 2. 'get_user_option_*_post'WP'nin özel verileri tanımasını sağlamak için kullanılacak fikir . Sadece çok fazla sevmiyorum düşünüyorum gerçekten güvenilir değil var wp_get_referergerçekten kullanımıdır ama bence "ana sorun" üstesinden gelmek için bir fikrim var;)$_SERVER
gmazzap

Teşekkürler, verilerin depolanmasının en iyi olacağı kullanıcı ve yayın sayısına bağlıdır. Belki de bu verilerin bir miktar TTL'si olmalı ve örneğin ayda bir kez silinmelidir? Evet wp_get_referer()yöntemle ilgili olarak size katılıyorum , bu yüzden zarif olmayan bir PHP çözümü olarak adlandırdım ;-) İlk önce her kullanıcı için geçerli posta kimliğini depolamayı düşündüm, ancak bir kullanıcı iki veya daha fazla düzenliyorsa işe yaramaz gönderir. "Ana sorun" hakkındaki fikrinizi duymak için sabırsızlanıyoruz Hafta sonu tadını çıkarın ;-)
birgire

43 gün sonra bir upvote bunu cevaplamamı hatırlıyor. Cevabınız için tekrar teşekkürler.
gmazzap

6

Tarafından sivri dışarı olarak birgire içinde onun cevabını , WordPress sonrası kimliği içermez güncelleme Metabokslar statü ve AJAX isteği geçirilen verilere AJAX kullanır ve bu da başına sonrası bazda güncelleme kutuları statüsüne zor hale getirir.

WordPress tarafından kullanılan AJAX eylemini bulduğumda, 'closed-postboxes'WordPress'in AJAX isteğini nasıl yaptığını bulmak için admin js klasöründe bu dizeyi aradım.

postbox.js118 numaralı satırda olduğunu gördüm .

Öyle görünüyor:

save_state : function(page) {
  var closed = $('.postbox').filter('.closed').map(function() {
      return this.id;
    }).get().join(',');
  var hidden = $('.postbox').filter(':hidden').map(function() {
      return this.id;
    }).get().join(',');
  $.post(ajaxurl, {
    action: 'closed-postboxes',
    closed: closed,
    hidden: hidden,
    closedpostboxesnonce: jQuery('#closedpostboxesnonce').val(),
    page: page
  });
}

Esasen, WordPress, 'postbox' sınıfı ve 'kapalı' sınıfı olan DOM öğelerine bakar ve kimliklerinin virgülle ayrılmış bir listesini oluşturur. Aynı şey 'postbox' sınıfına sahip gizli DOM öğeleri için de yapılır.

Benim düşüncem şuydu: Doğru sınıflara sahip olan ve gizli olan, kimliğini posta kimliğini içerecek şekilde ayarlayan sahte bir meta kutu oluşturabilirim ve bu şekilde AJAX isteğinde alabilirim.

Ben de bunu yaptım:

add_action( 'dbx_post_sidebar', function() {
    global $post;
    if ( $post->post_type === 'mycpt' ) {
        $id = $post->ID;
        $f = '<span id="fakebox_pid_%d" class="postbox closed" style="display:none;"></span>';
        printf( $f, $id );
    }
});

Bu şekilde, her zaman kapalı ve her zaman gizli olan bir meta kutu oluşturdum, bu yüzden WordPress kimliğini $_POSTAJAX isteğinde var olarak gönderecek ve sahte kutu kimliği tahmin edilebilir bir şekilde post ID içerdiğinde , gönderiyi tanıyabiliyorum.

Bundan sonra WordPress'in AJAX görevini nasıl gerçekleştirdiğine baktım.

Gelen admin-ajax.phphattı 72 at , WordPress kanca 'wp_ajax_closed-postboxes'önceliği 1 olan.

Yani, WordPress'ten önce hareket etmek için, aynı eylemi öncelik 0 ile bağlayabilirim.

add_action( 'wp_ajax_closed-postboxes', function() {

    // check if we are in right post type: WordPress passes it in 'page' post var
    $page = filter_input( INPUT_POST, 'page', FILTER_SANITIZE_STRING );
    if ( $page !== 'mycpt' ) return;

    // get post data
    $data = filter_input_array( INPUT_POST, array(
        'closed' => array( 'filter' => FILTER_SANITIZE_STRING ),
        'hidden' => array( 'filter' => FILTER_SANITIZE_STRING )
    ) );

    // search among closed boxes for the "fake" one, and return if not found
    $look_for_fake = array_filter( explode( ',', $data[ 'closed' ] ), function( $id ) {
         return strpos( $id, 'fakebox_pid_' ) === 0;
    } );
    if ( empty( $look_for_fake ) ) return;

    $post_id = str_replace( 'fakebox_pid_', '', $look_for_fake[0] );
    $user_id = get_current_user_id();

    // remove fake id from values
    $closed = implode(',', array_diff( explode(',', $data['closed'] ), $look_for_fake ) );
    $hidden = implode(',', array_diff( explode(',', $data['hidden'] ), $look_for_fake ) );

    // save metabox status on a per-post and per-user basis in a post meta
    update_post_meta( $post_id, "_mycpt_closed_boxes_{user_id}", $closed );
    update_post_meta( $post_id, "_mycpt_hidden_boxes_{user_id}", $hidden );

}, 0 );

Verilerin bir meta metaya kaydedilmesi, WordPress yükleme seçeneklerini post meta'den zorlamak için filtrelemeyi get_user_option_closedpostboxes_mycptve get_user_option_metaboxhidden_mycpt( filtrenin her iki varyasyonunu get_user_option_{$option}) mümkün kıldı :

add_filter( 'get_user_option_closedpostboxes_mycpt', function ( $result, $key, $user ) {
    global $post;
    $meta = get_post_meta( $post->ID, "_mycpt_closed_boxes_{$user->ID}", TRUE );
    if ( ! empty( $meta ) ) {
        $result = $meta;
    }
    return $result;
}, 10, 3 );

ve

add_filter( 'get_user_option_metaboxhidden_mycpt', function ( $result, $key, $user ) {
    global $post;
    $meta = get_post_meta( $post->ID, "_mycpt_hidden_boxes_{$user->ID}", TRUE );
    if ( ! empty( $meta ) ) {
        $result = $meta;
    }
    return $result;
}, 10, 3 );

İlgili bilgiler +1 ile gizli bir metabox kullanmak ne harika bir fikir
Birgire

thanks @birgire ve A için tekrar teşekkürler, hem kullanıcı başına hem de gönderi bazında veri kaydetme fikri tamamen sizindir :)
gmazzap
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.