Скрыть сообщения других пользователей в админ-панели

9

Я намеревался запустить сайт с несколькими авторами, я не хочу, чтобы посты других авторов отображались на /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 ()

Как изменить номер в, ()чтобы отразить номер, связанный только с автором?

DEV-джим
источник
Я просто размышляю вслух, потому что я собираюсь сделать то же самое. Мой сайт - это бейсбольный сайт с 10 авторами. Я продолжаю идти вперед и назад, скрывать ли черновики других авторов от текущего авторизованного автора. С одной стороны, я думаю, что им не нужно знать статьи других авторов, пока они не опубликуют. С другой стороны, я не хочу, чтобы 2 автора публиковали 2 практически идентичные статьи одновременно.
Трэвис Пфланц
Наконец я нашел решение для моей проблемы ... 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;
}

Источник

Bainternet
источник
1
Я задаю эти два вопроса как новичок WordPress: (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

Лучший путь

ВСЕ ЭТИ ОТВЕТЫ ЗДЕСЬ ИМЕЮТ БЕЗОПАСНОСТЬ.

Лучший способ - добавить пользовательские возможности, управлять сообщениями и т. Д. С помощью этих возможностей.


Легкий способ

Решение Артема кажется лучше, потому что WP не учитывает количество сообщений только на экране редактирования сообщения, но также в виджете Dashboard, ответе Ajax и т. Д.

Для лучшего решения, основанного на Артеме.

  1. очистить кеш подсчета сообщений по умолчанию.
    почему: wp_count_postsраньше возвращает количество записей в кэше, когда результат был ранее кэширован.
  2. кэшировать результат пользовательских подсчетов сообщений.
    почему: кеш увеличивает производительность.
  3. соблюдайте 3-й $permпараметр wp_count_postsхука.
    почему: в число сообщений должны входить личные сообщения пользователя на основе readableразрешений.
  4. применять фильтры в качестве фильтров высокого приоритета.
    почему: фильтры могут быть переопределены другими фильтрами.
  5. удалить (или изменить) количество липких сообщений.
    почему: количество прикрепленных постов включает посты других, и они подсчитываются отдельно WP_Posts_List_Table.
  6. используйте правильную возможность для Custom Post Type,
    почему: read_others_postsвозможность может быть изменена.

Возможно, вы захотите дополнительные настройки

  • Отфильтруйте комментарии других сообщений, установив post_authorзапрос 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)

Известная проблема: липкие сообщения, которые не принадлежат пользователю, учитываются. исправлено удаление липких сообщений.

Whizark
источник
Спасибо, это было прекрасно для того, что я использую и делаю. Просто изменил все «посты» на мои собственные названия возможностей.
Шон Ребело