Обмежувати користувачів переглядати лише завантажені ними файли медіатеки?


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

1
Якщо ви знайшли відповідь на власну проблему, краще додайте її як відповідь нижче, а не в самому питанні. Це краще узгоджується із системою, і ми можемо підкреслити вашу відповідь, що покращить вашу репутацію на цьому веб-сайті.
Ян Фабрі


Мені дійсно доводиться друкувати плагін "Переглянути власні повідомлення лише для медіа", він прекрасно працював для мене після пошуку скрізь рішення jquery або php / html / css.
waffl

Відповіді:


37

Ви завжди можете відфільтрувати список медіа- 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;
}

Я використовував обмеження для видалення сторінок як умову, щоб адміністратори та редактори все ще бачили повний список медіа.

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

Думав, я все-таки опублікую це, може бути корисним ..;)


Я дозволив завантажувати файли для користувачів, які підписалися на рівень. намагався використовувати ваш код, але не працює.
Сісір

1
"Не працює" - це не так вже й тривати.
t31о

Я можу підтвердити те саме спостереження. Для мене "не працює" означає, що роль "дописувача" все ще може бачити всі медіа-елементи, коли він йде завантажувати jpg. Однак, коли він переходить до медіатеки з меню, він порожній. (У моєї ролі "учасник" вже є додаткова можливість завантажувати файли, і це працює. )
Sparky

Таким чином, ваш код просто потрібно змінити для будь-якої сторінки, яка заповнює вкладку "Медіатека" у вікні завантаження. Я зараз це досліджую.
Спаркі

Якщо я пригадую правильно (і помилки трапляються), на момент написання цієї відповіді не було відповідних гачків, подібно до того, як не було гачок, щоб виправити кількість медіа. Однак з часу написання було 3 нових версії WordPress, тому рішення можуть бути можливі.
t31о

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 буде масивом, нульовим дано
chrismccoy

Вам просто потрібно визначити $ _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');

Це працює для мене!


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% людей навіть не дізнаються про це, але це все ще не оптимально. По-друге, він також перенаправляє адміністратора на сторінку профілю після завантаження. Вони можуть мати досить просте виправлення, перевіряючи ролі користувачів та лише перенаправляючи передплатників.

Якщо хтось має ідеї про приєднання до сторінки "Медіа", не заглиблюючись у основні файли, я вдячний. Дякую!


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

Збережіть код вище як management_your_media_only.php, застебніть його, завантажте як плагін на свою WP і активуйте його, ось і все.


1

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.