Ограничение просмотра медиа-библиотеки только загруженными пользователем файлами

7 сент. 2010 г., 20:51:44
Просмотры: 41.8K
Голосов: 49

Я хочу, чтобы пользователи могли загружать фотографии используя 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);
3
Комментарии

Если вы нашли решение своей проблемы, лучше добавить его как ответ ниже, а не в сам вопрос. Это лучше соответствует системе, и мы сможем проголосовать за ваш ответ, что повысит вашу репутацию на этом сайте.

Jan Fabry Jan Fabry
9 сент. 2010 г. 21:18:47

http://wordpress.org/plugins/view-own-posts-media-only/

Ramji Ramji
26 июл. 2013 г. 00:26:50

Я действительно должен поддержать рекомендацию плагина 'View Own Posts Media Only' - он идеально сработал для меня после долгих поисков решения на jquery или php/html/css.

waffl waffl
4 мар. 2014 г. 15:56:38
Все ответы на вопрос 9
11
46

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

Пример

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

Я использовал проверку возможности удаления страниц (delete_pages) в качестве условия, чтобы Администраторы и Редакторы по-прежнему видели полный список медиафайлов.

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

Решил опубликовать на всякий случай, может быть полезно.. ;)

20 нояб. 2010 г. 15:11:40
Комментарии

Я разрешил загрузку файлов для пользователей с уровнем подписчика. Пытался использовать ваш код, но он не работает.

Sisir Sisir
6 мая 2012 г. 20:52:08

"Не работает" — это слишком мало информации для анализа.

t31os t31os
9 авг. 2013 г. 01:03:13

Я могу подтвердить аналогичное наблюдение. В моем случае "не работает" означает, что пользователь с ролью "автор" всё ещё может видеть все элементы медиафайлов при загрузке jpg. Однако, когда он переходит в медиатеку из меню, она пуста. (Моя роль "автора" уже имеет дополнительную возможность загружать файлы, и это работает.)

Sparky Sparky
3 февр. 2014 г. 21:27:25

Таким образом, ваш код просто нужно адаптировать для страницы, которая отображается во вкладке "Медиабиблиотека" окна загрузки. Сейчас я изучаю этот вопрос.

Sparky Sparky
3 февр. 2014 г. 21:30:25

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

t31os t31os
3 февр. 2014 г. 21:33:47

Кроме того, возможно, просто нужно обновить условную проверку $pagenow, так как она предназначена для целевого запроса именно главной страницы медиабиблиотеки, которая не совпадает с вкладкой медиа во всплывающем окне загрузки.

t31os t31os
3 февр. 2014 г. 21:35:01

Меня не волнует, что счетчики отображаются неверно. В остальном ваш код работает из пункта меню "Медиафайлы" (WP v3.8.1). Я пытаюсь заставить это работать из окна загрузки, которое появляется при создании новой записи ("New Post"). Да, я согласен... Я пытаюсь найти правильную страницу для проверки $pagenow.

Sparky Sparky
3 февр. 2014 г. 21:45:46

Вот решение: http://wordpress.stackexchange.com/a/132319/11092

Sparky Sparky
4 февр. 2014 г. 00:03:38

if( !in_array( $pagenow, array( 'upload.php', 'admin-ajax.php' ) В этой строке вашего кода отсутствует закрывающая скобка ). Должно быть три ), но в вашем коде только две.

Ibrahim Ibrahim
10 дек. 2016 г. 08:52:15

Это, кажется, относится только к виду сетки. Есть рекомендации, как реализовать это и для списка?

Dedering Dedering
8 нояб. 2017 г. 22:17:31

Решение моего вопроса выше: if( ('upload.php' != $pagenow ) && ( 'admin-ajax.php' != $pagenow || $_REQUEST['action'] != 'query-attachments' ) )

Dedering Dedering
9 нояб. 2017 г. 00:01:36
Показать остальные 6 комментариев
0
39

Начиная с версии 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;
}
21 февр. 2015 г. 02:46:42
4
19

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

// Показывать только записи и медиафайлы текущего автора
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');
    }
}

// Исправление счетчиков записей
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,
            __('Все')
        );
        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,
            __('Опубликовано')
        );
        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,
            __('Черновики')
        );
        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,
            __('На рассмотрении')
        );
        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,
            __('Корзина')
        );
        endif;
    }
    return $views;
}

// Исправление счетчиков медиафайлов
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( __('Все <span class="count">(%s)</span>', 'загруженные файлы'), 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( __( 'Неприкрепленные <span class="count">(%s)</span>', 'отсоединенные файлы'), $total_orphans ) . '</a>';
    return $views;
}
27 нояб. 2011 г. 22:00:09
Комментарии

отличный сниппет, но если в медиатеке нет элементов, он выдает ошибки: Warning: array_sum() expects parameter 1 to be array, null given и Warning: array_keys() expects parameter 1 to be array, null given

chrismccoy chrismccoy
25 февр. 2012 г. 02:40:55

Вам просто нужно определить $_num_posts как массив в функции fix_media_counts(). $_num_posts = array();

Paul Paul
9 сент. 2012 г. 02:37:33

Код в этом ответе работает, но он также удаляет любые пользовательские поля, созданные плагином Advanced Custom Fields.

Sparky Sparky
3 февр. 2014 г. 22:26:02
0

Это модифицированная версия принятого ответа. Поскольку в принятом ответе ограничение касается только пункта меню "Медиа" в боковой панели, пользователи всё равно могли видеть всю медиатеку в модальном окне при загрузке изображения к записи. Данная модификация кода исправляет эту ситуацию. Теперь целевые пользователи будут видеть только свои собственные медиафайлы во вкладке "Медиатека" модального окна, которое появляется при загрузке медиа в записи.

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

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 ) // <-- работаем с этой строкой
        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' ) ) )

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

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

4 февр. 2014 г. 00:03:00
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' );
26 нояб. 2011 г. 20:46:32
Комментарии

Не следует использовать уровни пользователей, они в WordPress до сих пор присутствуют в основном для обратной совместимости (до версии WP 2.0) и не являются надежным способом определения возможностей пользователей в современном WordPress (так как они, вероятно, исчезнут из ядра, когда эта совместимость больше не потребуется). Используйте конкретные возможности (capabilities) для определения прав пользователей.

t31os t31os
28 янв. 2014 г. 15:56:29

Несмотря на наличие media-upload.php, ваш код не работает в модальном окне загрузки, создаваемом на странице редактирования записи. Все элементы медиатеки по-прежнему видны.

Sparky Sparky
3 февр. 2014 г. 21:58:34
0

У пользователя 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');

Это работает у меня!

14 апр. 2012 г. 01:18:26
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% людей даже не будут знать об этом, но это все равно не оптимально. Во-вторых, это также перенаправляет Администратора на страницу профиля после загрузки. Это можно исправить довольно просто, проверяя роли пользователей и перенаправляя только Подписчиков.

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

10 сент. 2010 г. 17:56:23
Комментарии

Существует хук admin_init, который выполняется при каждом запросе в админке. Если пользователь запрашивает upload.php и вы хотите это предотвратить, вы можете либо заблокировать этот запрос (например, wp_die('Доступ запрещен')), либо перенаправить на допустимую страницу через хук.

hakre hakre
11 сент. 2010 г. 03:49:09
0
<?php
/*
Plugin Name: Только ваши медиафайлы
Version: 0.1
*/

// Плагин "Только ваши медиафайлы"
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, запакуйте в zip, загрузите как плагин в WordPress и активируйте его — это всё.

8 дек. 2010 г. 13:29:52
0

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

11 янв. 2011 г. 13:01:20