관리자 패널에서 다른 사용자의 게시물 숨기기


10

여러 저자 사이트를 운영하려고했는데 다른 저자의 게시물이 /wp-admin/edit.php페이지에 표시되는 것을 원하지 않습니다 .

이 스레드 의 코드로이 문제를 해결했습니다 . 코드는 다음과 같습니다

function posts_for_current_author($query) {
    global $pagenow;

    if( 'edit.php' != $pagenow || !$query->is_admin )
        return $query;

    if( !current_user_can( 'manage_options' ) ) {
        global $user_ID;
        $query->set('author', $user_ID );
    }
    return $query;
}
add_filter('pre_get_posts', 'posts_for_current_author');

코드는 훌륭하게 작동하며 다른 저자의 게시물을 숨겨서 여기에 표시합니다. 그러나 다른 문제가 있습니다. 페이지 상단의 메뉴는 작성자의 관련 게시물 수를 변경하지 않으며 내 사이트의 모든 게시물 수를 보여줍니다.

내가 의미하는 메뉴는 다음과 같습니다.

Mine () | All () | Published () | Draft () | Trash ()

()저자와 관련된 숫자 만 반영하기 위해의 숫자 를 변경하는 방법은 무엇입니까?


나는 똑같은 일을 고려하고 있기 때문에 크게 생각하고 있습니다. 내 웹 사이트는 약 10 명의 저자가있는 야구 웹 사이트입니다. 나는 현재 로그인 한 저자로부터 다른 저자의 초안을 숨길 지 여부를 계속 생각하고 있습니다. 한쪽은 다른 저자의 기사를 출판 할 때까지 알 필요가 없다고 생각합니다. 다른 한편으로, 나는 2 명의 저자가 2 개의 거의 동일한 기사를 동시에 출판하는 것을 원하지 않습니다.
Travis Pflanz

마지막으로 내 문제에 대한 해결책을 찾았습니다 ... wordpress.org/support/topic/… 이것이 도움이 될 수 있습니다
dev-jim

답변:


11

내가 사용하는 것은 다음과 같습니다.

// Show only posts and media related to logged in author
add_action('pre_get_posts', 'query_set_only_author' );
function query_set_only_author( $wp_query ) {
    global $current_user;
    if( is_admin() && !current_user_can('edit_others_posts') ) {
        $wp_query->set( 'author', $current_user->ID );
        add_filter('views_edit-post', 'fix_post_counts');
        add_filter('views_upload', 'fix_media_counts');
    }
}

// Fix post counts
function fix_post_counts($views) {
    global $current_user, $wp_query;
    unset($views['mine']);
    $types = array(
        array( 'status' =>  NULL ),
        array( 'status' => 'publish' ),
        array( 'status' => 'draft' ),
        array( 'status' => 'pending' ),
        array( 'status' => 'trash' )
    );
    foreach( $types as $type ) {
        $query = array(
            'author'      => $current_user->ID,
            'post_type'   => 'post',
            'post_status' => $type['status']
        );
        $result = new WP_Query($query);
        if( $type['status'] == NULL ):
            $class = ($wp_query->query_vars['post_status'] == NULL) ? ' class="current"' : '';
            $views['all'] = sprintf(__('<a href="%s"'. $class .'>All <span class="count">(%d)</span></a>', 'all'),
                admin_url('edit.php?post_type=post'),
                $result->found_posts);
        elseif( $type['status'] == 'publish' ):
            $class = ($wp_query->query_vars['post_status'] == 'publish') ? ' class="current"' : '';
            $views['publish'] = sprintf(__('<a href="%s"'. $class .'>Published <span class="count">(%d)</span></a>', 'publish'),
                admin_url('edit.php?post_status=publish&post_type=post'),
                $result->found_posts);
        elseif( $type['status'] == 'draft' ):
            $class = ($wp_query->query_vars['post_status'] == 'draft') ? ' class="current"' : '';
            $views['draft'] = sprintf(__('<a href="%s"'. $class .'>Draft'. ((sizeof($result->posts) > 1) ? "s" : "") .' <span class="count">(%d)</span></a>', 'draft'),
                admin_url('edit.php?post_status=draft&post_type=post'),
                $result->found_posts);
        elseif( $type['status'] == 'pending' ):
            $class = ($wp_query->query_vars['post_status'] == 'pending') ? ' class="current"' : '';
            $views['pending'] = sprintf(__('<a href="%s"'. $class .'>Pending <span class="count">(%d)</span></a>', 'pending'),
                admin_url('edit.php?post_status=pending&post_type=post'),
                $result->found_posts);
        elseif( $type['status'] == 'trash' ):
            $class = ($wp_query->query_vars['post_status'] == 'trash') ? ' class="current"' : '';
            $views['trash'] = sprintf(__('<a href="%s"'. $class .'>Trash <span class="count">(%d)</span></a>', 'trash'),
                admin_url('edit.php?post_status=trash&post_type=post'),
                $result->found_posts);
        endif;
    }
    return $views;
}

// Fix media counts
function fix_media_counts($views) {
    global $wpdb, $current_user, $post_mime_types, $avail_post_mime_types;
    $views = array();
    $count = $wpdb->get_results( "
        SELECT post_mime_type, COUNT( * ) AS num_posts 
        FROM $wpdb->posts 
        WHERE post_type = 'attachment' 
        AND post_author = $current_user->ID 
        AND post_status != 'trash' 
        GROUP BY post_mime_type
    ", ARRAY_A );
    foreach( $count as $row )
        $_num_posts[$row['post_mime_type']] = $row['num_posts'];
    $_total_posts = array_sum($_num_posts);
    $detached = isset( $_REQUEST['detached'] ) || isset( $_REQUEST['find_detached'] );
    if ( !isset( $total_orphans ) )
        $total_orphans = $wpdb->get_var("
            SELECT COUNT( * ) 
            FROM $wpdb->posts 
            WHERE post_type = 'attachment' 
            AND post_author = $current_user->ID 
            AND post_status != 'trash' 
            AND post_parent < 1
        ");
    $matches = wp_match_mime_types(array_keys($post_mime_types), array_keys($_num_posts));
    foreach ( $matches as $type => $reals )
        foreach ( $reals as $real )
            $num_posts[$type] = ( isset( $num_posts[$type] ) ) ? $num_posts[$type] + $_num_posts[$real] : $_num_posts[$real];
    $class = ( empty($_GET['post_mime_type']) && !$detached && !isset($_GET['status']) ) ? ' class="current"' : '';
    $views['all'] = "<a href='upload.php'$class>" . sprintf( __('All <span class="count">(%s)</span>', 'uploaded files' ), number_format_i18n( $_total_posts )) . '</a>';
    foreach ( $post_mime_types as $mime_type => $label ) {
        $class = '';
        if ( !wp_match_mime_types($mime_type, $avail_post_mime_types) )
            continue;
        if ( !empty($_GET['post_mime_type']) && wp_match_mime_types($mime_type, $_GET['post_mime_type']) )
            $class = ' class="current"';
        if ( !empty( $num_posts[$mime_type] ) )
            $views[$mime_type] = "<a href='upload.php?post_mime_type=$mime_type'$class>" . sprintf( translate_nooped_plural( $label[2], $num_posts[$mime_type] ), $num_posts[$mime_type] ) . '</a>';
    }
    $views['detached'] = '<a href="upload.php?detached=1"' . ( $detached ? ' class="current"' : '' ) . '>' . sprintf( __( 'Unattached <span class="count">(%s)</span>', 'detached files' ), $total_orphans ) . '</a>';
    return $views;
}

출처


1
나는 워드 프레스 초보자로서이 두 가지 질문을하고있다 : (1) 왜 더 많은 배열을 사용하지 않는가 elseif? (2) 왜 번역을 사용하여 __()전체에 걸쳐 href아니라 단지에 All예를 들면?
cregox

3

답변을 기반으로 더 짧은 솔루션 https://wordpress.stackexchange.com/a/49200/83038 .

참고 : WordPress 3.7.0부터 사용 가능합니다.

function fix_count_orders( $counts, $type ) {
    global $wpdb;

    $query = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = %s";
    $query .= $wpdb->prepare( " AND post_author = %d", get_current_user_id() );
    $query .= ' GROUP BY post_status';

    $results = (array) $wpdb->get_results( $wpdb->prepare( $query, $type ), ARRAY_A );
    $counts = array_fill_keys( get_post_stati(), 0 );

    foreach ( $results as $row ) {
        $counts[ $row['post_status'] ] = $row['num_posts'];
    }

    return (object) $counts;
}


function query_set_only_author( $wp_query ) {
    global $current_user;

    // Add here post types for which you want to fix counts ('post' added for example).
    $allowed_types = array( 'post' );
    $current_type = get_query_var( 'post_type' ) ? get_query_var( 'post_type' ) : '';

    if( is_admin() && ! current_user_can( 'edit_others_posts' ) && in_array( $current_type, $allowed_types ) ) {
        $wp_query->set( 'author', $current_user->ID );
        add_filter( 'wp_count_posts', 'fix_count_orders' );
    }
}

add_action( 'pre_get_posts', 'query_set_only_author', 10, 2 );

2

가장 좋은 방법

이 모든 답변에는 보안 문제가 있습니다.

가장 좋은 방법은 사용자 지정 기능을 추가하고 기능별로 게시물 등을 관리하는 것입니다.


쉬운 방법

Artem의 솔루션은 WP가 게시물 편집 화면에서만뿐만 아니라 대시 보드 위젯, Ajax 응답 등에서도 게시물 수를 참조하기 때문에 더 나은 것 같습니다.

Artem의 솔루션을 기반으로 한 더 나은 솔루션.

  1. 기본 게시물 수 캐시를 지우십시오.
    이유 : wp_count_posts이전에 결과가 캐시 된 경우 캐시 된 게시물 수를 이전에 반환합니다.
  2. 맞춤 게시물 수의 결과를 캐시합니다.
    이유 : 캐시가 성능을 향상시킵니다.
  3. 후크 의 세 번째 $perm매개 변수를 존중하십시오 wp_count_posts.
    이유 : 게시물 수에는 readableperm을 기반으로하는 사용자 자신의 개인 게시물이 포함되어야합니다 .
  4. 필터를 우선 순위가 높은 필터로 적용하십시오.
    이유 : 필터가 다른 필터로 대체 될 수 있습니다.
  5. 고정 게시물 수를 제거 (또는 수정)합니다.
    이유 : 고정 게시물 수에는 다른 게시물이 포함되며으로 구분됩니다 WP_Posts_List_Table.
  6. 맞춤 게시물 유형에 적절한 기능을 사용하는
    이유 : read_others_posts기능을 수정할 수 있습니다.

추가 조정이 필요할 수 있습니다.

  • post_authorquery var를 로 설정하여 다른 게시물의 댓글 필터링WP_Comment_Query .
  • 주석은 wp_count_comments훅으로 계산합니다 .
  • 관리 화면에 대한 액세스를 제한해야합니다.

다음은 wp_post_counts()WP 4.8을 기반으로하는 수정 된 버전입니다 .

function clear_cache() {
    // deletes the default cache for normal Post. (1)
    $cache_key = _count_posts_cache_key( 'post' , 'readable' );

    wp_cache_delete( $cache_key, 'counts' );
}

add_action( 'admin_init', 'clear_cache' );    // you might use other hooks.

function fix_count_orders( $counts, $type, $perm ) {
    global $wpdb;

    if ( ! post_type_exists( $type ) ) {
        return new stdClass();
    }

    $query = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = %s";

    $post_type_object = get_post_type_object( $type );

    // adds condition to respect `$perm`. (3)
    if ( $perm === 'readable' && is_user_logged_in() ) {
        if ( ! current_user_can( $post_type_object->cap->read_private_posts ) ) {
            $query .= $wpdb->prepare(
                " AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))",
                get_current_user_id()
            );
        }
    }

    // limits only author's own posts. (6)
    if ( is_admin() && ! current_user_can ( $post_type_object->cap->edit_others_posts ) ) {
        $query .= $wpdb->prepare( ' AND post_author = %d', get_current_user_id() );
    }

    $query .= ' GROUP BY post_status';

    $results = (array) $wpdb->get_results( $wpdb->prepare( $query, $type ), ARRAY_A );
    $counts  = array_fill_keys( get_post_stati(), 0 );

    foreach ( $results as $row ) {
        $counts[ $row['post_status'] ] = $row['num_posts'];
    }

    $counts    = (object) $counts;
    $cache_key = _count_posts_cache_key( $type, 'readable' );

    // caches the result. (2)
    // although this is not so efficient because the cache is almost always deleted.
    wp_cache_set( $cache_key, $counts, 'counts' );

    return $counts;
}

function query_set_only_author( $wp_query ) {
    if ( ! is_admin() ) {
        return;
    }

    $allowed_types = [ 'post' ];
    $current_type  = get_query_var( 'post_type', 'post' );

    if ( in_array( $current_type, $allowed_types, true ) ) {
        $post_type_object = get_post_type_object( $type );

        if (! current_user_can( $post_type_object->cap->edit_others_posts ) ) {    // (6)
            $wp_query->set( 'author', get_current_user_id() );

            add_filter( 'wp_count_posts', 'fix_count_orders', PHP_INT_MAX, 3 );    // (4)
        }
    }
}

add_action( 'pre_get_posts', 'query_set_only_author', PHP_INT_MAX );    // (4)

function fix_views( $views ) {
    // For normal Post.
    // USE PROPER CAPABILITY IF YOU WANT TO RISTRICT THE READABILITY FOR CUSTOM POST TYPE (6).
    if ( current_user_can( 'edit_others_posts' ) ) {
        return;
    }

    unset( $views[ 'sticky' ] );

    return $views;
}

add_filter( 'views_edit-post', 'fix_views', PHP_INT_MAX );     // (5)

알려진 문제 : 사용자에게 속하지 않는 고정 게시물이 계산됩니다. 스티커 포스트보기를 제거하여 수정했습니다.


고마워, 이것은 내가 사용하고있는 일에 완벽했습니다. 모든 '게시물'을 사용자 정의 기능 이름으로 변경했습니다.
Shawn Rebelo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.