¿Cómo restringir a los usuarios para que solo vean los elementos de la biblioteca de medios que han subido?

7 sept 2010, 20:51:44
Vistas: 41.8K
Votos: 49

Quiero que los usuarios puedan subir fotos usando add_cap('upload_files') pero en su página de perfil, la Biblioteca de Medios muestra todas las imágenes que se han subido. ¿Cómo puedo filtrar esto para que solo puedan ver las imágenes que ellos subieron?

Aquí está mi solución por el momento... Estoy haciendo una consulta simple de WP, luego un bucle en la página de "Perfil" del usuario

$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
Comentarios

Si encontraste una solución a tu propio problema, es mejor que la agregues como una respuesta a continuación, no en la pregunta misma. Esto se ajusta mejor al sistema y podemos votar positivamente tu respuesta, lo que mejorará tu reputación en este sitio.

Jan Fabry Jan Fabry
9 sept 2010 21:18:47

Realmente tengo que apoyar el plugin 'View Own Posts Media Only', funcionó perfectamente para mí después de buscar en todas partes una solución con jquery o php/html/css.

waffl waffl
4 mar 2014 15:56:38
Todas las respuestas a la pregunta 9
11
46

Siempre podrías filtrar la lista de medios usando un filtro pre_get_posts que primero determine la página y las capacidades del usuario, y establezca el parámetro de autor cuando se cumplan ciertas condiciones.

Ejemplo

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

Utilicé la capacidad de eliminar páginas como condición para que los Administradores y Editores sigan viendo la lista completa de medios.

Hay un pequeño efecto secundario, para el cual no veo ningún hook disponible, y es con los conteos de adjuntos que se muestran encima de la lista de medios (que seguirán mostrando el conteo total de elementos multimedia, no el del usuario dado - consideraría esto un problema menor).

Pensé en publicarlo de todos modos, podría ser útil... ;)

20 nov 2010 15:11:40
Comentarios

He permitido la carga de archivos a usuarios con nivel de suscriptor. Intenté usar tu código pero no funciona.

Sisir Sisir
6 may 2012 20:52:08

"No funciona" no es mucha información para trabajar.

t31os t31os
9 ago 2013 01:03:13

Puedo confirmar la misma observación. Para mí "no funciona" significa que el rol de "colaborador" todavía puede ver todos los elementos multimedia cuando va a subir un jpg. Sin embargo, cuando va a la biblioteca multimedia desde el menú, está vacía. (Mi rol de "colaborador" ya tiene la capacidad adicional para subir archivos y eso sí funciona.)

Sparky Sparky
3 feb 2014 21:27:25

Así que tu código solo necesita ajustarse para cualquier página que llene la pestaña "Biblioteca de medios" de la ventana de carga. Estoy investigando esto ahora.

Sparky Sparky
3 feb 2014 21:30:25

Si recuerdo correctamente (y los errores ocurren), no había ningún hook apropiado en su momento cuando escribí esta respuesta, similar a cómo no había hooks disponibles para arreglar el conteo de medios. Han habido unas 3 nuevas versiones de WordPress desde entonces, así que ahora podrían existir soluciones.

t31os t31os
3 feb 2014 21:33:47

Adicionalmente, podría ser solo cuestión de actualizar la verificación condicional $pagenow, ya que esto apunta a dirigir la consulta específicamente para la página principal de medios, que no es lo mismo que la pestaña de medios en la ventana emergente de carga.

t31os t31os
3 feb 2014 21:35:01

No me importa que los conteos estén incorrectos. Por lo demás, tu código funciona desde el elemento Medios en el menú (WP v3.8.1). Estoy intentando que esto funcione desde la ventana de carga que aparece dentro de la página "Nueva Entrada". Sí, estoy de acuerdo... Estoy tratando de encontrar la página correcta para la verificación de $pagenow.

Sparky Sparky
3 feb 2014 21:45:46

Aquí está la solución: http://wordpress.stackexchange.com/a/132319/11092

Sparky Sparky
4 feb 2014 00:03:38

if( !in_array( $pagenow, array( 'upload.php', 'admin-ajax.php' ) A esta línea en tu código le falta un corchete de cierre ), Debería haber tres ), pero tu código solo tiene dos.

Ibrahim Ibrahim
10 dic 2016 08:52:15

Esto parece aplicarse solo a la vista de cuadrícula. ¿Alguna recomendación sobre cómo lograr esto también para la vista de lista?

Dedering Dedering
8 nov 2017 22:17:31

Solución a mi pregunta anterior: if( ('upload.php' != $pagenow ) && ( 'admin-ajax.php' != $pagenow || $_REQUEST['action'] != 'query-attachments' ) )

Dedering Dedering
9 nov 2017 00:01:36
Mostrar los 6 comentarios restantes
0
39

A partir de WP 3.7 existe una forma mucho mejor mediante el filtro ajax_query_attachments_args, como se proporciona en la documentación:

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 feb 2015 02:46:42
4
19

Aquí tienes una solución completa para tanto publicaciones como medios (este código está específicamente para autores, pero puedes modificarlo para cualquier rol de usuario). Esto también corrige el conteo de publicaciones/medios sin necesidad de modificar archivos del núcleo.

// Mostrar solo publicaciones y medios relacionados con el autor conectado
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');
    }
}

// Corregir conteos de publicaciones
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,
            __('Todos')
        );
        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,
            __('Publicado')
        );
        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,
            __('Borrador')
        );
        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,
            __('Pendiente')
        );
        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,
            __('Papelera')
        );
        endif;
    }
    return $views;
}

// Corregir conteos de medios
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( __('Todos <span class="count">(%s)</span>', 'archivos subidos'), 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( __( 'Sin adjuntar <span class="count">(%s)</span>', 'archivos no adjuntos' ), $total_orphans ) . '</a>';
    return $views;
}
27 nov 2011 22:00:09
Comentarios

gran fragmento de código, pero si no hay elementos en la biblioteca de medios, muestra errores: Warning: array_sum() expects parameter 1 to be array, null given, y Warning: array_keys() expects parameter 1 to be array, null given

chrismccoy chrismccoy
25 feb 2012 02:40:55

Solo tienes que definir $_num_posts como un array en la función fix_media_counts(). $_num_posts = array();

Paul Paul
9 sept 2012 02:37:33

El código en esta respuesta funciona, pero también elimina cualquier campo personalizado creado por el plugin Advanced Custom Fields.

Sparky Sparky
3 feb 2014 22:26:02
0

Esta es una versión modificada de la respuesta aceptada. Dado que la respuesta aceptada solo afecta al elemento del menú Medios en la izquierda, los usuarios aún podían ver toda la biblioteca de medios dentro del cuadro modal al subir una foto a una entrada. Este código ligeramente modificado corrige esa situación. Los usuarios afectados solo verán sus propios elementos de medios desde la pestaña Biblioteca de Medios del cuadro modal que aparece al subir contenido en una entrada.

Este es el código de la respuesta aceptada con un comentario marcando la línea a editar...

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 ) // <-- vamos a trabajar en esta línea
        return;

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

    return;
}

Para que los usuarios solo vean sus propios medios desde el menú Medios Y la pestaña Biblioteca de Medios del modal de subida, reemplaza la línea indicada con esto...

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

(saltos de línea y espaciado solo para mejor legibilidad aquí)

Lo siguiente es igual que lo anterior pero también les restringe a ver solo sus propias entradas desde el elemento del menú Entradas.

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

(saltos de línea y espaciado solo para mejor legibilidad aquí)

Notas: como en la respuesta aceptada, los contadores de entradas y medios serán incorrectos. Sin embargo, hay soluciones para esto en algunas otras respuestas en esta página. No las incorporé simplemente porque no las había probado.

4 feb 2014 00:03:00
2

Código funcional completo.. El único problema es que obtiene un conteo incorrecto de imágenes en la biblioteca multimedia en la página de Añadir Entrada.

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 nov 2011 20:46:32
Comentarios

No deberías usar niveles de usuario, todavía están en WordPress principalmente por compatibilidad con versiones anteriores (anteriores a WP 2.0), no son confiables para determinar capacidades de usuario en WordPress moderno (ya que probablemente desaparecerán del núcleo cuando esa compatibilidad ya no sea necesaria). Usa una capacidad real para determinar los derechos del usuario.

t31os t31os
28 ene 2014 15:56:29

A pesar de contener media-upload.php, tu código no funciona desde el modal de carga generado por la página de edición de entradas. Todavía se pueden ver todos los elementos de la biblioteca.

Sparky Sparky
3 feb 2014 21:58:34
0

t31os tiene una gran solución allí. Lo único es que el número de todas las publicaciones aún aparece.

Encontré una manera de evitar que aparezca el conteo de números usando jQuery.

Solo agrega esto a tu archivo de funciones.

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

¡Está funcionando para mí!

14 abr 2012 01:18:26
1

Resolví mi problema con una solución un poco rudimentaria pero funcional.

1) Instalé el plugin WP Hide Dashboard, para que el usuario solo vea un enlace al formulario de edición de su perfil.

2) En el archivo de plantilla author.php, inserté el código que usé anteriormente.

3) Luego, para usuarios logueados, mostré un enlace directo a la página de subida "wp-admin/media-new.php"

4) El siguiente problema que noté fue que después de subir la foto, los redirigía a upload.php... y podían ver todas las demás imágenes. No encontré un hook en la página media-new.php, así que terminé modificando el core "media-upload.php" para redirigirlos a su página de perfil:

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

Luego reemplacé wp_redirect( admin_url($location) ); con wp_redirect($userredirect);

Un par de problemas, sin embargo. Primero, el usuario logueado todavía puede ir a "upload.php", si sabe que existe. No pueden hacer nada excepto VER los archivos, y el 99% de la gente ni siquiera sabrá de ello, pero aún así no es óptimo. Segundo, también redirige al Admin a la página de perfil después de subir. Estos pueden tener una solución bastante simple verificando los roles de usuario y solo redirigiendo a los Subscriptores.

Si alguien tiene ideas sobre cómo engancharse a la página de Medios sin tocar los archivos core, lo agradecería. ¡Gracias!

10 sept 2010 17:56:23
Comentarios

Existe un hook admin_init que se ejecuta en cada solicitud de administración. En caso de que un usuario solicite upload.php y quieras evitar eso, podrías bloquear esa solicitud (por ejemplo, wp_die('Acceso denegado')) o redirigir a algún lugar válido mediante el hook.

hakre hakre
11 sept 2010 03:49:09
0
<?php
/*
Plugin Name: Gestiona Solo Tus Medios
Version: 0.1
*/

// Gestiona Solo Tus Medios
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' );
?>

Guarda el código anterior como manage_your_media_only.php, comprímelo en un zip, súbelo como plugin a tu WordPress y actívalo, eso es todo.

8 dic 2010 13:29:52
0

Una forma de hacer esto es utilizar el plugin Role Scoper, que también es excelente para gestionar roles y capacidades muy específicas. Puedes bloquear el acceso a las imágenes en la Biblioteca Multimedia para que solo sean accesibles aquellas subidas por cada usuario. Lo he estado utilizando en un proyecto en el que estoy trabajando actualmente y funciona bien.

11 ene 2011 13:01:20