Ограничение доступа пользователей к просмотру только загруженных ими элементов медиатеки?
Я хочу, чтобы пользователи могли загружать фотографии с помощью 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);
9 answers
Вы всегда можете отфильтровать список носителей с помощью фильтра 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;
}
Я использовал шапку "Удалить страницы" в качестве условия, чтобы администраторы и редакторы по-прежнему видели полный список носителей.
Есть один небольшой побочный эффект, для которого я не вижу никаких зацепок, и это связано с количеством вложений, показанным над списком носителей (который все равно будет показывать общее количество медиаэлементов, а не данного пользователя - я бы счел это незначительной проблемой).
Подумал, что я все равно опубликую это, может быть полезно..;)
Начиная с 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;
}
Вот полное решение как для сообщений, так и для средств массовой информации (этот код предназначен специально для авторов, но вы можете изменить его для любой роли пользователя). Это также исправляет количество сообщений/носителей без взлома основных файлов.
// 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;
}
Это модифицированная версия принятого ответа . Поскольку принятый ответ нацелен только на пункт меню Мультимедиа слева, пользователи все равно могут видеть всю медиатеку в модальном окне при загрузке фотографии в публикацию. Этот слегка измененный код исправляет эту ситуацию. Целевые пользователи будут видеть только свои собственные медиа-элементы на вкладке Медиа-библиотека модального окна, которое появляется в публикации.
Это код из принятого ответа с комментарием пометка строки для редактирования...
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' ) ) )
( разрывы строк и интервалы вставляются только для удобства чтения здесь)
Примечания: как и в принятом ответе, счетчики сообщений и средств массовой информации будут неверными. Однако для этого есть решения в некоторых других ответах на этой странице. Я не включил их просто потому, что не проверял их.
Полный рабочий код.. Единственная проблема заключается в неправильном подсчете изображений в медиатеке на странице Добавления публикации.
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' );
У 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) Я установил плагин 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 % людей даже не будут знать об этом, но это все еще не оптимально. Во-вторых, это также перенаправьте администратора на страницу профиля после загрузки. Это можно довольно просто исправить, проверив роли пользователей и перенаправив только подписчиков.
Если у кого-нибудь есть идеи о том, как подключиться к медиа-странице, не заходя в основные файлы, я был бы признателен. Спасибо!
<?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 и активируйте, вот и все.
Один из способов сделать это - использовать плагин для определения области действия ролей , он также отлично подходит для управления очень специфическими ролями и возможностями. На самом деле вы можете заблокировать доступ к изображениям в медиатеке только для тех, которые загружены каждым пользователем. Я использовал его для проекта, над которым сейчас работаю, и он хорошо работает.