Seperti yang ditunjukkan oleh birgire dalam jawabannya , WordPress menggunakan AJAX untuk memperbarui status metabox dan data yang diteruskan dalam permintaan AJAX tidak termasuk pos id, dan itu membuatnya sulit untuk memperbarui status kotak berdasarkan basis per-posting.
Setelah saya menemukan tindakan AJAX yang digunakan oleh WordPress 'closed-postboxes', saya mencari string ini di folder admin js untuk menemukan bagaimana WordPress membuat permintaan AJAX.
Saya menemukan itu terjadi pada postbox.jsbaris # 118 .
Sepertinya:
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
});
}
Pada dasarnya, WordPress melihat item DOM dengan kelas 'kotak pos' dan kelas 'tertutup' dan membuat daftar ID yang dipisahkan koma. Hal yang sama dilakukan untuk item DOM tersembunyi dengan kelas 'kotak pos'.
Jadi, pikiran saya adalah: Saya dapat membuat metabox palsu yang memiliki kelas yang tepat dan yang disembunyikan, mengatur id-nya untuk berisi ID posting, dan dengan cara ini saya dapat mengambilnya dalam permintaan AJAX.
Inilah yang telah saya lakukan:
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 );
}
});
Dengan cara ini saya membuat metabox yang selalu tertutup dan selalu disembunyikan, jadi WordPress akan mengirimkan ID-nya sebagai $_POSTvar dalam permintaan AJAX, dan begitu id kotak palsu berisi ID pos dengan cara yang dapat diprediksi, saya dapat mengenali pos tersebut.
Setelah itu saya melihat bagaimana WordPress melakukan tugas AJAX.
Pada admin-ajax.phpbaris 72 , WordPress terhubung 'wp_ajax_closed-postboxes'dengan prioritas 1.
Jadi, untuk bertindak sebelum WordPress, saya dapat mengaitkan tindakan yang sama dengan prioritas 0.
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 );
Setelah data disimpan dalam meta pos memungkinkan untuk memfilter get_user_option_closedpostboxes_mycptdan get_user_option_metaboxhidden_mycpt(keduanya variasi get_user_option_{$option}filter) untuk memaksa opsi pemuatan WordPress dari meta pos:
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 );
dan
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 );
'get_user_option_*_post'untuk membuat WP mengenali data khusus. Hanya saya pikir saya tidak terlalu suka penggunaanwp_get_refereritu pada$_SERVERvar yang tidak benar-benar dapat diandalkan tapi saya pikir saya punya ide untuk mengatasi "masalah utama";)