Einschränken, dass Benutzer nur von ihnen hochgeladene Medienbibliothekselemente anzeigen können?

46

Ich möchte, dass Benutzer Fotos über add_cap('upload_files')ihre Profilseite hochladen können. In der Medienbibliothek werden jedoch alle hochgeladenen Bilder angezeigt. Wie kann ich das filtern, damit sie nur die Bilder sehen können, die sie hochgeladen haben?

Hier ist meine Lösung für den Moment ... Ich mache eine einfache WP-Abfrage und dann eine Schleife auf der "Profil" -Seite des Benutzers

$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
quelle
1
Wenn Sie eine Antwort auf Ihr eigenes Problem gefunden haben, fügen Sie sie besser als Antwort unten hinzu, nicht in der Frage selbst. Dies passt besser zum System, und wir können Ihre Antwort verbessern, wodurch sich Ihr Ruf auf dieser Website verbessert.
Jan Fabry
Ich muss wirklich das Plugin 'View Own Posts Media Only' unterstützen, es hat bei mir perfekt funktioniert, nachdem ich überall nach einer jquery- oder php / html / css-Lösung gesucht habe.
Waffel

Antworten:

37

Sie können die Medienliste immer mit einem pre_get_postsFilter filtern, der zuerst die Seite und die Funktionen des Benutzers bestimmt und den Autor-Parameter festlegt, wenn bestimmte Bedingungen erfüllt sind.

Beispiel

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

Ich habe das Löschen von Seiten als Bedingung verwendet, damit Administratoren und Redakteure immer noch die vollständige Medienliste sehen.

Es gibt einen kleinen Nebeneffekt, für den ich keine Haken sehen kann, und zwar mit der Anzahl der Anhänge über der Medienliste (die immer noch die Gesamtzahl der Medienelemente anzeigt, nicht die des angegebenen Benutzers - ich würde halte dies jedoch für ein kleines Problem).

Dachte, ich würde es trotzdem posten, könnte nützlich sein ..;)

t31os
quelle
Ich habe das Hochladen von Dateien für Benutzer auf Abonnentenebene zugelassen. versucht, Ihren Code zu verwenden, aber nicht funktioniert.
Sisir
1
"Nicht arbeiten" ist nicht viel weiter.
t31os
Ich kann die gleiche Beobachtung bestätigen. Für mich bedeutet "funktioniert nicht", dass die Rolle "Mitwirkender" weiterhin alle Medienelemente sehen kann, wenn er ein JPG hochlädt. Wenn er jedoch über das Menü zur Medienbibliothek wechselt, ist diese leer. ( Meine Rolle als "Mitwirkender" hat bereits die zusätzliche Fähigkeit, Dateien hochzuladen, und das funktioniert. )
Sparky
Ihr Code muss also nur für jede Seite angepasst werden, die die Registerkarte "Medienbibliothek" des Upload-Fensters ausfüllt. Ich recherchiere das jetzt.
Sparky
Wenn ich mich richtig erinnere (und Fehler passieren), gab es zum Zeitpunkt des Schreibens dieser Antwort keine geeigneten Haken, ähnlich wie es keine Haken gab, um die Anzahl der Medien zu korrigieren. Seit dem Zeitpunkt des Schreibens gab es jedoch gute 3 neue Versionen von WordPress, sodass jetzt möglicherweise Lösungen möglich sind.
T31OS
32

Ab WP 3.7 gibt es einen viel besseren Weg über den ajax_query_attachments_argsFilter, wie in der Dokumentation beschrieben :

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
quelle
19

Hier finden Sie eine vollständige Lösung für Posts und Medien (dieser Code richtet sich speziell an Autoren, Sie können ihn jedoch für jede Benutzerrolle ändern). Dies behebt auch die Anzahl der Posts / Medien, ohne die Kerndateien zu hacken.

// 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;
}
Paul
quelle
Tolles Snippet, aber wenn sich keine Elemente in der Medienbibliothek befinden, werden Fehler ausgegeben. Warnung: array_sum () erwartet, dass Parameter 1 ein Array mit dem Wert null ist, und Warnung: array_keys () erwartet, dass Parameter 1 ein Array mit dem
Wert
Sie müssen nur $ _num_posts als Array in der Funktion fix_media_counts () definieren. $_num_posts = array();
Paul
4
Der Code in dieser Antwort funktioniert, entfernt jedoch auch alle benutzerdefinierten Felder, die vom Plug-in für erweiterte benutzerdefinierte Felder erstellt wurden.
Sparky
1
Viel im Zusammenhang: wordpress.stackexchange.com/questions/178236/…
cregox
5

Dies ist eine modifizierte Version der akzeptierten Antwort . Da die akzeptierte Antwort nur auf das Menüelement Medien auf der linken Seite zielt, können Benutzer beim Hochladen eines Fotos in einen Beitrag immer noch die gesamte Medienbibliothek im modalen Feld sehen. Dieser leicht geänderte Code behebt diese Situation. Die Zielbenutzer sehen nur ihre eigenen Medienelemente auf der Registerkarte Medienbibliothek des Modalfelds, das in einem Beitrag angezeigt wird.

Dies ist der Code aus der akzeptierten Antwort mit einem Kommentar, der die zu bearbeitende Zeile markiert ...

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

Wenn Benutzer ihre eigenen Medien nur über das Menü Medien UND die Registerkarte Medienbibliothek des Upload-Modals anzeigen möchten, ersetzen Sie die angezeigte Zeile durch ...

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

( Zeilenumbrüche und Abstände werden hier nur zur besseren Lesbarkeit eingefügt )

Das Folgende ist dasselbe wie oben, beschränkt sie jedoch auch darauf, ihre eigenen Beiträge über den Menüpunkt Beiträge zu sehen.

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

( Zeilenumbrüche und Abstände werden hier nur zur besseren Lesbarkeit eingefügt )

Anmerkungen : Wie in der akzeptierten Antwort sind die Beiträge und Medienzähler falsch. In einigen anderen Antworten auf dieser Seite finden Sie jedoch Lösungen dafür. Ich habe diese nicht einfach eingebaut, weil ich sie nicht getestet hatte.

Sparky
quelle
2

Vollständiger Arbeitscode. Das einzige Problem ist, dass die Anzahl der Bilder in der Medienbibliothek auf der Seite "Beitrag hinzufügen" falsch ist.

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
quelle
2
Sie sollten keine Benutzerebenen verwenden, sie sind in WordPress immer noch hauptsächlich aus Gründen der Abwärtskompatibilität (vor WP 2.0), und sie sind nicht zuverlässig, um die Benutzerfähigkeiten in WordPress von heute zu bestimmen (da sie wahrscheinlich vom Kern verschwinden, wenn diese Kompatibilität nicht mehr erforderlich ist ). Verwenden Sie eine tatsächliche Fähigkeit , um Benutzerrechte zu bestimmen.
28.
Trotz media-upload.phpdes Inhalts funktioniert Ihr Code nicht mit dem von der Post-Edit-Seite generierten Upload-Modus. Kann immer noch alle Bibliothekselemente sehen.
Sparky
2

t31os hat da oben eine großartige Lösung. Das einzige ist, dass die Anzahl aller Posts immer noch angezeigt wird.

Ich habe einen Weg gefunden, um zu verhindern, dass die Anzahl der Zahlen mit jQuery angezeigt wird.

Fügen Sie dies einfach Ihrer Funktionsdatei hinzu.

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

Es funktioniert für mich!

user15182
quelle
1

Ich habe mein Problem mit einer ziemlich groben, aber praktikablen Lösung gelöst.

1) Ich habe das WP Hide Dashboard-Plugin installiert, sodass dem Benutzer nur ein Link zu seinem Profilbearbeitungsformular angezeigt wird.

2) In die author.php-Vorlagendatei habe ich den oben verwendeten Code eingefügt.

3) Dann habe ich für angemeldete Benutzer einen direkten Link zur Upload-Seite "wp-admin / media-new.php" angezeigt

4) Das nächste Problem, das mir auffiel, war, nachdem sie das Foto hochgeladen hatten, dass sie zu upload.php weitergeleitet wurden ... und sie alle anderen Bilder sehen konnten. Ich habe keinen Haken in der Seite media-new.php gefunden, also habe ich mich in die zentrale Datei "media-upload.php" gehackt und sie auf ihre Profilseite weitergeleitet:

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

Dann ersetzt wp_redirect( admin_url($location) );durchwp_redirect($userredirect);

Ein paar Probleme. Erstens kann der angemeldete Benutzer immer noch zu "upload.php" gehen, wenn er weiß, dass es existiert. Sie können nichts anderes tun, als die Akten anzuschauen, und 99% der Leute wissen nicht einmal davon, aber es ist immer noch nicht optimal. Zweitens wird der Administrator nach dem Hochladen auch zur Profilseite umgeleitet. Diese Probleme können relativ einfach behoben werden, indem Benutzerrollen überprüft und nur Abonnenten umgeleitet werden.

Wenn jemand Ideen hat, wie man sich in die Medienseite einbinden kann, ohne in die Kerndateien zu gehen, würde ich das begrüßen. Vielen Dank!

TerryMatula
quelle
2
Es gibt einen admin_initHaken, der bei jeder Administratoranforderung ausgeführt wird. Wenn ein Benutzer upload.php anfordert und Sie verhindern möchten, dass Sie diese Anforderung blockieren (z. B. wp_die('Access Denied')) oder an einen gültigen Ort pro Hook umleiten können.
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' );
?>

Speichern Sie den obigen Code als manage_your_media_only.php, komprimieren Sie ihn, laden Sie ihn als Plugin in Ihr WP hoch und aktivieren Sie ihn.


quelle
1

Eine Möglichkeit, dies zu tun, ist die Verwendung des Role Scoper-Plugins , das sich auch hervorragend zum Verwalten sehr spezifischer Rollen und Funktionen eignet. Sie können den Zugriff auf Bilder in der Medienbibliothek nur für die von jedem Benutzer hochgeladenen Bilder sperren. Ich habe es für ein Projekt verwendet, an dem ich gerade arbeite, und es funktioniert gut.

Rick Curran
quelle