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.