Ograniczasz użytkownikom przeglądanie tylko tych elementów biblioteki multimedialnej, które przesłali?

46

Chcę, aby użytkownicy mogli przesyłać zdjęcia przy użyciu, add_cap('upload_files')ale na stronie profilu w bibliotece multimediów wyświetlane są wszystkie przesłane zdjęcia. Jak mogę filtrować, że tak, że mogą jedynie przeglądać obrazy one załadowane?

Oto moje rozwiązanie na chwilę… Wykonuję proste zapytanie WP, a następnie zapętlam stronę użytkownika „Profil”

$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
źródło
1
Jeśli znalazłeś odpowiedź na swój problem, lepiej dodaj ją jako odpowiedź poniżej, a nie w samym pytaniu. Jest to lepiej zgodne z systemem i możemy podnieść głos na twoją odpowiedź, co poprawi twoją reputację na tej stronie.
Jan Fabry
Naprawdę muszę poprzeć wtyczkę „View Own Posts Media Only”, działała idealnie dla mnie po szukaniu wszędzie jquery lub php / html / css.
waffl

Odpowiedzi:

37

Zawsze możesz przefiltrować listę multimediów za pomocą pre_get_postsfiltra, który najpierw określa stronę oraz możliwości użytkownika i ustawia parametr autora, gdy zostaną spełnione określone warunki.

Przykład

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

Jako warunku użyłem cap stron usuwania, więc administratorzy i redaktorzy nadal widzą pełną listę multimediów.

Jest jeden mały efekt uboczny, dla którego nie widzę żadnych haczyków, a to z liczbą załączników pokazaną nad listą multimediów (która nadal będzie pokazywać całkowitą liczbę elementów multimedialnych, a nie danego użytkownika - chciałbym uważają to za drobny problem).

Pomyślałem, że mimo wszystko to opublikuję, może się przydać ..;)

t31os
źródło
Zezwoliłem na przesyłanie plików do użytkowników na poziomie subskrybenta. próbował użyć twojego kodu, ale nie działał.
Sisir
1
„Nie działa” nie ma wiele do zrobienia.
t31os
Mogę potwierdzić tę samą obserwację. Dla mnie „nie działa” oznacza, że ​​rola „współautora” nadal może wyświetlać wszystkie elementy multimedialne, kiedy idzie przesłać plik jpg. Jednak kiedy idzie do biblioteki multimediów z menu, jest pusta. ( Moja rola „współautora” ma już dodatkową możliwość przesyłania plików i to działa. )
Sparky
Więc twój kod musi zostać dostosowany do strony, która wypełnia kartę „Biblioteka multimediów” w oknie przesyłania. Badam to teraz.
Sparky
Jeśli dobrze pamiętam (a błędy się zdarzają), w momencie pisania tej odpowiedzi nie było żadnych odpowiednich haczyków, podobnie jak w przypadku braku haków do naprawy liczby mediów. Jednak od czasu pisania były dobre 3 nowe wersje WordPress, więc rozwiązania mogą być teraz możliwe.
t31os
32

Począwszy od WP 3.7 istnieje znacznie lepszy sposób przez ajax_query_attachments_argsfiltr, jak podano w dokumentacji :

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
źródło
19

Oto kompletne rozwiązanie zarówno dla postów, jak i dla mediów (ten kod jest specjalnie dla autorów, ale możesz go zmienić dla dowolnej roli użytkownika). To także naprawia liczbę postów / multimediów bez włamywania się do podstawowych plików.

// 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;
}
Paweł
źródło
świetny fragment kodu, ale jeśli w bibliotece multimediów nie ma żadnych elementów, wyrzuca błędy, Ostrzeżenie: array_sum () oczekuje, że parametr 1 będzie tablicą, podano wartość null, a Ostrzeżenie: array_keys () oczekuje, że parametr 1 będzie tablicą, wartość null podana
chrismccoy
Musisz tylko zdefiniować $ _num_posts jako tablicę w funkcji fix_media_counts (). $_num_posts = array();
Paweł,
4
Kod w tej odpowiedzi działa, ale usuwa również pola niestandardowe utworzone przez wtyczkę Advanced Custom Fields.
Sparky
5

To jest zmodyfikowana wersja zaakceptowanej odpowiedzi . Ponieważ zaakceptowana odpowiedź jest skierowana tylko na pozycję menu Media po lewej stronie, użytkownicy nadal mogą zobaczyć całą bibliotekę multimediów w polu modalnym podczas przesyłania zdjęcia do posta. Ten nieznacznie zmodyfikowany kod naprawia tę sytuację. Docelowi użytkownicy zobaczą tylko własne elementy multimedialne z zakładki Biblioteka multimediów w polu modalnym, które pojawia się w poście.

To jest kod z zaakceptowanej odpowiedzi z komentarzem oznaczającym linię do edycji ...

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

Aby użytkownicy mogli wyświetlać tylko własne multimedia z menu Media ORAZ zakładki Biblioteka multimediów w module przesyłania, zastąp wskazaną linię tym ...

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

( wstawiono tutaj podział wiersza i odstępy tylko dla czytelności )

Poniższe czynności są takie same jak powyżej, ale ograniczają również ich dostęp do własnych postów z pozycji menu Posty.

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

( wstawiono tutaj podział wiersza i odstępy tylko dla czytelności )

Uwagi : podobnie jak w zaakceptowanej odpowiedzi posty i liczniki mediów będą błędne. Istnieją jednak rozwiązania tego problemu w niektórych innych odpowiedziach na tej stronie. Nie włączyłem ich po prostu dlatego, że ich nie przetestowałem.

iskrzący
źródło
2

Kompletny działający kod. Jedynym problemem jest błędna liczba zdjęć w bibliotece multimediów na stronie Dodaj wpis.

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' );
Nitin
źródło
2
Nie powinieneś używać poziomów użytkowników, są one w WordPressie wciąż przede wszystkim dla kompatybilności wstecznej (przed WP 2.0), nie są niezawodne w określaniu możliwości użytkownika we współczesnym WordPressie (ponieważ prawdopodobnie znikną z rdzenia, gdy ta zgodność nie jest już wymagana ). Użyj rzeczywistych możliwości, aby określić prawa użytkownika.
t31os
Mimo że zawiera media-upload.phpkod, Twój kod nie działa z modalu przesyłania wygenerowanego przez stronę edycji postów. Nadal widzi wszystkie elementy biblioteki.
Sparky
2

t31os ma tam świetne rozwiązanie. Jedyną rzeczą jest to, że wciąż wyświetla się liczba wszystkich postów.

Wymyśliłem sposób, aby nie wyświetlać liczby przy użyciu jQuery.

Po prostu dodaj to do pliku funkcji.

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

To działa dla mnie!

użytkownik15182
źródło
1

Rozwiązałem swój problem dość szorstkim, ale wykonalnym rozwiązaniem.

1) Zainstalowałem wtyczkę WP Hide Dashboard, aby użytkownik widział tylko link do formularza edycji profilu.

2) W pliku szablonu autor.php wstawiłem kod, którego użyłem powyżej.

3) Następnie dla zalogowanych użytkowników wyświetliłem bezpośredni link do strony przesyłania „wp-admin / media-new.php”

4) Kolejnym problemem, który zauważyłem, było to, że po przesłaniu zdjęcia przekieruje ich na upload.php ... i będą mogli zobaczyć wszystkie pozostałe zdjęcia. Nie znalazłem haka na stronie media-new.php, więc ostatecznie włamałem się do podstawowego „media-upload.php” i przekierowałem je na stronę profilu:

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

Następnie zastąpiony wp_redirect( admin_url($location) );przezwp_redirect($userredirect);

Jednak kilka problemów. Po pierwsze, zalogowany użytkownik może nadal przejść do „upload.php”, jeśli wie, że istnieje. Nie mogą zrobić nic poza WYGLĄDEM na plikach, a 99% ludzi nawet się o tym nie dowie, ale nadal nie jest to optymalne. Po drugie, przekierowuje również administratora na stronę profilu po przesłaniu. Mogą one mieć dość prostą poprawkę, sprawdzając role użytkowników i przekierowując tylko subskrybentów.

Jeśli ktoś ma pomysły na podłączenie się do strony Media bez wchodzenia do podstawowych plików, byłbym wdzięczny. Dzięki!

TerryMatula
źródło
2
Na admin_initkażdym żądaniu administratora działa hak. W przypadku, gdy użytkownik zażąda upload.php i chcesz uniemożliwić albo zablokowanie tego żądania (np. wp_die('Access Denied')), Albo przekierowanie do pewnego prawidłowego miejsca na hak.
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' );
?>

Zapisz kod powyżej jako manage_your_media_only.php, spakuj go, załaduj jako wtyczkę do WP i aktywuj, to wszystko.


źródło
1

Jednym ze sposobów jest użycie wtyczki Role Scoper , która doskonale nadaje się również do zarządzania bardzo specyficznymi rolami i możliwościami. W rzeczywistości możesz zablokować dostęp do zdjęć w Bibliotece multimediów tylko do tych przesłanych przez każdego użytkownika. Używałem go do projektu, nad którym obecnie pracuję i działa dobrze.

Rick Curran
źródło