[Membership 2 Pro] Display Posts with Custom Query and Filter Out Protected Content

Trying to create a short code to display posts onto a page. The content on that page is within a Membership shortcode for only members to see. This site is "sub-memberships" that allow each member to view different content/posts. When I run my query and find all posts and display them, I'm somehow bypassing the Membership filter, so all posts are being displayed in my loop, however when clicking on them I get the "no permission" message, which is correct. However, I need them not to display in my query in the first place. I was hoping to be able to pass an argument into my query, or run a check while in the loop or something.

Here is my relevant code...
https://pastebin.com/jTC2cQYK

  • Christopher

    Well I couldn't find a way to pull the posts memberships.... so I got this to work sort of.

    Before my Query

    $api = ms_api();
        $member = $api->get_current_member();
        $membership = $api->detect_membership();

    Then In the Loop

    $access = $membership->has_access_to_post( get_the_ID() );
    
                    if ( $access ) { POST HERE }

    However, the issue now is that it's not returning all posts. It is finding ONE membership a person might have and running posts against that. However, if a user has multiple memberships it wont check posts against ALL memberships.

    Example: A user has two memberships A & B, and there are two posts, one protected by A and another by B. The script will find that the user has membership A and check both posts against it, which fails on the second post (protected by B).

  • Christopher

    Here is my existing code....

    $posts = '';
        $postCount = 0;
    
        $api = ms_api();
        $member = $api->get_current_member();
        $membership = $api->detect_membership();
    
        $args = array(
            'post_type'              => array( 'post' ),
            'post_status'            => array( 'publish' ),
            'posts_per_page'         => '9',
        );
    
        $query = new WP_Query( $args );
    
        if ( $query->have_posts() ) {
            while ( $query->have_posts() ) {
                $query->the_post();
    
                    $access = $membership->has_access_to_post( get_the_ID() );
    
                    if ( $access ) {
    
                    $postCount =+ 1;
                    $postdate = get_the_date('F j, Y');
    
                    $posts .= '<div class="row">
                                    <div class="post-single">
                                        <div class="thumb" style="background:url('.wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'large' )[0].');"></div>
                                        <div class="title">
                                            <a href="'.get_the_permalink().'">
                                                <h4 class="news-title">'.get_the_title().'</h4>
                                            </a>
                                            <div class="post-details">
                                                <i class="fa fa-calendar" aria-hidden="true"></i> '.$postdate.' <span class="divider">|</span> ';
                                                foreach((get_the_category()) as $category) {
                                                        $posts .= '<span class="category-badge">'. $category->cat_name .'</span>';
                                                    }
    
                                            $posts .= '</div>
                                        </div>
                                        <div class="excerpt">'.get_the_excerpt().'</div>
                                    </div>
                               </div>';
                    }
    
            }
        } else {
            $posts .= 'Sorry, no News Updates were found.';
        }
    
        if ($postCount == 0) {
            $posts .= 'Sorry, we were not able to find any News Updates that you have access to.';
        }
    
    $output = '<section id="blog">
                        <div class="container">
                            '.$posts.'
                        </div>
                    </section>';
    
        return $output;
    
        wp_reset_postdata();
  • Panos

    Hi Christopher ,

    Apologies for delay here!

    This is not how the plugin is supposed to work as it only protects when accessing a protected item. It allows them to be listed so this needs some custom solution.

    Since you have your query, we need to exclude the protected items from args, with post__not_in

    I have prepared a custom function which should return the list of protected post ids but allowing post ids that are protected by the current member's membership ids:

    function wpmudev_ms_list_protected_posts_ids() {
    
    	$member_memberships = array();
    
    	if ( is_user_logged_in() ) {
    		$member = MS_Model_Member::get_current_member();
    		$member_memberships = $member->get_membership_ids();
    
    		if ( current_user_can( 'manage_options' ) ) {
    			return array();
    		}
    	}
    
    	$membership_ids = MS_Model_Membership::get_membership_ids();
    	// Post ids that are protected
    	$protected_post_ids = array();
    	// Post ids that member memberships allow to access, even if protected
    	$allowed_post_ids 	= array();
    	//$rule_types 		= MS_Model_Rule::get_rule_types();
    	$rule_types 		= array( 'post', 'page', 'cpt_group' );
    
    	foreach ( $membership_ids as $membership_id ){
    
    		$membership = MS_Factory::load( 'MS_Model_Membership', $membership_id );
    
    		foreach ( $rule_types as $rule_type ) {
    			$rule = $membership->get_rule( $rule_type );
    
    			if ( $rule->rule_type != $rule_type ) {
    				continue;
    			}
    
    			if ( is_array( $rule->rule_value ) && ! empty( $rule->rule_value ) ) {
    
    				$rule_post_ids = array();
    
    				foreach ( $rule->rule_value as $post_id => $protected ){
    					if ( $protected ) {
    						$rule_post_ids[] = $post_id;
    					}
    				}
    				if ( ! empty( $rule_post_ids ) ) {
    					$protected_post_ids = array_merge( $protected_post_ids, $rule_post_ids );
    
    					if( in_array( $membership_id, $member_memberships ) ) {
    						$allowed_post_ids = array_merge( $allowed_post_ids, $rule_post_ids );
    					}
    
    				}
    
    			}
    
    		}
    
    	}
    
    	$protected_post_ids = array_diff(
    		array_unique( $protected_post_ids ),
    		array_unique( $allowed_post_ids )
    	);
    
    	return $protected_post_ids;
    
    }

    In your query args you can try add:

    post__not_in => wpmudev_ms_list_protected_posts_ids()

    Hope this helps!

    Cheers!