Skip Navigation

[Resolved] View with child post type: hide posts where parent is private/concept

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

Problem: I have a View of child posts. I would like to apply a query filter so that the View only shows children of parents that are NOT marked "private".

Solution:
This type of filter does not exist, but you can add some custom code using the wpv_filter_query and toolset_get_related_posts APIs to create the query in code.

add_filter('wpv_filter_query', 'ts_parent_not_private_func', 10, 3);
function ts_parent_not_private_func($query, $view_settings, $view_id) {
  $views = array( 16813, 16403 ); // only filter these views
  if( in_array( $view_id, $views ) ) {
    $child_ids = array(); // we will push IDs here if the parent is not found, or private
    $children_args = array(
      'post_type' => 'training-datum',
      'posts_per_page' => '-1',
      'post_status' => 'publish',
      // you may want to add more filters here to improve the performance of this query
    );
    $children = new WP_Query($children_args);
    foreach( $children->posts as $child ){
      $parent = toolset_get_related_post( $child, 'training_training-datum', 'parent' );
      // if there is no parent or the parent is private, push this ID into the exclusion array
      if( !$parent || get_post_status($parent) == 'private' ){
        array_push( $child_ids, $child->ID );
      }
    }
  
    $query['post__not_in'] = isset( $query['post__not_in'] ) ? $query['post__not_in'] : array();
    $query['post__not_in'] = array_merge($query['post__not_in'], $child_ids );
  }
  return $query;
}

Relevant Documentation:
See follow up post here: https://toolset.com/forums/topic/view-with-child-post-type-hide-posts-where-parent-is-private-concept-part-3/

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 5 replies, has 2 voices.

Last updated by martijnH 6 years, 2 months ago.

Assisted by: Christian Cox.

Author
Posts
#1119026

I was not able to reopen
https://toolset.com/forums/topic/view-with-child-post-type-hide-posts-where-parent-is-private-concept/, but still need help.

I do not use a nested view to display parent and child posts. It is just a single view which only shows data of the child CPT. The CPT does have a parent CPT, but this CPT is not involved in showing the child data in this view.

Is it possible to filter on status of the parent CPT even if it is not a nested view?

#1119301

Hi, you can't use the Views GUI to filter a View of CPT A based on information from CPT B or CPT C, etc. even if these posts are in a post relationship. Some improvements are in development for Views that will help you use filters with post relationships more effectively, but I haven't received a timeline for the delivery of those improvements yet.

The best way to do this now is to use custom code. Use the wpv_filter_query_post_process filter to inspect and modify the results of a View before they are displayed. Use the toolset_get_related_post API to determine a parent in a post relationship. Use the get_post_status API (a WordPress native API) to determine the parent post's status. Another ticket I was working on today discusses a similar request:
https://toolset.com/forums/topic/filter-a-view-with-no-relationship/#post-1119289
In their case, they want to only show posts with no parent. In your case, you want to only show posts with parent not having a specific post status. So lines 8-11 in that code sample would be replaced with something like this:

        if( get_post_status( $prnt ) != 'private' ) {
          // add this post if the parent is not "private" status
          array_push($single_children, $this_child);
        }

This is the best way to set up this type of filter right now.

One simpler alternative is to use conditional HTML in the Loop of a View of child posts. Test the post status of the parent post, and show or hide the results based on that conditional. This method has limitations, for example, it doesn't work well with pagination or results counts because conditionals come into play after pagination and post counts are calculated.

[wpv-conditional if="( '[wpv-post-status item="@relationship-slug.parent"]' ne 'private' )"]
  [wpv-post-link]
[/wpv-conditional]
#1119774

Hi Christian,

I used your first suggestion, which works... almost

It looks like my post count is not modified... My view has max 7 items, with one post where parent is private. The view filters this post, but shows 6 items instead of 7.

Can that be solved?

My code

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( 16813, 16403 ); // 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, 'training_training-datum', 'parent' );
        if( get_post_status( $prnt ) != 'private' ) {
			// add this post if the parent is not "private" status
			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
}

p.s. Maybe you should inform alexanderl-2 who was interested in the solution for https://toolset.com/forums/topic/view-with-child-post-type-hide-posts-where-parent-is-private-concept/ 🙂

#1120830

Okay in this case, I think a different filter is best:

add_filter('wpv_filter_query', 'ts_parent_not_private_func', 10, 3);
function ts_parent_not_private_func($query, $view_settings, $view_id) {
  $views = array( 16813, 16403 ); // only filter these views
  if( in_array( $view_id, $views ) ) {
    $child_ids = array(); // we will push IDs here if the parent is private
    $parent_args = array(
      'post_type' => 'training',
      'post_status' => 'private',
      'posts_per_page' => -1,
      // add any additional parent filters here to optimize this query
    );
    $parents = new WP_Query($parent_args); // we will get all private parents
    foreach ($parents->posts as $parent ) {
      $children = toolset_get_related_posts(
        $parent->ID,
        'training_training-datum',
        'parent',
        1000000,
        0,
        null,
        'post_id',
        'child'
      );
      $child_ids = array_merge($child_ids, $children); // now push those private parents' children into the exclusion 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'], $child_ids );
  }
  return $query;
}

We're effectively looping over all private parent posts here, and calling the toolset_get_related_posts API on each one. It may be a good idea to add any relevant query criteria to the $parent_args array to help speed up the performance of this filter.

#1126280

My issue is resolved now. Thank you!

#1132754

Sorry, not resolved. I was logged in and eveything looked right. The childs with private parents were not shown. But when I logged out, the childs with private parent showed up again in the view.