Home › Toolset Professional Support › [Waiting for user feedback] Filtering backend post listings by relationship
This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.
Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.
This topic contains 1 reply, has 1 voice.
Last updated by Christopher Amirian 19 hours, 14 minutes ago.
Assisted by: Christopher Amirian.
Tell us what you are trying to do?
I would like to create a role, Manager, that can only view posts from the Providers post type when both the Manager and the Provider are associated with a third post type called Zip Code. The goal is to assign Providers to Zip Codes, and to assign Managers of those Provider posts to overlapping Zip Codes and let the Managers view / edit those providers who are in Zip Codes that the Manager has been assigned to.
Is there any documentation that you are following?
We did explore this a bit: https://toolset.com/forums/topic/display-related-posts-chosen-in-the-backend/
Is there a similar example that we can see?
What is the link to your site?
hidden link ... providers can be seen by clicking on a county map on the homepage, taking you to a location like hidden link where they are listed below.
Hi,
Welcome to Toolset support. I have an idea that is considered a custom development. So I will be able to give you a starting point, but a complete implementation will be on your shoulders.
The WordPress admin list can't be filtered by relationships out of the box, but you can achieve exactly what you want with a tiny bit of code + Toolset Access.
Overall Idea:
- Keep two many-to-many relationships:
provider-zip: Providers <> Zip Codes
manager-zip: Managers <> Zip Codes
- Create a Manager user role (Toolset > Access).
- Represent each manager as a "Manager" CPT post authored by that user (1:1). This lets us use Toolset's relationship API with users indirectly.
- In wp-admin, filter the Providers list so a logged-in Manager only sees Providers sharing at least one Zip Code with their Manager post.
- Also, hard-enforce edit permission for single posts.
You would add the implementation code using the method below:
https://toolset.com/documentation/programmer-reference/adding-custom-code/using-toolset-to-add-custom-code/
1- Filter the Providers list in wp-admin
Add the code below:
<?php
// --- Helpers ---------------------------------------------------------------
function dsp_get_manager_zip_ids( $user_id ) {
// Find the Manager CPT authored by this user.
$mgr = get_posts([
'post_type' => 'manager', // <-- your Manager CPT slug
'author' => $user_id,
'posts_per_page' => 1,
'fields' => 'ids',
]);
if (empty($mgr)) return [];
$manager_post_id = $mgr[0];
// Get Zip Codes related to the Manager via the manager-zip relationship.
// Adjust query_by_role to match how you defined the sides.
$zip_ids = toolset_get_related_posts( $manager_post_id, 'manager-zip', [
'query_by_role' => 'parent', // or 'child' as per your setup
'return' => 'ids',
'args' => ['posts_per_page' => -1],
]);
return array_map('intval', (array) $zip_ids);
}
function dsp_get_provider_ids_for_zip_ids( array $zip_ids ) {
$out = [];
foreach ($zip_ids as $zip_id) {
// Get Providers related to each Zip Code.
$prov = toolset_get_related_posts( $zip_id, 'provider-zip', [
'query_by_role' => 'parent', // or 'child' as per your setup
'return' => 'ids',
'args' => ['posts_per_page' => -1],
]);
$out = array_merge($out, (array) $prov);
}
return array_values(array_unique(array_map('intval', $out)));
}
function dsp_manager_can_access_provider( $user_id, $provider_id ) {
$mgr_zips = dsp_get_manager_zip_ids($user_id);
if (empty($mgr_zips)) return false;
// Zip codes linked to this Provider.
$prov_zips = toolset_get_related_posts( $provider_id, 'provider-zip', [
'query_by_role' => 'child', // opposite of what you used above
'return' => 'ids',
'args' => ['posts_per_page' => -1],
]);
return (bool) array_intersect( $mgr_zips, (array) $prov_zips );
}
// --- 1) Limit Providers list in admin -------------------------------------
add_action('pre_get_posts', function( $q ){
if ( ! is_admin() || ! $q->is_main_query() ) return;
if ( $q->get('post_type') !== 'provider' ) return;
$user = wp_get_current_user();
if ( ! in_array( 'manager', (array) $user->roles, true ) ) return;
$zip_ids = dsp_get_manager_zip_ids( $user->ID );
$provider_ids = dsp_get_provider_ids_for_zip_ids( $zip_ids );
// If none match, show empty list.
$q->set( 'post__in', $provider_ids ?: [0] );
});
// --- 2) Enforce edit/read/delete on single posts ---------------------------
add_filter('user_has_cap', function( $all_caps, $caps, $args, $user ){
$requested = $caps[0] ?? '';
if ( ! in_array( $requested, ['edit_post','read_post','delete_post'], true ) ) return $all_caps;
$post_id = $args[2] ?? 0;
$post = get_post( $post_id );
if ( ! $post || $post->post_type !== 'provider' ) return $all_caps;
if ( ! in_array( 'manager', (array) $user->roles, true ) ) return $all_caps;
if ( ! dsp_manager_can_access_provider( $user->ID, $post_id ) ) {
$all_caps[ $requested ] = false;
}
return $all_caps;
}, 10, 4);
Replace slugs to match your site:
- CPT slugs: provider, zip-code, manager
- Relationship slugs: provider-zip, manager-zip
- Relationship roles (parent/child) as created in Toolset.
The code above will achieve the points below:
In Posts > Providers, Managers only see Providers that share at least one Zip with them.
If a Manager tries to access a Provider directly (URL), permission is denied.
2- Toolset Access
- Create Manager role.
- Grant it the minimal caps for the Provider CPT (e.g., read, edit).
- The code above will further limit which Providers they can see/edit.
- Leave admin/editor with full access.
I think this will be a good starting point and a solid foundation for what you want to achieve.
Needless to say, I did not personally test the steps, and it is just an idea for further implementation by you.
Thanks.