Restricționarea utilizatorilor pentru a vedea doar elementele din biblioteca media pe care le-au încărcat
Vreau ca utilizatorii să poată încărca fotografii folosind add_cap('upload_files')
dar în pagina lor de profil, Biblioteca Media afișează fiecare imagine care a fost încărcată. Cum pot filtra astfel încât ei să poată vedea doar imaginile pe care le-au încărcat ei?
Iată soluția mea pentru moment... Fac o interogare WP simplă, apoi o iterare pe pagina de "Profil" a utilizatorului
$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);
Puteți filtra întotdeauna lista de fișiere media folosind un filtru pre_get_posts
care determină mai întâi pagina și capabilitățile utilizatorului, apoi setează parametrul autor atunci când sunt îndeplinite anumite condiții..
Exemplu
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;
}
Am folosit capabilitatea 'delete_pages' ca condiție, astfel încât Administratorii și Editorii să vadă în continuare întreaga listă de fișiere media.
Există un mic efect secundar, pentru care nu văd vreun hook disponibil, și anume numărul de fișiere afișat deasupra listei de media (care va arăta în continuare numărul total de fișiere media, nu doar cele ale utilizatorului curent - consider însă că aceasta este o problemă minoră).
Am considerat totuși util să împărtășesc această soluție, poate fi de folos.. ;)

Am permis încărcarea de fișiere pentru utilizatorii cu nivel de abonat. Am încercat să folosesc codul tău, dar nu funcționează.

Pot confirma aceeași observație. Pentru mine "nu funcționează" înseamnă că rolul de "contributor" poate vedea toate elementele media când încarcă un fișier jpg. Totuși, când accesează biblioteca media din meniu, aceasta este goală. (Rolul meu de "contributor" are deja capacitatea suplimentară de a încărca fișiere și asta funcționează.)

Deci codul tău trebuie doar ajustat pentru orice pagină umple fila "Bibliotecă Media" din fereastra de încărcare. Fac cercetări acum pe această temă.

Dacă îmi amintesc corect (și greșelile se întâmplă), nu existau niciun fel de hook-uri adecvate la momentul scrierii acestui răspuns, similar cu modul în care nu existau hook-uri pentru a repara numărul de fișiere media. Au trecut vreo 3 versiuni noi de WordPress de atunci, așa că soluții pot fi acum posibile.

În plus, ar putea fi doar o problemă de actualizare a condiției de verificare $pagenow
, deoarece acesta vizează specific interogarea pentru pagina principală de media, care nu este una și aceeași cu fila de media din popup-ul de încărcare.

Nu-mi pasă dacă numărătoarea este greșită. În rest, codul tău funcționează din elementul Media din meniu (WP v3.8.1). Încerc să fac asta să funcționeze din fereastra de încărcare care apare în pagina "Postare nouă". Da, sunt de acord... Încerc să găsesc pagina corectă pentru verificarea $pagenow
.

Iată soluția: http://wordpress.stackexchange.com/a/132319/11092

if( !in_array( $pagenow, array( 'upload.php', 'admin-ajax.php' )
Această linie din codul tău lipsește o paranteză de închidere )
, Ar trebui să fie trei )
, dar codul tău are doar două.

Aceasta pare să se aplice doar la vizualizarea grilă. Aveți recomandări despre cum să realizăm acest lucru și pentru vizualizarea listă?

Începând cu WP 3.7 există o metodă mult mai bună prin intermediul filtrului ajax_query_attachments_args
, așa cum este prezentat în documentație:
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;
}

Iată o soluție completă pentru ambele tipuri de conținut - postări și fișiere media (acest cod este conceput special pentru autori, dar îl poți adapta pentru orice rol de utilizator). Această soluție rezolvă și problema numărării postărilor/fișierelor fără a modifica fișierele de bază ale WordPress.
// Afișează doar postările și fișierele media asociate autorului logat
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');
}
}
// Corectează numărul de postări
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,
__('Toate')
);
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,
__('Publicate')
);
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,
__('Ciorne')
);
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,
__('În așteptare')
);
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,
__('Coș de gunoi')
);
endif;
}
return $views;
}
// Corectează numărul de fișiere 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( __('Toate <span class="count">(%s)</span>', 'fișiere încărcate'), 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( __( 'Neatașate <span class="count">(%s)</span>', 'fișiere detașate'), $total_orphans ) . '</a>';
return $views;
}

fragment excelent, dar dacă nu există elemente în biblioteca media, afișează erori, Warning: array_sum() expects parameter 1 to be array, null given, și Warning: array_keys() expects parameter 1 to be array, null given

Trebuie doar să definești $_num_posts ca un array în funcția fix_media_counts(). $_num_posts = array();

Codul din acest răspuns funcționează, dar elimină și orice câmpuri personalizate create de plugin-ul Advanced Custom Fields.

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

Aceasta este o versiune modificată a răspunsului acceptat. Deoarece răspunsul acceptat se adresează doar elementului de meniu Media din stânga, utilizatorii puteau vedea întreaga bibliotecă de media în caseta modală la încărcarea unei fotografii într-un articol. Acest cod ușor modificat rezolvă această situație. Utilizatorii vizate vor vedea doar propriile elemente media din fila Biblioteca Media a casetei modale care apare în interiorul unui articol.
Acesta este codul din răspunsul acceptat, cu un comentariu care marchează linia de editat...
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 ) // <-- să lucrăm la această linie
return;
if( !current_user_can('delete_pages') )
$wp_query_obj->set('author', $current_user->id );
return;
}
Pentru ca utilizatorii să vadă doar propriile media atât din meniul Media, cât și din fila Biblioteca Media a casetei modale de încărcare, înlocuiți linia indicată cu aceasta...
if( ( 'upload.php' != $pagenow ) &&
( ( 'admin-ajax.php' != $pagenow ) || ( $_REQUEST['action'] != 'query-attachments' ) ) )
(întreruperi de linie și spațiere adăugate doar pentru lizibilitate aici)
Următorul cod este la fel ca cel de mai sus, dar restricționează și vizualizarea propriilor articole din elementul de meniu Articole.
if( ( 'edit.php' != $pagenow ) &&
( 'upload.php' != $pagenow ) &&
( ( 'admin-ajax.php' != $pagenow ) || ( $_REQUEST['action'] != 'query-attachments' ) ) )
(întreruperi de linie și spațiere adăugate doar pentru lizibilitate aici)
Note: ca și în răspunsul acceptat, contoarele pentru articole și media vor fi greșite. Cu toate acestea, există soluții pentru aceasta în alte răspunsuri de pe această pagină. Nu le-am încorporat pur și simplu pentru că nu le-am testat.

Cod funcțional complet.. Singura problemă este că se afișează numărul greșit de imagini în biblioteca media pe pagina de Adăugare Postare.
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' );

Nu ar trebui să folosești niveluri de utilizator, acestea sunt încă în WordPress în principal pentru compatibilitate retroactivă (anterior WP 2.0), nu sunt fiabile pentru determinarea capacităților utilizatorilor în WordPressul modern (deoarece vor dispărea probabil din nucleu când acea compatibilitate nu va mai fi necesară). Folosește o capabilitate reală pentru a determina drepturile utilizatorului.

t31os are o soluție excelentă mai sus. Singurul lucru este că numărul total de articole încă apare.
Am găsit o modalitate de a preveni afișarea numărului de articole folosind jQuery.
Adaugă acest cod în fișierul tău de funcții.
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');
Funcționează perfect pentru mine!

Am rezolvat problema mea cu o soluție destul de dură, dar funcțională.
1) Am instalat plugin-ul WP Hide Dashboard, astfel încât utilizatorul să vadă doar un link către formularul de editare a profilului său.
2) În fișierul șablon author.php, am inserat codul pe care l-am folosit mai sus.
3) Apoi, pentru utilizatorii autentificați, am afișat un link direct către pagina de încărcare "wp-admin/media-new.php"
4) Următoarea problemă pe care am observat-o a fost că după ce încărcau fotografia, erau redirecționați către upload.php... și puteau vedea toate celelalte imagini. Nu am găsit un hook în pagina media-new.php, așa că am ajuns să modific fișierul core "media-upload.php" și să-i redirecționez către pagina lor de profil:
global $current_user;
get_currentuserinfo();
$userredirect = get_bloginfo('home') . "/author/" .$current_user->user_nicename;
Apoi am înlocuit wp_redirect( admin_url($location) );
cu wp_redirect($userredirect);
Câteva probleme, totuși. În primul rând, utilizatorul autentificat poate încă accesa "upload.php", dacă știe că există. Nu pot face altceva decât să VADĂ fișierele, iar 99% dintre oameni nici măcar nu vor ști despre asta, dar totuși nu este optim. În al doilea rând, redirecționează și Administratorul către pagina de profil după încărcare. Acestea pot fi rezolvate destul de simplu prin verificarea rolurilor utilizatorilor și redirecționarea doar a Abonaților.
Dacă cineva are idei despre cum să folosească un hook în pagina Media fără a modifica fișierele core, aș aprecia. Mulțumesc!

Există un hook admin_init
care rulează la fiecare solicitare în administrare. În cazul în care un utilizator solicită upload.php și doriți să împiedicați acest lucru, puteți fie să blocați acea solicitare (de exemplu, wp_die('Acces interzis')
), fie să redirecționați către un loc valid prin intermediul hook-ului.

<?php
/*
Plugin Name: Gestionează Doar Media Ta
Version: 0.1
*/
//Gestionează Doar Media Ta
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' );
?>
Salvează codul de mai sus ca manage_your_media_only.php, arhivează-l în format zip, încarcă-l ca plugin în WordPress și activează-l, asta e tot.

O modalitate de a face acest lucru este să folosești plugin-ul Role Scoper, care este excelent pentru gestionarea rolurilor și capabilităților foarte specifice. De fapt, poți restricționa accesul la imaginile din Biblioteca Media doar pentru cele încărcate de fiecare utilizator. Eu l-am folosit pentru un proiect la care lucrez în prezent și funcționează foarte bine.
