오픈 / 클로즈드 / 숨겨진 / 표시된 메타 박스 상태를 포스트별로 저장하는 방법은 무엇입니까?


9

내 진짜 문제는 약간 복잡하기 때문에 여기서 추상화하고 간단하게 유지하려고 노력할 것입니다.

WordPress를 기반으로하는 맞춤형 앱을 만들고 있습니다. 맞춤 게시물 유형을 등록했습니다. 사람에 대한 정보를 저장하는 "사람"이라고하겠습니다.

CPT는 게시물 제목 및 게시물 내용 기본 필드 만 지원하지만 개인 정보를 저장하는 메타 박스가 있습니다 (주소록으로 내 앱을 생각하십시오).

개인 정보를 저장하는 메타 박스, 소셜 네트워크 정보를 저장하는 메타 박스, 업무 관련 정보를 저장하는 메타 박스가 있습니다.

여기에서는 단순화했지만 12 개의 일관된 양의 메타 박스가 있습니다.

내 문제는 정보를 저장하려는 일부 사람들이 단지 임의의 연락처이며 개인 정보 만 저장하고 싶고 다른 사람들은 친구이고 개인 정보와 소셜 네트워크 정보를 저장하고 싶다는 것입니다. 업무 관련 정보를 저장하고 싶습니다.

게시물을 편집 할 때 화면 옵션 메뉴 를 통해 숨기 거나 필요하지 않은 메타 박스를 닫으면 필요한 다른 게시물을 열 때 다시 표시하거나 열어야합니다. 이는 메타 박스 위치 / 상태 / 명령이 사용자 메타 데이터와 같은 사용자별로 저장되기 때문에 .

일부 게시물에 2 개의 메타 박스가 필요하다고 생각하면 약 10 및 5에 메타 박스가 모두 있음을 알 수 있습니다. 모든 화면을 열어 놓은 상태로 유지하면 편집 화면을 액세스 할 수 없도록 만듭니다 (스크롤 바는 끝이없는 것 같습니다). 그리고 때로는 내가 찾는 정보가 정보가없는 많은 메타 박스 후 페이지 끝에서 ...

질문:

특정 게시물 유형에 대해 메타 박스 위치 / 상태 / 순서를 게시물별로 저장할 수 있습니까?


추신 : 일부 js / jQuery가 문제를 해결할 수 있다는 것을 알고 있지만 가능하면 자바 스크립트 솔루션을 피할 것입니다.

답변:


8

주요 문제 :

여기에 가장 큰 문제는에 있다는 것이다 마무리 - , hiding-ordering- 아약스 호출, 페이로드로 전송되지 후 ID가 없습니다. 다음은 두 가지 양식 데이터 예입니다.

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]:

우리는 다른 사용자 정의 아약스 호출을 사용 하여이 문제를 해결할 수 있습니다.

물론 save_post게시물을 저장할 때마다 후크에 연결하고 데이터를 수정할 수 있습니다. 그러나 그것은 일반적인 UI 경험이 아니므로 여기서는 고려하지 않습니다.

아래에 설명 된, PHP와 함께 사용할 수있는 또 다른 비고 유적 인 솔루션이 있습니다.

자바 스크립트가 아닌 솔루션 :

문제는 데이터를 어디에 저장할 것인가? 로 사용자 메타 데이터, 포스트 메타 데이터 또는 어쩌면 사용자 정의 테이블에서?

여기에서 우리는 사용자 메타 데이터로 저장하고 받아 폐쇄 예를 들어 메타 상자.

closedpostboxes_post메타 값이 업데이트됩니다, 우리는에 저장 closedpostboxes_post_{post_id}메타 값뿐만 아니라.

그런 다음 closedpostboxes_post사용자 ID 및 게시물 ID를 기반으로 해당 메타 값으로 재정의하기 위해 가져 오기를 도용합니다 .

a) closed-postboxes아약스 작업 중 업데이트 :

를 통해 게시물 ID를 wp_get_referer()가져온 다음 편리한 url_to_postid()기능 을 사용할 수 있습니다. 나는 몇 달 전에 @s_ha_dum 에서 답을 읽은 후에이 "재미있는"함수에 대해 처음 알았습니다. ;-) 불행히도이 함수는 ?post=123GET 변수를 인식하지 못하지만 , 그 함수를 변경하기 위해 약간만 변경하면됩니다 p=123.

에 연결할 수 있습니다 updated_user_meta. 사용자 메타 데이터 closedpostboxes_post가 업데이트 된 직후에 발생합니다 .

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) 데이터를 가져 오는 중 :

사용자 메타 get_user_option_closedpostboxes_post에서 가져온 데이터를 수정하기 위해 후크에 연결할 수 있습니다 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 );

게시물 기반이없는 경우에 대해서도 생각하고 싶을 수도 closedpostboxes_post_{post_id}있습니다. 따라서에서 마지막으로 저장된 설정을 사용합니다 closedpostboxes_post. 기본 설정에서 모두 열거 나 닫을 수 있습니다. 이 동작을 수정하는 것은 쉽습니다.

다른 맞춤 게시물 유형의 경우 해당 closedpostboxes_{post_type}후크를 사용할 수 있습니다 .

및 메타 사용자 와 함께 메타 박스 의 순서숨기기 에 대해서도 동일해야합니다 .metaboxhidden_{post_type}meta-box-order_{post_data}

추신 : 항상 짧고 유쾌해야하기 때문에 너무 긴 주말 답변에 대해 죄송합니다.


대단한 +1. 긴 대답을위한 N / P, 나는 짧은 것을 기대하지 않을 것입니다. 솔직히 말해서 주말에는 기대하지 않았습니다. :) 내가 가장 좋아하는 두 가지 : 1 사용자 게시물별로 데이터를 저장하는 아이디어 : 내 아이디어는 포스트 메타에 저장하는 것이었지만 모든 방식으로 사용자는 동일한 상태를 갖습니다. 두 번째 아이디어 'get_user_option_*_post'는 WP가 사용자 정의 데이터를 인식 하도록 하는 데 사용 합니다. 만 너무 많이 좋아하지 않는 생각의 사용이다 wp_get_referer정말로 그 $_SERVER의 VAR 정말 신뢰할 수 없습니다는 하지만 난이 "큰 문제"를 극복하는 아이디어가 생각)
gmazzap

감사합니다. 데이터를 저장하는 것이 가장 좋은 사용자 및 게시물 수에 따라 다릅니다. 이 데이터에 TTL이 있고 한 달에 한 번 지워 져야합니까? 예, 나는 그 wp_get_referer()방법 에 대해 당신에게 동의합니다. 그래서 나는 그것을 비 PHP PHP 솔루션이라고 불렀습니다. 브라우저에서 게시물. "주요 문제"에 대한 귀하의 아이디어에 대한 기대를 기대하십시오 주말을 즐기십시오 ;-)
birgire

43 일이 지난 후 공감 한 사람은 이것에 대해 답할 것을 기억합니다. 귀하의 답변에 다시 한번 감사드립니다.
gmazzap

6

답변 에서 birgire 가 지적한 것처럼 WordPress는 AJAX를 사용하여 메타 박스 상태를 업데이트하고 AJAX 요청에 전달 된 데이터에는 포스트 ID가 포함되지 않으므로 포스트별로 박스 상태를 업데이트하기가 어렵습니다.

WordPress에서 사용하는 AJAX 작업이 발견되면 'closed-postboxes'admin js 폴더에서이 문자열을 검색하여 WordPress가 AJAX 요청을 수행하는 방법을 찾았습니다.

postbox.js# 118 행에서 발생했습니다 .

다음과 같이 보입니다 :

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
  });
}

기본적으로 WordPress는 'postbox'클래스와 'closed'클래스가있는 DOM 항목을보고 쉼표로 구분 된 ID 목록을 만듭니다. 'postbox'클래스가있는 숨겨진 DOM 항목에 대해서도 마찬가지입니다.

그래서 내 생각은 : 올바른 클래스를 가지고 있고 숨겨진 ID를 게시 ID를 포함하도록 ID를 설정 하는 가짜 메타 박스를 만들 수 있으며,이 방법으로 AJAX 요청에서 검색 할 수 있습니다.

이것이 내가 한 일입니다.

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 );
    }
});

이렇게하면 항상 닫히고 항상 숨겨지는 메타 박스를 만들었으므로 WordPress는 $_POSTAJAX 요청에서 ID를 var 로 보내며 가짜 상자 ID에 예측 가능한 방식으로 게시물 ID가 포함되면 게시물을 인식 할 수 있습니다.

그 후 WordPress가 AJAX 작업을 수행하는 방법을 살펴 보았습니다.

에서는 admin-ajax.php라인 (72)에서 , 워드 후크 'wp_ajax_closed-postboxes'우선 1.

따라서 WordPress 전에 행동하기 위해 우선 순위가 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 );

포스트 메타에 저장된 데이터를 갖는 것은 가능 필터에 만든 get_user_option_closedpostboxes_mycptget_user_option_metaboxhidden_mycpt(의 두 변이 get_user_option_{$option}포스트 메타에서 힘 워드 프레스로드 옵션 필터) :

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 );

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 );

관련 정보가 +1 인 숨겨진 메타 박스를 사용하는 것이 얼마나 좋은 아이디어입니까
birgire

당신의 A에 대한 다시 감사 @birgire 감사, 사용자 별 및 포스트 기준 모두에 데이터를 저장의 개념은 모든 당신입니다 :)
gmazzap
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.