How to restrict users to view only their own media library items in wordpress

By default in WP 3.1.1 any user can view and manage any media library item. Even if it was uploaded by other user. In this howto I described the way to avoid this.

I got the idea from Philip Borisov's plugin. It solves the issue howewer leave total amount of items unchanged: All (58) | Images (44) | Unattached (18)

WordPress Media Library WordPress Media Library

To solve this issue I modified a plugin:

<?php
/*
Plugin Name: Manage Your Media Only
Version: 0.2
*/

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

/*
 * Count only allowed media library items
 * Added by Vladimir Shugaev <vladimir.shugaev@junvo.com>
 */

add_filter('count_attachments','count_own_attachments');
function count_own_attachments( $default, $mime_type ) {
	global $wpdb, $current_user, $pagenow;


    if( !is_a( $current_user, 'WP_User') )
        return $default;

    if( 'upload.php' != $pagenow )
        return $default;

    if( !current_user_can('delete_pages') ){
        $and = wp_post_mime_type_where( $mime_type );
		$count = $wpdb->get_results( "SELECT post_mime_type, COUNT( * ) AS num_posts FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status != 'trash' AND post_author= '$current_user->id' $and GROUP BY post_mime_type", ARRAY_A );
	
		$stats = array( );
		foreach( (array) $count as $row ) {
			$stats[$row['post_mime_type']] = $row['num_posts'];
		}
		$stats['trash'] = $wpdb->get_var( "SELECT COUNT( * ) FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status = 'trash' AND post_author= '$current_user->id' $and");
		$stats['orphans'] = $wpdb->get_var( "SELECT COUNT( * ) FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status != 'trash' AND post_parent < 1 AND post_author= '$current_user->id' $and");
		return (object)$stats;
	}
    return $default;
}
?>

Save the code above to manage_your_media_only-v0.2.php, zip it, upload as a plugin to WordPress and activate it.

You also must to modify a couple of files:

In /wp-includes/post.php modify function wp_count_attachments:

function wp_count_attachments( $mime_type = '' ) {
	global $wpdb;

	$and = wp_post_mime_type_where( $mime_type );
	$count = $wpdb->get_results( "SELECT post_mime_type, COUNT( * ) AS num_posts FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status != 'trash' $and GROUP BY post_mime_type", ARRAY_A );

	$stats = array( );
	foreach( (array) $count as $row ) {
		$stats[$row['post_mime_type']] = $row['num_posts'];
	}
	$stats['trash'] = $wpdb->get_var( "SELECT COUNT( * ) FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status = 'trash' $and");
	$stats['orphans'] = $wpdb->get_var( "SELECT COUNT( * ) FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status != 'trash' AND post_parent < 1 $and");

	return apply_filters( 'count_attachments', (object) $stats, $mime_type ); 
}

In /wp-admin/includes/class-wp-media-table.php in function get_views replace

$_total_posts = array_sum($_num_posts) - $_num_posts['trash'];
if ( !isset( $total_orphans ) )
	$total_orphans = $wpdb->get_var( "SELECT COUNT( * ) FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status != 'trash' AND post_parent < 1" );

with

$_total_posts = array_sum($_num_posts) - $_num_posts['trash'] - $_num_posts['orphans'];
if ( !isset( $total_orphans ) )
	$total_orphans = $_num_posts['orphans'];

After that you'll have nice media library with right permission.