Запретить пользователям просматривать только те элементы медиатеки, которые они загрузили?

46

Я хочу, чтобы пользователи могли загружать фотографии с помощью, add_cap('upload_files')но на странице своего профиля в библиотеке мультимедиа отображаются все загруженные изображения. Как я могу отфильтровать это так, чтобы они могли только просматривать загруженные ими изображения ?

Вот мое решение на данный момент ... Я делаю простой запрос WP, а затем цикл на странице "Профиль" пользователя

$querystr = " SELECT wposts.post_date,wposts.post_content,wposts.post_title, guid 
FROM $wpdb->posts wposts
WHERE wposts.post_author = $author 
AND wposts.post_type = 'attachment' 
ORDER BY wposts.post_date DESC";

$pageposts = $wpdb->get_results($querystr, OBJECT);
TerryMatula
источник
1
Если вы нашли ответ на свой вопрос, лучше добавить его в качестве ответа ниже, а не в самом вопросе. Это лучше в соответствии с системой, и мы можем проголосовать за ваш голос, что улучшит вашу репутацию на этом сайте.
Ян Фабри
Мне действительно нужен второй плагин «View Own Posts Media Only», он отлично сработал, когда я везде искал решение для jquery или php / html / css.
вафля

Ответы:

37

Вы всегда можете отфильтровать список мультимедиа, используя pre_get_postsфильтр, который сначала определяет страницу и возможности пользователя, и устанавливает параметр author, когда выполняются определенные условия.

пример

add_action('pre_get_posts','users_own_attachments');
function users_own_attachments( $wp_query_obj ) {

    global $current_user, $pagenow;

    $is_attachment_request = ($wp_query_obj->get('post_type')=='attachment');

    if( !$is_attachment_request )
        return;

    if( !is_a( $current_user, 'WP_User') )
        return;

    if( !in_array( $pagenow, array( 'upload.php', 'admin-ajax.php' ) ) )
        return;

    if( !current_user_can('delete_pages') )
        $wp_query_obj->set('author', $current_user->ID );

    return;
}

Я использовал ограничение удаления страниц в качестве условия, чтобы администраторы и редакторы по-прежнему видели полный список СМИ.

Есть один небольшой побочный эффект, для которого я не вижу никаких хуков, и это с количеством вложений, показанным над списком мультимедиа (которое по-прежнему будет показывать общее количество элементов мультимедиа, а не данного пользователя - я бы считают это незначительной проблемой, хотя).

Думаю, я все равно выложу, может быть полезно ..;)

t31os
источник
Я разрешил загрузку файлов пользователям уровня подписчика. пытался использовать ваш код, но не работает.
Сисир
1
«Не работает» не так уж и много.
t31os
Я могу подтвердить то же самое наблюдение. Для меня «не работает» означает, что роль «участника» все еще может видеть все элементы мультимедиа, когда он собирается загрузить JPG. Однако, когда он заходит в медиатеку из меню, она пуста. ( Моя роль «автора» уже имеет дополнительную возможность загружать файлы, и это работает. )
Sparky
Таким образом, ваш код просто необходимо настроить для любой страницы, заполняющей вкладку «Медиатека» окна загрузки. Я исследую это сейчас.
Sparky
Если я правильно помню (и ошибки все-таки случаются), на момент написания этого ответа не было никаких подходящих зацепок, подобно тому, как не было зацепок для определения количества носителей. Тем не менее, с момента написания этой статьи было выпущено 3 хороших версии WordPress, поэтому решения могут быть возможны.
t31os
32

Начиная с WP 3.7, через ajax_query_attachments_argsфильтр существует гораздо лучший способ , как указано в документации :

add_filter( 'ajax_query_attachments_args', 'show_current_user_attachments' );

function show_current_user_attachments( $query ) {
    $user_id = get_current_user_id();
    if ( $user_id ) {
        $query['author'] = $user_id;
    }
    return $query;
}
Дэвид
источник
19

Вот полное решение для постов и медиа (этот код специально для авторов, но вы можете изменить его для любой роли пользователя). Это также исправляет количество записей / медиа без взлома основных файлов.

// 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="%1$s"%2$s>%4$s <span class="count">(%3$d)</span></a>',
            admin_url('edit.php?post_type=post'),
            $class,
            $result->found_posts,
            __('All')
        );
        elseif( $type['status'] == 'publish' ):
            $class = ($wp_query->query_vars['post_status'] == 'publish') ? ' class="current"' : '';
            $views['publish'] = sprintf(
            '<a href="%1$s"%2$s>%4$s <span class="count">(%3$d)</span></a>',
            admin_url('edit.php?post_type=post'),
            $class,
            $result->found_posts,
            __('Publish')
        );
        elseif( $type['status'] == 'draft' ):
            $class = ($wp_query->query_vars['post_status'] == 'draft') ? ' class="current"' : '';
            $views['draft'] = sprintf(
            '<a href="%1$s"%2$s>%4$s <span class="count">(%3$d)</span></a>',
            admin_url('edit.php?post_type=post'),
            $class,
            $result->found_posts,
            __('Draft')
        );
        elseif( $type['status'] == 'pending' ):
            $class = ($wp_query->query_vars['post_status'] == 'pending') ? ' class="current"' : '';
            $views['pending'] = sprintf(
            '<a href="%1$s"%2$s>%4$s <span class="count">(%3$d)</span></a>',
            admin_url('edit.php?post_type=post'),
            $class,
            $result->found_posts,
            __('Pending')
        );
        elseif( $type['status'] == 'trash' ):
            $class = ($wp_query->query_vars['post_status'] == 'trash') ? ' class="current"' : '';
            $views['trash'] = sprintf(
            '<a href="%1$s"%2$s>%4$s <span class="count">(%3$d)</span></a>',
            admin_url('edit.php?post_type=post'),
            $class,
            $result->found_posts,
            __('Trash')
        );
        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;
}
Павел
источник
отличный фрагмент, но если в библиотеке мультимедиа нет ни одного элемента, он выдает ошибки, Предупреждение: array_sum () ожидает, что параметр 1 будет массивом, задан ноль, и Предупреждение: array_keys () ожидает, что параметр 1 будет массивом, задан
ноль
Вам просто нужно определить $ _num_posts как массив в функции fix_media_counts (). $_num_posts = array();
Пол
4
Код в этом ответе работает, но он также удаляет все пользовательские поля, созданные плагином Advanced Custom Fields.
Sparky
1
Многое связано: wordpress.stackexchange.com/questions/178236/…
cregox
5

Это модифицированная версия принятого ответа . Поскольку принятый ответ относится только к элементу меню «Медиа» слева, пользователи все равно могут видеть всю медиатеку внутри модального поля при загрузке фотографии в публикацию. Этот слегка измененный код исправляет эту ситуацию. Целевые пользователи будут видеть только свои собственные элементы мультимедиа на вкладке «Библиотека мультимедиа» модального поля, которое появляется в сообщении.

Это код из принятого ответа с комментарием, отмечающий строку для редактирования ...

add_action('pre_get_posts','users_own_attachments');
function users_own_attachments( $wp_query_obj ) {

    global $current_user, $pagenow;

    if( !is_a( $current_user, 'WP_User') )
        return;

    if( 'upload.php' != $pagenow ) // <-- let's work on this line
        return;

    if( !current_user_can('delete_pages') )
        $wp_query_obj->set('author', $current_user->id );

    return;
}

Чтобы пользователи могли просматривать только свои собственные медиафайлы из меню «Медиа» И вкладки «Медиатека» модального окна загрузки, замените указанную строку этой ...

if( (   'upload.php' != $pagenow ) &&
    ( ( 'admin-ajax.php' != $pagenow ) || ( $_REQUEST['action'] != 'query-attachments' ) ) )

( разрывы строк и интервалы вставляются только для удобства чтения здесь )

Ниже приведено то же, что и выше, но оно также ограничивает просмотр их собственных сообщений из пункта меню «Сообщения».

if( (   'edit.php' != $pagenow ) &&
    (   'upload.php' != $pagenow ) &&
    ( ( 'admin-ajax.php' != $pagenow ) || ( $_REQUEST['action'] != 'query-attachments' ) ) )

( разрывы строк и интервалы вставляются только для удобства чтения здесь )

Примечания : как и в принятом ответе, сообщения и счетчики будут неверными. Однако, есть решения для этого в некоторых других ответах на этой странице. Я не включил их просто потому, что не проверял их.

Спарки
источник
2

Полный рабочий код. Единственная проблема заключается в неправильном подсчете изображений в библиотеке мультимедиа на странице добавления поста.

function my_files_only( $wp_query ) {
if ( strpos( $_SERVER[ 'REQUEST_URI' ], '/wp-admin/upload.php' ) !== false ) {
    if ( !current_user_can( 'level_5' ) ) {
        global $current_user;
        $wp_query->set( 'author', $current_user->id );
    }
}
else if ( strpos( $_SERVER[ 'REQUEST_URI' ], '/wp-admin/media-upload.php' ) !== false ) {
    if ( !current_user_can( 'level_5' ) ) {
        global $current_user;
        $wp_query->set( 'author', $current_user->id );
    }
}
}
add_filter('parse_query', 'my_files_only' );
Нитин
источник
2
Вы не должны использовать пользовательские уровни, они в WordPress по-прежнему в основном для обратной совместимости (до WP 2.0), они не надежны для определения пользовательских возможностей в современном WordPress (так как они, вероятно, исчезнут из ядра, когда эта совместимость больше не требуется). ). Используйте фактическую возможность определения прав пользователя.
t31os
Несмотря на содержание media-upload.php, ваш код не работает из модальности загрузки, созданной на странице редактирования сообщения. Можно еще увидеть все элементы библиотеки.
Sparky
2

У t31os есть отличное решение. Единственное, что количество всех постов по-прежнему отображается.

Я нашел способ, как предотвратить подсчет числа с помощью jQuery.

Просто добавьте это в свой функциональный файл.

    function jquery_remove_counts()
{
    ?>
    <script type="text/javascript">
    jQuery(function(){
        jQuery("ul.subsubsub").find("span.count").remove();
    });
    </script>
    <?php
}
add_action('admin_head', 'jquery_remove_counts');

Это работает для меня!

user15182
источник
1

Я решил свою проблему с помощью довольно грубого, но работоспособного решения.

1) Я установил плагин WP Hide Dashboard, чтобы пользователь мог видеть только ссылку на форму редактирования своего профиля.

2) В файл шаблона author.php я вставил код, который использовал выше.

3) Затем для зарегистрированных пользователей я отобразил прямую ссылку на страницу загрузки «wp-admin / media-new.php».

4) Следующая проблема, которую я заметил, заключалась в том, что после того, как они загрузили фотографию, она перенаправила бы их на upload.php ... и они могли видеть все остальные фотографии. Я не нашел хука на странице media-new.php, поэтому в итоге я взломал ядро ​​«media-upload.php» и перенаправил их на страницу своего профиля:

    global $current_user;
    get_currentuserinfo();
    $userredirect =  get_bloginfo('home') . "/author/" .$current_user->user_nicename;

Затем заменить wp_redirect( admin_url($location) );наwp_redirect($userredirect);

Пара вопросов, хотя. Во-первых, вошедший в систему пользователь все еще может перейти к «upload.php», если он знает, что он существует. Они ничего не могут сделать, кроме как СМОТРЕТЬ на файлы, и 99% людей даже не узнают об этом, но это все еще не оптимально. Во-вторых, он также перенаправляет администратора на страницу профиля после загрузки. Это может быть довольно просто исправить, проверяя роли пользователей и перенаправляя только подписчиков.

Если у кого-то есть идеи о подключении к странице «Медиа», не вдаваясь в основные файлы, я был бы признателен за это. Спасибо!

TerryMatula
источник
2
Есть admin_initловушка, которая запускается на каждый запрос администратора. В случае, если пользователь запрашивает upload.php, и вы хотите предотвратить, вы можете либо заблокировать этот запрос (например wp_die('Access Denied')), либо перенаправить в какое-то действительное место на ловушку.
Хакре
1
<?php
/*
Plugin Name: Manage Your Media Only
Version: 0.1
*/

//Manage Your Media Only
function mymo_parse_query_useronly( $wp_query ) {
    if ( strpos( $_SERVER[ 'REQUEST_URI' ], '/wp-admin/upload.php' ) !== false ) {
        if ( !current_user_can( 'level_5' ) ) {
            global $current_user;
            $wp_query->set( 'author', $current_user->id );
        }
    }
}

add_filter('parse_query', 'mymo_parse_query_useronly' );
?>

Сохраните приведенный выше код как manage_your_media_only.php, заархивируйте его, загрузите как плагин на свой WP и активируйте, вот и все.


источник
1

Один из способов сделать это - использовать плагин Role Scoper , он также отлично подходит для управления очень специфическими ролями и возможностями. Вы можете заблокировать доступ к изображениям в библиотеке мультимедиа только для тех, которые загружены каждым пользователем. Я использовал его для проекта, над которым я сейчас работаю, и он работает хорошо.

Рик Керран
источник