• I have a need to limit items in the media library for users without a specific capability. There are a lot of examples out there for how to limit them to only items that a given user has uploaded, but my need is more complex than that.

    I need to limit media items for users without a specific capability to those attachments that are NOT:

    1. header images (i.e., set in Appearance > Headers)
    2. page thumbnails (i.e., featured images)

    Below is the solution I’ve come up.

    /*
     * restrict media items available to users without cap=mycap to those that are NOT:
     *
     * 1. theme headers (i.e., set in Appearance > Headers)
     * 2. page thumbnails (i.e., featured images)
     */
    add_action ('pre_get_posts', 'restrict_media') ;
    function
    restrict_media ($query)
    {
    	if (!is_admin () || $query->get ('post_type') != 'attachment' ||
    			current_user_can ('mycap')) {
    		return ;
    		}
    
    	// get our theme's headers (i.e., set in Appearance > Headers)
    	$args = array (
    		'post_type' => 'attachment',
    		'post_status' => array ('inherit', 'private'),
    		'posts_per_page' => -1,
    		'meta_query' => array (
    			'relation' => 'AND',
    			array (
    				'key' => '_wp_attachment_context',
    				'value' => 'custom-header',
    				),
    			array (
    				'key' => '_wp_attachment_is_custom_header',
    				'value' => 'antelopevalley',
    				),
    			),
    		) ;
    	// remove ourself from pre_get_posts to avoid infinite regression
    	remove_action ('pre_get_posts', array ($this, 'restrict_media')) ;
    	$headers = new WP_Query ($args) ;
    	// get the IDs of the headers
    	$header_ids = array_map (function ($p) { return ($p->ID) ; }, $headers->posts) ;
    
    	// add ourself back to pre_get_posts for subsequent queries
    	add_action ('pre_get_posts', array ($this, 'restrict_media')) ;
    
    	// get posts with thumbnails
    	$args = array (
    		'post_type' => 'page',
    		'post_status' => array ('publish', 'pending', 'draft', 'private'),
    		'posts_per_page' => -1,
    		'meta_query' => array (
    			array (
    				'key' => '_thumbnail_id',
    				'compare' => 'EXISTS',
    				),
    			),
    		) ;
    	$with_thumbnail = new WP_Query ($args) ;
    	// get the IDs of the thumbnails
    	$thumbnail_ids = array_map (function ($p) { return (get_post_meta ($p->ID, '_thumbnail_id', true)) ; },
    		$with_thumbnail->posts) ;
    
    	// exclude all theme headers and thumbnails
    	$query->set ('post__not_in', array_merge ($header_ids, $thumbnail_ids)) ;
    
    	return ;
    }

    The above solution works; however, it seems overly complex to me!

    I’m wondering if anyone can suggest a simpler solution.

    Note: I’ve tried the post_{where,join} filters before for other needs and have found them too complex to maintain so I didn’t even try to figure out a solution to this problem using them, but I’m more than open to one that uses them

Viewing 1 replies (of 1 total)
  • Moderator bcworkz

    (@bcworkz)

    I would be inclined to write a complete mySQL query that returns exactly what I want and use it with $wpdb. In my mind, the only big advantage to WP_Query besides familiarity is pagination which doesn’t sound like an issue here.

Viewing 1 replies (of 1 total)
  • The topic ‘complex restriction of items in media library’ is closed to new replies.