1

I am trying to list all private pages that user has access to read. To explain in more details, below is the initial setup:

Each user has a specific role created and assigned only ability to read private pages. Then these roles are selected for specific pages to limit access to that page.

Example:

  • "user 1" role name = "user_1_role", capabilities = "Read Private Pages"
  • "user 2" role name = "user_2_role", capabilities = "Read Private Pages"
  • "Page 1", visibility set to Private, limit access to "user_1_role"
  • "Page 2", visibility set to Private, limit access to "user_1_role" and "user_2_role"

Goal:

  • When "user 1" is logged in, I would like to list all pages that this user is able to read. In this example that would be "Page 1" only.
  • For "user 2" the listing would be "Page 1" and "Page 2" as this user is able to read both pages.

I tried following code but this is listing all existing private pages and not only those with limited access to currently logged in user:

    $pages = get_pages(
        array('post_status' => array( 'private' ),
    ));
    foreach ( $pages as $page ) {
      if (current_user_can( 'read_private_pages', $page->ID )) {
          echo $page->post_title . "<br/>";
      }
    }

Any help would be much appreciated.

EDIT: I did not mention in original post that there can be unlimited number of pages and also user roles and users. So ideally the solution should work for any number of posts, users and roles.

I tried also following code similar to the above but with the same result:

    $user = wp_get_current_user();
    $pages = get_pages(
        array('post_status' => array( 'private' ),
    ));
    foreach ( $pages as $page ) {
      if ($user->has_cap( 'read_private_pages', $page->ID )) {
          echo $page->post_title . "<br/>";
      }
    }

When I try to change the capability to e.g. current_user_can( 'read_pages', $page->ID ), it is correctly not showing any pages in the list as there is no user with read_pages permissions, just with read_private_pages. So the current_user_can() somehow works, I just think the second parameter with $page->ID is for some reason not taken into account.

EDIT 2: I also forgot to mention that I am using a 3rd party plugin to create roles and restrict pages, known as MembersPress, so the answer/code must be able to work in conjunction with the aforementioned plugin.

1 Answer 1

0

I have made the following code for you to copy and paste in to your functions.php file.

I'm sure there is a simpler solution, however this is the working solution I came up with.

The first part of the section adds the new roles.

function anakeme_custom_roles() {

    add_role(
        'level_1',
        'Level 1',
        [
            'read_private_pages' => true,
            'read_level_1' => true,
        ]
    );

    add_role(
        'level_2',
        'Level 2',
        [
            'read_private_pages' => true,
            'read_level_2' => true,
        ]
    );

}
add_action( 'init', 'anakeme_custom_roles' );

The second part of the code creates the foreach loop and adds conditions depending on the users capabilities and page level.

function anakeme_shortcode_level() {

    $pages = get_pages(
        array(
            'post_status' => array( 'private' ),
        )
    );

    foreach ( $pages as $page ) {

        $page_level = get_post_meta( $page->ID, 'visibility_level', true );
        $read_1 = current_user_can( 'read_level_1', $page->ID );
        $read_2 = current_user_can( 'read_level_2', $page->ID );

        if ( $read_1 && $page_level == 1 ) {

            echo $page->post_title . "<br/>";

        } else if( $read_2 && $page_level >= 1 ) {

            echo $page->post_title . "<br/>";

        }

    }

}
add_shortcode( 'list_pages_level', 'anakeme_shortcode_level' );

Now for this to work, you must create a custom field in the pages you want to remain exclusive for certain roles/levels. The roles I created in my example use a numbering system.

So for Level 1 users to access level 1 pages, I simply added the custom field visibility_level and the value 1. Same goes for Level 2 users, just swapping the value 1 for 2.

Once that numbering system was established, I used a condition to check if the number was equal to 1 or more, then displayed the results accordingly.

To implement this anywhere in your site, use the shortcode list_pages_level.

If you would like further help in understanding the above code, or help expanding on the code, please reply with your questions(s)

EDIT

The above code will work without using third party plugins, however as the OP requires a code to work in conjunction with a plugin known as 'MembersPress', the below code should satisfy the OP's requirements of displaying pages that the currently logged in user has access to.

function anakeme_shortcode_level() {
    
    global $current_user;

    /**
      *
      * Get 'private' pages as array.
      *
      */
    $pages = get_pages(
        array(
            'post_status' => 'private',
        )
    );
    
    /**
      *
      * Loop through all pages.
      *
      */
    foreach ( $pages as $page ) {
        
        /**
          *
          * Get current users role.
          *
          */
        $user_roles = $current_user->roles;
        $user_role = array_shift( $user_roles );
        
        /**
          *
          * Check the current user can read private pages.
          *
          */
        $private = current_user_can( 'read_private_pages', $page->ID );
        
        /**
          *
          * Get the roles that have access to the associated page.
          *
          */
        $restricted = get_post_meta( $page->ID, '_members_access_role' );
        
        /**
          *
          * Find and echo only pages where the user has access to private pages and the `users role` is equal to the `role` restriction on the page set by MembersPress.
          *
          */
        if( ( $private ) && ( $user_role == in_array( $user_role, $restricted ) ) ) {
                
            echo $page->post_title . "<br/>";
            
        }

    }

}
add_shortcode( 'list_pages_level', 'anakeme_shortcode_level' );

Please note that the code provided above is NOT normally provided by StackOverflow members as it is relating to a 3rd party plugin (MembersPress). Please be sure to contact the plugin's customer support in the future for any coding requests.

Please be sure to mark the answer as correct if this is what you required and to also upvote the answer as a kind-of thank you :)

13
  • Thank you Anake very much for the code and your effort. It is clear and for above described example it would work fine. The real world scenario is a bit more difficult and I am not sure how to adapt this approach. To explain further, there could be unlimited number or users, roles and also pages. Selecting what user roles are able to read specific pages is done in WP admin UI. I would then like to programmatically list all private pages that currently logged user has access rights to read.
    – Jospo
    Apr 5, 2021 at 19:47
  • Unfortunately this is something that would require A LOT more coding. It would be best to approach a plugin developer or to search for a plugin to achieve your result. This forum is only here to help with debugging code errors or steer users/developers in the right direction. The original request was to List all private pages user has access rights to read, which has been accomplished in the above code.
    – Anake.me
    Apr 5, 2021 at 23:49
  • Thanks Anake, understood. Do you have an explanation please why my original sample code does not work? I don't see anything obvious why it shouldn't work. I will also add an info in the original post that I would like to list all private pages user has access rights to read and that there can be unlimited number of user roles to make it more clear. Thanks!
    – Jospo
    Apr 6, 2021 at 8:29
  • If you wrap your code in a function and add a shortcode action, you would be able to display your private pages, but without any conditions relating to the restrictions, it would display ALL private pages.
    – Anake.me
    Apr 6, 2021 at 14:38
  • Sorry, Im not sure I was clear in my response - unfortunately users on StackOverflow are not here to provide free coding services, but instead to help you with YOUR code. If you have further code you have made/used in relation to this subject, please do share it via editing the OP.
    – Anake.me
    Apr 6, 2021 at 14:46

Your Answer

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

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