Limitare gli utenti a visualizzare solo gli elementi della libreria multimediale che hanno caricato
Voglio che gli utenti possano caricare foto usando add_cap('upload_files')
ma nella loro pagina del profilo, la Libreria Multimediale mostra tutte le immagini che sono state caricate. Come posso filtrare in modo che possano vedere solo le immagini che hanno caricato loro?
Ecco la mia soluzione per il momento... Sto facendo una semplice query WP, poi un ciclo sulla pagina "Profilo" dell'utente
$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);
Puoi sempre filtrare l'elenco dei media utilizzando un filtro pre_get_posts
che prima determina la pagina e le capacità dell'utente, e imposta il parametro author quando vengono soddisfatte determinate condizioni..
Esempio
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;
}
Ho utilizzato la capacità delete_pages come condizione in modo che gli Amministratori e gli Editori continuino a vedere l'elenco completo dei media.
C'è un piccolo effetto collaterale, per il quale non vedo alcun hook disponibile, ed è con i conteggi degli allegati mostrati sopra l'elenco dei media (che mostreranno ancora il conteggio totale degli elementi multimediali, non quello dell'utente specifico - considererei comunque questo un problema minore).
Ho pensato di pubblicarlo comunque, potrebbe essere utile.. ;)

Ho permesso il caricamento di file agli utenti con livello subscriber. Ho provato a usare il tuo codice ma non funziona.

Posso confermare la stessa osservazione. Per me "non funziona" significa che il ruolo "contributor" può ancora vedere tutti gli elementi multimediali quando va a caricare un jpg. Tuttavia, quando accede alla libreria multimediale dal menu, è vuota. (Il mio ruolo "contributor" ha già la capacità aggiuntiva di caricare file e quello funziona.)

Quindi il tuo codice ha solo bisogno di essere modificato per qualunque pagina riempia la scheda "Libreria Media" della finestra di caricamento. Sto facendo ricerche su questo ora.

Se ricordo correttamente (e gli errori possono capitare), al momento della stesura di questa risposta non c'erano hook appropriati disponibili, in modo simile a come non c'erano hook per sistemare il conteggio dei media. Sono passate almeno 3 nuove versioni di WordPress da allora, quindi ora potrebbero esserci soluzioni possibili.

Inoltre, potrebbe essere semplicemente una questione di aggiornare il controllo condizionale $pagenow
, dato che questo punta a indirizzare la query specificamente per la pagina principale dei media, che non è la stessa cosa della scheda media nel popup di caricamento.

Non mi interessa se i conteggi sono sbagliati. A parte questo, il tuo codice funziona dalla voce Media nel menu (WP v3.8.1). Sto cercando di farlo funzionare dalla finestra di upload che si apre all'interno della pagina "Nuovo articolo". Sì, sono d'accordo... sto cercando di trovare la pagina corretta per il controllo $pagenow
.

Ecco la soluzione: http://wordpress.stackexchange.com/a/132319/11092

if( !in_array( $pagenow, array( 'upload.php', 'admin-ajax.php' )
Questa riga nel tuo codice manca di una parentesi di chiusura )
, dovrebbero esserci tre )
, ma il tuo codice ne ha solo due.

Questo sembra applicarsi solo alla vista griglia. Qualche consiglio su come realizzarlo anche per la vista elenco?

A partire da WP 3.7 esiste un metodo molto migliore tramite il filtro ajax_query_attachments_args
, come fornito nella documentazione:
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;
}

Ecco una soluzione completa sia per i post che per i media (questo codice è specifico per gli autori, ma puoi modificarlo per qualsiasi ruolo utente). Questo sistema corregge anche il conteggio dei post/media senza modificare i file core.
// Mostra solo post e media relativi all'autore loggato
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');
}
}
// Corregge il conteggio dei post
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,
__('Tutti')
);
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,
__('Pubblicati')
);
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,
__('Bozze')
);
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,
__('In attesa')
);
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,
__('Cestino')
);
endif;
}
return $views;
}
// Corregge il conteggio dei media
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( __('Tutti <span class="count">(%s)</span>', 'file caricati' ), 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( __( 'Non collegati <span class="count">(%s)</span>', 'file scollegati' ), $total_orphans ) . '</a>';
return $views;
}

ottimo snippet ma se non ci sono elementi nella libreria multimediale, restituisce errori, Warning: array_sum() expects parameter 1 to be array, null given, e Warning: array_keys() expects parameter 1 to be array, null given

Devi solo definire $_num_posts come un array nella funzione fix_media_counts(). $_num_posts = array();

Il codice in questa risposta funziona ma rimuove anche tutti i campi personalizzati creati dal plugin Advanced Custom Fields.

Molto correlato: http://wordpress.stackexchange.com/questions/178236/correct-post-count-all-published-drafts-pending-trash-for-custom-pos

Questa è una versione modificata della risposta accettata. Poiché la risposta accettata si concentra solo sulla voce Media nel menu a sinistra, gli utenti potevano comunque vedere l'intera libreria multimediale all'interno della finestra modale durante il caricamento di una foto in un articolo. Questo codice leggermente modificato risolve quella situazione. Gli utenti mirati vedranno solo i propri elementi multimediali dalla scheda Libreria multimediale della finestra modale che appare all'interno di un articolo.
Questo è il codice della risposta accettata con un commento che segna la riga da modificare...
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 ) // <-- lavoriamo su questa riga
return;
if( !current_user_can('delete_pages') )
$wp_query_obj->set('author', $current_user->id );
return;
}
Affinché gli utenti vedano solo i propri media dal menu Media E dalla scheda Libreria multimediale della finestra modale di caricamento, sostituire la riga indicata con questa...
if( ( 'upload.php' != $pagenow ) &&
( ( 'admin-ajax.php' != $pagenow ) || ( $_REQUEST['action'] != 'query-attachments' ) ) )
(a capo e spaziatura inseriti solo per migliorare la leggibilità qui)
Quello che segue è lo stesso codice di sopra ma restringe anche la visualizzazione dei propri articoli dalla voce di menu Articoli.
if( ( 'edit.php' != $pagenow ) &&
( 'upload.php' != $pagenow ) &&
( ( 'admin-ajax.php' != $pagenow ) || ( $_REQUEST['action'] != 'query-attachments' ) ) )
(a capo e spaziatura inseriti solo per migliorare la leggibilità qui)
Note: come nella risposta accettata, i contatori di articoli e media saranno errati. Tuttavia, ci sono soluzioni per questo in alcune altre risposte in questa pagina. Non le ho incorporate semplicemente perché non le avevo testate.

Codice funzionante completo.. L'unico problema è che ottiene un conteggio errato delle immagini nella libreria multimediale nella pagina Aggiungi articolo.
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' );

Non dovresti utilizzare i livelli utente, sono ancora presenti in WordPress principalmente per compatibilità con le versioni precedenti (antecedenti a WP 2.0), non sono affidabili per determinare le capacità degli utenti nella versione moderna di WordPress (poiché probabilmente scompariranno dal core quando tale compatibilità non sarà più necessaria). Utilizza una capability effettiva per determinare i diritti degli utenti.

t31os ha una soluzione eccellente lì sopra. L'unica cosa è che il numero totale dei post continua a essere visualizzato.
Ho trovato un modo per evitare che il conteggio dei numeri venga mostrato utilizzando jQuery.
Aggiungi semplicemente questo al tuo file delle funzioni.
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');
Funziona perfettamente per me!

Ho risolto il mio problema con una soluzione un po' grezza ma funzionante.
1) Ho installato il plugin WP Hide Dashboard, in modo che l'utente visualizzi solo un link alla pagina di modifica del proprio profilo.
2) Nel file template author.php, ho inserito il codice che ho usato sopra.
3) Poi, per gli utenti loggati, ho mostrato un link diretto alla pagina di Upload "wp-admin/media-new.php"
4) Il problema successivo che ho notato è che dopo aver caricato la foto, venivano reindirizzati a upload.php... e potevano vedere tutte le altre immagini. Non avendo trovato un hook nella pagina media-new.php, alla fine ho modificato il core "media-upload.php" reindirizzandoli alla loro pagina profilo:
global $current_user;
get_currentuserinfo();
$userredirect = get_bloginfo('home') . "/author/" .$current_user->user_nicename;
Poi ho sostituito wp_redirect( admin_url($location) );
con wp_redirect($userredirect);
Un paio di problemi però. Primo, l'utente loggato può ancora accedere a "upload.php", se sa che esiste. Non può fare altro che VEDERE i file, e il 99% delle persone non lo saprà mai, ma comunque non è ottimale. Secondo, reindirizza anche l'Admin alla pagina profilo dopo il caricamento. Questi problemi possono essere risolti abbastanza facilmente verificando i ruoli utente e reindirizzando solo gli Iscritti (Subscribers).
Se qualcuno ha idee su come agganciarsi alla pagina Media senza modificare i file core, lo apprezzerei. Grazie!

Esiste un hook admin_init
che viene eseguito ad ogni richiesta di amministrazione. Nel caso in cui un utente richieda upload.php e tu voglia impedirlo, puoi bloccare la richiesta (ad esempio wp_die('Accesso Negato')
) oppure reindirizzare a una pagina valida tramite l'hook.

<?php
/*
Plugin Name: Gestisci Solo i Tuoi Media
Version: 0.1
*/
//Gestisci Solo i Tuoi Media
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' );
?>
Salva il codice sopra come manage_your_media_only.php, zippalo, caricalo come plugin nel tuo WordPress e attivalo, questo è tutto.

Un modo per farlo è utilizzare il plugin Role Scoper, che è ottimo anche per gestire ruoli e capacità molto specifici. Puoi effettivamente bloccare l'accesso alle immagini nella Libreria multimediale solo a quelle caricate da ciascun utente. Lo sto usando per un progetto su cui sto lavorando al momento e funziona bene.
