Skip Navigation

[Resolved] Filter a view with No relationship

This thread is resolved. Here is a description of the problem and solution.

Problem: I have two post types in a many-to-many (M2M) post relationship. I would like to show a View of one of these post types, and apply a filter so that only posts that have no assigned relationship are shown.

Solution:
You can use the wpv_filter_query API along with the toolset_get_related_posts API to apply a custom Query Filter.

/**
 * Apply a custom filter to only show Projects which are not yet related to any Client (M2M relationship).
 * This filter is currently used on the Single Company page.
 */
add_filter('wpv_filter_query', 'ts_not_linked_to_client_filter', 10, 3);
function ts_not_linked_to_client_filter($query, $view_settings, $view_id) {
  $views = array( 64 ); // only filter these views
  if( in_array( $view_id, $views ) ) {
    $project_ids = array(); // push all related project IDs here
    $client_args = array(
      'post_type' => 'client',
      'posts_per_page' => -1,
    );
    $clients = new WP_Query($client_args); // get all clients
    foreach ($clients->posts as $client ) {
      $projects = toolset_get_related_posts(
        $client->ID,
        'client-project',
        'parent',
        1000000,
        0,
        null,
        'post_id',
        'child'
      );
      $project_ids = array_merge($project_ids, $projects); // push the related project IDs into this array
    } 
    $query['post__not_in'] = isset( $query['post__not_in'] ) ? $query['post__not_in'] : array();
    $query['post__not_in'] = array_merge($query['post__not_in'], $project_ids ); // update the main query to exclude related project ids
  }
  return $query;
}

Relevant Documentation:
https://toolset.com/documentation/customizing-sites-using-php/post-relationships-api/#toolset_get_related_posts
https://toolset.com/documentation/programmer-reference/views-filters/#wpv_filter_query

This support ticket is created 6 years, 2 months ago. There's a good chance that you are reading advice that it now obsolete.

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.

Sun Mon Tue Wed Thu Fri Sat
8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 - -
13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 - -

Supporter timezone: America/New_York (GMT-04:00)

This topic contains 7 replies, has 2 voices.

Last updated by grahamA 6 years, 2 months ago.

Assisted by: Christian Cox.

Author
Posts
#1118993

Tell us what you are trying to do?
I have a display list of ALL posts in a given post type and a relationship form for the User to link them with another post type.
I would like to be able to remove the post title from the original display list once it has been related to the new post type.

Is it possible to create a query filter that says 'select items that have NO relationship'? ie show only post titles that are not yet related to anything, or is there some sort of work around.

Many thanks

#1119289

Hi, is this a One-to-One post relationship? We plan to enhance 1-1 Relationship Forms so that the post selection fields do not include posts that are already part of a O2O relationship. This may eliminate the need for a separate View, depending on what you want to accomplish. That ticket is under development now, but I don't have a timeline for delivery available just yet.

As a workaround, you can use the wpv_filter_query_post_process API along with the toolset_get_related_post API to show a list of posts with no relationship. The toolget_get_related_post API will return a "0" if no related post exists. Here's an example showing how you would filter a View of some child post type in a one-to-one relationship with the slug "p-child":

add_filter( 'wpv_filter_query_post_process', 'ts_only_single_children_query', 10, 3 );
function ts_only_single_children_query( $query, $view_settings, $view_id ) {
    $views = array( 12345 ); // only filter these views
    if( in_array( $view_id, $views ) ) {
      $single_children = array();
      foreach( $query->posts as $this_child ) {
        $prnt = toolset_get_related_post( $this_child->ID, 'p-child', 'parent' );
        if( $prnt == 0 ) {
          // only add unrelated children to this array
          array_push($single_children, $this_child);
        }
      }
      $query->posts = $single_children; // modify the query results to only include single children
      $query->found_posts = count($single_children); // modify the count of found posts
      $query->post_count = count($single_children); // modify the count of displayed posts
    }
    return $query; // return the query
}

Replace 12345 with the numeric ID of your View of Child posts, and replace 'p-child' with the actual relationship slug. I can provide more assistance if you tell me about the post types and post relationship. I need to know the post type slugs and relationship slug, which post type is parent and which post type is child, and the type of post relationship.

We have documentation for these APIs available here:
https://toolset.com/documentation/customizing-sites-using-php/post-relationships-api/#toolset_get_related_post
https://toolset.com/documentation/programmer-reference/views-filters/#wpv_filter_query_post_process

#1122614

Hi Thanks for this reply. Your clean up robot has nudged me 🙂

I am awaiting my coding guy to come free to look at this (it's over my head :P) so please keep this thread open . Thanks

#1122967

Sure, I will stand by for your update.

#1123916

Hi Christian
It looks like I wont get my coder guy to help me with this so I don't know if it is a step too far to ask the following.
Could you implement your suggestion on my test site so I can copy it to my development site?

I would give you ftp and admin access but all the boxes to give you the info appear to have disappeared in this thread. How can I give you site access please

#1124006

Sure, I can reactivate private reply fields here. Let me know where I can see the issue on the front-end of your site, and I will take a closer look in wp-admin.

#1124586

Okay please check the site now. I was working on this Client: hidden link

The list of available Projects now only shows those Projects which are not yet related to a Client. I tested by adding a relationship to Project 12, which is now added to the first View and removed from the second View. I added this code snippet in Toolset > Settings > Custom Code:

/**
 * Apply a custom filter to only show Projects which are not yet related to any Client (M2M relationship).
 * This filter is currently used on the Single Company page.
 * Toolset support reference: https://toolset.com/forums/topic/filter-a-view-with-no-relationship/
 */
add_filter('wpv_filter_query', 'ts_not_linked_to_client_filter', 10, 3);
function ts_not_linked_to_client_filter($query, $view_settings, $view_id) {
  $views = array( 64 ); // only filter these views
  if( in_array( $view_id, $views ) ) {
    $project_ids = array(); // push all related project IDs here
    $client_args = array(
      'post_type' => 'client',
      'posts_per_page' => -1,
    );
    $clients = new WP_Query($client_args); // get all clients
    foreach ($clients->posts as $client ) {
      $projects = toolset_get_related_posts(
        $client->ID,
        'client-project',
        'parent',
        1000000,
        0,
        null,
        'post_id',
        'child'
      );
      $project_ids = array_merge($project_ids, $projects); // push the related project IDs into this array
    } 
    $query['post__not_in'] = isset( $query['post__not_in'] ) ? $query['post__not_in'] : array();
    $query['post__not_in'] = array_merge($query['post__not_in'], $project_ids ); // update the main query to exclude related project ids
  }
  return $query;
}
#1125302

My issue is resolved now. Thank you!

Awesome plugin - awesome support!