5

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.

4 Answers 4

11

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;
}
3
  • 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
    Commented Nov 28, 2011 at 18:19
  • 2
    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
    Commented May 24, 2013 at 14:58
  • The code above doesn't count "Published" and "Trash" elements properly for some reason. Commented May 29, 2013 at 7:26
1

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

1

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

-1

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.

4
  • 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
    Commented Oct 7, 2011 at 0:59
  • Nope, it's one of the reasons people gravitate to a more "flexible" CMS, maybe one day:)
    – Wyck
    Commented Oct 7, 2011 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
    Commented Oct 7, 2011 at 2:40
  • What is problem with PHP, I mean WordPress filter solution?
    – Mamaduka
    Commented Oct 7, 2011 at 7:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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