Skip Navigation

[Resolved] Filter view on whether child posts exist

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

Problem: I would like to give my site visitors the ability to use a checkbox in a custom search View that filters based on whether or not the post has child posts.

Solution: This filter is not built-in to Views, but you can set up a custom field on the parent post type that stores a 1 if child posts exists and stores nothing if no child posts exist. That custom field value can be managed automatically with code.

add_action( 'toolset_association_created', 'toolset_number_child_posts', 10, 5 );
add_action( 'toolset_before_association_delete', 'toolset_number_child_posts', 10, 5 );
 
function toolset_number_child_posts( $relationship_slug, $parent_id, $child_id, $intermediary_id, $association_uid ) {
  // add a 1 if child properties exist to facilitate filtering by existence of child post
  if( get_post_type($parent_id)=='developments' ) {
    // get most recent property post
    $property_args = array(
      'numberposts'           =>   1,
      'post_type'             =>   'property',
      'orderby'               =>   'post_date',
      'order'                 =>   'DESC',
      'toolset_relationships' => array(
        'role'          => 'child',
        'related_to'    => $parent_id,
        'relationship'  => 'developments_property'
      ),
    );
    $properties_query = new WP_Query( $property_args );
    $properties = $properties_query->posts;
 
    if(isset($properties[0])) {
      // set the checkbox custom field value here using update_post_meta
      update_post_meta( $parent_id, 'wpcf-has-vacant-properties', 1);
    }else {
      delete_post_meta( $parent_id, 'wpcf-has-vacant-properties');
    }
  }
}

function toolset_count_child_properties_on_save( $post_id ) {
  if( get_post_type( $post_id ) == 'developments' ) {
    toolset_number_child_posts( 'developments_property', $post_id, null, null, null );
  }
}
add_action( 'save_post', 'toolset_count_child_properties_on_save', 1000);

Relevant Documentation:
https://toolset.com/documentation/customizing-sites-using-php/post-relationships-api/
https://codex.wordpress.org/Plugin_API/Action_Reference/save_post

This support ticket is created 6 years, 3 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.

No supporters are available to work today on Toolset forum. Feel free to create tickets and we will handle it as soon as we are online. 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)

This topic contains 7 replies, has 2 voices.

Last updated by Chris 6 years, 2 months ago.

Assisted by: Christian Cox.

Author
Posts
#1093787

Hi,

I have a site which lists housing developments. These may have vacant properties, which are a child post type with housing developments as the parent.

I want to be able to filter the view according to whether a housing development has any vacant properties. Ie I want a checkbox labelled something like "show only developments that have vacancies". I don't need to show the actual vacancies on this view, just filter on whether any exist.

Is it possible to create such a filter?

Link to the development version of the site: hidden link

Many thanks,

Chris

#1094030

Hi, it's not currently possible to filter a View of post type A by the existence of a related post type B. One way you could get around this is to create a separate View of post type B, filtered by post relationship, where the related housing development post is set by the current post in the loop. In the Loop editor of the new View, you will find two sections:
- wpv-items-found
- wpv-no-items-found

Display information about the parent housing development inside the wpv-items-found section. Display nothing in the wpv-no-items-found section. This will effectively filter the parent posts by whether or not they have child posts. Unfortunately it's not easy to set up a custom search filter that lets your visitors turn this on or off, so it's not very flexible. This approach can also have negative impacts on pagination if your View of housing developments is paginated - the conditional can throw off the number of results per page.

Another option requires custom code, but is well-integrated with custom search and pagination. You will add a custom field to housing developments that holds a 0 or a 1 to indicate whether or not there are vacant properties. Whenever a vacant property post is connected to or disconnected from a post relationship with a housing development, this code will be triggered. It will count the total number of child posts for the housing development and modify the custom field value programmatically. Then you can use this custom field value in a custom search filter.

I recently assisted another client who had a similar request to count the number of related posts:
https://toolset.com/forums/topic/i-would-like-to-sort-the-view-by-the-count-of-relationship-posts/

Let me know which approach you would prefer to take and we can go from there.

#1094798

Hi Christian,

Thanks for getting back to me. Yes, I had suspected that this capability wasn't built in. I think the first approach won't work for me, as what I want is for users to be able to use a control to filter whether to show only developments with vacancies.

But the second approach looks promising, and I get a sense of how to approach it from the example in the link. If you're able to give some more pointers on how to implement this, that would be very helpful.

Many thanks,

Chris

#1095163

Okay sure, I have modified that example so it is more relevant to your case:

add_action( 'toolset_association_created', 'toolset_number_child_posts', 10, 5 );
add_action( 'toolset_before_association_delete', 'toolset_number_child_posts', 10, 5 );
function toolset_number_child_posts( $relationship_slug, $parent_id, $child_id, $intermediary_id, $association_uid ) {
  // apply auto number to property posts that are children of development posts
  if( get_post_type($parent_id)=='development' && get_post_type($child_id)=='property' ) {
    // get 2 most recent sibling property posts
    $property_args = array(
      'numberposts'           =>   2,
      'post_type'             =>   'property',
      'orderby'               =>   'post_date',
      'order'                 =>   'DESC',
      'toolset_relationships' => array(
        'role'          => 'child',
        'related_to'    => $parent_id,
        'relationship'  => 'development_property'
      ),
    );
    $propertys_query = new WP_Query( $property_args );
    $propertys = $propertys_query->posts;

    if(isset($propertys[0])) {
      add_filter('wpcf_fields_postmeta_value_save' , function( $value, $type, $slug, $cf, $obj ) use ( $child_id, $last_id ) {
        if ( $obj->post->ID === $child_id && 'has-vacant-property' === $slug ) {
            return 1;
        }
        return '0';
      }, 10, 5 );
    }
  }
}

You'll have to modify post type slugs, relationship slugs, and custom field slugs.

#1099605

Hi Christian,

Many thanks for your example code. I've added a custom field to the 'developments' post type, and I've adjusted the slugs to match mine.

I also noticed that I was getting an error in line 23: the variable $last_id doesn't exist. I've deleted $last_id from that line as it doesn't seem to be used anyway.

I've tried adding and removing associations with properties, but the 'has-vacant-properties' field isn't being updated. (I notice that the slug for the field is actually 'wpcf-has-vacant-properties', but presumably since we're using the toolset filter, it will add the prefix in behind the scenes?)

Any thoughts on what else I need to check?

Thanks,

Chris

#1099718

I also noticed that I was getting an error in line 23: the variable $last_id doesn't exist. I've deleted $last_id from that line as it doesn't seem to be used anyway.
Ah yes, left over from a different example. Sorry for the confusion.

I'll be glad to take a look. Can you provide login credentials here in the private reply fields?

#1100677

1. Checkboxes that are set to "Save 0 when nothing is checked" are not recommended for custom search Views. This setting is known to cause problems with custom searches and should be avoided. I modified this custom field to save nothing when nothing is checked instead. You should resave all Housing Development posts in wp-admin to reset these values correctly.

2. Since the custom field is on the parent post, not the child post or an intermediary, the add_filter bit isn't going to work here. You must manually change the custom field value using update_post_meta:

add_action( 'toolset_association_created', 'toolset_number_child_posts', 10, 5 );
add_action( 'toolset_before_association_delete', 'toolset_number_child_posts', 10, 5 );

function toolset_number_child_posts( $relationship_slug, $parent_id, $child_id, $intermediary_id, $association_uid ) {
  // add a 1 if child properties exist to facilitate filtering by existence of child post
  if( get_post_type($parent_id)=='developments' ) {
    // get most recent property post
    $property_args = array(
      'numberposts'           =>   1,
      'post_type'             =>   'property',
      'orderby'               =>   'post_date',
      'order'                 =>   'DESC',
      'toolset_relationships' => array(
        'role'          => 'child',
        'related_to'    => $parent_id,
        'relationship'  => 'developments_property'
      ),
    );
    $properties_query = new WP_Query( $property_args );
    $properties = $properties_query->posts;

    if(isset($properties[0])) {
      // set the checkbox custom field value here using update_post_meta
      update_post_meta( $parent_id, 'wpcf-has-vacant-properties', 1);
    }else {
      delete_post_meta( $parent_id, 'wpcf-has-vacant-properties');
    }
  }
}

3. Now you must also trigger this code again whenever the Housing Development post is saved. For example, if you are editing a Housing Development post with no vacant properties, the checkbox is unchecked. If you add two new Properties, the code above will set the custom field value to 1. But then if you change something in the Housing Development post and click Update without reloading the post editor first, the custom field value will be overwritten with an empty value. To fix that I added the save_post hook.

function toolset_count_child_properties_on_save( $post_id ) {
  if( get_post_type( $post_id ) == 'developments' ) {
    toolset_number_child_posts( 'developments_property', $post_id, null, null, null );
  }
}
add_action( 'save_post', 'toolset_count_child_properties_on_save', 1000);

Check it and let me know the results.

#1100697

Hi Christian,

That's great. I've tried that amended code and that now works well.

Many thanks for your help!

Best wishes,

Chris