Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Simply put - how might I completely hide media files uploaded by any other users other then themselves? Id like to disable access to these links & files since they are a way for non-admin users to be able to access and edit a custom post type that is normally not visible to them otherwise in the backend of wordpress.

Note: Id still like for them to be able to upload and edit their "own" media files just to be clear.

share|improve this question
add comment

4 Answers

up vote 8 down vote accepted

Actually you can, and here's how to do it:

This code hides all posts and media that do not belong to the currently logged in author (you can change it to apply to other user roles). It also fixes the post and media count on the filter bars (e.g. All | Images | Videos | Unattached).

// 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="%s"'. $class .'>All <span class="count">(%d)</span></a>', 'all'),
                admin_url('edit.php?post_type=post'),
                $result->found_posts);
        elseif( $type['status'] == 'publish' ):
            $class = ($wp_query->query_vars['post_status'] == 'publish') ? ' class="current"' : '';
            $views['publish'] = sprintf(__('<a href="%s"'. $class .'>Published <span class="count">(%d)</span></a>', 'publish'),
                admin_url('edit.php?post_status=publish&post_type=post'),
                $result->found_posts);
        elseif( $type['status'] == 'draft' ):
            $class = ($wp_query->query_vars['post_status'] == 'draft') ? ' class="current"' : '';
            $views['draft'] = sprintf(__('<a href="%s"'. $class .'>Draft'. ((sizeof($result->posts) > 1) ? "s" : "") .' <span class="count">(%d)</span></a>', 'draft'),
                admin_url('edit.php?post_status=draft&post_type=post'),
                $result->found_posts);
        elseif( $type['status'] == 'pending' ):
            $class = ($wp_query->query_vars['post_status'] == 'pending') ? ' class="current"' : '';
            $views['pending'] = sprintf(__('<a href="%s"'. $class .'>Pending <span class="count">(%d)</span></a>', 'pending'),
                admin_url('edit.php?post_status=pending&post_type=post'),
                $result->found_posts);
        elseif( $type['status'] == 'trash' ):
            $class = ($wp_query->query_vars['post_status'] == 'trash') ? ' class="current"' : '';
            $views['trash'] = sprintf(__('<a href="%s"'. $class .'>Trash <span class="count">(%d)</span></a>', 'trash'),
                admin_url('edit.php?post_status=trash&post_type=post'),
                $result->found_posts);
        endif;
    }
    return $views;
}

// Fix media counts
function fix_media_counts($views) {
    $_total_posts = array();
    $_num_posts = array();
    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;
}
share|improve this answer
    
I already implemented an older solution of hiding the Media menu all together for non-admins but this looks interesting so Ill have to try it in my next project and report back, thanks for taking the time to post your solution. –  Mr.Brown Nov 28 '11 at 18:19
    
With Advanced Custom Field it doesn't work well. As the admin i can see my custom fields but with other users the ACF just doesn't load. Any clues on that ? –  Warface May 24 '13 at 14:58
    
The code above doesn't count "Published" and "Trash" elements properly for some reason. –  DiH May 29 '13 at 7:26
add comment

In all honestly with how WordPress works right now, you can't. You would have to write your own PHP to enable this.

It really needs major work with regards to how it handles both users and media.

share|improve this answer
    
Ahh man, not what I wanted to hear! :( I was hoping their would be a simple, but maybe overlooked solution with custom user capabilities possibly. –  Mr.Brown Oct 7 '11 at 0:59
    
Nope, it's one of the reasons people gravitate to a more "flexible" CMS, maybe one day:) –  Wyck Oct 7 '11 at 2:12
    
Dang, that totally sucks. Now my only option is to fully hide the media menu all together but I didnt really want to do that since I predict the client is gonna dislike that. Fricken Wordpress! I love & hate it, i swear. –  Mr.Brown Oct 7 '11 at 2:40
    
What is problem with PHP, I mean WordPress filter solution? –  Mamaduka Oct 7 '11 at 7:55
add comment

To make Paul's solution work with ACF, simply change the first function to:

function current_author_posts( $wp_query ) {

if ( strpos( admin_url(), '/edit.php' ) !== false ) {
    if ( !current_user_can( 'delete_pages' ) ) {
        global $current_user;
        $wp_query->set( 'author', $current_user->ID );
        add_filter('views_edit-post', 'fix_post_counts');
        add_filter('views_upload', 'fix_media_counts');
    }
}
}
add_filter('parse_query', 'current_author_posts' );

For reference, see ACF Support forum and the latest post there

share|improve this answer
add comment

This one is much easier to add on the functions.php and works like charm :

function hide_media_by_other($query) {
global $pagenow;

if( 'upload.php' != $pagenow || !$query->is_admin ){
    return $query;
}

if( !current_user_can( 'manage_options' ) ) {
    global $user_ID;
    $query->set('author', $user_ID );
}
return $query;
    }
    add_filter('pre_get_posts', 'hide_media_by_other');

To view the full tutorial including hiding the images on the media iframe by clicking the 'Add Media' button please follow the steps here : http://jeffreycarandang.com/tutorials/hide-wordpress-posts-media-uploaded-users/

Cheers, phpbits

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.