Home › Toolset Professional Support › [Resolved] View with child post type: hide posts where parent is private/concept
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 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.
Our next available supporter will start replying to tickets in about 1.25 hours from now. Thank you for your understanding.
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)
Related documentation:
This topic contains 5 replies, has 2 voices.
Last updated by martijnH 6 years, 1 month ago.
Assisted by: Christian Cox.
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?
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]
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/ 🙂
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.
My issue is resolved now. Thank you!
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.