¿Restringir a los usuarios para que solo vean los elementos de la biblioteca multimedia que han subido?

46

Quiero que los usuarios puedan subir fotos usando add_cap('upload_files')pero en su página de perfil, la Biblioteca de medios muestra cada imagen que se ha subido. ¿Cómo puedo filtrar eso para que solo puedan ver las imágenes que cargaron?

Aquí está mi solución por el momento ... Estoy haciendo una simple consulta WP, luego un bucle en la página "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);
TerryMatula
fuente
1
Si encontró una respuesta a su propio problema, es mejor que la agregue como respuesta a continuación, no en la pregunta misma. Esto es mejor en línea con el sistema, y ​​podemos votar su respuesta, lo que mejorará su reputación en este sitio.
Jan Fabry
Realmente tengo que secundar el complemento 'Ver Propias publicaciones solo para medios', funcionó perfectamente para mí después de buscar en todas partes una solución jquery o php / html / css.
waffl

Respuestas:

37

Siempre puede filtrar la lista de medios utilizando un pre_get_postsfiltro que primero determina la página y las capacidades del usuario, y establece el parámetro del autor cuando se cumplen 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é el límite de eliminación de páginas como condición para que los administradores y editores todavía vean la lista completa de medios.

Hay un pequeño efecto secundario, para el que no puedo ver ningún gancho, y es con los recuentos de archivos adjuntos que se muestran arriba de la lista de medios (que aún mostrará el recuento total de elementos de medios, no el del usuario dado). Considere esto como un problema menor).

Pensé que lo publicaría de todos modos, podría ser útil ...;)

t31os
fuente
He permitido subir archivos a usuarios de nivel de suscriptor. Intenté usar su código pero no funcionó.
Sisir
1
"No funciona" no es mucho para continuar.
t31os
Puedo confirmar la misma observación. Para mí "no funciona" significa que el rol de "colaborador" todavía puede ver todos los elementos de los medios cuando va a subir un jpg. Sin embargo, cuando va a la biblioteca de medios desde el menú, está vacío. ( Mi rol de "colaborador" ya tiene la capacidad adicional de cargar archivos y eso está funcionando. )
Sparky
Por lo tanto, su código solo debe modificarse para cualquier página que llene la pestaña "Biblioteca de medios" de la ventana de carga. Estoy investigando esto ahora.
Sparky
Si recuerdo correctamente (y ocurren errores), no había ningún gancho apropiado en el momento de escribir esta respuesta, de manera similar a cómo no había ganchos para corregir el conteo de medios. Sin embargo, ha habido unas 3 nuevas versiones de WordPress desde el momento de la escritura, por lo que las soluciones ahora pueden ser posibles.
t31os
32

A partir de WP 3.7 hay una manera mucho mejor a través del ajax_query_attachments_argsfiltro, 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;
}
David
fuente
19

Aquí hay una solución completa para publicaciones y medios (este código es específicamente para autores, pero puede cambiarlo para cualquier rol de usuario). Esto también corrige el recuento de publicaciones / medios sin hackear los archivos principales.

// 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;
}
Pablo
fuente
gran fragmento, pero si no hay elementos en la biblioteca de medios, escupe errores, Advertencia: array_sum () espera que el parámetro 1 sea matriz, nulo dado, y Advertencia: array_keys () espera que el parámetro 1 sea matriz, nulo dado
chrismccoy
Solo tiene que definir $ _num_posts como una matriz en la función fix_media_counts (). $_num_posts = array();
Paul
44
El código en esta respuesta funciona pero también elimina los campos personalizados creados por el complemento Campos personalizados avanzados.
Sparky
5

Esta es una versión modificada de la respuesta aceptada . Dado que la respuesta aceptada solo se dirige al elemento del menú Medios a la izquierda, los usuarios aún pueden ver toda la biblioteca de medios dentro del cuadro modal al cargar una foto en una publicación. Este código ligeramente modificado corrige esa situación. Los usuarios seleccionados solo verán sus propios elementos multimedia desde la pestaña Biblioteca multimedia del cuadro modal que aparece dentro de una publicación.

Este es el código de la respuesta aceptada con un comentario que marca la línea para 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 ) // <-- let's work on this line
        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ú de medios Y la pestaña Biblioteca de medios del modo de carga, reemplace la línea indicada con esto ...

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

( los saltos de línea y el espaciado solo se insertan para facilitar la lectura aquí )

Lo siguiente es lo mismo que arriba pero también les restringe a ver sus propias publicaciones desde el elemento del menú Publicaciones.

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

( los saltos de línea y el espaciado solo se insertan para facilitar la lectura aquí )

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

Chispeante
fuente
2

Código de trabajo completo. El único problema es obtener un recuento incorrecto de imágenes en la biblioteca multimedia en la página Agregar publicación.

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' );
Nitina
fuente
2
No debe usar los niveles de usuario, todavía están en WordPress principalmente por compatibilidad con versiones anteriores (antes de WP 2.0), no son confiables para determinar las capacidades del usuario en WordPress moderno (ya que probablemente desaparecerán del núcleo cuando esa compatibilidad ya no sea necesaria) ) Use una capacidad real para determinar los derechos del usuario.
t31os
A pesar de contener media-upload.php, su código no funciona desde el modo de carga generado por la página Publicar edición. Todavía puedo ver todos los elementos de la biblioteca.
Sparky
2

t31os tiene una gran solución ahí arriba. Lo único es que todavía se muestra el número de todas las publicaciones.

Descubrí una manera de evitar que el recuento de números aparezca con jQuery.

Simplemente agregue esto a su 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');

¡Me está funcionando!

usuario15182
fuente
1

Resolví mi problema con una solución bastante tosca pero factible.

1) Instalé el complemento WP Hide Dashboard, por lo que el Usuario solo vería un enlace a su formulario de edición de perfil.

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

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

4) El siguiente problema que noté fue que después de cargar la foto, los redirigiría a upload.php ... y podrían ver todas las demás imágenes. No he encontrado un enlace en la página media-new.php, así que terminé pirateando el núcleo "media-upload.php" y redirigiéndolos a su página de perfil:

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

Luego reemplazado wp_redirect( admin_url($location) );conwp_redirect($userredirect);

Sin embargo, hay un par de problemas. Primero, el usuario conectado aún puede ir a "upload.php", si sabe que existe. No pueden hacer nada excepto MIRAR los archivos, y el 99% de las personas ni siquiera lo sabrán, pero aún así no es óptimo. En segundo lugar, también redirige al administrador a la página de perfil después de cargarlo. Estos pueden tener una solución bastante simple al verificar los roles de los usuarios y solo redirigir a los suscriptores.

Si alguien tiene ideas sobre conectarse a la página de Medios sin entrar en los archivos principales, se lo agradecería. ¡Gracias!

TerryMatula
fuente
2
Hay un admin_initenlace que se ejecuta en cada solicitud de administrador. En caso de que un usuario solicite upload.php y desee evitar que pueda bloquear esa solicitud (por ejemplo wp_die('Access Denied')) o redirigir a algún lugar válido por enlace.
Hakre
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' );
?>

Guarde el código anterior como manage_your_media_only.php, comprímalo, cárguelo como complemento en su WP y actívelo, eso es todo.


fuente
1

Una forma de hacerlo es utilizar el complemento Role Scoper , también es excelente para administrar funciones y funciones muy específicas. En realidad, puede bloquear el acceso a las imágenes en la Biblioteca de medios solo a las subidas por cada usuario. Lo he estado usando para un proyecto en el que estoy trabajando en este momento y funciona bien.

Rick Curran
fuente