1

I'd like to disable access to posts in the back-end/Admin from a user that doesn't have the privilege to view those posts. This will function similar to the Author role however this "privilege" is controlled by an ACF User relationship field and not by a WP Core role or privilege.

One level of complexity deeper, the User relationship field is actually pointing to a parent/grouping custom post type that is then tied to the children post elements I'm attempting to filter. So rather than show just the posts that user has authored, it's also showing posts that others have authored but that they have been granted permission to manage. Let me explain this below...

Custom Post Type: Shoes [shoe]
Custom Post Type: Brands [brand]

  • Let's say you have a "shoe" called "Air Jordans" and you have a "brand" called "Nike".
  • So you create an ACF bidirectional relationship between "Air Jordan" and "Nike".
  • Now let's say you create a user on your site that you want to be able to edit all "Nike" shoes.
  • So you create an ACF User relationship field type in the "brand" post type, and you can assign multiple users to admin that brand.
  • So, when that user logs into the back-end and views all shoes, I want just Nikes shoes to show up and they will have the ability to edit all Nike shoes.

I've built out the logic to handle this on the front-end and it works perfect, and now I'd like to duplicate this on the back-end for filtering there as well. Here's what I built out on the front-end for reference:

$current_user = wp_get_current_user();

/* Get All Brands the Current User can Administer */
$brands_admin_args = array(
  'post_type'   => 'brand',
  'meta_query'  => array(
      array(
          'key'     => 'admins', // This is my ACF User field that tracks brand admins.
          'value'   => '"' . $current_user->ID . '"',
          'compare' => 'LIKE'
      ),
  ),
);
$brands_admin = get_posts($brands_admin_args);


/* Get All Shoes The User Can Administer Based On Each Brand They Can Administer*/
$approved_shoes_args = array(
  'post_type'       => 'shoe',
  'meta_query'      => array(
      'relation'    => 'OR'
  ),
);

foreach ($brands_admin as $ba) {
  array_push($approved_shoes_args['meta_query'], array(
      'key'       => 'shoe_brands', // This is my ACF Relationship field between Shoes and Brands 
      'value'     =>  '"' . $ba->ID . '"',
      'compare'   => 'LIKE'
  ));
}
$approved_shoes = new WP_Query($approved_shoes_args);

2 Answers 2

1

Your best bet is to use the pre_get_posts hook to adjust the query on the admin side.

Your logic is pretty complicated so I won't try to give you a working example but the snippet below will get you started. Basically, you want to be sure your in the admin and managing the main query.

Codex link

add_action( 'pre_get_posts', 'customize_admin_query' );

function customize_admin_query( $wp_query ) {
    if ( $wp_query->is_admin() && $wp_query->is_main_query() ) {
        // do your customizations in here.
    }
}
0

Taking @Welcher's suggestion of using pre_get_posts, I took my existing code and compiled the following to filter edit.php page for my custom post based on an ACF field granting the current user's access rights:

add_action( 'pre_get_posts', 'customize_products_for_admins' );
function customize_products_for_admins( $wp_query ) {

    if ( is_admin() && $wp_query->is_main_query() && current_user_can('editor') ) { // I know I need more conditional statements here

        $current_user = wp_get_current_user();

        /* Get All Brands the Current User can Administer */
        $brands_admin_args = array(
            'post_type'   => "brand",
            'meta_query'  => array(
                array(
                    'key'     => "admins",
                    'value'   => '"' . $current_user->ID . '"',
                    'compare' => "LIKE"
                ),
            ),
        );
        $brands_admin   = get_posts($brands_admin_args);

        /* Get All Shoes The User Can Administer Based On Each Brand They Can Administer */
        $approved_shoes_args = array(
            'meta_query'      => array(
                'relation'    => "OR"
            ),
        );

        foreach ($brands_admin as $ba) {
            array_push($approved_shoes_args['meta_query'], array(
                'key'       => "shoe_brands", // This is my ACF Relationship field between Shoes and Brands
                'value'     =>  '"' . $ba->ID . '"',
                'compare'   => "LIKE"
            ));
        }
        $wp_query->set('meta_query', $approved_shoes_args);
    }
}

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.